forum logo image
caferacer-forum.de - Das Forum für Petrolheads, Garagenschrauber, Ölfinger, Frickelracer und Alteisentreiber

Elektronik Bastelei mit Arduino (Selbstbau Tacho, DZM etc)

Technische Fragen und Antworten, Tipps und Tricks für Profis und Bastler
Benutzeravatar
ed881
Beiträge: 265
Registriert: 19. Jul 2016
Motorrad:: Honda CX500
Yamaha XT 350, Bj. 1987
Wohnort: Ludwigsau

Re: Elektronik Bastelei mit Arduino (Selbstbau Tacho, DZM etc)

Beitrag von ed881 »

SebastianM hat geschrieben: 14. Aug 2018 In der draw() Funktion werden die Display Inhalte generiert.

Mfg
Mich interessiert wie du die alten Werte im Display überschreibst. Schreibst du den alten Wert vorher nochmal in der Hintergrundfarbe über? Oder wie hast du das gelöst?

SebastianM
Beiträge: 1287
Registriert: 2. Sep 2015
Motorrad:: ..
Wohnort: Vaterstetten

Re: Elektronik Bastelei mit Arduino (Selbstbau Tacho, DZM etc)

Beitrag von SebastianM »

Darum kümmert sich die u8g2 lib.
In loop() rufe ich nur .clearbuffer / draw() /.sendbuffer auf.


Mfg Basti

Benutzeravatar
NyFAZ
Beiträge: 288
Registriert: 2. Nov 2016
Motorrad::  
BMW R80
KTM LC400 Mil
Wohnort: Braunschweig

Re: Elektronik Bastelei mit Arduino (Selbstbau Tacho, DZM etc)

Beitrag von NyFAZ »

https://github.com/olikraus/u8g2/wiki/u8g2reference für die Interessierten.

LG Roland

SebastianM
Beiträge: 1287
Registriert: 2. Sep 2015
Motorrad:: ..
Wohnort: Vaterstetten

Re: Elektronik Bastelei mit Arduino (Selbstbau Tacho, DZM etc)

Beitrag von SebastianM »

So... kleines Update:
Letzte Woche kamen die kleineren RTC-Module (kosten sage und schreibe 1,09€ :shock: ), und glücklicherweise ist die Pinbelegung bei den RTCs identisch zum Display. Somit konnte ich die beiden Teile einfach zusammenstecken und verlöten. Hoffentlich kommt bald mein Beetle mit Atmega32u4, dann kann ich die finale Hardware fertig stellen.
Es zeichnet sich aber jetzt schon ab, dass alles in die Gabelbrücke passen wird (auch wenn ich Ecken beim Display abzwicken musste).

mfg
Basti
IMG_20180819_230217.jpg
IMG_20180819_230245.jpg
IMG_20180819_230521.jpg
Du musst registriert und eingeloggt sein, um die Dateianhänge dieses Beitrags sehen zu können.

multimomba
Beiträge: 1
Registriert: 28. Aug 2018
Motorrad:: Kawasaki ER 6F 2012

Re: Elektronik Bastelei mit Arduino (Selbstbau Tacho, DZM etc)

Beitrag von multimomba »

Hallo und guten Tag!
Ich bin neu hier und habe mich primär auf Grund dieses Themas hier angemeldet.
Und hoffe, dass ich von euch etwas Hilfe bekomme.

Vorweg:
Ihr leistet hier grandiose Arbeit und zum Teil bin ich dadurch angefixt worden, mir auch ein kleines Tacho selber zu bauen.
Nun. Was mich leider enttäuscht hat ist, dass es leider keine Funktionen gibt, die man wieder verwenden könnte.
z.B. eine Funktion, die die Impulszahl pro Sekunde zurück gibt
eine andere, die aus der Impulszahl die Radumdrehung pro Sekunde ermittelt
eine neue, die aus der Radumdrehung pro Sekunde dann km/h die Stunde macht.

