Messwerte Messschieber auf 16x2LCD richtig darstellen

Guten Abend zusammen,

der folgende Code überträgt das Datenprotokoll ( lt. Vertreiber Pewetools (ebay) ein 1 x 24 bit Protokoll ) eines Messschiebers über einen Arduino Mega 2560 auf ein LCD-Display 16 x 2:

#include <LiquidCrystal.h>                    // LCD Library einbinden

LiquidCrystal lcd(12,11,7,6,5,4); 

int i;

int sign;

long value;

float result;

int clockpin = 2;  

int datapin = 3;

unsigned long tempmicros;

 

 

void setup() {

  Serial.begin(9600);

  pinMode(clockpin, INPUT);

  pinMode(datapin, INPUT);
lcd.begin(16,2);                            // Display hat 2 Zeilen a 16 Zeichen
lcd.print("X-Achse");
lcd.setCursor(0, 1);                        // cursor an den Anfang der 2. Zeile
lcd.print("       mm");                      // Leerzeichen für Messwert freihalten
}


 void loop () {

  while (digitalRead(clockpin)==HIGH) {} 

  tempmicros=micros();

  while (digitalRead(clockpin)==LOW) {} //wait for the end of the HIGH pulse

  if ((micros()-tempmicros)>500) { //if the HIGH pulse was longer than 500 micros we are at the start of a new bit sequence

    decode(); //decode the bit sequence

  }

}

 

void decode() {

  sign=1;

  value=0;

  for (i=0;i<23;i++) {

    while (digitalRead(clockpin)==HIGH) { } //wait until clock returns to HIGH- the first bit is not needed

    while (digitalRead(clockpin)==LOW) {} //wait until clock returns to LOW

    if (digitalRead(datapin)==LOW) {

      if (i<20) {

        value|= 1<<i;

      }

      if (i==20) {  //wenn Bit 20 LOW ist, dann ist Messwert negativ

        sign=-1;  //deshalb vor dem Messwert ein Minuszeichen setzen

      }

    }

  }

  result=(value*sign)/100.00; //Messwert x Vorzeichen/100 ergibt Meßwert mit 2 Stellen hinter dem Komma
  
lcd.setCursor(0, 1);// cursor an Position bringen

lcd.print(result);
 
  delay(100);

}

Dieser Code stammt nicht von mir, ich habe ihn mir aus der arduino-Community zusammengesucht.

Das funktioniert auch grundsätzlich. Wenn jedoch zunächst ein Messwert mit einer höheren Stellenzahl ( z.B. -110.31 ) als der neue Messwert mit z.B. 30,46 angezeigt worden ist, so zeigt das Display den Wert 30.4631. Die letzten beiden Stellen des alten Wertes werden nicht gelöscht.
Die Hilfe von guntherb im Topic :http://forum.arduino.cc/index.php?topic=210178.0 habe ich gesehen, kann sie aber nicht umsetzen, weil ich nicht weiß, wie ich sie genau in meinen sketch einbinden soll ( bin halt kein C-Programmierer).
Wer könnte mir da helfen?

Viele Grüße

Safran

Du kannst es auch vereinfacht so machen:

lcd.setCursor(0, 1);
lcd.print("      ");
lcd.setCursor(0, 1);
lcd.print(result);

Bei ersten print() dann so viel Leerzeichen angeben wie die Ausgabe maximal breit ist. Das sorgt dafür dass die alte Ausgabe gelöscht wird bevor die neue geschrieben wird.

Vielen Dank, Serenifly,

genau das war die Lösung!

Der Vollständigkeit halber: Das Clock- und Data-Signal wird von ca. 1,5 V ( Batteriespannung des Messschiebers ) mit einer einfachen Verstärkerschaltung mit einem NPN-Transistor auf TTL-Niveau gebracht und dann über die Pins 2 und 3 in den Arduino zur Verarbeitung eingespeist. GND des Messschiebers wird mit GND des Arduino verbunden.

Viele Grüße

Safran

safran: genau das war die Lösung!

Ist es egal, dass die Anzeige beim Wechseln des Anzeigewerts immer kurz flackert?

