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
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.