Ein Drehzahlmesser bestimmt die Umdrehungen eines Objekts pro Sekunde (Frequenz) oder pro Minute (RPM). Meistens kommt hier ein Laser zum Einsatz, der eine Berührung des Objekts unnötig macht. Damit der Laser die Umdrehungen erfassen kann, muss auf dem Objekt ein reflektierender Streifen angebracht werden. In meinem Fall war es ein Stück Aluklebeband umgeben von schwarzen Klebeband.
Das Arduino-Programm bestimmt nun die Zeit τ zwischen zwei erfassten Laserreflexionen. Daraus ergibt sich mit f = 1/τ ganz einfach die Rotationsfrequenz bzw. durch 60·f die Umdrehungen pro Minute.
Als Lichtsensor verwende ich einen IR-Näherungsschalter. Dieser besteht aus einer Infrarot-LED (Sender), einer IR-Photodiode (Empfänger) und einem Komparator. Übersteigt die mit der Photodiode erfasste Lichtintensität einen bestimmten mit dem Potentiometer einzustellenden Wert, so geht der Ausgang des Komparators auf LOW. Ist die Lichtintensität zu gering, ist der Ausgang HIGH. Mit einem sog. interrupt erfasst nun der Arduino genau den Wechsel von HIGH auf LOW und berechnet die Periodendauer bzw. erhöht den Zähler um 1.
Der Schaltplan ist denkbar einfach. Die ermittelte Frequenz wird auf einem 16×2 Display angezeigt.
Getestet habe ich den Drehzahlmesser mit meinem Flettnerrotor. Dabei verglich ich die mit dem Arduino ermittelte Frequenz mit jener des Oszilloskops. Die Übereinstimmung (konkret f = 15.2 Hz) war zufriedenstellend:
Hier das Signal am Oszilloskop:
Und hier die Arduino-Ausgabe:
Leider machte der Drehzahlmesser bei Frequenzen > 60 Hz (3600 RPM) schlapp. Ich habe deshalb ein zweites Arduino-Programm geschrieben, welches die ankommenden Pulse innerhalb 1 Sekunde erfasst und dann diesen Wert (= Frequenz) anzeigt. So muss das interrupt weniger arbeiten verglichen mit der Berechnung der Periodendauer bei jeder Auslösung des Interrupts (erstes Programm).
Erstes Arduino-Programm mit Berechnung der Frequenz nach jedem interrupt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
#include <LiquidCrystal_I2C.h> #include <Wire.h> LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display. ACHTUNG: Adresse kann auch 0x3F sein !!! // Anschlüsse: // GND - GND // VCC - 5V // SDA - ANALOG Pin 4 // SCL - ANALOG pin 5 int sensor = 2; unsigned long currentTime; unsigned long lastTime; //unsigned long pulse_freq; unsigned long period; float pulse_freq; // =========================== // ======= SETUP ========= // =========================== void setup() { pinMode(sensor, INPUT); Serial.begin(9600); attachInterrupt(digitalPinToInterrupt(sensor), pulse, FALLING); // Setup Interrupt lcd.begin(); // initialize the lcd lcd.backlight(); lcd.setCursor(0,0); lcd.print("Drehzahl-"); lcd.setCursor(0,1); lcd.print("messer"); delay(3000); lcd.setCursor(0,0); lcd.print(" "); lcd.setCursor(0,1); lcd.print(" "); lastTime = micros(); } // ======================== // ======= LOOP ========= // ======================== void loop () { pulse_freq = 1000000.0 / period; lcd.setCursor(0,0); lcd.print("f = "); lcd.print(pulse_freq, 2); lcd.print(" Hz "); lcd.setCursor(0,1); lcd.print(pulse_freq * 60, 0); lcd.print(" RPM "); } // ============================= // ======= INTERRUPT ========= // ============================= void pulse () // Interrupt function { currentTime = micros(); period = currentTime - lastTime; lastTime = currentTime; } |
Zweites Arduino-Programm mit Bestimmung der innerhalb einer Sekunde ankommenden interrupts:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
#include <LiquidCrystal_I2C.h> #include <Wire.h> LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display. ACHTUNG: Adresse kann auch 0x3F sein !!! // Anschlüsse: // GND - GND // VCC - 5V // SDA - ANALOG Pin 4 // SCL - ANALOG pin 5 int sensor = 2; unsigned long currentTime; unsigned long lastTime; unsigned long pulse_freq; // =========================== // ======= SETUP ========= // =========================== void setup() { pinMode(sensor, INPUT); Serial.begin(9600); attachInterrupt(digitalPinToInterrupt(sensor), pulse, FALLING); // Setup Interrupt currentTime = millis(); lastTime = currentTime; lcd.begin(); // initialize the lcd lcd.backlight(); lcd.setCursor(0,0); lcd.print("Drehzahl-"); lcd.setCursor(0,1); lcd.print("messer"); delay(3000); lcd.setCursor(0,0); lcd.print(" "); lcd.setCursor(0,1); lcd.print(" "); } // ======================== // ======= LOOP ========= // ======================== void loop () { currentTime = millis(); // Every second, calculate frequency if(currentTime >= (lastTime + 1000)) { lastTime = currentTime; /* Serial.print(pulse_freq); Serial.println(" Hz"); */ lcd.setCursor(0,0); lcd.print("f = "); lcd.print(pulse_freq); lcd.print(" Hz "); lcd.setCursor(0,1); lcd.print(pulse_freq * 60); lcd.print(" RPM "); pulse_freq = 0; // Reset Counter } } // ============================= // ======= INTERRUPT ========= // ============================= void pulse () // Interrupt function { pulse_freq++; } |