Strecke errechnen aus Geschwindigkeit und dauerhaftes Speichern

Hallo liebes Forum,

Dies ist mein erster Post hier und ich weis nicht ob ich hier richtig gelandet bin.

Ich bin gerade daran mir einen Tacho zu bauen, der aus einem PWM Signal die Geschwindigkeit errechnet und auf einem TFT Display anzeigt.

Jetzt möchte ich ähnlich wie beim Auto einen Zähler der gesamten Strecke haben, der auch im
Auszustand gespeichert wird, und einen, der bei jedem aus und wieder an von null beginnt.

Meine vorhandenen Variablen sind die Geschwindigkeit und die Zeit, für die ich die millis(); Funktion des Microcontrollers benutzen würde.

Als Speichermöglichkeit habe ich einen SDKartenslot am Display, den ich gerne Benutzen würde.

Da mein Code aber noch sehr Träge auf mich wirkt und ich nicht so ganz mit der Strukturierung klarkomme, Suche ich hier Hilfe.

#include <Adafruit_GFX.h>    
#include <Adafruit_ST7735.h> 
#include <Adafruit_ST7789.h> 
#include <SPI.h>
#define TFT_CS        10
#define TFT_RST        8 
#define TFT_DC         9
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
#define pin1 3

unsigned long freqInPin1High,  
              freqInPin1Low,  
              calcValPin1High,     
              dutycycle,
              tachval;

void setup() {
  delay(100);
 tft.initR(INITR_GREENTAB);//TFT Display initialisieren
 tft.setRotation(1);
 tft.fillScreen(ST77XX_BLACK);
  tft.setTextColor(ST77XX_WHITE);
  tft.setCursor(90,0);
  tft.setTextSize(2);
  tft.println("Km/h");
  pinMode(pin1, INPUT);
}

void loop() {
    pwmread();
    yield();
}

void pwmread(){
        freqInPin1High = pulseInLong(pin1, HIGH, 150);
        freqInPin1Low = pulseInLong(pin1, LOW, 150);
            calcValPin1High = freqInPin1High * 100;     //High sequenz des dutycycle mit 100 multiplizieren
            dutycycle = calcValPin1High / (freqInPin1High + freqInPin1Low);     //dutycycle in Prozent errechnen
            if(dutycycle <= 100){ //nur einen Dutycycle unter 100% zulassen, da der pin auch dauerhaft HIGH, bzw. LOW sein kann
            tachval = map(dutycycle, 0, 100, 35, 0);
            }
            int pinread1 = digitalRead(pin1);
            if(freqInPin1High == 0 && freqInPin1Low == 0 && pinread1 == 1){
              tachval = 0;
            }
            if(freqInPin1High == 0 && freqInPin1Low == 0 && pinread1 == 0){
              tachval = 35;
            }
    lcdwrite();//Aufs TFT schreiben
}

void lcdwrite(){
  tft.setTextColor(ST77XX_WHITE, ST77XX_BLACK);
  tft.setCursor(0,0);
  tft.setTextSize(7);
  tft.print(tachval);
  if(tachval < 10){//Leerstelle bei variablen unter 10, da sonst wenn nach 35 eine null geschrieben wird zB. 05 rauskommt
  tft.print(" ");
  }
 delay(100);
}

Schonmal Vielen Dank im Voraus, Tom!

Bei Deinem Code und der Beschreibung kommen mir etliche Fragen.

Woher kommt das Signal, bei dem der duty cycle eine wichtige Rolle spielt?
Normalerweise reicht ein (eingebauter) Zähler zum Zählen von Impulsen. Die momentane Geschwindigkeit ergibt sich dann aus der Zeit, in der eine bestimmte Anzahl Impulse eingetroffen ist.

Zur Speicherung im Aus-Zustand kann ich wenig sagen, solange nicht klar ist, wie dieser Zustand hergestellt wird, und ob dann noch die Versorgungsspannung anliegt. Im Prinzip kann vor dem Abschalten der Kilometerstand im EEPROM gespeichert werden.

Das Signal kommt aus einem Steuergerät, das aus dem Hallsensor eines Motors die Drehzahl errechnet und diese dann per PWM ausgibt.

Die Versorgungsspannung liegt im ausgeschaltenem Zustand noch an.

Die frage ist nur, wie lange das EEPROM hält? Bei an die Tausend Speicherzyklen im Jahr wäre da die Lebensdauer schon begrenzt, oder?

mega_user:
Die frage ist nur, wie lange das EEPROM hält? Bei an die Tausend Speicherzyklen im Jahr wäre da die Lebensdauer schon begrenzt, oder?

Die Lebensdauer ist natürlich begrenzt - schlappe 100.000 Schreibzugriffe sind vom Hersteller angegeben. Du kannst damit also ungefähr 100 Jahre auskommen. Ich hoffe, dass das genügt :slight_smile:

