Tacho für ein Moped (Oldtimer)

Guten Morgen Leute,

ich bin dabei mit einen Code zusammenzuschstern aus allem was ich weiss, kann und irgendwo finde. So sieht dieser Code aktuell vermutlich auch aus.

Was will ich haben und wofür?

Ich will einen Tacho für ein Oldtimer Modep. Warum kein Originales? Weil ich die Teile nur schwer oder gar nicht finden kann. Warum dann eins mit Arduino? Warum auch nicht, es macht ja Spaß. :slight_smile:

Was soll es können?

  1. Geschwindigkeit in km/h anzeigen
  2. Gefahrene Kilometer aufzeichnen, speichern und beim einschalten wieder auslesen
  3. Temperatur anzeigen (als nettes Extra, muss aber nicht)

Was habe ich bisher?
Einen Code, der aus meiner Sicht gut aussieht aber vermutlich genau das Gegenteil davon ist.

Was brauche ich?

Dringend Hilfe. Ich habe 1. keine Ahnung ob das so gut geschrieben ist und 2. fehlt mir jeglicher Ansatz für die EEPRom Geschichte und das zählen der Kilometer.

Ich muss aber auch sagen, dass meine Skills blutig anfängerisch sind. EIgentlich ist dieses Projekt für meinen Wissen/Können etliche Nummern zu groß.

Was verwende ich hierzu?

  1. Hall Sensor (als Baugruppe mit Platine)
  2. OLED Display (128x64)
  3. Arduino Nano / Atmega 328P

Im Anhang ein paar Fotos und folgend dann der Code. Über jede Hilfe die ich bekomme bin ich dankbar.

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4 // not used / nicht genutzt bei diesem Display
Adafruit_SSD1306 display(OLED_RESET);

byte DZM_InputPin = 2;
volatile unsigned long RPM_T2, RPM_Count;
unsigned long RPM , RPM_T1;

int KMH;
//int URad = 1.571; // Umfag des Rad in METER
int RaD = 0.25; // Halber Raddurchmesser in METER
const float Pi = 3.14159265359; // Zahl Pi für die Formel zur Berechnun der Geschwindigkeit in km/h

void setup()   {             
   
  // initialize with the I2C addr 0x3C / mit I2C-Adresse 0x3c initialisieren
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  
  // random start seed / zufälligen Startwert für Random-Funtionen initialisieren
  randomSeed(analogRead(0));

    pinMode(DZM_InputPin, INPUT_PULLUP);
  RPM_T1 = 0;
  RPM_T2 = 0;
  RPM_Count = 0;


  attachInterrupt(0, RPM_Meter, FALLING);    // Interrupt0 wird bei fallender Flanke auf Pin2
  
}

#define DRAW_DELAY 118
#define D_NUM 47


void loop() {

      char RPMStr[5];
  display.clearDisplay();
  // set text color / Textfarbe setzen
  display.setTextColor(WHITE);
  // set text size / Textgroesse setzen
  display.setTextSize(1);
  // set text cursor position / Informationen
  display.setCursor(1,0);
  // show text / Text anzeigen
  display.println(" Derbi Antorcha 2019"); // Info Text frei wählbar (X Wert / Y Wert)
  display.setTextSize(4);
  display.setCursor(17,15);
  display.println(KMH);
  display.setTextSize(2);
  display.setCursor(80,15);
  display.println("km/h"); // Info-Anziege km/h
  display.setTextSize(1);
  display.setCursor(14,56);
  display.println("000000 km");
  display.setCursor(80,56);
  display.println("T: 21 C"); // Temperatur-Anzeige
  display.display();
  delay(100);

    if (RPM_T2 > RPM_T1) {
    RPM = (unsigned)(long)(60000 * RPM_Count / (RPM_T2 - RPM_T1));
    KMH = ((2 * 0.25 * Pi * ((unsigned)(long)(60000 * RPM_Count / (RPM_T2 - RPM_T1))) * 60) / 1000) ;
    RPM_T1 = RPM_T2;
    RPM_Count = 0;
  }
  else {
    RPM = 0;
    KMH = 0;
  }

}

