Laufschrift mit millis()

Ich probiere einen für das Display zu lange Text in Laufschift auszugeben, wenn eine Taste gedrückt wurde. Dies funktioniert einwandfrei, wenn ich es mit delay realisiere, jedoch nicht, wenn ich es mit millis() probiere.

Wenn die Taste lang gedrückt wird, erscheinen permanent o's, welche in Laufschift in der ersten Zeile ausgegeben werden. Wenn die Taste nur kurz gedrückt wird, erscheint für 1s der Text, wenn die Taste wieder kurz gedrückt wird, erscheint für 1s ein anderer Teil des Textes.
Das bedeutet, dass es prinzipiell passt, nur wird der eigentliche Text nur bei kurzem Tastendrücken richtig ausgegeben, jedoch nicht bei langem.

Hier der Code:

#include <LiquidCrystal.h> 

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

const int anzahlZeilen = 2;
const int anzahlSpalten = 16;
const char* Nachricht = "Beispiel Nachricht, die absichtlich zu lang ist.";
const int nachrichtenLaenge = 48;

long OnTime = 200;      // Millisekunden bis Display ON              
long OffTime = 1000;    // Millisekunden bis Display OFF
unsigned long previousMillis = 0;
int button = LOW;

void setup() 
{
  lcd.clear();
  pinMode(6, INPUT);
  Serial.begin(9600);
  lcd.begin(anzahlSpalten, anzahlZeilen);
}

void loop() 
{
  static int nPosition = 0;
  int i;
  unsigned long currentMillis = millis();
  button = digitalRead(6);

  if((button == HIGH) && (currentMillis - previousMillis >= OnTime))
  {
    if(nPosition < (nachrichtenLaenge - anzahlSpalten))
    {
      for(i = 0; i < anzahlSpalten; i++)
      {
        lcd.setCursor(i, 0);
        lcd.print(Nachricht[nPosition + i]);
      }
    }
    else
    {
      int nChars = nachrichtenLaenge - nPosition;
    
      for(i = 0; i < nChars; i++)
      {
        lcd.setCursor(i, 0);
        lcd.print(Nachricht[nPosition + i]);
      }

      for(i = 0; i < (anzahlSpalten - nChars); i++)
      {
        lcd.setCursor(nChars + i, 0);
        lcd.print(Nachricht[i]);
      }
    }

    nPosition++;
    if(nPosition >= nachrichtenLaenge)
    {
      nPosition = 0;
    }
  }
  else if((button == LOW) && (currentMillis - previousMillis >= OffTime))
  {
    previousMillis = currentMillis;     
    lcd.clear();                        
  }
}

Okay, ich weiß woran es liegt, die Buchstaben werden zu schnell ausgegeben und wieder in ihrer Position geändert. Das bedeutet, dass ich ein delay einbauen muss, ohne dass ich delay() verwende :o

Das bedeutet, dass ich ein delay einbauen muss, ohne dass ich delay() verwende

Hihihi...

Einen endlichen Automaten!
Mit zeitgesteuerten Übergängen.

....
Ja, ich glaube, das möchtest du bauen ....
:wink:

Richtig, wobei ich unsicher bin, wie mir das genau weiter hilft ^^

An für sich könnte ich auch eine variable runterzählen lassen, wobei das wohl auf das Selbe wie bei der Verwendung von delay() führen würde.

Ich will mit meinem restlichen Code nicht von delay() eingeschränkt werden.

Ignoty:
Ich will mit meinem restlichen Code nicht von delay() eingeschränkt werden.

Guter Vorsatz!

combie:
Hihihi...
...
Ja, ich glaube, das möchtest du bauen ....

Bis Weihnachten, wenn's recht ist!

Gruß

Gregor

Bis Weihnachten ...

Das kann doch klappen! Oder?
Muss man nur eben den Blickwinkel ändern.

Ist das normal hier, dass keiner überhaupt probiert zu helfen?

Ich komm mit einem konkreten Code, mit einer genauen Beschreibung was ich erreichen will und was das Problem darstellt.

Und trotzdem kam nicht eine hilfreiche Antwort, im Gegenteil, es wird sich noch darüber lustig gemacht.

