Hallo Kollegen,
ich hab ein komisches Problem mit einem Motorradtacho-Sketch, welches ich nicht recht inWorte fassen kann.. daher hab ich auch keinen aussagekräftigeren Titel gewählt (Falls jemand eine gute Idee hat - bitte melden ):
Also... Ich programmiere mir gerade einen kleinen Tacho für mein Motorrad. Vereinfacht gesagt wird per Reedschalter eine Interruptroutine ausgelöst, in der ich die Geschwindigkeit berechne. Das ganze wird dann auf einem 0.96" oled dargestellt und der Kilometerstand (Gesamt & Trip) zyklisch ins Eeprom weggeschrieben.
Bis gestern funktionierte auch alles, dann bin ich aber über ein (für mich) unerklärliches Phänomen gestolpert.
Sobald ich in void setup() die drei zeilen ab // if (GesamtMeter > 3000 ) ..... einkommentiere, gibt mir die RunningAverage Funktion (zur "Glättung" der Geschwindkeit) nur noch "nan" (not a number) aus und der Tacho funktioniert nicht mehr. Kommentiert man diese drei Zeilen wieder raus, klappt alles.
Ich konnte das Problem auf die Variable "Gesamtmeter" eingrenzen. Sobald man damit irgendwas in void-setup anstellt, funktinoiert RunningAverage nicht mehr... (Serial.println(GesamtMeter); führt zum selben Problem)
Wieso tangiert diese Variable die RunningAverage Funktion?
Für mich als Anfänger ist das sehr befremdlich
Unten findet ihr den aufs wesentliche gekürzten Code. Als Attachement habe ich die ungekürzte Version angehängt.
danke im Voraus
mfg
Basti
#include <EEPROM.h>
#include <RunningAverage.h>
#include <Wire.h>
#include "OneButton.h"
#include <U8g2lib.h>
#include "RTClib.h"
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ 16, /* data=*/ 17); // ESP32 Thing, HW I2C with pin remapping
RTC_DS3231 rtc;
RunningAverage myRA(5);
volatile unsigned long dauer = 0;
volatile unsigned long last = 0; // Zählerwert beim letzten Interrupt
short geschwindigkeit;
short VAnzeige;
const int buttonPin = 4;
const int reedPin = 3;
int screen = 0;
volatile int RotationCounter = 0;
OneButton button(buttonPin, true);
char Minute[3];
char Stunde[3];
const int RadUmfang = 1862;
char Uhrzeit[10];
char Temperatur[15];
char Speed[10];
float dummyInterval = (RadUmfang/1000.0 * 160.0);
unsigned long GesamtMeter;
unsigned long TripMillimeter;
int GesamtMeter_ADDR = 0;
int TripMillimeter_ADDR = GesamtMeter_ADDR + 4;
char TripKm[10];
char GesamtKm[10];
int testMeter = 0;
boolean reset = 0;
void setup() {
Serial.begin(9600); // open the serial port at 9600 bps:
if (reset) { resetEEPROM(); } //alles auf 0 setzen
pinMode(reedPin, INPUT_PULLUP); // Reed-Sensor an Pin 3
pinMode(buttonPin, INPUT_PULLUP); // Taster an Pin 2
attachInterrupt(digitalPinToInterrupt(reedPin), readmillis, RISING);
GesamtMeter = eepromReadLong(GesamtMeter_ADDR);
TripMillimeter = eepromReadLong(TripMillimeter_ADDR);
// if (GesamtMeter > 3000 ) {
// Serial.println("EEPROMschonen()");
// }
myRA.clear();
button.attachClick(klick);
button.attachLongPressStop(langDruck);
u8g2.begin();
delay(500);
}
void loop() {
if (RotationCounter >= 160) { //ungefähr alle 300m Tachostand ins EEprom wegschreiben und GesamtMeter hochzählen
RotationCounter = 0;
GesamtMeter += dummyInterval; //alle 160 Umdrehungen Radumfang (mm) auf Gesamtlaufleistung (Meter) addieren
eepromWriteLong(GesamtMeter, GesamtMeter_ADDR);
eepromWriteLong(TripMillimeter, TripMillimeter_ADDR);
}
button.tick();
if (millis()-last >= 2000) {
myRA.clear(); //wenn keine Radumdrehung innerhalb von 2 Sek stattgefunden hat --> Geschwindigkeit nullen
}
VAnzeige = myRA.getAverage(); // Mittelwert errechnen
u8g2.clearBuffer();
draw();
u8g2.sendBuffer();
delay(100);
}
void draw() {
u8g2_prepare();
DateTime now = rtc.now();
sprintf(Uhrzeit, "%02d:%02d", now.hour(), now.minute());
int hunderter = (TripMillimeter / 100000) % 10;
int tausender = TripMillimeter / 1000000;
sprintf(GesamtKm, "%6dkm", GesamtMeter/1000);
sprintf(TripKm, "%5d.%dkm", tausender, hunderter);
sprintf(Speed, "%3d", VAnzeige);
switch (screen) {
case 0:
u8g2.setFont(u8g2_font_logisoso38_tn);
u8g2.drawStr( 5, 15, Uhrzeit);
break;
case 1:
u8g2.drawXBMP( 80, 0, tachoSymbol_width, tachoSymbol_height, tachoSymbol);
u8g2.setFont(u8g2_font_logisoso38_tn);
u8g2.drawStr( 0, 15, Speed);
u8g2.setFont(u8g2_font_logisoso20_tr);
u8g2.drawStr( 75, 32, "kmh");
break;
case 2:
u8g2.setFont(u8g2_font_logisoso20_tr);
u8g2.drawStr( 0, 10, "Trip:");
u8g2.drawStr( 0, 40, TripKm);
u8g2.drawXBMP( 80, 0, route_width, route_height, route_bits);
break;
case 3:
u8g2.drawStr( 0, 40, TripKm);
u8g2.drawStr( 5, 10, GesamtKm);
break;
case 4:
u8g2.setFont(u8g2_font_logisoso38_tn);
u8g2.setCursor(0, 15);
u8g2.print(tempDS3231(), 1);
u8g2.drawCircle(98, 20, 5, U8G2_DRAW_ALL); //nicht besonders schön, aber speicher-optimalste Veriante ??
u8g2.drawCircle(98, 20, 4, U8G2_DRAW_ALL);
u8g2.drawXBMP( 105, 0, thermometer_width, thermometer_height, thermometer_Symbol);
break;
}
}
void u8g2_prepare(void) {
u8g2.setFontRefHeightExtendedText();
u8g2.setDrawColor(1);
u8g2.setFontPosTop();
u8g2.setFontDirection(0);
}
void readmillis() { // Interrupt-Routine
unsigned long m = millis(); // Microsekundenzähler auslesen
unsigned long v = m - last; // Differenz zum letzten Durchlauf berechnen
if (v > 20) { // ignorieren wenn <= 10ms (Kontaktpreller)
dauer = v; // Dauer einer Radumdrehung in ms
last = m; // und wieder den neuen Wert merken
geschwindigkeit = RadUmfang*3.6/dauer; // Geschwindigkeit: 1 Interrupt alle 1861mm (Radumfang)
myRA.addValue(geschwindigkeit); // Wert zur Mittelwerberechnung hinzufügen
TripMillimeter += RadUmfang; //pro Umdrehung 1861mm gefahren
RotationCounter += 1;
Serial.println(myRA.getAverage());
}
}
void klick() { //durchtoggeln der Screens
screen++;
if (screen > 4) { screen= 0; }
}
void langDruck() {
if (screen == 2) {
TripMillimeter = 0; //Trip zurücksetzen
eepromWriteLong(TripMillimeter, TripMillimeter_ADDR);
}
}
float tempDS3231() { // Die Temperatur des DS3231 auslesen
float temp;
int msb, lsb;
Wire.beginTransmission(0x68);
Wire.write(0x11); // DS3231 Register zu 11h
Wire.endTransmission();
Wire.requestFrom(0x68, 2); // 2 Byte Daten vom DS3231 holen
msb = Wire.read();
lsb = Wire.read();
temp=((msb << 2) + (lsb >> 6) ) /4.0;
return temp;
}
void eepromWriteLong(long lo, int adr) {
byte by;
for(int i=0;i< 4;i++) {
by = (lo >> ((3-i)*8)) & 0x000000ff;
EEPROM.write(adr+i, by);
}
}
long eepromReadLong(int adr) {
long lo=0;
for(int i=0;i< 3;i++){
lo += EEPROM.read(adr+i);
lo = lo << 8;
}
lo += EEPROM.read(adr+3);
return lo;
}
tacho.txt (10.1 KB)