-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsource_Drehzahlmesserv3.pde.txt
102 lines (93 loc) · 4.74 KB
/
source_Drehzahlmesserv3.pde.txt
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
90
91
92
93
94
95
96
97
98
99
100
101
// Drehzahlmesser für Duemilanove
// -------------------------------------------------------------------
#include <LiquidCrystal.h> // LCD Library einbinden
#define LCDdimmer 10 // LCD Hintergrundbeleuchtung an Pin 10
#define Eingang 2 // Drehzahl-Eingang: Pin2 / Interrupt 0
#define AVG 8 // runden über 8 Werte
#define REFRESH 200 // Display refresh alle 200ms
#define HELLIGKEIT 200 // LCD Hintergrundbeleuchtung
#define SENSORS 1 // Anzahl Sensoren / Impulse pro U
// Variablen
uint32_t last=0; // Zählerwert beim letzten Interrupt
uint16_t rra[AVG]; // Array für rolling Average
uint8_t ptr=0; // Array Pointer
volatile int32_t prep=0; // Avg prep
volatile uint8_t cnt=0; // Avg count
volatile uint16_t drehzahl=0; // selbstredend
volatile uint16_t timeout=10; // dynamic timeout
volatile uint16_t wdog=10; // um Stillstand zu erkennen
char buf[18]; // Pufferstring für sprintf
LiquidCrystal lcd(8, 11, 9, 4, 5, 6, 7); // Display Anschlußpins definieren
void setup() {
pinMode(Eingang, INPUT); // Eingangspin auf Eingang stellen
digitalWrite(Eingang, HIGH); // und Pullup-Widerstand einschalten
pinMode(LCDdimmer, OUTPUT); // Display-Dimmer-Pin auf Ausgang
analogWrite(LCDdimmer, HELLIGKEIT); // Helligkeit einstellen (via PWM)
lcd.begin(16, 2); // Display hat 2 Zeilen a 16 Zeichen
lcd.home(); // cursor an den Anfang der 1. Zeile
lcd.print("-=- Drehzahl -=-"); // Überschrift ausgeben
lcd.setCursor(0, 1); // cursor an den Anfang der 2. Zeile
lcd.print("** ???? U/min **"); // 2. Zeile ausgeben
attachInterrupt(0, readmicros, FALLING); // Interrupt 0 auf Routine readmicros setzen
}
void loop() { // Hauptprogramm
if (wdog <= timeout) { // dynamic timeout
wdog++;
} else {
cli(); // kein Impuls erhalten
drehzahl = 0; // alle Werte auf 0
cnt = 0;
prep = 0;
last = 0;
sei();
}
drehzahl = myround(drehzahl); // runden auf 5 / 10 / 50 / 100 - optional
sprintf(buf, "%5u ", drehzahl); // als 5stellig formatierte Zahl in den Puffer
lcd.setCursor(2, 1); // cursor an Position bringen
lcd.print(buf); // Puffer ausgeben
delay(REFRESH); // etwas warten
}
void readmicros() { // Interrupt-Routine
uint32_t m, dur;
uint16_t rpm;
m = micros(); // Microsekundenzähler auslesen
dur = m - last; // Differenz zum letzten Durchlauf berechnen
if (dur > 5000L) { // plausibel? Drehzahl bis max 12000 U/min
if (last > 0) { // ersten Messzyklus ignorieren
rpm = (60000000L / SENSORS) / dur; // Drehzahl ausrechnen
if (cnt < AVG) { // |
cnt++; // |
} else { // |
prep -= rra[ptr]; // |
} // | rolling Average
rra[ptr++] = rpm; // |
prep += rpm; // |
ptr %= AVG; // |
drehzahl = prep / cnt; // |
}
last = m; // letzten Wert merken
timeout = dur / (REFRESH * 500L); // timeout nach 2 fehlenden Impulsen
}
wdog = 0; // timeout watchdog
}
uint16_t myround(uint16_t value) { // Gewichtete Rundung
uint16_t rto;
if (value > 10000) { // Rundungswert bestimmen
rto = 100;
} else if (value > 3000) {
rto = 50;
} else if (value > 500) {
rto = 10;
} else if (value > 100) {
rto = 5;
} else {
return (value);
}
return (_myround(value, rto));
}
uint16_t _myround(uint16_t value, uint8_t roundto) { // Rundung Hilfsroutine
value += (roundto >> 1); // halben roundto Wert addieren
value /= roundto; // integer division
value *= roundto; // integer multiplikation
return (value);
}