Go Down

Topic: Frage eines Anfängers zu einem LCD Display 16x2 oder so (Read 1 time) previous topic - next topic

skyfox60

Hallo,

als blutiger Anfänger habe ich bezüglich LCD Display eine Frage.

Ich habe einen Sketch, der läuft soweit auch bestens. Nun möchte ich ein paar Werte in ein LCD Display schreiben., Ich weiß nur nicht, wie ich das ansteuern soll.

Der geamte Sketch läuft je Sekunde etwa 3 mal durch. Er ist also recht langsam.

Wenn ich nun die Werte nur 3 mal je Sekunde in das Display schreibe, dann wird das arg flackern.

Aus dem Grund habe ich bisher nie Displays verbaut. Schneller bekomme ich den Sketch auch nicht mehr, das ist schon ziemlich ausgereizt.

Eine Überlegung war, einfach zwischen jeder Zeile und der jeweils nächsten, immer wieder dasDisplay neu zu beschreiben, damit am Ende min so 25 Hz rauskommen, damit das Auge das als Schrift, und nicht als Geflacker wahrnimmt.

Bedenken machen mir da aber z.B. Befehle, wie Sensorabfragen, wo Daten hin und her fliessen, und allein dieser Schritt ja ein wenig dauern. Da kann man ja auch nicht zwischenfunken.
Waitstates wie z.B. 20000µs beim Einlesen eines Impulses von RC-Kanälen machen auch Todzeit, hat man meghrere davon, sammelt sich das.
Manchmal dauern berechnungen ja auch unterschiedlich lang, so das nie eine stabile Frequenz zu Stande kommt beim beschreiben des Displays.

Daher die Frage, wie bekommt ihr eure Programme so schnell, das die Displays genügent oft gefüttert werden, ohne das es ein Geflacker gibt. 25Hz ist ja so die untere Grenze, die das Auge noch als Dauernd an erkennt. Mehr wäre besser.
Laufen alle eure Programme in der praxis mehr als 25 mal die Sekunde komplett durch?

Bevor ich nun in ein Display investere, hätte ich gern gewussst, ob sich das lohnt.
Bisher reichen meine Programmierkenntnisse nicht recht weit.
Es ist halt nur blöd, sich durch Zählen von Tastendrücken, die aktuell eingegebenen Werte zu merken, die hätte ich gern auf dem Diplay.
Im konkreten Fall geht es um ein Thermostat, wo ich den Sollwert in °C ablesen können möchte.
Der soll dort angezeigt werden, auf ein Grad genau würde reichen, also eigentlich nur zwei Stellen.
Das °C braucht nicht, ich weiß ja das es eine Temperatur ist.
Vielleicht ist das auch einfacher mit einem simplen zweistelligen Sieben-Segment Baustein, aber ... keine Ahnung.
Vielleicht weiß jemand, wie ich das am besten löse.


Der leckerste Fisch ist immer noch der Rumpsteak.

MicroBahner

Du hast eine falsche Vorstellung davon, wie diese 16x2 LCD's funktiomieren.

Wenn Du da was drauf schreibst, zeigen die das selbständig dauerhaft an. Dass musst Du nicht dauernd refreshen. Es ist im Gegenteil eher nachteilig, wenn man da zu oft drauf schreibt. Das sollte man nur machen, wenn sich an dem angezeigten Text wirklich was ändert.

Ich wüsste kein LCD - weder rein Text noch Grafik - dass Du über den Ardino 'refreshen' müsstest.

Gruß, Franz-Peter

gregorss

[Geflacker]
Seit meinem ersten LC-Display in den 90ern habe ich nie eins gesehen, das geflackert hätte. Du Siehst einen Wechsel des Inhalts normalerweise nur, wenn es von Dir gewollt ist, ganz ohne Geflacker. Du aktualisierst den Inhalt und fertig.

Gruß

Gregor
Mir wird übel. (Uwe)

HotSystems

Aus dem Grund habe ich bisher nie Displays verbaut. Schneller bekomme ich den Sketch auch nicht mehr, das ist schon ziemlich ausgereizt.
.....
Bevor ich nun in ein Display investere, hätte ich gern gewussst, ob sich das lohnt.
.....
Diese Invesatition lohnt sich bestimmt.

Wenn du mit den Beispielen der zugehörigne Library das dann aufbaust, wirst du sehen, da flackert nix.

