Arduino als Frequenzteiler

Der Arduino kann als Frequenzteiler verwendet werden. Mich hat dabei interessiert bis zu welcher Frequenz das möglich ist.

Der Eingang : Dazu muß an einem Eingang das Signal als TTL Pegel anliegen (0/5V beim UNO, NANO, MEGA oder 0/3V beim DUE…) Ich habe hier den Eingang Pin 7 verwendet.

Das Programm: Der Arduino erkennt mit pulsIn(inPin, HIGH) eine steigende Flanke des Eingangssignals.

Der Ausgang: Als schnellen Ausgang habe ich den PORT B genommen und mit dem Assembler Befehl PORTB^=B11111111 umgeschaltet.

Wenn nach jeder Eingangsflanke das Ausgangssignal umgeschaltet wird dann wird die Frequenz halbiert. Es ist also ein Frequenzteiler durch 2 ( :2 ).

// frequency divider :2 with an Arduino
// need ttl signal on input inPin
// divided output signal is on: 
//   UNO, NANO : pin D8-D13
//   MEGA : pin D10-13
// Input frequency max approx. 120 kHz
//
// Matthias Busse 26.12.2018 version 1.0

int inPin=7;

void setup() {
  pinMode(inPin, INPUT);
  DDRB = B11111111;           // port B is output D8-D13 (D10-D13)
  PORTB=B11111111;            // init port B
}

void loop() {
    pulseIn(inPin, HIGH);
    PORTB^=B11111111;          // change all bits
}

Wenn bei jeder 2. Eingangsflanke das Ausgangssignal umgeschaltet wird, ist es ein Frequenzteiler :4

// frequency divider :4 with an Arduino
// need ttl signal on input inPin
// divided output signal is on: 
//   UNO, NANO : pin D8-D13
//   MEGA : pin D10-13
// Input frequency max approx. 80 kHz
//
// Matthias Busse 26.12.2018 version 1.0

int inPin=7;

void setup() {
  pinMode(inPin, INPUT);
  DDRB = B11111111;           // port B is output D8-D13 (D10-D13)
  PORTB=B11111111;            // init port B
}

void loop() {
    pulseIn(inPin, HIGH);
    pulseIn(inPin, HIGH);
    PORTB^=B11111111;          // change all bits
}

Hier der Frequenzteiler :6

// frequency divider :6 with an Arduino
// need ttl signal on input inPin
// divided output signal is on: 
//   UNO, NANO : pin D8-D13
//   MEGA : pin D10-13
// Input frequency max approx. 80 kHz
//
// Matthias Busse 26.12.2018 version 1.0

int inPin=7;

void setup() {
  pinMode(inPin, INPUT);
  DDRB = B11111111;           // port B is output D8-D13 (D10-D13)
  PORTB=B11111111;            // init port B
}

void loop() {
    pulseIn(inPin, HIGH);
    pulseIn(inPin, HIGH);
    pulseIn(inPin, HIGH);
    PORTB^=B11111111;          // change all bits
}

Und zum Schluß der Teiler der auf die serielle Eingabe reagiert und so auf eine gradzahlige Teilung ( 2, 4, 6, 8 … 65534 ) eingestellt werden kann.

// variable frequency divider with an arduino
// need ttl signal on input inPin
// divided output signal is on: 
//   UNO, NANO : pin D8-D13
//   MEGA : pin D10-13
// serial divider values 2, 4, 6, 8 ...
// max.. frequency approx 50kHz 
//
// Matthias Busse 26.12.2018 version 1.0

String inputString="     ";   // serial input string
bool stringComplete=false;    // input strins completed
int inPin=7;
unsigned int i, divider=2;    // use unsigned long if divider is > 65535

void setup() {
  Serial.begin(38400);        // serial input
  pinMode(inPin, INPUT);
  DDRB = B11111111;           // port B is output D8-D13 (D10-D13)
  PORTB=B11111111;            // init port B
}

void loop() {
  for(i=0; i<divider/2 ; i++) 
    pulseIn(inPin, HIGH);
  PORTB^=B11111111;
  if(stringComplete) {        // read input
    stringComplete=false;
    divider=inputString.toInt();
    divider=(divider/2)*2;    // only even numbers are allowed
    if(divider < 2) divider=2; // min. 2, also for wrong input (>0)
    Serial.println(divider);
    inputString="";
  }
}

void serialEvent() {
// called outside loop() when serial data is available.
  while(Serial.available()) {        // read all data from rx buffer
    char inChar=(char)Serial.read(); // read one char
    if(inChar == '\n') {             // string terminate
      stringComplete=true; 
    }
    else {                            // add char
      inputString+=inChar; 
    }
  }
}

In den Programmen muß jede steigende Flanke des Eingangssignals erkannt werden. Zwischen den pulseIn() Zeilen führt der Arduino Code aus und das dauert eine gewisse Zeit. Das darf aber nicht länger dauern als bis zur nächsten steigenden Franke, sonst wird erst die übernächste Flanke wieder erkannt und es wird falsch geteilt.

Dadurch ergeben sich beim UNO / MEGA usw. mit 16MHz Taktfrequenz diese ermittelten maximalen Eingangsfrequenzen
:2  max 120 kHz
:4  max 80 kHz
:6  max 80 kHz
variable max 50 kHz

Mit einer höheren Taktfrequenz (z.B. Arduino DUE mit 84MHz) sind entsprechend höhere Eingangsfrequenzen möglich.

Verwendet wurden:
Arduino MEGA 2650 mit 16MHz
Arduino Software 1.8.0
Frequenzgenerator aus diesem Beitrag
Ein selbst gebauter Umsetzer 0-1V Sinus zum 0-5V TTL Rechteck-Signal
– aus  einem OP TL072 als Spannungsfolger einfach mit 0/5V betrieben
– und einem Inverter aus dem 74HC04 IC
Tektronix 2465A Oszilloskop zur Anzeige des Eingang- und Ausgangssignals

von Matthias Busse

Ein Gedanke zu „Arduino als Frequenzteiler

  1. Gunther

    Was für ein toller Code !!! Am Wochende wollte ich den Dreh-Encoder meiner CNC-Drehbank nutzen, um die Drehzahl des Spannfutters zu ermitteln und anzuzeigen. Das Messen des (TTL)Encoders ergab 30 Impulse pro Umdrehung. Den Frequenzteiler auf 1/30 eingestellt, und siehe, die Drehzahlanzeige deckt sich mit der Anzeige eines externen Laser-Drehzahlmessers.
    Solange der Antrieb der Drehbank läuft, ist alles perfekt, nur wenn der Antrieb abgescheltet ist (Drehzahl 0) fängt der Arduino manchmal an „wirres Zeug“ zu machen. Es erscheint eine Drehzahlanzeige zwischen 60 und ca. 250 auf meinem Display. Auch die LED auf dem Arduino Nano (D13) flackert unregelmäßig. Sobald wieder Impulse vom Encoder kommen ist alles wieder „normal“. Ich kann gut mit diesem kleinen „Problem“ leben, aber mich würde schon der Grund dafür interessieren.

    Antworten

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.