Go Down

Topic: Ersatz Fahrrad Computer durch Uno (Read 5934 times) previous topic - next topic

jurs


Wie kann man eigentlich die Anzeige der Kilometer so machen, das die Werte immer an der gleichen Stelle dargestellt werden?


Im Normalfall macht man das, indem man auf eine feste Stellenzahl formatiert.

Beispiel: Der Kilometerzähler soll bis 99999 km auf ganze km ohne Nachkommastellen angezeigt werden, dann formatierst Du den Kilometerstand auf einen String mit 5 Zeichen Breite, keine Nachkommastellen, und wenn Du den String immer an derselben Position ausgibst, erscheinen die Einerstellen immer ganz rechts, die Zehnerstellen als zweite Stelle von rechts usw. und das ganz unabhängig davon, ob der Kilometerstand ein-, zwei-, drei-, vier-, oder fünfstellig ist.

-Micky

Nun hab ich es auch verstanden. 12345,67 muß dann heißen: 8,2,buffer.

Oder 123,456: 7,3 buffer.

Die Zahl vor dem Komma dient als Platzhalter für zu erwartende Zahlen und die hinter dem Komma für die Nachkommastellen. In Nullstellung wird aber nur die Null vor dem Komma aber alle Nullen nach dem Komma angezeigt.

Ich hoffe das stimmt jetzt so.


Micky

jurs


Nun hab ich es auch verstanden. 12345,67 muß dann heißen: 8,2,buffer.


Ja, das sind 8 Zeichen gesamt, 2 Stellen nach dem Dezimalpunkt.


Oder 123,456: 7,3 buffer.


Ja, das sind 7 Zeichen gesamt, 3 Stellen nach dem Dezimalpunkt.

Übrigens: Das Array zur Aufnahme der Zeichen muss immer (Minimum!) um eins länger sein, also 9 bzw 8 für eine Formatierung auf 8 und 7 Stellen: C-Strings werden intern nämlich immer mit einem abschließenden Nullzeichen gespeichert. Wenn der Puffer aus Versehen zu klein ist und Du formatierst über das Pufferende hinaus, können im Programm sehr schwierig zu entdeckende Fehler in anderen Programmstellen auftreten.

-Micky

#33
Jul 20, 2013, 02:41 pm Last Edit: Jul 20, 2013, 07:57 pm by -Micky Reason: 1
Hier mal was zum aktuellen Stand. Ist aber noch nicht ganz fertig. Ein Bild zeigt die Steuereinheit und das andere das Display.


Micky

-Micky

Wie bekomme ich die große Schrift auf einem 8x2 Display unter? Paßt natürlich so nicht. Und ich weiß nicht wo ich den Code so abändern kann das nur drei Zahlen dargestellt werden.


Micky

jurs


Wie bekomme ich die große Schrift auf einem 8x2 Display unter? Paßt natürlich so nicht. Und ich weiß nicht wo ich den Code so abändern kann das nur drei Zahlen dargestellt werden.


Das ist jetzt aber die Wärme, oder?

Du brauchst nur die Display-Initialisierung auf das 8x2 Display anpassen und dann mußt Du eben die Ausgabe so kurz halten, dass nicht hinter das achte Zeichen geschrieben wird. Z.B. eine Anzeige nur mit dreistelliger Geschwindigkeit, ohne Nachkommastellen, linksbündig:
Code: [Select]

void tachoAnzeige()
{
  byte umdrehungen;
  unsigned long zeit;
  float kph, kilometer;
  int kphRounded;
  char buffer[10];
  noInterrupts();            // Interrupts sperren
    umdrehungen=reedCountSum;// Zählvariable umkopieren
    reedCountSum=0;          // Zählvariable auf 0 zurücksetzen
    zeit=reedMillisSum;      // Zeitzähler umkopieren
    reedMillisSum=0;         // Zeitzähler auf 0 zurücksetzen
  interrupts();              // Interrupts wieder zulassen
  if (umdrehungen>0)
    kph=float(RADUMFANG)*(float)umdrehungen/(float)zeit*3.6;
  else
    kph=0.0; 
  kphRounded=int(kph+0.5); // auf ganze kph gerundet
   
  kphRounded = kphRounded % 1000;       // drop any digits above 999
  printbigchar(kphRounded / 100,0);     // print the speed hundreds
  kphRounded = kphRounded % 100;        // drop any digits above 99
  printbigchar(kphRounded/10,1);        // print the speed tens
  kphRounded = kphRounded % 10;         // drop any digits above 9
  printbigchar(kphRounded,2);           // print the speed ones
}

-Micky