Wernn doch, hast du etwas falsch programmiert und da können wir sicher helfen.
Gruß Dieter

I2C = weniger ist mehr: weniger Kabel, mehr Probleme. 8)

Whandall

Bedenken machen mir da aber z.B. Befehle, wie Sensorabfragen, wo Daten hin und her fliessen, und allein dieser Schritt ja ein wenig dauern. Da kann man ja auch nicht zwischenfunken.
Waitstates wie z.B. 20000µs beim Einlesen eines Impulses von RC-Kanälen machen auch Todzeit, hat man meghrere davon, sammelt sich das.
Man kann das (fast immer) auch so programmieren, dass loop dennoch sehr schnell wiederholt wird.
Würdest du deinen Kode posten, könnte man mehr dazu sagen.

Bevor ich nun in ein Display investere, hätte ich gern gewussst, ob sich das lohnt.
Ich schenk dir mal ein 'i', das hast du wohl verloren.  ;)



2,81 € (freier Versand) für ein 16x2 LCD mit I2C Interface empfindest du als Investition?
Ah, this is obviously some strange usage of the word 'safe' that I wasn't previously aware of. (D.Adams)

skyfox60

Hallo zusammen,

erst einmal vielen Dank für die schnelle Hilfe.

Das heißt also, die Dinger haben einen Zwischenspeicher, der diese Aufgabe erledigt.

Das läßt vieles für mich jetzt in einem ganz anderen Licht erscheinen.

Ich beschäftige mich erst seit einem Monat mit dem Arduino überhaupt.
Bis dahin waren alle Dinge rund um ihn für mich Neuland.

Und vieles verstehe ich immer noch nicht.

Als Modellflieger dreht sich meine Programmiererei hauptsächlich um alles, was in, am, um um das Flugzeug passiert.

Das Thermostat soll einen Heizkoffer beflügeln. Die kann  man zwar auch fertig für 1,99 in China kaufen, aber das ist ja langweilig.  :)

Momentan versuche ich, die Sache mit den Timern zu verstehen, aber da tue ich mich echt schwer.
Werd mal einfach was damit programmieren, und experimentieren.

Ich brauche da was Ineinandergeschachteltes, was quasi im Hintergrund läuft.
Einfacher Timer, ok, das hab ich soweit gerafft.
ich möchte aber:

1 - 1,5 Sek. Aus
50µS an
50µS aus
50µS an
50µS aus
50µS an
50µ aus
50µS an
50µS aus
dann von Vorne, also wieder 1,5S Pause, und 4 mal 50µS an-aus usw.

Dazwischen kommen Dinge, wie Servopuls abfragen und andere Aus und Eingänge schalte.
Und ein Loop, der ca. 1,5 Sek. eh schon dauert für ein schwellendes Licht ( PWM steigt, fällt kontinuierlich. ) Möglicherweise kann man das sogar ebenfalls über einen zweiten Timer laufen lassen.
Ich weiß nicht.

Konventionell habe ich das gelößt, und es läuft auch Prima,
aber der Sketch ist dadurch sehr lang und unübersichtlich.
Geht, aber ist weit entfernt von auch nur annähernd professionell.
Der leckerste Fisch ist immer noch der Rumpsteak.

skyfox60

Hallo Whandall,

danke für das "I", hatte ich übersehen beim Korrekturlesen.

Nun ja, es geht nicht um die ~3€.
Ich empfinde eine Investition dann als schlecht, wenn ich anschliessend nichts damit machen kann.

Da geht es weniger um die Höhe des Betrages, als um den zu erwartenden Erfolg der Aktion.
Die Erwartungshaltung hat sich ja durch die schnellen Antworten gerade deutlich nach oben bewegt.

Sogar so weit, das ich mehr ausgegeben habe, und eines gekauft hab, das von Deutschland versandt wird, um es schneller zu haben, und das hiesige Bruttosozialprodukt zu unterstützen. :)
Der leckerste Fisch ist immer noch der Rumpsteak.

Serenifly

Der geamte Sketch läuft je Sekunde etwa 3 mal durch. Er ist also recht langsam.

Wenn ich nun die Werte nur 3 mal je Sekunde in das Display schreibe, dann wird das arg flackern.
Sooo extrem langsam sind die Displays auch nicht. Außerdem soll man das ja auch noch als Mensch lesen können.

