//Programm: Drehzahlmessung
//Author: Lukas Pimeshofer
//Datum: 26.11.2024
//Bibliotheken
//Konstanten
#define BUTTON 4 //Pin 4 für Encoder Eingang (Button)
#define FILTERSIZE 20
#define DELAY 1000
#define PULSPERREVOLUTION 20 //Anzahl der Pulse pro Umdrehung
#define DEBOUNCETIME 5 //Entprellzeit in Millisekunden
//Globale Variablen
unsigned long prevISR = 0; //Zeit für Entprellung
unsigned long prevMillisMean = 0; //Zeit für Mittelwertberechnung
unsigned long timePulses = 0; //Zeit der letzten Zeitmarke eines Pulses
float Drehzahl = 0;
unsigned long element; //Variable zum Speichern eines Wertes aus der Warteschlange
int filterArray[FILTERSIZE];
unsigned int filterIndex = 0;
/*Ich habe die Filterung mit einem Array umgesetzt, da dies für mich mit
einem Array am einfachsten vorkam zu lösen :). */
QueueHandle_t queue; // Warteschlange für die Übertragung der Pulse
//Interrupt Service Routine
void IRAM_ATTR buttonISR() {
unsigned long duration;
//Entprellung: Verhindert, dass zu schnelle aufeinanderfolgende ausgelöste Pulse verarbeitet werden
if (millis() - prevISR >= DEBOUNCETIME) {
prevISR = millis(); //Aktualiersiert die Zeitmarke der letzten Verarbeitung
duration = millis() - timePulses; //Berechnet die Zeit seitdem letzten Puls
timePulses = millis(); //Aktualiersiert die Zeitmarke des aktuellen Pulses
xQueueSend(queue, &duration, portMAX_DELAY); //Sendet die Pulsdauer in die Warteschlange
}
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println("Drehzahlmessung");
//Konfiguriert den Button-Pin mit interen Pull-UP-Widerstand
pinMode(BUTTON, INPUT_PULLUP);
//Aktiviert den Interrupt für fallende Flanke (Wenn Button gedrückt wird)
attachInterrupt(BUTTON, buttonISR, FALLING);
//Erstellt eine Warteschlange für bis zu 20 Pulse
queue = xQueueCreate(20, sizeof(unsigned long));
//Array auf 0 setzen
for (int i = 0; i < FILTERSIZE; i++) {
filterArray[i] = 0;
}
}
void loop() {
// put your main code here, to run repeatedly:
unsigned long dt = millis() - prevMillisMean;
if (queue != NULL) {
//Holt den nächsten Wert aus der Warteschlange
xQueueReceive(queue, &element, portMAX_DELAY);
//Verarbeitet nur gültige Werte
if (element > 0) {
//Konvertiert Pulsdauer in Sekunden
float pulseInterval = (float)element / 1000.0;
//Berechnet die Drehzahl in RPM
Drehzahl = (60.0 / PULSPERREVOLUTION) / pulseInterval;
//Drehzahl ins Array speichern
filterArray[filterIndex] = Drehzahl;
//Filterindex erhöhen
filterIndex++;
//Rücksetzten Filterindex
if (filterIndex == FILTERSIZE) {
filterIndex = 0;
}
}
}
if (dt >= DELAY) {
prevMillisMean = millis();
//Mittelwertberechnung im Filter-Array
float meanRPM = 0;
for (int i = 0; i < FILTERSIZE; i++) {
meanRPM += filterArray[i];
}
meanRPM /= FILTERSIZE;
//Ausgabe der gefilterten Drehzahl
Serial.print("Gefilterte Drehzahl:");
Serial.println(meanRPM);
}
}