#36
Jul 30, 2013, 10:52 pm Last Edit: Jul 30, 2013, 11:02 pm by -Micky Reason: 1
Nee, daran liegt es nicht. Ich hab schon alles mögliche versucht. Ich kriege zwar eine zweistellige Anzeige hin, nur brauche ich aber eine dreistellige. Was geholfen hat ist statt long short zu nehmen.

Ich weiß nicht wo man die Nachkommastellen angibt. Bei diesem hier wäre das klar:

Code: [Select]
lcd.setCursor(0, 0);
 dtostrf(kilometer,9,3,buffer);
 lcd.print(buffer);
 lcd.print(" km");
 lcd.setCursor(0, 1);
 lcd.print("KM/H ");
 dtostrf(kph,5,1,buffer);


nicht aber bei dem von Dir genommenen Code. Hier ist der Code wie ich ihn eben nehme:

Code: [Select]
//Anzahl Spalten des Display (8)
//#define LCD_WIDTH 8

//Anzahl Zeilen des Display (2)
//#define LCD_HEIGHT 2

// Pin für Reed-Kontakt, Digital-2 für Interrupt 0
#define REEDPIN 2

// Hardware-Interrupt für den Reed-Pin
#define REEDINTERRUPT 0

// Radumfang in mm
#define RADUMFANG 1540


//#include <LiquidCrystal.h>
//LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

#include <LiquidCrystal_I2C.h> // Für I2C LCD Display
#include <Wire.h>
LiquidCrystal_I2C lcd(0x27,8,2);  // I2C LCD Adresse auf 0x20 gesetzt, 16 Zeichen / 2 Zeilen LCD


// build 2-line digit font data array
// Digits are 3 characters wide.
byte bignums[10][2][3] = {
// Define which characters to use for each number. 255 is a solid block; 254 is a space  
// The format is { {TopLeft, TopMiddle, TopRight}, {BottomLeft, BottomMiddle, BottomRight} }
{ {255, 0, 255}, {255, 1, 255} },        // data to display "0"
{ {0, 255, 254}, {1, 255, 1} },          // data to display "1"
{ {2, 2, 255}, {255, 1, 1} },            // data to display "2"
{ {0, 2, 255}, {1, 1, 255} },            // data to display "3"
{ {255, 1, 255}, {254, 254, 255} },      // data to display "4"
{ {255, 2, 2}, {1, 1, 255} },            // data to display "5"
{ {255, 2, 2}, {255, 1, 255} },          // data to display "6"
{ {0, 0, 255}, {254, 255, 254} },        // data to display "7"
{ {255, 2, 255}, {255, 1, 255} },        // data to display "8"
{ {255, 2, 255}, {254, 254, 255} }       // data to display "9"
};

void loadchars() {                        // This subroutine programs the custom character data into the LCD
 lcd.command(64);
// Custom character 0
 lcd.write(byte(B11111));
 lcd.write(byte(B11111));
 lcd.write(byte(B11111));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 
// Custom character 1
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B11111));
 lcd.write(byte(B11111));
 lcd.write(byte(B11111));
 
// Custom character 2
 lcd.write(byte(B11111));
 lcd.write(byte(B11111));
 lcd.write(byte(B11111));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B11111));
 lcd.write(byte(B11111));
 lcd.write(byte(B11111));
 
// Custom character 3
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B01110));
 lcd.write(byte(B01110));
 lcd.write(byte(B01110));
 
// Custom character 4
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B01110));
 lcd.write(byte(B01110));
 lcd.write(byte(B01110));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 
// Custom character 5
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 
// Custom character 6
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 
// Custom character 7
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));
 lcd.write(byte(B00000));

 lcd.home();
}

void printbigchar(byte digit, byte col) { // This subroutine prints the big font characters on the LCD screen
if (digit > 9) return;                   // reject anything above 9
for (int i = 0; i < 2; i++) {            // count i from 0 to 1
  lcd.setCursor(col*4 , i);              // set LCD cursor at correct point
  for (int j = 0; j < 3; j++) {          // count j from 0 to 2
    lcd.write(bignums[digit][i][j]);     // write proper block to LCD from array
  }
  lcd.write(254);                        // write an empty space
}
lcd.setCursor(col + 4, 0);               // move the cursor to the top line, col + 4
}


void setup(){
 
 // LCD I2C Initilaisieren und Hintergrundbeleuchtung aktivieren
  lcd.init();
  lcd.backlight();    
 
  lcd.init();                                        // LCD-Anzeige initialisieren
  lcd.clear();
 
 pinMode(REEDPIN, INPUT_PULLUP); // Reedkontakt direkt und ohne Widerstand angeschlossen  
 //lcd.begin(LCD_WIDTH, LCD_HEIGHT);
 loadchars();
 attachInterrupt(REEDINTERRUPT, reedISR, FALLING);
}