Wodurch viele Anfänger Flackern produzieren ist indem sie das Display immer komplett löschen und dann neu beschreiben. Oder indem sie einzelne Zeilen komplett mit Leerzeichen überschreiben und dann den neuen Inhalt.
Richt macht man es wenn man seinen Text auf eine konstante Breite formatiert, alten Text direkt überschreibt und nur den Rest mit Leerzeichen auffüllt

gregorss

Ich beschäftige mich erst seit einem Monat mit dem Arduino überhaupt.
Bis dahin waren alle Dinge rund um ihn für mich Neuland.
Wenn Du auch Programmierneuling bist, solltest Du Dich vom Start weg darum kümmern, dass Dein Code gut aussieht. Wie sehr sowas bei der Fehlersuche hilft, lernst Du noch :-)))

Gruß

Gregor
Mir wird übel. (Uwe)

skyfox60

Hallo Gregor,

ich geb mir ja schon Mühe. Hier mal mein Sketch für die Originalgetreue Beleuchtung eines Flugzeuges.

Code: [Select]
/*
  Scale like anticollision-light, strobe-light, NAV-lights and landing-light for RC-Aircraft

  Digital Channels Output
  NAV_light    = D5  ( Left = red, Right = green, Back = white ) digital out
  ACL          = D6  PWM _ Channel for intensity regulation ( ACL = Anticollision Light )
  Landinglight = D7  digital out
  Strobe       = D8  digital out
 
  Receiverchannel Inputs:
  Input a Servochannel from Receiver to D10, Try-State Switch is recommended ( 1000µs, >1500µs, 2000µs )
 
  In normal ( out ) condition ( a > 1400 a <2100 ) only the mainloop and ACL_only-routine is ruinning.
  This makes the ACL ( anticollision-light ) running as soon as the battery is plugged on and the lamp-test ist finished.
  I made this because in real aircraft the first action after switching the main switch on, is to activate the ACL, there should be no need to activate a switch at the transmitter for that.
  Also, the ACL remains Fading up and down, until battery is unplugged and aircraft save.
  If you have a transmitter that allowes the switch-position-test at the beginning, set it so that the light switch has to be in 2000µs position before transmitter starts.
  When switch in appx mid position ( a <1400 ) the ACL_NAV_Strobe-Loop runs. You find at first a similar routine like in ACL_only.
  This was required due to the need of some other values to have the same visiual appearence of ACL the and nearly continuing as it was.
  there is a Lamptest to check all lamps. 10 flashes wake up for you, followed by single test and finally 10 flashes to finish and exit to Mainloop.
 
*/

  int NAV_light = 5;
  int ACL = 6;                     // the PWM pin the LED is attached to
  int Landinglight = 7;
  int Strobelight = 8;
  int brightness = 7;              // how bright the LED is, 0 at startup
  int brightness_increment = 7;    // How many points increment or decrement per step to fade the LED, if you change this value ( default is 7 ), you have also to change the counter1 steps ( default is 68 ), just for the case you changed it and do not remember
                                   // Also max Brightness has to be altered, if you cange any of the values. ( default is 231 )

                                 
  int counter1 = 1;
  int counter2 = 0;


void setup()
{

  pinMode(5, OUTPUT);              // NAV_light
  pinMode(6, OUTPUT);              // output ACL
  pinMode(7, OUTPUT);              // output Landinglight
  pinMode(8, OUTPUT);              // putput Strobelight
  pinMode(10, INPUT);              // reads a and cycles ACL and Strobelight
}