Guten Abend, Jurs!

Ich benutze ein Display mit weißer Schrift und blauem Hintergrund. Die Anzeige ist ziemlich träge und flackert schon allein deshalb. Wenn ein anderer Wert angezeigt wird, erscheint kurz eine invertierte ( also dunkelblaue ) Schrift. Die Wartezeit von 100 ms möchte ich nicht verlängern, weil mir sonst beim Einsatz an der Drehbank die Genauigkeit flöten geht. Solltest Du eine Idee haben, dies abzustellen, immer her damit :-)

Viele Grüße

Safran

Bei mir kann auch bestätigen, dass es selbst wenn man die Stelle nur einmal beschreibt flackert, bzw. der Schaltvorgang so langsam ist, dass man ihn deutlich sieht.

Bei meinem Vorschlag wird das jetzt zweimal kurz hintereinander beschrieben. Das ist natürlich nicht ideal, aber es ist kurz und auch für Anfänger verständlich. Selbstverständlich gibt es bessere Lösungen.

Ich habe gerade mal beide Varianten verglichen: Die Anzeige ist so lahm, da sieht man keinen Unterschied. Bis auf die gelöschten Stellen. :-D

safran:
Solltest Du eine Idee haben, dies abzustellen, immer her damit :slight_smile:

Für einen zulässigen Wertebereich von “-99.99” bis “999.99” (wg. Einhaltung der max. 6 Stellen) mit Bereichsüberprüfung:

if (result<-99.99) result=-99.99;
if (result>999.99) result=999.99;
char strResult[7];
dtostrf(result,6,2,strResult);
lcd.print(strResult);

ich habe jetzt den code

lcd.print("       ");
lcd.setCursor(0, 1);
lcd.print(result);

auskommentiert und stattdessen Deinen Code eingefügt. Es wird jedoch nichts angezeigt außer dem Text, der schon im Bereich void setup() vorgegeben wurde. Irgendetwas übersehe ich wohl.

safran: ich habe jetzt den code

lcd.print("       ");
lcd.setCursor(0, 1);
lcd.print(result);

auskommentiert und stattdessen Deinen Code eingefügt. Es wird jedoch nichts angezeigt außer dem Text, der schon im Bereich void setup() vorgegeben wurde. Irgendetwas übersehe ich wohl.

lcd.setCursor(0, 1); darf nicht auskommentiert sein, sondern die Cursorposition muss schon vorher noch gesetzt werden, bevor die Ausgabe kommt.

Er sollte aber trotzdem irgendwas schreiben. Und zwar an die Stelle an der der Cursor nach dem letzten Schreibvorgang stand. Der wird ja intern nach jedem Zeichen inkrementiert.

Ich habe das jetzt mal richtig ( :slight_smile: ) eingefügt:

result=(value*sign)/100.00; //Messwert x Vorzeichen/100 ergibt Meßwert mit 2 Stellen hinter dem Komma
  
lcd.setCursor(0, 1);
if (result<-999.99) result=-999.99;
if (result>999.99) result=999.99;
char strResult[7];
dtostrf(result,7,2,strResult);
lcd.print(strResult);
 
  delay(100);

Da auch im Minusbereich über 100 mm erreicht werden können, habe ich die Ausgabe entsprechend angepasst.
Vorteil dieses Codes: Die letzte Stelle springt nicht mehr.
Das Flimmern ist nicht behoben, weil es von der Schaltgeschwindigkeit des Displays abhängt.

Danke an Serenifly und Jurs

Du musst auch das Array eins größer machen: char strResult[8];

C-Strings sind Null-terminiert um deren Ende zu erkennen. Daher müssen die Arrays eins größer als die Anzahl der sichtbaren Zeichen sein.

safran:
Da auch im Minusbereich über 100 mm erreicht werden können, habe ich die Ausgabe entsprechend angepasst.

In dem Fall, dass der String mit Minuszeichen insgesamt 7 Zeichen lang werden kann, muß das Char-Array ebenfalls angepaßt werden und mindestens 8 Zeichen aufnehmen können (C-String 7 Zeichen lang plus abschließendes Nullzeichen = 8 insgesamt), also:

