Hallo Besucher, der Thread wurde 2,2k mal aufgerufen und enthält 12 Antworten

letzter Beitrag von Cihan am

Kann mir jemand mit dem Arduinocode helfen?

  • Ich bin mir gerade ein Kombiinstrument für Dirt 2 am basteln.


    Benutzt werden ein Arduino Uno, Dot Matrix LED MAX7219 und ein 7 Segment Display auch mit MAX7219.


    Bis auf das 7 Segment funktioniert es auch wie es soll. Nur kriege ich keine Daten auf das 7 Segment. Einzelne Werte kann ich anzeigen lassen, nur als String nicht.


    Hier der der Code:


    //Read all values
    gear = GetOBD2GearValue(); //Notice: offset +1 because of reverse gear
    speed= GetOBD2SpeedValue();
    rpm = GetOBD2RpmValue();
    rpm=rpm/4;
    if(gear!=-1 && speed!=-1 && rpm!=-1)
    {
    digitalWrite(13, LOW); //We have connection and all values are ok, turn on the LED
    //Do here your LCD or display stuff
    char* neutral = "n"; // sets the character for neutral
    char* reverse = "r"; // sets the character for reverse
    //
    if (gear==0){
    sprintf(message,"%s:%s %s:%5d",rapport, reverse , trmin, rpm);
    sprintf(message1,"%s:%3d %s",speed1, speed , speedunit);
    lcd.setCursor(0,0);
    lcd.write(message); //envoi le message sur l'écran 1 ere ligne
    lcd.setCursor(0,1);
    lcd.write(message1); //envoi le message sur l'écran 2 eme ligne
    mydisplay.setRow(0,0,B11111111);
    mydisplay.setRow(0,1,B11111111);
    mydisplay.setRow(0,2,B11111111);
    mydisplay.setRow(0,3,B00011011);
    mydisplay.setRow(0,4,B00011011);
    mydisplay.setRow(0,5,B11111111);
    mydisplay.setRow(0,6,B11111111);
    mydisplay.setRow(0,7,B11101110);
    mydisplay.setDigit(1, 7, rpm, false);
    mydisplay.setDigit(1, 2, speed, false);
    }



    Ich will das RPM und speed auf dem 7 Segment angezeigt werden sollen. Ich dachte so klappt es. mydisplay.setDigit(1, 7, rpm, false);
    Aber leider geht das nicht.


    http://www.x-sim.de/forum/viewtopic.php?t=155


    Hier benutzt jemand ein TM1638

  • Das geht so nicht.
    Der boolean, welchen c64 junior meint, schaltet nur den Dezimalpunkt ein und aus.


    Die LedControl-Bibliothek hat keine Methode, um ganze Zahlen auf dem Display auszugeben, die müsstest du selbst schreiben.
    Siehe: https://github.com/wayoda/LedC…ter/src/LedControl.h#L170


    Ich würde immer wieder modulo 10 rechnen, und die einzelnen Ziffern der Zahl aufs Display schreiben.

  • Gibt es denn eine fertige Library?


    Mein Gedankengang war ja folgender. Wenn es auf dem LCD richtig erscheint, dann ist der Wert schon richtig formatiert.


    Jungs um ehrlich zu sein werde ich von jeder Seite dumm angemacht. Von wegen so geht das doch nicht. Lerne die Grundlagen...
    Ich wollte keine Grundlagenforschung betreiben. Dafür habe ich sowas selten vor.


    Aber ich frage nochmal im X Sim Forum nach. Daher habe ich auch den Sketch.

  • Gibt es denn eine fertige Library?

    Die setzt du schon ein :-)
    Für die Ansteuerung des Displays benutzt du gerade eine Lib namens "LedControl".


    Eine Funktion zu schreiben, welche alle Ziffern einer Zahl an das LED-Display schickt, ist ja nun wirklich kein Hexenwerk.


    Schau z.B. mal hier in der Doku:
    http://playground.arduino.cc/M…Control#NumberSeg7Control


    Da haben die Entwickler genau so eine Funktion schon fertig geschrieben.

  • Ich schreibe das jetzt mal so auf, wie ich verstehe wie es funktioniert.


    Ich hole mir mit einer Funktion die Drehzahl über die Serielle Schnittstelle ab.


    //010c Request RPM, remember: OBD2 RPM is ((A*256)+B)/4int GetOBD2RpmValue(){ //010c Serial.write('0'); Serial.write('1'); Serial.write('0'); Serial.write('c'); Serial.write('\r'); return ReceiveValueWithTimeout('4','0','C',10);}Das wird dann ständig im Loop ausgeführt, weil:int rpm=0;rpm = GetOBD2RpmValue(); rpm=rpm/4;Das erste startet dann die Funktion und ich habe dann den Wert. Dieser wird dann nochmal durch 4 geteilt und als rpm neu deklariert. Dies geht, weil es wie eine Ablaufsteuerung ist.Erst den Wert abfragen und dann formatieren. Danach kann ich das LCD beschreiben. sprintf(message,"%s:%s %s:%5d",rapport, reverse , trmin, rpm);lcd.setCursor(0,0);lcd.write(message);So habe ich die Drehzahl in Vierstellig. Klappt ja auch mit dem LCD. So jetzt will ich dies aber auf dem 7 Segment haben.Im Loop benutze ich folgenden Code, um beim starten die 7 Seg alle auf ß zu stellen. mydisplay.setDigit(1, 0, 0, false); mydisplay.setDigit(1, 1, 0, false); mydisplay.setDigit(1, 2, 0, false); mydisplay.setDigit(1, 3, 0, false); mydisplay.setDigit(1, 4, 0, true); mydisplay.setDigit(1, 5, 0, false); mydisplay.setDigit(1, 6, 0, false); mydisplay.setDigit(1, 7, 0, false);Jetzt fängt es schon damit an, das eins auf true steht und ich nicht weiß warum. Funktionieren tut es wie es soll. Doch die eigentliche Frage ist, ich kann ja mit segDigit eine Zahl darstellen. Wie in meinem Fall 0.Warum geht das mit der Drehzahl nicht? Warum muss ich dort alle bits einzeln setzen?Ich verstehe ja das ich einen nackten Wert in für mich brauchbares Format umwandeln muss. Aber das geschieht ja anscheinend, da ja auf dem LCD der Wert korrekt angezeigt wird.Und wie kann ich den Wert in einzelne Ziffern umwandeln?

  • Laut Doku bestimmt das vierte Argument den Dezimalpunkt der 7-Segment-Anzeige - Du müsstest also sehen können, dass der Punkt bei Stelle 4 anders ist als bei den anderen.

    Doch die eigentliche Frage ist, ich kann ja mit segDigit eine Zahl darstellen. Wie in meinem Fall 0.Warum geht das mit der Drehzahl nicht? Warum muss ich dort alle bits einzeln setzen?

    Die Funktion beeinflusst eine 7-Segment-Anzeige. Wie sollte man darauf eine mehrstellige Zahl anzeigen? Also musst Du Deinen Wert rpm wiederholt durch Zehn teilen und jedes Mal den Rest (also eine Dezimalziffer) in eine 7-Segment-Anzeige schreiben.

    Ich verstehe ja das ich einen nackten Wert in für mich brauchbares Format umwandeln muss. Aber das geschieht ja anscheinend, da ja auf dem LCD der Wert korrekt angezeigt wird.

    Die Funktionen für das LCD sind dafür gemacht, Strings anzuzeigen. Die Funktionen für 7-Segment-Anzeigen nicht, da dort immer nur eine Anzeige beeinflusst wird.

  • Habe mal bisschen gegoogelt und folgend gelöst.


    int speed=0;
    int rpm=0;
    int gear=GetOBD2GearValue();
    int speed1=0;
    int speed2=0;
    int speed3=0;
    int rpm1=0;
    int rpm2=0;
    int rpm3=0;
    int rpm4=0;


    gear = GetOBD2GearValue(); //Notice: offset +1 because of reverse gear
    speed= GetOBD2SpeedValue();
    rpm = GetOBD2RpmValue();
    rpm=rpm/4;
    speed1 = speed/100;
    speed2 = (speed-speed3)/10;
    speed3 = speed%10;
    rpm1 = rpm/1000;
    rpm2 = (rpm-(rpm3*10+rpm4))/100;
    rpm3 = (rpm-rpm4)/10;
    rpm4 = rpm%10;


    mydisplay.setDigit(1, 3, rpm1, false);
    mydisplay.setDigit(1, 2, rpm2, false);
    mydisplay.setDigit(1, 1, rpm3, false);
    mydisplay.setDigit(1, 0, rpm4, false);
    mydisplay.setDigit(1, 7, speed1, false);
    mydisplay.setDigit(1, 6, speed2, false);
    mydisplay.setDigit(1, 5, speed3, false);



    Mein Problem ist das zwischendrin auch Buchstaben auftauchen. Was könnte das sein?

  • Der Code fragt die Inhalte einiger Variablen an, bevor er sie überhaupt setzt (speed3, rpm3, rpm4). Wenn das ganze in einer Endlosschleife läuft, werden also die aktuellen Werte mit den vorigen verrechnet, und wenn dabei dann Differenzen von 10 bis 15 entstehen, siehst Du Hexziffern.


    Ein ordentlicher Compiler sollte hier allerdings Warnungen werfen ("warning: ‘speed3’ is used uninitialized in this function").

  • Ich sehe gerade, auch mit korrigierter Reihenfolge wäre das hier noch problematisch:
    speed2 = (speed-speed3)/10;
    "speed" ist der Originalwert, "speed3" ist die Ziffer auf der Einerstelle. Wenn man die Differenz durch Zehn teilt, kann da immer noch etwas >9 herauskommen, und das gäbe wieder Hexziffern.


    Etwas übersichtlicher wären die Rechnungen so:

    Die IF-Abfrage ist nur für den Fall, dass die Zahl gar nicht in drei Stellen passt.