// the loop routine runs over and over again forever:
void  loop() {
Serial.begin(9600);
goto Mainloop;
// Lamptest to check all lamps. 10 flashes wake up for you, then single test and then 10 flashes finish and exit to Mainloop

  for ( int L1 = 0; L1 <= 10; L1++ )
{
  digitalWrite (Strobelight,HIGH); ; digitalWrite(NAV_light, HIGH);  digitalWrite(ACL, HIGH);  digitalWrite(Landinglight, HIGH); delay(50);
  digitalWrite (Strobelight,LOW); digitalWrite(NAV_light, LOW);  digitalWrite(ACL, LOW);  digitalWrite(Landinglight, LOW);delay(50);
}
  for ( int L = 0; L <= 1; L++) { digitalWrite (NAV_light, HIGH); delay(300);  digitalWrite (NAV_light, LOW);delay(300); digitalWrite ( ACL, HIGH ); delay(300); digitalWrite ( ACL, LOW );delay(300); digitalWrite (Landinglight,HIGH);
  delay(300); digitalWrite (Landinglight,LOW);delay(300);  digitalWrite (Strobelight,HIGH);delay(300);digitalWrite (Strobelight,LOW);delay(300);
}
  for ( int L1 = 0; L1 <= 10; L1++ )
{
  digitalWrite (Strobelight,HIGH); ; digitalWrite(NAV_light, HIGH);  digitalWrite(ACL, HIGH);  digitalWrite(Landinglight, HIGH); delay(50);
  digitalWrite (Strobelight,LOW); digitalWrite(NAV_light, LOW);  digitalWrite(ACL, LOW);  digitalWrite(Landinglight, LOW);delay(50);
 
}


  Mainloop:;   
 
 // digitalWrite(ACL,brightness);
  counter1 = 1;
  counter2 = 0;
 
  int    a = pulseIn(10,HIGH,25000);        // Read in pulse lenght, 3rd parameter has to be finetuned with receiver behavior
 
  if ( a >=1600 & a <=2100 ) { digitalWrite (NAV_light, LOW);  digitalWrite (Landinglight, LOW); goto ACL_only; }
  if ( a >950 & a <1200 ) { digitalWrite (Landinglight, HIGH); }
  if ( a >1200 ) { digitalWrite (Landinglight, LOW);  }
  if ( a >=950 & a <=1600) { digitalWrite (NAV_light, HIGH); goto ACL_NAV_Strobe; }
 
 
       
  ACL_only:; 
 
   analogWrite(brightness, 7);
   for (brightness <=7; brightness <252; brightness = brightness + brightness_increment){ analogWrite(ACL, brightness); delay(20); Serial.println(brightness); }   
   for (brightness <=253; brightness >=7; brightness = brightness - brightness_increment){ analogWrite(ACL, brightness); delay(30); Serial.println(brightness); }
     
   delay(400); // this delay is importand to have not jump in the brightness of ACL when switching NAV-lights and strobe on and of. do not change this value.
 
  goto Mainloop;
 

 
  ACL_NAV_Strobe:;
 
  counter1 = counter1+1;
 
  analogWrite(brightness, 7); // brightness = 7; // for synchronisation, to have small remaining brightness at the lower end, like a downgoing bulb at the ACL
   for (brightness <=7; brightness <252; brightness = brightness + brightness_increment){ analogWrite(ACL, brightness); delay(20); Serial.println(brightness); }   
   for (brightness <=253; brightness >=7; brightness = brightness - brightness_increment){ analogWrite(ACL, brightness); delay(30); Serial.println(brightness); }
    // this two lines became necessary to synchronize the status of the ACL brightness when switching NAV lights and strobe on and off.
    //without the repeat of that two lines, a small jump occures, that is visible. Took me time to find out:) 
 
 
 
// the loop function Strobe runs 4 times ( 4 flashes ) and returns to Mainloop to check again the switch ( pulse ) status.

  Strobe:;
 
  counter2 = counter2+1; 
  digitalWrite(Strobelight, HIGH);         // turn the LED on by making voltge HIG
  delay(40);                               // wait for 50ms on time
  digitalWrite(Strobelight, LOW);          // turn the LED off by making the voltage LOW
  delay(60);   // wait for a second        // Wait for 50ms off time
  if ( counter2 == 4 ) { goto Mainloop; }  // the 4 is the number of flashes in each cycle
  { goto Strobe; } 

}
Der leckerste Fisch ist immer noch der Rumpsteak.

Serenifly

Goto solltest du dir sofort abgewöhnen. Es gibt ein paar Nischen-Anwendung dafür, aber nicht hier

Und so viele Anweisungen in einer Zeile ist auch nicht gut. Eine oder zwei kurze danach sind ok, aber so ist das unübersichtlich. Und eine Anweisung direkt dahinter macht man eigentlich um sich die Klammern zu sparen:
Code: [Select]

if ( a >950 & a <1200 ) { digitalWrite (Landinglight, HIGH); }

Wenn dann so:
Code: [Select]
if ( a >950 & a <1200 ) digitalWrite (Landinglight, HIGH);
Oder:
Code: [Select]

if ( a >950 & a <1200 )
  digitalWrite (Landinglight, HIGH);

noiasca

vereinfacht gesagt:

STRG-T drücken in der IDE, damit man die Einrückungen besser sieht.
kein Delay verwenden.
kein Goto verwenden.