Ignoty:
Ist das normal hier, dass keiner überhaupt probiert zu helfen?

Ich komm mit einem konkreten Code, mit einer genauen Beschreibung was ich erreichen will und was das Problem darstellt.

Und trotzdem kam nicht eine hilfreiche Antwort, im Gegenteil, es wird sich noch darüber lustig gemacht.

Das sehe ich aber anders, der Tip mit dem endlichen Automaten war doch da, und
darüber findes du im Forum genug.

Deine einzige konkrete Frage war doch wie du wartest ohne deinen Code zu blockieren und das
ist die Antwort.

Ulli

beeblebrox:
Deine einzige konkrete Frage war doch wie du wartest ohne deinen Code zu blockieren und das
ist die Antwort.

Das liest sich so jedoch nicht aus seinem Satzbau heraus. Wäre es beispielsweise wie folgt formuliert "Informier dich mal über endliche Autmaten mit zeitgesteuerten Übergängen", wäre es sofort ersichtlich gewesen.

Mindestens weiß ich jetzt in welcher Richtung ich mich bewegen muss, danke beeblebrox.

Du bist ja schon ein paar Wochen hier im Forum unterwegs, und es ist auch nicht dein allererster Beitrag. Dann solltest du eigentlich schon mitbekommen haben, das manchmal viel Ironie und Witz in den Beiträgen ist. Neben dem fachlichen Niveau hier ist das etwas, was mir und offensichtlich vielen anderen gut gefällt.
Ich muss allerdings zugeben, dass man gewisse Dinge erst nach einer gewissen Zeit versteht, wie. z.B. die Anspielungen beim "endlichen Automaten".

Versteh mich nicht falsch, ich hab absolut nichts gegen Ironie und Witz bei Beiträgen, jedoch sollte auch versucht werden dem Threadersteller geholfen zu werden. Ansonsten wirkt dies sehr frustrierend.

Es tut mir leid, wenn meine Antwort dir nicht unmittelbar geholfen hat. Bei deiner Frage, und vor allen Dingen, bei dem nachgeschobenen Beitrag, hatte ich den Eindruck, dass dir ein Denkanstoß weiter helfen könnte. Denn Wille und der analytische Ansatz ist klar für mich zu erkennen.

Offensichtlich hast du meine Antwort bewertet, und für nicht hilfreich eingestuft.
Darum stellt sich mir die Frage: Ist die Antwort falsch, oder die Bewertungsregel?
Wer weiß... vielleicht von beidem was....

OK, dann versuche ich mal klarer und ernsthafter zu antworten, auch wenn es dann vielleicht grob klingt, es ist nicht so gemeint.

Du hast erkannt, dass delay() für deine Anwendung schädlich ist. Dem stimme ich mal zu!
Du hast erkannt, dass das einfache ersetzen von delay() durch eine Schleife, nix bringt.
Auch ja!

Wie mir scheint, denkst du in sequenziellen Abläufen. So hast du dein Programm geschrieben. Im Grunde richtig, denn der Prozessor arbeitet sequenziell. Aber das hilft an dieser Stelle nicht weiter, denn die Delay() Blockaden stören andere Programmteile.
Es ist also deine ureigenste Aufgabe dein Denken zu modifizieren.
Denke in nebenläufigen Prozessen.
Schreibe nebenläufige Prozesse, welche sich nicht in die Quere kommen.

Eins der möglichen Stichworte ist: Kooperatives Mutitasking.
Da braucht man keine Lib für, das geht mit ganz einfachen Mitteln.

Hier mal ein Beispiel aus meiner Wühlkiste.
Es ist nicht das, was du möchtest, aber es zeigt, einen endlichen Automaten mit Übergängen auf Tastendruck und per Zeitsteuerung.
Du könntest in loop() dutzende von solchen Automaten unterbringen, und keiner würde den anderen blockieren.

/*

Aufgabe:
Hi
Ich möchte eine kleine LED über einen 
digitalen Input dimmen. Die LED soll, auch wenn nur ganz kurz ein 
High Signal am digitalen Input liegt, vollständig hochdimmen und 
beim hellsten Zustand bleiben. Dann soll die LED nach einer 
einstellbaren Zeit wieder runterdimmen und aus bleiben, bis 
wieder ein kurzes High-Signal kommt.

*/