Leider bin ich aktuell auch noch nicht so weit, denn ich habe das größte Problem damit, den Code auch nur irgendwie logisch in meinen Kopf zu sortieren, daher schreibe ich erstmal in Pseudocode und hoffe, dass ihr mir auf die Sprünge helfen könnt
(Ich habe zwar schon ein wenig KOT geschrieben, aber leider ist er nicht über den Status von Müll gekommen)

Code: Alles auswählen

Ich habe es wie folgt versucht, angemessen die Geschwindigkeit zu ermittel:
$Var RadumfanginMM
$Var ImpulseProRadumdrehung

$Do zähle Impulse innerhalb einer Sekunde -> Schreibe in $Var ImpulseSekundeSumme

$Do Errechne die Radumdrehung-in-der-Sekunde aus: ImpulseSekundeSumme : (geteilt durch)  ImpulseProRadumdrehung
$Do Berechne die Gefahrenen-Meter-in-der-Sekunde aus: Radumdrehung-in-der-Sekunde * (multipliziert) RadumfanginMM
$Do Berechne die Gefahrenen-KMH aus: $Do Berechne die Gefahrenen-Meter-in-der-Sekunde * 3,6
Eigentlich dürfte das so passen, aber ich vermute, dass ich wohl in der technischen Umsetzung ein BUG habe.
Da ich aktuell kein Signalgeber habe - sondern das mit zwei offenen Kabelenden versucht habe zu simulieren, stellte ich schnell fest, dass da was nicht passt.
Es wurden Mitunter mehrere Impulse in der Sekunde gezählt, obwohl ich versucht habe nur EINEN zu machen. (So zwischen 3 - 18 Impulse)
Daher stelle ich hier erstmal mein Code rein, der aber definitiv noch von mir zu überarbeiten ist.
Bsp. passen aktuell einfach nicht mal mehr die Beschreibungen.
....

Code: Alles auswählen