char strResult[8];

Sonst bekommst Du bei Minuswerten in den Hundertern einen Buffer-Overflow im Programm, der ggf. unentdeckt bleibt, wenn das Programm zunächst trotzdem funktioniert.

Hallo,

ich habe den gleichen Code von der c't und habe einen Meßschieber von Tchibo. Nur funktioniert bei mir rein gar nichts. Ich bekomme nur paar wilde Zahlen auf die serielle Schnittstelle wenn ich am Meßschieber Zero drücke. Sonst passiert nichts. Hab schon die Logik invertiert. Mit Oszi versucht das Signal anzuschauen. Ist zu unregelmäßig / zu angsam für's Oszi. Ich erahne zumindestens ein Signal was so aussieht wie im c't Bsp. und weiterführende Links. Mit der Pulslängenerkennung im Code habe ich experimentiert. Ideen? Sonst hat der Tchibo eventuell nicht das Datenprotokoll was hier verwendet wird.

Edit: spontan neu gegoogelt. Ich denke meiner hat das "2x24bit" Sylvac Protokoll. Mal sehen was sich machen lässt.

@ Doc_Arduino

Schau Dir zur Darstellung der Datenpakete auf einem Oszilloskop doch mal folgende Seite an:

http://www.yadro.de/digital-messleiste/protokoll.html

In den Fotos sind unten die Einstellungen am Oszi zu sehen. Ich hatte am Anfang auch große Probleme mit der Darstellung, weil ich völlig falsche Werte für die Spannung und die Zeit eingestellt habe ( so oft benutze ich mein Oszi nicht ).

Hallo,

was der hat ist ein Speicheroszi. Hab das doch nochmal probiert. Diesmal mit Nutzung vom Triggereingang am Oszi. Hab ein Hameq HM303-3. Was auch geht, fiel mir jetzt wieder auf, die Nutzung von AT/NORM und etwas am Level-Poti drehen. Jetzt läuft das Signal nicht mehr weg, es steht also stabil. Wenn ich 2x24Bit Takt auf den Schirm "einstelle" sieht es gut aus. Nehme ich das Datensignal dazu wird es nur alternierend brauchbar. Aber so richtig schön sichtbar zum ablesen wird das auch nichts. Am geflacker dreht man ja durch.

Deshalb habe ich das anders gelöst. http://forum.arduino.cc/index.php?topic=212280.msg1556563#msg1556563

Guten Abend zusammen !

Falls es besser wäre, zu der folgenden Frage einen neuen Thread zu öffnen, bitte melden.

Ich möchte den auf Seite 1 gezeigten Sketch so erweitern, dass ich gleichzeitig drei Messschieberwerte auf drei unterschiedlichen LCD ausgeben kann, Benutzt wird ein Mega 2560 R3.

Ich habe mir das wie folgt vorgestellt:

Zunächst werden alle Variablen und die LCD mit Zusatznamen versehen, die einen Hinweis auf die entsprechende Achse geben, so z.B. statt int i im Deklarationsteil die Ausdrücke int ixachse, int iyachse und int izachse. Die Pins werden entsprechend verteilt.

Im Loop-Bereich habe ich vor, zunächst die X-Achsen-Daten verarbeiten und dann in void decodexachse () anzeigen zu lassen. Kann ich im Loop-Bereich danach einfach die Verarbeitungssequenz für die X-Achsen-Daten kopieren und unter Verwendung der Variablen mit Y-Achsen-Bezug die y-Achsen-Daten auswerten und in void decodeyachse () anzeigen lassen?

Für die Z-Achse würde ich dann genau so vorgehen.

Bevor ich mich aber ans Kopieren und die Vergabe von Variablennamen mache, frage ich lieber mal die Experten im Forum, ob das grundsätzlich möglich ist.

Guten Morgen zusammen !