void RPM_Meter () {

  RPM_Count++;
  RPM_T2 = millis();

}

Viele liebe Grüße

Hi

Bin bis jetzt erst beim Anfang von loop():
Als Erstes löscht Du das Display - Das solltest Du SO nicht machen, da loop() so schnell wie möglich durchlaufen werden soll.
Wenn der Arduino noch was Anderes machen soll, als Hier und Da das Display zu löschen und (vll. gar nicht sooo neuen) Text drauf zu brutzeln, würde ich Das nur machen, wenn sich auf dem Display was geändert hat bzw. die Display-Zeit gekommen ist (las ich was von DRAW_DELAY 118, 'riecht' bisher nach Display).

Dein Fest-Text (Name, Kilometerstand 000000...) gehört eher ins setup(), als in loop() - auch solltest Du zuvor die Kilometer ausgelesen haben (ok, darum geht's Dir ja gerade, trotzdem sehe ich noch keinen Ansatz, daß sich diese '0000000' irgendwie dynamisch verhalten sollen.
Also z.B. eine Variable 'kilometerstand', Die dort ausgegeben wird - Die kann ja noch im Sketch mit 0 initialisiert werden - DAS bekämen wir schon umgebogen.

Kommentare ... sehe ich nicht Einen mit 'Sinn und Verstand'.
Die Variablen-Benennung ist - ..., was wird Dir 'RPM_T2' in vier Wochen sagen?
Wahrscheinlich so viel wie mir 'geht wohl um die Motordrehzahl oder so ... Nummer 2'.

Wie oft muß sich die Anzeige ändern bzw. wie oft KANN die Anzeige sich ändern, daß man auch noch was drauf erkennen kann?
Daran sollten wir uns orientieren.
Wie viele Magnete hast Du pro Umdrehung - wird wohl eher Rad-Umdrehung rein, sind ja bei einem Tacho :slight_smile:
Diese Zahl vermisse ich im Sketch - auch eine EINS kann hier, für Nachbauer, durchaus hilfreich sein, um den Sketch einfach an eigene Bedürfnisse anzupassen.

EEprom ist unglücklich, da Du hier eigentlich 'nur selten' speichern solltest.
Wenn Du nur vor dem Abstellen speichern willst, brauchst Du noch eine Erkennung, ob der Strom 'gleich weg ist' - das in die Zukunft sehen kann der Arduino nicht so gut, also wird Hardware benötigt.
Hier wäre mein Ansatz FRam, einen 512 BYTE IC im DIP-Gehäuse gibt's für einen schmalen Taler auf eBay und Konsorten.
Vorteil hier:

  • beliebig oft beschreibbar (nicht nach 100000 Schreibzugriffen Schluss)
  • beliebig schnell beschreibbar (keine 3ms Zwangspause benötigt)
  • Datenerhalt wie EEprom
  • identische Pinbelegung, man kann z.B. den EEprom einer DS3231 (RTC) gegen einen SMD-FRam tauschen

Man könnte den EEprom aber auch so lange beschreiben, bis Er kaputt ist - und dann 'eine Speicherstelle weiter nach Hinten gehen' - ist momentan nur eine theoretische Überlegung!
An erster Stelle steht die Nummer, auf welchem 'Block' wir aktuell zugreifen.
Immer, wenn sich am KM-Wert was geändert hat, wird Dieser in diesen Block geschrieben.
Zurück gelesen und mit den Daten, Die geschrieben werden sollten, verglichen.
Wenn diese beiden Daten differieren, wird die 'Blocknummer' ausgelesen, +1, geschrieben.
Da diese Speicherstelle nur bei Fehl-Lesungen erhöht wird - und nicht bei jedem x-ten loop()-Durchlauf, wird diese Speicherstelle 'ewig' halten.
Nun der gleiche Versuch auf der neuen Block-Adresse, ebenfalls mit Rücklesen, hier sollte jetzt aber die Korrektur-Prüfung erfolgreich ausfallen.

Wenn Du 'alle Meter Fahrweg' speicherst, dürfte die erste Block-Adresse 100000:1000=100 km 'halten' - Puls/Minus, wobei diese 100000 vom Hersteller im Datenblatt garantiert werden.
So, nun benutzt Du also 'alle 100km' einen neuen Speicherbereich - wie groß ist das EEprom im Arduino? (Welcher überhaupt?)
Uno 1kB, Mega 4kB (zumindest mit aktuellen µC drauf, siehe hier)
Bei einem (unsigned) long-Wert wären das 1024/4 = 256 (minus Einen für die Block-Adresse) Speicherbereiche.
Das Moped könnte also, theoretisch, mit dieser EEprom-Speicherung, 255000km Laufleistung im Tacho speichern, bei Abspeicherung bei jedem Meter Fahrweg.
Bei 3ms 'Wartezeit' dürfte der Reifen 300 Umdrehungen pro Sekunde machen - Das wären 300m/s, wären (x4-10%, eigentlich x3,6, das Vorne ist aber das Gleiche und rechnet sich im Kopf besser) 1080km/h ... ok, für's EEprom haben wir wohl doch genug Zeit, so flott wird der Oldie wohl dann doch nicht sein :wink:
Mit Zurücklesen und ggf. erneut schreiben veranschlagen wir die 4-fache Zeit (Lesen müsste aber schneller gehen), wären wir bei 270km/h - sollte auch noch reichen!

Hast Du Dir auch schon Gedanken zu EMV und Wetter gemacht? (als kleiner Einwurf)

Ok, wie angehen?
State-Maschine:

  • alle x Millisekunden wird der Tacho aktualisiert
  • alle gefahrene Meter das EEprom
  • den Rest der Zeit wird einfach Nichts gemacht

Bei den Versuchen 'dahin' wird Dir wohl der eine oder andere EEprom 'partiell' versterben, die Abläufe müssen ja schon ausgiebig getestet werden.
Libs zu EEprom sind in der IDE per Klick einbindbar, dort sollten auch Beispiele enthalten sein.

Zur State-Maschine noch ein Link zu Combies State-Maschine-Sammelsorium

MfG

Guten Morgen,

danke für die Antwort. Für mein bescheidenes Wissen zu viel Information. :slight_smile:

Grundsätzlich will ich einen Magneten am Rad / Speiche befestigen, der Hall Sensor an der Gabel.

Ich fahre so selten mit dem Moped, dass ich mir vorstellen könnte in den kommenden Jahren auf meine 100km zu kommen. :slight_smile:

Bezüglich dem Wetter ist es so, dass ich im Regen das Moped gar nicht erst aus dem Schopf hole.

Die Kommentare sind aus den verschiedenen Codes die ich kopiert habe, einige sind von mir selbst. Alles chaotisch ich weiss.

Vll. wäre es sinnvoller von vorne zu beginnen um den Code im ganzen auch besser zu verstehen und das notwendige zu lernen. Ggf. kann mir hier geholfen werden.

Anfangen im Code würde ich jetzt grundsätzlich mit dem Aufruden der Bibliotheken die ich brauche.

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4 // not used / nicht genutzt bei diesem Display
Adafruit_SSD1306 display(OLED_RESET);

Wann lege ich meine Variablen fest? Kann ich das direkt im Anschluss auf die Bibliotheken machen?

float Radius = 0.285; // Radius des Rads in Meter
float Raddurchmesser = 0.57; // Raddurchmesser in Meter
float UmfangRad = 1.791; // Radumfang und Wegstrecke / Umdrehung
const float Pi = 3.14159265359; // Zahl Pi für die Formel zur Berechnun der Geschwindigkeit in km/h

Bekannte und notwendige Werte:

Der Radius bzw. das Maß von Drehachse zum Boden entspricht: 0,285 m
Raddruchmesser: 0,57 m
Umfang des Rads: 1.791 m (entspricht logischerweise auch der zurückgelegten Stecke bei einer Umdrehung)

Jetzt gibt es Void_Setup und Void_Loop, was genau kommt in den Setup? Die Pinbelegung des Hall-Sensors, Display, usw?

Bis hier hin erstmal, dann weiter.

Danke dir.

Grüße

Und nun habe ich den Text der immer unverändert bleibt, also sozusagen das Displaylayout in den Void_Setup geschrieben.

Aktuell sieht es so aus:

// Auswahl der benötigten Bibliotheken zum Betreiben des OLED Displays.

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4 // not used / nicht genutzt bei diesem Display
Adafruit_SSD1306 display(OLED_RESET);

// Definition von festen Werten in Variabeln.  

float Radius = 0.285; // Radius des Rads in Meter
float Raddurchmesser = 0.57; // Raddurchmesser in Meter
float UmfangRad = 1.791; // Radumfang und Wegstrecke/Umdrehung in Meter
const float Pi = 3.14159265359; // Zahl Pi für die Formel zur Berechnun der Geschwindigkeit in km/h


void setup()   {             
   
  // initialize with the I2C addr 0x3C / mit I2C-Adresse 0x3c initialisieren
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  
display.clearDisplay();
  display.setTextColor(WHITE); // Displayfarbe setzen "weiss"
  display.setTextSize(1); // Textgröße wählen
  display.setCursor(1,0); // Textposition (X-Wert, Y-Wert)
  display.println(" Derbi Antorcha 2019"); // Anzuzeigender Text

  display.setTextSize(2);
  display.setCursor(80,15);
  display.println("km/h"); // Textinformation km/h

  display.setTextSize(1);
  display.setCursor(60,56);
  display.println("km"); // Textinformation für gefahree km
  
  display.setCursor(80,56);
  display.println("T:    C"); // Textinformation für Temperatur-Anzeige
  
display.display();

}

void loop()   { 

}

JeBaFe:
Vll. wäre es sinnvoller von vorne zu beginnen um den Code im ganzen auch besser zu verstehen und das notwendige zu lernen. Ggf. kann mir hier geholfen werden.
[...]
Wann lege ich meine Variablen fest? Kann ich das direkt im Anschluss auf die Bibliotheken machen?

Das kommt ganz drauf an. Wenn du globale Variablen meinst, also Variablen auf die du von überall zugreifen kannst, dann ist es nur wichtig, dass sie eingeführt wurden, bevor du sie benutzt. Meistens erwartet man sie allerdings oben, unterhalb der includes, also ja.

Da deine Werte Konstanten sind, markiere sie mit dem Schlüsselwort 'const', z.B.:

const float Radius = 0.285; // Radius des Rads in Meter

JeBaFe:
Jetzt gibt es Void_Setup und Void_Loop, was genau kommt in den Setup? Die Pinbelegung des Hall-Sensors, Display, usw?

Beides sind Funktionen, void ist der Datentyp des Rückgabewertes (in diesem Fall wird nichts zurückgegeben). Setup wird einmal aufgerufen, nachdem der Arduino resettet wurde. Loop wird immer wieder aufgerufen.

Ins setup kommt daher Code, der nur einmal ausgeführt werden soll. Dazu gehören meistens Initialisierungsroutinen für externe Sensoren, Aktuatoren, interne Hardware (I/O-Pins), etc.

JeBaFe:
3. Arduino Nano / Atmega 328P

#include <Adafruit_SSD1306.h>

Die Bibliothek von Adafruit benötigt recht viel Speicher, den der Nano ja nur begrenzt hat. Eventuell lohnt sich ein Blick auf die Bibliothek von Oli Kraus. Da gibt es Fonts nur mit Zahlen und unterschiedliche Arten, den Hintergrund zu behandeln.

Hi

Die Werte, Die sich berechnen lassen, solltest Du auch berechnen.
Wenn Du jetzt für Radius und Durchmesser zwei unpassende Werte angibst, macht Das dem Sketch rein gar Nichts.

const float Pi = 3.14159265359; // Zahl Pi für die Formel zur Berechnun der Geschwindigkeit in km/h
const float inch2cm = 2.54;   //falls ein Nachbauer die Radgröße in Zoll angeben will
const float cm2inch = 1/inch2cm;  //oder den anderen Weg braucht - Konstanten 'fressen kein Brot'
const float Radius = 0.285; // Radius des Rads in Meter
const float Raddurchmesser = 2*Radius; // Raddurchmesser in Meter
const float UmfangRad = 2*Pi*Radius; // Radumfang und Wegstrecke / Umdrehung

Du solltest weiter den Standard-Ausdruck des Display mit einer Funktion ausgeben.
Das hat den Hintergrund, daß Du dann auch im laufendem Betrieb das Display 'Mal' regenerieren kannst.
Wenn das Display Müll versteht, zeigt Es auch Müll an - Das wird Dir - irgendwann - auch passieren!
Dann schadet Es nicht, wenn das Display alle paar Sekunden komplett neu aufgebaut wird - aber halt nicht bei JEDER Änderung, Die auf's Display geschrieben wird.

Packe Alles, was Du irgendwie aufteilen kannst, in einzelne Funktionen und rufe Diese in der korrekten Reihenfolge auf, daß Deine Ausgabe wieder passt.
Gib den Funktionen sprechende Namen, damit man beim Lesen des Sketch direkt 'sieht', was Da passiert.

MfG

Guten Abend,

also vielen Dank für das ganze Feedback und die Infos.

Ich habe mich bzgl. der Temperaturmessung für einen GY-BME280 entschieden, auch weil ich hier noch andere Werte ziehen kann. Ich brauche diese zwar nicht unbedint für die Fahrt mit dem Moped, aber es ist immer gut etwas zum erzählen zu haben. :slight_smile:

Ich habe nun den Code um die Einbeziehung der Bibliothek für den BMW-280 erweitert und das Display-Layout dahingehend erweitert, dass die Werte irgendwo angezeigt werden.

Ich vermute mal, dass es besser un freundlicher gecodet ist, wenn ich die Zeilen wie die folgende die aktuell im Void_Setup steht später in den Loop nehme und dort wo die Leerstellen sind eben die Variable "Temperatur" einfüge?

  display.setCursor(80,56);
  display.println("T:    C"); // Textinformation für Temperatur-Anzeige

Der gesamte Code ist aktuell wie folgt:

// Auswahl der benötigten Bibliotheken zum Betreiben des OLED Displays.

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#include "cactus_io_BME280_I2C.h"

#define OLED_RESET 4 // not used / nicht genutzt bei diesem Display
Adafruit_SSD1306 display(OLED_RESET);

// Definition von festen Werten in Variabeln. 


const float Pi = 3.14159265359; // Zahl Pi für die Formel zur Berechnun der Geschwindigkeit in km/h
const float inch2cm = 2.54;   //falls ein Nachbauer die Radgröße in Zoll angeben will
const float cm2inch = 1/inch2cm;  //oder den anderen Weg braucht - Konstanten 'fressen kein Brot'
const float Radius = 0.285; // Radius des Rads in Meter const float Raddurchmesser = 2*Radius; // Raddurchmesser in Meter const float UmfangRad = 2*Pi*Radius; // Radumfang und Wegstrecke / Umdrehung
    
const int hallpin = 4; // Anschluss Hallsensor an Digitalport 4 . 5V Versorgung!

int Temperatur; // Variable für Temperatur
int Drehzahl; // Variable für Drehzahl


void setup()   {             
   
  pinMode(4, INPUT);  // Hallsensor als INPUT Signal festlegen
    
  // initialize with the I2C addr 0x3C / mit I2C-Adresse 0x3c initialisieren
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
 
display.clearDisplay();
  display.setTextColor(WHITE); // Displayfarbe setzen "weiss"
  display.setTextSize(1); // Textgröße wählen
  display.setCursor(1,0); // Textposition (X-Wert, Y-Wert)
  display.println(" Derbi Antorcha 2019"); // Anzuzeigender Titel-Text

  display.setCursor(60,56);
  display.println("km"); // Textinformation für gefahrene km (Einheit)  
    
  display.setCursor(80,56);
  display.println("T:    C"); // Textinformation für Temperatur-Anzeige  
    
  display.setCursor(80,46);
  display.println("H:    %"); // Textinformation für Luftfeuchte-Anzeige
    
  display.setCursor(80,36);
  display.println("A:    m"); // Textinformation für Luftdruck-Anzeige
    
  display.setTextSize(2);
  display.setCursor(80,15);
  display.println("km/h"); // Textinformation km/h
 
display.display();

}

void loop()   {

}

Du solltest dir unbedingt den Tipp mit der Library von agmue zu Herzen nehmen.
Da kommst du mit deiner Programmierart nicht so schnell an die Grenzen.

Guten Abend,

die Library die Agmue vorschlägt kenne ich. Bei einem alten Projekt hat man den Unterschied beim verwendeten Speicher gesehen. Welten sind das...aber nichts desto trotz geht es mir vorranging um den Code weniger um die Anzeige, die natürlich auch passen muss ich mir aber eher sicher bin, dass ich dies später auch noch auf die U...Library umgeschrieben bekomme.

Ich habe mit die letzten Tage dann doch noch mal arg den Kopf zerbrochen, da ich nun nicht genau weiss wie ich die Rechnung auf dem Arduino für das herausfiltern der Drehzahl erhalte. Ich weiss wie die Formel theoretisch im Kopf sein sollte, kann diese aber nicht ins Arduino umsetzen. Da reicht mein Wissen einfach nicht ganz aus. Kennt ihr ein Beispiel, an dem ich mich gut orientieren kann, dass dann auch noch so kommentiert ist, dass ich den Code nachvollziehen kann?

Viele Grüße

Wenn Du die Formel im Kopf hast, dann schreibe sie doch einfach mal auf und dann hier ins Forum.

Gruß Tommy

Also folgendes im Code, übernommen aus dem "ur-Code" den ich hatte:

int getRPM()
{
  int count = 0;
  boolean countFlag = LOW;
  unsigned long currentTime = 0;
  unsigned long startTime = millis();
  while (currentTime <= sampleTime)
  {
    if (digitalRead(hallSensorPin) == HIGH)
    {
      countFlag = HIGH;
    }
    if (digitalRead(hallSensorPin) == LOW && countFlag == HIGH)
    {
      count++;
      countFlag=LOW;
    }
    currentTime = millis() - startTime;
  }
  int countRpm = int(60000/float(sampleTime))*count;
  return countRpm;
}

Der gesamte Code lautet nun wie folgt:

// Auswahl der benötigten Bibliotheken zum Betreiben des OLED Displays.

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#include "cactus_io_BME280_I2C.h"

#define OLED_RESET 4 // not used / nicht genutzt bei diesem Display
Adafruit_SSD1306 display(OLED_RESET);

// Definition von festen Werten in Variabeln. 


const float Pi = 3.14159265359; // Zahl Pi für die Formel zur Berechnun der Geschwindigkeit in km/h
const float inch2cm = 2.54;   //falls ein Nachbauer die Radgröße in Zoll angeben will
const float cm2inch = 1/inch2cm;  //oder den anderen Weg braucht - Konstanten 'fressen kein Brot'
const float Radius = 0.285; // Radius des Rads in Meter const float Raddurchmesser = 2*Radius; // Raddurchmesser in Meter const float UmfangRad = 2*Pi*Radius; // Radumfang und Wegstrecke / Umdrehung
    
const int hallSensorPin = 2; // Anschluss Hallsensor an Digitalport 4 . 5V Versorgung!
const unsigned long sampleTime = 1000;

int Temperatur; // Variable für Temperatur
int Drehzahl; // Variable für Drehzahl


void setup()   {             
//
//int rpm = getRPM;
  pinMode(2, INPUT);  // Hallsensor als INPUT Signal festlegen
  randomSeed(analogRead(0));
  
  // initialize with the I2C addr 0x3C / mit I2C-Adresse 0x3c initialisieren
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
 
display.clearDisplay();
  display.setTextColor(WHITE); // Displayfarbe setzen "weiss"
  display.setTextSize(1); // Textgröße wählen
  display.setCursor(1,0); // Textposition (X-Wert, Y-Wert)
  display.println(" Derbi Antorcha 2019"); // Anzuzeigender Titel-Text

  display.setCursor(60,56);
  display.println("km"); // Textinformation für gefahrene km (Einheit)  
    
  display.setCursor(80,56);
  display.println("T:    C"); // Textinformation für Temperatur-Anzeige  
    
  display.setCursor(80,46);
  display.println("H:    %"); // Textinformation für Luftfeuchte-Anzeige
    
  display.setCursor(80,36);
  display.println("A:    m"); // Textinformation für Luftdruck-Anzeige
    
  display.setTextSize(2);
  display.setCursor(80,15);
  display.println("km/h"); // Textinformation km/h
 
display.display();

}

void loop()   {

int rpm = getRPM();
//display.clearDisplay();
  display.setTextSize(4);
  display.setCursor(17,15);
    display.println(rpm);
  display.display();
  delay(1000);

}


int getRPM()
{
  int count = 0;
  boolean countFlag = LOW;
  unsigned long currentTime = 0;
  unsigned long startTime = millis();
  while (currentTime <= sampleTime)
  {
    if (digitalRead(hallSensorPin) == HIGH)
    {
      countFlag = HIGH;
    }
    if (digitalRead(hallSensorPin) == LOW && countFlag == HIGH)
    {
      count++;
      countFlag=LOW;
    }
    currentTime = millis() - startTime;
  }
  int countRpm = int(60000/float(sampleTime))*count;
  return countRpm;
}

Jetzt habe ich aber das Problem des "überschreibens" im Display...der löscht den Wert nicht auf dem Display ab, sondern schreibt sozusagen Wert über Wert. Was fehlt denn? Ein display.clearDisplay(); im Loop kann es ja nicht sein, dies würde mir ja das ganze Display Layput aus dem Setup löschen?

Du musst Deine Displayausgaben auf eine feste Länge formatieren, so dass immer alle Stellen neu geschrieben werden.

Gruß Tommy

Sorry, ich verstehe nicht was du meinst. Kannst du mir das bitte etwas erläutern?

Dein rpm kann je nachdem, wie schnell Du fährst einstellig (bis runter 0, wenn Du stehst), zweistellig, ? dreistellig werden.
Deine Ausgabe schreibt aber immer nur die Stellen, die dem Wert entsprechen.
Nehmen wir mal an, Der Wert kann 3-Stellig werden:

char buf[4]; // Stellenzahl+1;
sprintf(buf,"%3d",rpm); // 3 Stellen mit führenden Leerzeichen
display.print(buf);

Damit werden immer 3 Zeichen geschrieben. Bei Displays verwendet man eher Print, als println.

Gruß Tommy

Hi,

danke für die schnelle Antwort. Ich verstehe...woher kommst du an diese Befehle? Wo finde ich diese?
Grundsätzlich schreibt er es richtig, aber er löscht die Werte nicht wieder ab. Wenn ich jetzt beispielsweise die Drehzahl 180 angezeigt bekomme und dann aber beschleunige, dann schreibt er den neuen Wert über die angezeigten 180, so dass ich dann keinen Wert mehr ablesen kann weil sich die Werte an dieser Stelle überlagern. Ich müsste jetzt entweder das Display Layout das im Setup steht komplett in den Looü nehmen, oder einen Befehl haben, der mir partiel nur diesen Wert wieder ablöscht. Gibt es da was? Ich suche mir grad nen Wolf... :frowning:

Viele Grüße

Hi

Wenn nur die aktiven Punkte der Zeichen den Alt-Display-Inhalt 'übermalen', musst Du vorher den Alt-Wert in Hintergrundfarbe überschreiben.
Das kann allerdings zu einem Flackern führen, besonders, wenn der Wert sich gar nicht geändert hat.
Schöner wäre Es, wenn Du nur die Stellen in Hintergrundfarbe umfärbst, Die auch später Hintergrundfarbe sein sollen.

Bevor Du ausrechnest, welcher Pixel sich wie macht, wird's wohl einfacher sein, das invertierte Zeichen in Hintergrundfarbe auszugeben und das eigentliche Zeichen in Soll-Farbe.
Dazu würde ich mir die Library wohl anpassen - die Zeichen werden als Array vorhanden sein - Das liest die Methode zur Zeichenausgabe aus und 'setzt die benutzten Punkte' - die Unbenutzten lässt Es einfach unberührt - hier würde ich ansetzen.

Und: Natürlich musst Du, wenn vorher drei Ziffern ausgegeben wurden, jetzt aber nur noch Zwei, dafür sorgen, daß Das ebenfalls korrigiert wird - entweder mit einer festen Länge (halt ein Leerzeichen davor setzen), oder die letzte Stelle auslöschen.

MfG

PS: Du bindest von Adafruit eine Lib ein - Die ist allerdings sehr umfangreich - aber genau darin sind die 'Befehle' (in einer Lib heißen die Dinger Methoden, im Sketch wären Es Funktionen) drin enthalten.

JeBaFe:
Hi,

danke für die schnelle Antwort. Ich verstehe...woher kommst du an diese Befehle? Wo finde ich diese?
Grundsätzlich schreibt er es richtig, aber er löscht die Werte nicht wieder ab. Wenn ich jetzt beispielsweise die Drehzahl 180 angezeigt bekomme und dann aber beschleunige, dann schreibt er den neuen Wert über die angezeigten 180, so dass ich dann keinen Wert mehr ablesen kann weil sich die Werte an dieser Stelle überlagern. Ich müsste jetzt entweder das Display Layout das im Setup steht komplett in den Looü nehmen, oder einen Befehl haben, der mir partiel nur diesen Wert wieder ablöscht. Gibt es da was? Ich suche mir grad nen Wolf... :frowning:

Viele Grüße

Das sind Grundlagen, die man einfach lernen muss. Da gibt es genug C/C++ Tutorials und auch dicke Bücher.

Ich hatte nicht geschnallt, dass Du ein Grafikdisplay benutzt. Da musst Du Dir den alten buf-Wert merken (z.B. buf global machen) und den in der Hintergrundfarbe ausgeben (das löscht) und danach den neuen Wert ermitteln und schreiben.

Gruß Tommy

buf global?

Es tut mir echt leid wenn ich hier 1000 Fragen stellen muss, aber ich bin absolut unerfahren. Grundsätzlich will ich es aber schon lernen und verstehen, merke aber dass da ganz schön viel Hintergrundwissen fehlt. :frowning:

Wie muss der Code an der Stelle lauten um den Wert abzulöschen? Wenn ich das vorgekaut bekomme, kann ich mich an dem Rest weiter versuchen (umrechnen in KM/H, Temperaut, usw.) und ich wäre euch 1000 fach dankbar .

Grüßle

Du stellst oben, außerhalb von und vor setup und loop eine Deklaration:

char buf[4] = ""; // 3 Stellen + 1 fürs 0-Byte
...
// im Loop
// Textfarbe auf Hintergrundfarbe setzen musst Du in Deiner lib schauen
display.print(buf);
display.show();
// Textfarbe auf Vordergrundfarbe setzen musst Du in Deiner lib schauen
sprintf(buf,"%3d",rpm); // 3 Stellen mit führenden Leerzeichen
display.print(buf);
display.show();

Die Farbsetzung musst Du selbst klären.

Gruß Tommy