int int_fkt_geschwindigkeit(int int_RadUmfang_in_mm, int int_Impulse_pro_Umdrehung, int int_ReadPin, bool int_debug_function){
  /* diese Funktion soll über eine vorgegebene Anzahl an 
  Impulsen und den Radumfang die Geschwindigkeit als Wert in eine paar GLOBALE Variablen schreiben/ übergeben
  und ein TRUE bei Bewegung oder ein FALSE bei Stillstand zurückgeben
  - int_Rumf = der Radumfang wird übegeben in mm
  - int_Impulse_pro_Umdrehung = Impulse pro Umdrehungen des Rades int
  - Int_ReadPin = der GPIO-Pin
  ---------------------------------------------------------------------------
  Folgende globale Variablen werden benötigt:
  int int_GlobVar_Geschwindigkeit_in_KMH = 0; // Übergabewert aus der Funktion bool_fkt_geschwindigkeit
  int int_GlobVar_Geschwindigkeit_in_MPH = 0; // Übergabewert aus der Funktion bool_fkt_geschwindigkeit
  int int_GlobVar_Geschwindigkeit_M-S = 0;    // Meter in einer Sekunde Übergabewert aus der Funktion bool_fkt_geschwindigkeit
  int int_GlobVar_Radumdrehung_pro_Sek = 0;   // Übergabewert aus der Funktion bool_fkt_geschwindigkeit
  */

  // Ermittelung für Debug möglicherweise für Serial-Out
  if (int_debug_function) {
    int int_RadUmdrehung_fuer_ein_km = 1000000 / int_RadUmfang_in_mm;
    int int_Impulse_fuer_ein_km = int_RadUmdrehung_fuer_ein_km * int_Impulse_pro_Umdrehung;
    Serial.print("Es werden x Umdrehungen fuer 1km gebraucht ");
    Serial.println(int_RadUmdrehung_fuer_ein_km);
    Serial.print("Es werden y Impulse fuer 1km gebraucht ");
    Serial.println(int_Impulse_fuer_ein_km);
    Serial.print("Aktuelle Impulse pro Radumdrehung: ");
    Serial.println(int_Impulse_pro_Umdrehung);
  }

  // Setze benötigte Variablen zur Berechnung und Ermittlung
  unsigned long UnLon_RadUmdrehung_in_der_Sekunde = 0;
  unsigned long UnLon_Meter_in_der_Sekunde_zurueckgelegt = 0;
  unsigned long UnLon_KiloMeter_TRIP_zurueckgelegt = 0;
  unsigned long UnLon_Impulse_TRIP_zurueckgelegt = 0;
  
  //ab jetzt werden die Impulse in einer Sekunde gezählt
  unsigned long int_Anzahl_der_Impulse_zaehlen = 0;
  unsigned long UnLon_aktuelle_Laufzeit = (millis());
  [color=#FF0000]do{
    if (pulseIn(int_ReadPin, HIGH)>0) int_Anzahl_der_Impulse_zaehlen++;
  }
  while (millis() -  UnLon_aktuelle_Laufzeit < 1000);
[/color]
  // aktuelle Pulsanzahl steht nun in "int_Anzahl_der_Impulse_zaehlen"
  // Berechne nun die Werte zur Ermittlung der Geschwindigkeit.
  [color=#FF0000]UnLon_RadUmdrehung_in_der_Sekunde = int_Anzahl_der_Impulse_zaehlen / int_Impulse_pro_Umdrehung;
  UnLon_Meter_in_der_Sekunde_zurueckgelegt = (UnLon_RadUmdrehung_in_der_Sekunde * int_RadUmfang_in_mm / 1000);[/color]

  // Hier soll der TRIP-COUNTER implementiert werden, da habe ich aber aktuell noch keine Idee zu!
  // TRIP-COUNTER

  UnLon_Impulse_TRIP_zurueckgelegt = UnLon_Impulse_TRIP_zurueckgelegt + int_Anzahl_der_Impulse_zaehlen; 
  
  if (int_debug_function) {
    Serial.print("Impulse: ");
    Serial.print(int_Anzahl_der_Impulse_zaehlen);
    Serial.print(" | Rad Umdrehung/s: ");
    Serial.println(UnLon_RadUmdrehung_in_der_Sekunde);
    Serial.print(UnLon_Meter_in_der_Sekunde_zurueckgelegt);
    Serial.print(" m/s |b ");
    Serial.print(UnLon_Meter_in_der_Sekunde_zurueckgelegt*3.6);
    Serial.print(" km/h | ");
    Serial.print(UnLon_Meter_in_der_Sekunde_zurueckgelegt*2.23);
    Serial.println(" mp/h ");
  }

  return UnLon_Meter_in_der_Sekunde_zurueckgelegt*3.6;
  /*if (UnLon_Meter_in_der_Sekunde_zurueckgelegt > 0) {
    return true; // Signalisiert, dass eine Bewegung ermittelt wurde
  }else {
    return false; // Signalisiert, dass KEINE Bewegung ermittelt wurde
  }*/
}

=> Achso, meine Intention ist es, Funktionen zu bauen, die ein Jeder via Copy and Paste nutzen kann und die immer nur ein Wert zurück geben. Ich bin rein auf Communtiyentwicklung und Handhabung bei meinen Scripten aus, so habe ich Privat auf Basis von einem ESP8266 auch ein Smarthome-Sensor gebaut, der Temp, Luftfeuchte, Luftdruck, Helligkeit ausließt und bei Bedarf auch Bewegung erkennt.
Nähere Infos gebe ich gerne raus, bei Interesse.

Ich hoffe, ich falle jetzt nicht mit der Tür ins Haus:


Gruß
Christian

Edit:
Ich habe jetzt ganz vergessen zu erklären, was mich zu diesem Projekt bewegt: Ganz einfach, die Mechanik vom Bulli-Tacho hat leider nun den Geist aufgegeben und auf Grund des Sportlenkrades sehe ich quasi den Bereich zwischen 40 und 140 auf dem Tacho nicht - daher wollte ich auf Digital umbauen und die hässlichen Zusatzinstrumente wie Drehzahlmesser, Öldruck- und Öltemperaturanzeiger gleich mit 'Entsorgen'. Um H-Gutachten mache ich mir aktuell keine Sorgen, da zu einem Transporter umgebauter Camper mit Fremdmotor....
Edit2: Möglicherweise werde ich sonst statt des Arduino Micros auf ein ESP32 setzen - weil der wesentlich mehr Speicherplatz hat. Aber ich bin mir noch eben nicht sicher...

Benutzeravatar
NyFAZ
Beiträge: 288
Registriert: 2. Nov 2016
Motorrad::  
BMW R80
KTM LC400 Mil
Wohnort: Braunschweig

Re: Elektronik Bastelei mit Arduino (Selbstbau Tacho, DZM etc)

Beitrag von NyFAZ »

NyFAZ hat geschrieben: 22. Jul 2018 Mahlzeit,

Readmillis macht alles was Du benötigst. Grundlagen darfst Du dir selber beibringen. K-Wert beschreibt die Anzahl der Impulse pro festgelegte Strecke. Wikipedia hilft hierbei.
Für deine unerwünschte Anzahl an Zählern hilft dir das Stichwort debounce oder kontaktprellen.

Hier noch der Code, den ich gerade benutze, aber noch nicht fertig ist. Es fehlen noch die Temperaturwerte.
Ich bin kein Programmierer, wenn jemand Verbesserungspotential findet, dann bitte :).