Ich habe gestern mal den Sketch entsprechend erweitert. Grundsätzlich werden die Werte angezeigt, jedoch in dieser Form erst mit einer Verzögerung von bis zu 180 Sekunden auf die LCD ausgegeben.
Wenn ich die Codezeilen im Loop-Bereich und decode-Bereich für die Z-Achse herausnehme, werden veränderte Werte sofort auf den Displays dargestellt. Auch im Serial-Monitor sind diese Zeitunterschiede sichtbar.

Kann mir da jemand helfen?

#include <LiquidCrystal.h>                    // LCD Library einbinden

LiquidCrystal lcddrehzahl(12, 3, 7, 8, 9, 10); //sketch wird später noch erweitert
LiquidCrystal lcdxachse(12, 4, 7, 8, 9, 10);
LiquidCrystal lcdyachse(12, 5, 7, 8, 9, 10); 
LiquidCrystal lcdzachse(12, 6, 7, 8, 9, 10); 

int ixachse;
int iyachse;
int izachse;

int signxachse;
int signyachse;
int signzachse;

long valuexachse;
long valueyachse;
long valuezachse;

float resultxachse;
float resultyachse;
float resultzachse;

int clockpinxachse = 23;  
int clockpinyachse = 27; 
int clockpinzachse = 31; 

int datapinxachse = 25;
int datapinyachse = 29;
int datapinzachse = 33;

unsigned long tempmicrosxachse;
unsigned long tempmicrosyachse;
unsigned long tempmicroszachse;
 

 

void setup() {

  Serial.begin(9600);

  pinMode(clockpinxachse, INPUT);
  pinMode(clockpinyachse, INPUT);
  pinMode(clockpinzachse, INPUT);
  
  pinMode(datapinxachse, INPUT);
  pinMode(datapinyachse, INPUT);
  pinMode(datapinzachse, INPUT);

lcddrehzahl.begin (16,2);
lcddrehzahl.print("keine Drehzahl");
lcddrehzahl.setCursor(0,1);
lcddrehzahl.print("messbar");

lcdxachse.begin(16,2);                            // Display hat 2 Zeilen a 16 Zeichen
lcdxachse.print("X-Achse");
lcdxachse.setCursor(0, 1);                        // cursor an den Anfang der 2. Zeile
lcdxachse.print("         mm");                    // Leerzeichen für Messwert freihalten

lcdyachse.begin(16,2);                            // Display hat 2 Zeilen a 16 Zeichen
lcdyachse.print("Y-Achse");
lcdyachse.setCursor(0, 1);                        // cursor an den Anfang der 2. Zeile
lcdyachse.print("         mm");
 
lcdzachse.begin(16,2);                            // Display hat 2 Zeilen a 16 Zeichen
lcdzachse.print("Z-Achse");
lcdzachse.setCursor(0, 1);                        // cursor an den Anfang der 2. Zeile
lcdzachse.print("         mm");                    
}


 void loop () {

  // zuerst die X-Achse
  while (digitalRead(clockpinxachse)==LOW) {} 

  tempmicrosxachse=micros();

  while (digitalRead(clockpinxachse)==HIGH) {} 

  if ((micros()-tempmicrosxachse)>500) { 

    decodexachse(); //decode the bit sequence
    
    //jetzt die Y-Achse
    while (digitalRead(clockpinyachse)==LOW) {} 

  tempmicrosyachse=micros();

  while (digitalRead(clockpinyachse)==HIGH) {} 

  if ((micros()-tempmicrosyachse)>500) { 

    decodeyachse(); //decode the bit sequence

//jetzt die Z-Achse
while (digitalRead(clockpinzachse)==LOW) {} 

  tempmicroszachse=micros();

  while (digitalRead(clockpinzachse)==HIGH) {} 

  if ((micros()-tempmicroszachse)>500) { 

    decodezachse(); //decode the bit sequence

    }

   }
  }
 }
 
//jetzt Decodierung und Anzeige der X-Achse