volatile byte reedCountSum;
volatile short reedMillisSum;

unsigned short lastReedMillis;

void reedISR()
{
 if (millis()-lastReedMillis>=25)  // 25ms entspricht max. 40 Radumdrehungen pro Sekunde
 {
   reedCountSum++;                 // eine Radumdrehung zählen
   reedMillisSum+=millis()-lastReedMillis;   // Zeit addieren
   lastReedMillis=millis();       // Zeit merken
 }
}

unsigned short gesamtUmdrehungen;

void tachoAnzeige()
{
 byte umdrehungen;
 unsigned short zeit;
 float kph, kilometer;
 int kphRounded;
 char buffer[10];
 noInterrupts();            // Interrupts sperren
   umdrehungen=reedCountSum;// Zählvariable umkopieren
   reedCountSum=0;          // Zählvariable auf 0 zurücksetzen
   zeit=reedMillisSum;      // Zeitzähler umkopieren
   reedMillisSum=0;         // Zeitzähler auf 0 zurücksetzen
 interrupts();              // Interrupts wieder zulassen
 gesamtUmdrehungen+= umdrehungen; // Aufsummieren aller Radumdrehungen
 kilometer=(float)gesamtUmdrehungen*(float)RADUMFANG/1000000.0; // Fahrtkilometerzähler
 if (umdrehungen>0)
   kph=float(RADUMFANG)*(float)umdrehungen/(float)zeit*3.6;
 else
   kph=0.0;  
 /*  
 lcd.setCursor(0, 0);
 dtostrf(kilometer,9,3,buffer);
 lcd.print(buffer);
 lcd.print(" km");
 lcd.setCursor(0, 1);
 lcd.print("KM/H ");
 dtostrf(kph,5,1,buffer);
 */
 kphRounded=int(kph+0.5); // auf ganze kph gerundet
 // Ausgabe kph in grossen Ziffern
 
 kphRounded = kphRounded % 1000;       // drop any digits above 999
 printbigchar(kphRounded / 100,0);     // print the speed hundreds
 kphRounded = kphRounded % 100;        // drop any digits above 99
 printbigchar(kphRounded/10,1);        // print the speed tens
 kphRounded = kphRounded % 10;         // drop any digits above 9
 printbigchar(kphRounded,2);           // print the speed ones
 //lcd.setCursor(12, 1);
 //lcd.print("km/h");
}


unsigned short letzteSekunde=0;
void loop()
{
 unsigned short dieseSekunde=millis()/1000;
 // Tachoanzeige wird genau einmal pro Sekunde aktualisiert
 if (letzteSekunde != dieseSekunde)
 {
   tachoAnzeige();
   letzteSekunde=dieseSekunde;
 }
}


Das entscheidene ist ja wohl der Teil den Du hier vorhin reingesetzt hast. Nur wo bitte muß ich da was ändern?

Hinzu kommt noch das die Anzeige nun viel zu träge reagiert.


Micky


jurs


Nee, daran liegt es nicht. Ich hab schon alles mögliche versucht. Ich kriege zwar eine zweistellige Anzeige hin, nur brauche ich aber eine dreistellige.


Dann nimm wieder das 16x2 Display, ein 8x2 Display ist dafür zu klein!

Für eine Anzeige großer Ziffern mit "printbigchar" brauchst Du immer 3 Zeichen Breite, das macht bei dreistelliger Anzeige:
printbigchar 3 Zeichen + 1 Zeichen Abstand + printbigchar 3 Zeichen + 1 Zeichen Abstand + printbigchar 3 Zeichen
= 11 Zeichen insgesamt
Da ist ein Display mit 8 Zeichen insgesamt zu wenig.

Selbst wenn Du sagst, Geschwindigkeiten unter 200 km/h reichen aus und Du würdest als 1 einen einfachen Strich von 1 Zeichen Breite nehmen, passt es immer noch nicht. Dann brauchst die dargestellte Ziffer "1" per printbigchar zwar 2 Zeichen weniger, macht also 9 statt 11 Zeichen insgesamt, aber 9 ist immer noch eins zuviel für ein Display mit 8 Zeichen in einer Zeile.

-Micky

Dann liegt es doch nicht daran das ich es nicht hinbekomme. Das Display ist halt ein bißchen zu klein. Das macht aber nichts. Dann nehme ich halt die normale Schriftgröße.

Oder halt eine Vergrößerungsfolie darüber befestigen.


Micky

Go Up