Code: Alles auswählen

#include <Arduino.h>
#include <U8g2lib.h>
#include <Wire.h>
#include <RunningAverage.h>
#include "Adafruit_FRAM_I2C.h"

#include <Bounce2.h>
#define pinTacho 3
uint32_t aktMillis, altMillis, drueckMillis = 3000;
bool status;
Bounce debouncer = Bounce();

/* Connect SCL    to analog 5
   Connect SDA    to analog 4
   Connect VDD    to 5.0V DC
   Connect GROUND to common ground */

U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ SCL, /* data=*/ SDA);  //Mein Display (OLED 182x32)
Adafruit_FRAM_I2C fram = Adafruit_FRAM_I2C();

RunningAverage myRA(5);
volatile unsigned long dauer = 0;             // microsekunden seit dem letzten Interrupt
volatile unsigned long last = 0;              // Zählerwert beim letzten Interrup
volatile short geschwindigkeit;               // selbstredend
volatile int counter = 0;
int aktuell = 0;
int VAnzeige;
unsigned long Gesamtmeter;
unsigned long Tagesmillimeter;

int Gesamtmeter_ADDR = 0;
int Tagesmillimeter_ADDR = 4;
int Tageshunderter = 0;
int Tripkilometer = 0;
char Trip[10];
char Speed[10];
char Gesamtkilometer[10];

void setup(void) {
  Serial.begin(9600);
  pinMode(2, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(2), readmillis, RISING);
  myRA.clear();
  u8g2.begin();
  fram.begin();
  pinMode(pinTacho, INPUT_PULLUP);
  debouncer.attach(pinTacho);
  debouncer.interval(30);
  Gesamtmeter = eepromReadLong(Gesamtmeter_ADDR);
  Tagesmillimeter = eepromReadLong(Tagesmillimeter_ADDR);
  Tripkilometer = (Tagesmillimeter / 1000000);
  Tageshunderter = (Tagesmillimeter / 100000) % 10;

  u8g2.setFont(u8g2_font_profont22_tr);
  u8g2.drawStr(20, 20 , "READY :)");
  u8g2.sendBuffer();
  delay(2000);
  u8g2.clearDisplay();
}