void decodexachse() {

  signxachse=1;

  valuexachse=0;

  for (ixachse=0;ixachse<23;ixachse++) {

    while (digitalRead(clockpinxachse)==LOW) { } 

    while (digitalRead(clockpinxachse)==HIGH) {} 

    if (digitalRead(datapinxachse)==HIGH) {

      if (ixachse<20) {

        valuexachse|= 1<<ixachse;

      }

      if (ixachse==20) {  //wenn Bit 20 LOW ist, dann ist Messwert negativ

        signxachse=-1;  //deshalb vor dem Messwert ein Minuszeichen setzen

      }

    }

  }

  resultxachse=(valuexachse*signxachse)/100.00; //Messwert x Vorzeichen/100 ergibt Meßwert mit 2 Stellen hinter dem Komma
  
  
lcdxachse.setCursor(0, 1);
if (resultxachse<-999.99) resultxachse=-999.99;
if (resultxachse>999.99) resultxachse=999.99;
char strResultxachse[8];
dtostrf(resultxachse,8,2,strResultxachse);
lcdxachse.print(strResultxachse);
 Serial.print(strResultxachse);
 } 

//jetzt Decodierung und Anzeige der Y-Achse

void decodeyachse() {

  signyachse=1;

  valueyachse=0;

  for (iyachse=0;iyachse<23;iyachse++) {

    while (digitalRead(clockpinyachse)==LOW) { } 

    while (digitalRead(clockpinyachse)==HIGH) {} 

    if (digitalRead(datapinyachse)==HIGH) {

      if (iyachse<20) {

        valueyachse|= 1<<iyachse;

      }

      if (iyachse==20) {  //wenn Bit 20 LOW ist, dann ist Messwert negativ

        signyachse=-1;  //deshalb vor dem Messwert ein Minuszeichen setzen

      }

    }

  }

  resultyachse=(valueyachse*signyachse)/100.00; //Messwert x Vorzeichen/100 ergibt Meßwert mit 2 Stellen hinter dem Komma
  
  
lcdyachse.setCursor(0, 1);
if (resultyachse<-999.99) resultyachse=-999.99;
if (resultyachse>999.99) resultyachse=999.99;
char strResultyachse[8];
dtostrf(resultyachse,8,2,strResultyachse);
lcdyachse.print(strResultyachse);
 Serial.print(strResultyachse);
  
}

//jetzt Decodierung und Anzeige der Z-Achse

void decodezachse() {

  signzachse=1;

  valuezachse=0;

  for (izachse=0;izachse<23;izachse++) {

    while (digitalRead(clockpinzachse)==LOW) { } 

    while (digitalRead(clockpinzachse)==HIGH) {} 

    if (digitalRead(datapinzachse)==HIGH) {

      if (izachse<20) {

        valuezachse|= 1<<izachse;

      }

      if (izachse==20) {  //wenn Bit 20 LOW ist, dann ist Messwert negativ

        signzachse=-1;  //deshalb vor dem Messwert ein Minuszeichen setzen

      }

    }

  }

  resultzachse=(valuezachse*signzachse)/100.00; //Messwert x Vorzeichen/100 ergibt Meßwert mit 2 Stellen hinter dem Komma
  
  
lcdzachse.setCursor(0, 1);
if (resultzachse<-999.99) resultzachse=-999.99;
if (resultzachse>999.99) resultzachse=999.99;
char strResultzachse[8];
dtostrf(resultzachse,8,2,strResultzachse);
lcdzachse.print(strResultzachse);
 Serial.print(strResultzachse);
  
}

Viele Grüße
Safran

Guten Morgen !

Problem ist gelöst. Ich hatte den Messschieber für die Z-Achse noch nicht angeschlossen. Das die Daten trotzdem ab und zu aktualisiert worden sind, dürfte an irgendwelchen Einstreuungen gelegen haben, die Kabel sind noch nicht abgeschirmt.

Schön wäre es natürlich, wenn das Programm nach dem Einschalten selbst prüft, welche Messschieber angeschlossen sind ( Ich möchte die Anzeigen an der Drehbank mit 2 Messschiebern und an der Fräse mit 3 Messschiebern betreiben ) und dann auch nur von diesen Messschiebern die Daten abruft. Aber ich habe keine Idee, wie ich das dem Programm sagen könnte. Gibt es dazu Vorschläge?

Viele Grüße

Safran