//   Lösung:


// Diese Variablen werden vom Compiler weg optimiert, fressen also kein Ram
const unsigned int dimpin     = 3;     // pwmpin -- R -- LED -- GROUND
const unsigned int tasterpin  = 4 ;    // Pin -- Taster -- GROUND
const unsigned int dimSpeed   = 50;    // mS pro dimschritt 
const unsigned long warteZeit = 5000;  // mS zwischen up und down

class Automat {
                protected:
                    enum  AutomatenStatus {A_Taster,A_DimUp,A_Warte,A_DimDown} status ;
                    unsigned long lastHit;
                    byte dim;
                    byte pwmpin;
                    byte taster;
                 public: 
                    Automat(byte dimpin, byte tasterpin); // Konstruktor
                    void handle();
                } ; 
                



Automat FSM(dimpin, tasterpin);

void setup() 
{
}

void loop() 
{
   FSM.handle();
}  



// **********************************



Automat::Automat(byte dimpin, byte tasterpin) // Konstruktor
{
  pwmpin  = dimpin;
  taster  = tasterpin;
  lastHit = millis();
  dim     = 0;
  status  = A_Taster;
  analogWrite(pwmpin,dim);
  pinMode(tasterpin,INPUT_PULLUP);
}


void Automat::handle() 
{
  switch(status)
  {
    case A_Taster: if(!digitalRead(taster)) // low = taster gedrückt
                   {
                     status = A_DimUp; // Schritt weiter setzen
                     lastHit = millis();
                   }
                   break;
  
    case A_DimUp:  if(millis() - lastHit > dimSpeed)  
                   {
                     lastHit = millis();
                     dim++;
                     analogWrite(pwmpin, dim);
                     if(255 == dim) status = A_Warte; // Schritt weiter setzen
                    }
                   
                   break;
 
    case A_Warte:  if(millis() - lastHit > warteZeit) 
                   {
                     lastHit = millis(); 
                     status = A_DimDown; // Schritt weiter setzen
                   }
                   break;
  
    case A_DimDown: if(millis() - lastHit > dimSpeed) 
                    {
                      lastHit = millis();
                      dim--;
                      analogWrite(pwmpin,dim);
                      if(0 == dim) status = A_Taster; // Wieder auf start setzen
                    }
                   break;
   }
}

Ignoty:
Ist das normal hier, dass keiner überhaupt probiert zu helfen?
...
Und trotzdem kam nicht eine hilfreiche Antwort, im Gegenteil, es wird sich noch darüber lustig gemacht.

Du hast doch im zweiten Beitrag geschrieben, dass Du das Problem gelöst hast. Stimmte das etwa nicht?!

Gruß

Gregor

PS: HURRAAA! WOCHENENDE!

gregorss:
Du hast doch im zweiten Beitrag geschrieben, dass Du das Problem gelöst hast.

Hmm...
Klarer erkannt... (so habe ich es verstanden)
Das meinte ich auch mit analytisch denken.

Ignoty:
.. jedoch sollte auch versucht werden dem Threadersteller geholfen zu werden.

Ich versuche es mal mit einem Link zu meinem Beitrag "Anleitung Ein Endlicher Automat entsteht". Bitte beachte auch die Links und frage, wenn Du Erläuterungen haben möchtest.

agmue:
Ich versuche es mal mit einem Link zu meinem Beitrag ...

Ich habe den Anfang dieses Threads mal überflogen. Die Wenigsten wissen, dass es ganz schön schwierig ist, sowas zu schreiben. Da mich das Thema „Endliche Automaten“ interessiert, werde ich bei Gelegenheit versuchen das mal richtig nachzuvollziehen.

Gruß

Gregor

gregorss:
... werde ich bei Gelegenheit versuchen das mal richtig nachzuvollziehen.

So wie ich Dich einschätze, bist Du ein guter Kandidat für Verbesserungsvorschläge. Auch wenn ich kein Kompendium schreiben möchte, bin ich dafür offen!