void loop(void) {
  debouncer.update();
  aktMillis = millis();
  if (last > 0) {
    if (millis() - last > 4000) {                         // Nach 4 Sekunden stillstand Display löschen
      u8g2.clearDisplay();
      myRA.clear();
      if ( debouncer.fell()  ) {    // Taste gedrückt
        altMillis = aktMillis;
        status = true;
      }
      if ( debouncer.rose()  ) {    // Taste losgelassen
        status = false;
        if (aktMillis - altMillis < drueckMillis) {
          Serial.println("Kurz");
          Gesamtmeter = eepromReadLong(Gesamtmeter_ADDR);
          Serial.print("Gesamtkilometer:");
          Serial.println(Gesamtkilometer);
          sprintf(Gesamtkilometer, "%6d" , Gesamtmeter / 1000);
          status = false;
          u8g2.setFont(u8g2_font_t0_13b_tf);
          u8g2.drawStr(10, 14, "Gesamtkilometer:");
          u8g2.setFont(u8g2_font_profont22_tr);
          u8g2.drawStr(0, 32, Gesamtkilometer);
          u8g2.sendBuffer();
          delay(2000);
          u8g2.clearDisplay();
        }
      }
      if (status && (aktMillis - altMillis >= drueckMillis)) {
        status = false;
        Serial.println("Lang");
        eepromWriteLong(0, Tagesmillimeter_ADDR);
        Tagesmillimeter = eepromReadLong(Tagesmillimeter_ADDR);
        Tripkilometer = (Tagesmillimeter / 1000000);
        Tageshunderter = (Tagesmillimeter / 100000) % 10;
        u8g2.setFont(u8g2_font_profont22_tr);
        u8g2.drawStr(0, 23, "Trip reset");
        u8g2.sendBuffer();
        delay(2000);
        u8g2.clearDisplay();
      }
    }
    else {
      VAnzeige = myRA.getAverage();
      if (aktuell < counter) {       // eine Umdrehung -> Interrupt durchlaufen
        aktuell = counter;
        Serial.print("Counter:");
        Serial.println(counter);
        Tagesmillimeter += 714;
        Serial.print("Tagesmillimeter:");
        Serial.println(Tagesmillimeter);
        Tripkilometer = (Tagesmillimeter / 1000000);
        if (Tripkilometer > 999) {
          Tripkilometer = 0;
        }
        Tageshunderter = (Tagesmillimeter / 100000) % 10;
        Serial.print("Tageshunderter:");
        Serial.println(Tageshunderter);
        if (counter % 100 == 0) {
          eepromWriteLong(Tagesmillimeter, Tagesmillimeter_ADDR);
        }
        if (counter >= 500) {
          counter = 0;
          aktuell = 0;
          Gesamtmeter += 357;
          eepromWriteLong(Gesamtmeter, Gesamtmeter_ADDR);
          Serial.print("Gesamtmeter in Speicher:");
          Serial.println(Gesamtmeter);
        }
      }
      sprintf(Trip, "%5d.%d" , Tripkilometer, Tageshunderter);
      sprintf(Speed, "%3u", VAnzeige);
      u8g2.clearBuffer();
      u8g2.setFont(u8g2_font_logisoso32_tn);
      u8g2.drawStr(0, 32, Speed);
      u8g2.setFont(u8g2_font_logisoso16_tf);
      u8g2.drawStr(70, 32, "km/h");
      u8g2.setFont(u8g2_font_synchronizer_nbp_tf);
      u8g2.drawStr(70, 10, "T:");
      u8g2.drawStr(70, 10, Trip);
      u8g2.sendBuffer();
    }
  }
}

void readmillis() {                           // Interrupt-Routine
  detachInterrupt(2);                         // Interrupt ausschalten damit er uns nicht beißt
  volatile unsigned long m = millis();          // Microsekundenzähler auslesen
  volatile unsigned long v = m - last;          // Differenz zum letzten Durchlauf berechnen
  if (v > 10) {                               // ignorieren wenn <= 10ms (Kontaktpreller)
    dauer = v;                                // Wert in dauer übernehmen
    last = m;                                 // und wieder den letzten Wert merken
    geschwindigkeit = 2572 / dauer;           // Geschwindigkeit ausrechnen mit k-Wert 1,4 (1 Umdrehung/s = 0,714m/s = 2,570km/h)
    myRA.addValue(geschwindigkeit);           // Wert zur Mittelwerberechnung hinzufügen
    counter += 1;
  }
  attachInterrupt(digitalPinToInterrupt(2), readmillis, RISING);    // Interrupt wieder einschalten.
}