Gruß

Gregor

Hi

Dann wäre 'nur noch' interessant, wie das PWM-Signal denn aussieht und wie man Dieses zu interpretieren hat.

MfG

Hallo,

dann ist das PWM signal ja bereits eine Geschwindigkeit und ehr dazu gedacht das das analog ausgewerte wird. Wenn Du das jedoch digital messen willst reicht es eigendlich z.B die HIGH Zeit zu messen. Die Frequenz des PWM Signals sollte ja konstant sein. Dann musst Du noch wissen die dieses PWM Signal skaliert ist.

Um jetzt sie gesamte Strecke zu berechnen muss man eigendlich das Integral berechnen. Hört sich erst mal kompliziert an. In der Realität macht man das so das man in sinvollen Zeitabständen die gemessene Geschwindigkeit mit der Zeitdifferenz zum letzten mal multipliziert. Man geht also davon aus das man im gesamten Zeitsegment mit konstanter Geschwindigkeit gefahren ist.

Heinz

Also, das Steuergerät hat eine Frequenz von 16kHz und einen Dutycycle von 0%=3000RPM - 100%=0RPM, also invertiert.

Nach dem Getriebe sind das 0-35Km/h am Rad.

Dass was ich meinte ist, wie denn konkrete Möglichkeiten aussehen das Integral zu berechnen. Mit meinen zwei delays lege ich den Microcontroller ja sequentiell komplett lahm.

Mit meinen zwei delays lege ich den Microcontroller ja sequentiell komplett lahm.

Nicht komplett!
Aber wenn dir delay() nicht schmeckt, dann lass es weg.

Die Versorgungsspannung liegt im ausgeschaltenem Zustand noch an.

Dann reichts doch wenn du ins EEPROM schreibst, wenn das "Gerät" einige Zeit rumsteht.
Und dann gibts da ja auch noch "wear leveling"

Also, das Steuergerät hat eine Frequenz von 16kHz und einen Dutycycle von 0%=3000RPM - 100%=0RPM,

Suchtipp: micros() oder pulseIn()

Ich hatte den Code schon mal mit pulsein geschrieben.
Leider kam da nicht das raus was ich mir erhofft hatte. Die Geschwindigkeit Sprang einfach hin und her.

Außerdem hat der Roller eine Zündung, dementsprechend kann ich dann einfach, wenn die Zündung aus geht, die werte ins EEPROM schreiben und dann killt sich der Prozessor selbst.
Je nachdem, was er verbraucht kann er auch an bleiben.

Ich hatte den Code schon mal mit pulsein geschrieben.
Leider kam da nicht das raus was ich mir erhofft hatte. Die Geschwindigkeit Sprang einfach hin und her.

pulseIn() ist das Arduinowerkzeug um kurze Zeiten zu messen.

Wenn dir das nicht reicht, dann könntest du auch einen der Hardware Timer bemühen.

Dann werde Ich Googlen und das auch mal machen.

Problem war, dass der Arduino einfach einzelne pulse übersprungen hat. Also zum Beispiel im oberen und unteren Geschwindigkeitsbereich wurde immer mal wieder auf 0 bzw. 35 und wieder zurück gesprungen.

Mit meinem jetzigen Code ist die Geschwindigkeit Richtig und stabil. Wenn das Problem also nicht unbedingt dadurch gelöst wird, den auszutauschen, würde ich ihn behalten.

würde ich ihn behalten.

Ja dann ....

mega_user:
Mit meinem jetzigen Code ist die Geschwindigkeit Richtig und stabil. Wenn das Problem also nicht unbedingt dadurch gelöst wird, den auszutauschen, würde ich ihn behalten.

Welches Problem denn? Wenn die Berechnung der Geschwindigkeit so funktioniert lass sie doch so.

Zum Kilometerzählen musst du nur die Geschwindigkeit integrieren. Das geht z. B. so: wenn du alle x Sekunden die Geschwindigkeit in m/s nimmst und sie mal x rechnest hast du einen Summanden. Den rechnest du immer zur bisherigen Strecke dazu.

Für x empfehle ich nichts über 0,1, da es sonst ungenau wird. Generell ist die Methode nur eine Näherungslösung. Eine bessere Näherung bietet die Trapezmethode.

Zum Kilometerzählen musst du nur die Geschwindigkeit integrieren

Was natürlich suboptimal wäre, wenn die Geschwindigkeit erst vorher aus Impulse/Zeit (oder bei dir evtl. die Pausenlänge) bestimmt wurde. Prüfe erst mal, ob dein PWM nicht aus einem kurzen Impuls/Weg und einer je nach Geschwindigkeit unterschiedlichen Pause besteht.