alle int überprüfen ob sie int sein müssen.

Sonst noch Fragen?

Lege deinen Sketch zur Seite, mach eine klare Aufstellung, welche Lampe in welchem Rhytmus blinken soll und wie die Lampen zueinander in Beziehung stehen. Mit Delay und Goto wird das nix.
how to react on postings:
- post helped: provide your final sketch, say thank you & give karma.
- post not understood: Ask as long as you understand the post
- post is off topic (or you think it is): Stay to your topic. Ask again.
- else: Ask again.

MicroBahner

#12
Feb 15, 2020, 05:37 pm Last Edit: Feb 15, 2020, 05:38 pm by MicroBahner
Hallo Fuchs des Himmels ;)

Da hat man dir ja schon so allerhand von deinem Sketch zerrissen ;) . Aber es stimmt schon - so einige grundsätzliche Fehler sollte man von Anfang an vermeiden, damit man sie sich garnicht erst angewöhnt.

Vielleicht kannst Du auch meine MobaTools gebrauchen. Damit ist z.B. das Faden von Leds genauso einfach wie das harte Ein- und Ausschalten. Auch das Vermeiden von delay's geht damit ein wenig einfacher und übersichtlicher als die direkte und 'harte' Tour mit den millis().
Installieren kannst Du die direkt über den Bibliotheksverwalter in der IDE (Strg+Shift+I und dann im Suchfeld mobatools eingeben ).

Auch musst Du dir genauer überlegen, was inn setup(), und was in loop() gehört. Alles was nur zum Start des Sketches einmalig gemacht werden soll/muss gehört ins setup() - z.B. auch das Serial.begin(). Auch die Testroutine für deine Beleuchtung solltesr Du dahin verschieben. Das wird dann bei jedem Start des Sketches einmal gemacht, und dann geht's erst los mit der eigentlichen Funktionalität.
Gruß, Franz-Peter

skyfox60

Yep, da simmer schon beim Thema.

Hab mal was mit millis probiert.
Erwartungsgemäß funktioniert das nicht so, wie ich das gerne hätte.

Anbei das Beispiel:

Die intere LED flasht mit 50 mills, also ein Bltzlicht.

Code kopiert und hochgeladen, und läuft.

Sobald aber daneben andere Dinge laufen, passt das nicht mehr. Die Led geht jetzt ganz lansam, das "daneben" verzögert alles.
Frage??:
Wo ist da der Denkfehler?

Code: [Select]
unsigned long startMillis;  //some global variables available anywhere in the program
unsigned long currentMillis;
const unsigned long period = 50;  //the value is a number of milliseconds

const byte ledPin = 13;    //using the built in LED

void setup()
{
 
  Serial.begin(9600);  //start Serial in case we need to print debugging info
  pinMode(ledPin, OUTPUT);
  startMillis = millis();  //initial start time
}

void loop()
{
  currentMillis = millis();  //get the current "time" (actually the number of milliseconds since the program started)
  if (currentMillis - startMillis >= period)  //test whether the period has elapsed
  {
    digitalWrite(ledPin, !digitalRead(ledPin));  //if so, change the state of the LED.  Uses a neat trick to change the state
    startMillis = currentMillis;  //IMPORTANT to save the start time of the current LED state.
  }

 // Bis hier funktionierte das. Unten stehendes soll einen längeren Programablauf simulieren
 // währed dessen aber das Blitzen oben munter weiter laufen sollte.
 
   for (int a=1; a<200; a++)
  {
    Serial.println ("waiting");
  }
 
}
Der leckerste Fisch ist immer noch der Rumpsteak.

MicroBahner

#14
Feb 15, 2020, 05:56 pm Last Edit: Feb 15, 2020, 06:03 pm by MicroBahner
Deine for-Schleife ist praktisch ein 'delay'. Wenn das mit den millis funktionieren soll, muss der gesamte Ablauf im loop so geschrieben werden, dass nichts blockiert bzw wartet.

Edit: hast Du früher auch mal 'Eisenbahn' gespielt und Züge im Kreis fahren lassen? Für das Vermeiden von delay habe ich mal ein Tutorial geschrieben, wo das mit einer im Kreis fahrenden Lok erklärt wird.
Ansonsten gibt's noch die 'Nachtwächtererklärung'.
Gruß, Franz-Peter

Go Up