void eepromWriteLong(unsigned long lo, int adr) {
  // long Wert in das EEPROM schreiben
  // Eingabe : adr Speicherplatz
  // Eingabe : lo Zahl, Wertebereich -2.147.483.648 bis 2.147.483.647
  //
  // Matthias Busse 23.5.2014 Version 1.0 -> RS Geändert von EEprom auf Fram und ULong

  byte by;

  for (int i = 0; i < 4; i++) {
    by = (lo >> ((3 - i) * 8)) & 0x000000ff;
    fram.write8(adr + i, by);
  }
} // eepromWriteLong

long eepromReadLong(int adr) {
  // long int Wert aus 4 Byte EEPROM lesen
  // Eingabe : adr bis adr+3
  // Ausgabe : long Wert
  //
  // Matthias Busse 23.5.2014 Version 1.0 -> RS Geändert von EEprom auf Fram und ULong

  unsigned long lo = 0;

  for (int i = 0; i < 3; i++) {
    lo += fram.read8(adr + i);
    lo = lo << 8;
  }
  lo += fram.read8(adr + 3);
  return lo;
} // eepromReadLong
LG Roland

Benutzeravatar
NyFAZ
Beiträge: 288
Registriert: 2. Nov 2016
Motorrad::  
BMW R80
KTM LC400 Mil
Wohnort: Braunschweig

Re: Elektronik Bastelei mit Arduino (Selbstbau Tacho, DZM etc)

Beitrag von NyFAZ »

Ach Basti,

hat das RTC-Modul nicht auch beschreibbaren Speicher? Könntest Dir ggf. das Reservieren auf dem Atmel sparen, wenn Platz knapp. Nur so eine Idee...

LG Roland

Aceli
Beiträge: 168
Registriert: 2. Jul 2013
Motorrad:: Ducati Monster 620
Ducati ST2

Re: Elektronik Bastelei mit Arduino (Selbstbau Tacho, DZM etc)

Beitrag von Aceli »

bin mit meinem Projekt / Display anzeige auch schon ein gutes Stück weiter....

überlege die ganze Zeit wie man eine Ganganzeige hinbekommt....
benötigt wird ja Geschwindigkeit, Drehzahl und Neutral um den jeweiligen Gang zu ermitteln oder?

zerbreche mir momentan das kleine hirn :/
Projekt : Ducati ST 2

Fußhupe
Beiträge: 706
Registriert: 22. Sep 2013
Motorrad:: Kawasaki Gpz900R, Bj85
Ducati 900SS, Bj 92
Honda CX500, Bj 82
Honda CBX750, Bj 86

Re: Elektronik Bastelei mit Arduino (Selbstbau Tacho, DZM etc)

Beitrag von Fußhupe »

Wenn Du Geschwindigkeit und Drehzahl hast (Neutral brauchst Du nicht unbedingt), bilde einen Quotienten und Du hast eine Konstante, die dann dem Gang zugeordnet werden kann. Geschwindigkeit und Drehzahl sind in einem Gang ja proportional.
Wenn der Quotient dann 0 ist oder sehr groß wird (je nach Rechnung), dann ist der Leerlauf drin.
So eine Rechnung geht natürlich in die Hose, wenn die Kupplung betätigt wird oder rutscht, wäre mir persönlich aber egal. Dann stimmt die Ganganzeige an der Ampel halt nicht :dontknow:

Gruß
Jürgen

Aceli
Beiträge: 168
Registriert: 2. Jul 2013
Motorrad:: Ducati Monster 620
Ducati ST2

Re: Elektronik Bastelei mit Arduino (Selbstbau Tacho, DZM etc)

Beitrag von Aceli »

genau da liegt noch der Hund begraben..... wie bekomme ich die passenden Werte in den Arduino.
Werde mir nochmal alles durchlesen wie Sebastian und NyFaz das gelöst haben und vielleicht kann ich was abgreifen....
Projekt : Ducati ST 2

Antworten

Zurück zu „Elektrik/Beleuchtung“

Axel Joost Elektronik