I2C-LCD braucht zuviel Zeit.

Guten Morgen die zweite,
ich baue gerade eine Schrittmotorsteuerung und habe hier ein LCD in Betrieb. Das Display wird alle 200ms aktualisiert.
Wenn ich nun den Motor drehen lasse, bekomme ich ca jede Sekunge ein Stocken. ausklammern der Display-Funktion hilft, aber dann wird das Display natürlich nicht angesteuert.
Kann es sein das der I2C-bus so langsam ist?
Ich verwende keine Delays, alles wird über if(currentTime-lastTime>delay){} realisiert.
Hier irgendwelche Tips?

Hallo derHerrKohler
Machen wir einen Tausch: Code von Dir gegen Tips von uns. Du fängst an. :wink: :wink:
Grüße Uwe

uwefed:
Hallo derHerrKohler
Machen wir einen Tausch: Code von Dir gegen Tips von uns. Du fängst an. :wink: :wink:
Grüße Uwe

Nice!

Hab witzigerweise ein ähnliches Problem gerade heute im mikrocontroller.net Forum entdeckt. Da wurde festgestellt, dass die Displaysteuerung per I2C zu aufwendig (und deswegen langsam) für den kleinen Kerl ist :wink:

Lösung: einen Prozessor für die Schrittmotoren, ein Prozessor für die Displaysteuerung - und die beiden per I2C quatschen lassen.

Hm das wäre richtig doof.
Ich poste hier mal meinen Code, vielleicht kann man's ja doch noch retten :wink:

#include <Wire.h>
#include <LiquidCrystal_I2C.h> 
LiquidCrystal_I2C lcd(0x27,16,2);

void setup() {
  // die Pinbelegung habe ich hier raus genommen ...

}

void loop() {
  ct = micros();   // current Time
  if (mode!=0)    // if the stepper is active
  {
    runStepper();  // call the routine to drive
  }  
  anzeige();
}

void runStepper(){
  if (ct - lastSTEP > stepperSpeed){  // stepperSpeed kommt vom POTI
    digitalWrite(step_pin,HIGH);      // make a step
    delayMicroseconds(stepperSpeed);  // wait for some time
    digitalWrite(step_pin,LOW);      // end of the step
    lastSTEP = ct;              
  }

}


void anzeige(){   
  if (ct - lastRESET > 200000){ // currentTime - lastResetOfLCD > DELAY 

    switch (LCDmode){ 
    case 0:
      slideLCD();  
      break;
    case 3:
      a = "Position:";
      b = stepperPosition;
      c = "Time:";
      d = "mm/s";
      break;
    case 4:
      a = "Position:";
      b = stepperPosition;
      c = "T:";
      d = "0:00:00";
      break;
    }  

    if (a!=lastA || b!=lastB || c!=lastC || d!=lastD){
      lcd.clear();
    } 

    lcd.setCursor(0, 0);
    lcd.print(a);
    int posB = 16 - b.length();
    lcd.setCursor(posB, 0);  
    lcd.print(b);
    lcd.setCursor(0, 1);  
    lcd.print(c);
    int posD = 16 - d.length();
    lcd.setCursor(posD, 1);  
    lcd.print(d);
    lastA = a;
    lastB = b;
    lastC = c;
    lastD = d;  
    lastRESET = ct;
  }
}

Der Code ist hier stark verkürzt, nicht an den fehlenden Variablenzuweisungen stören bitte... ich dachte mir: Mach mal nur die wichtigen Sachen rein!

also am Code fällt mir jetzt nichts spezielles auf. Vielleicht holst du noch etwas geschwindigkeit heraus, wenn du das, was angezeigt werden soll in einen String schreibst und ihn über einen einzelnen "print" ausgibst... aber sonst sehe ich da wenig Potential. Was passiert, wenn du das delay (die 200ms) raufsetzt? Immer noch jede sekunde ein stocken oder länger / kürzer?

edit:
Ich seh gerade, du clearst jedesmal das komplette Display, wenn sich etwas ändert. Da könnte man evtl auch noch ansetzen, indem man nur die zu ändernden Positionen anfährt...

Beim erhöhen des Delays taucht das Problem in längeren anständen auf.
gibt es eine schöne Möglichkeit, Strings so zu verketten um nur 2 Prints (je Zeile einen) zu verwenden?
Mir fällt da gerade kein weg ein.

String1 + String 2 :slight_smile:

sprich :

string a = "hallo Welt ";
string b = " dies ";
string c = " ist ein Test."
double d = 27 /4.5;

print (a + b + c + d);

Ausgabe:
"Hallo Welt dies ist ein Test.6";

EDIT:
für die Rechtsausrichtung kannst du die posLänge als schleife in den String Leerzeichen machen;
string leer = "";
for (int i =0; i<posX;i++) leer+= " ";

Nochmal EDIT:
Du kannst es mit Autolinebreak auch in eine Zeile machen, da dank der eingefügten Leerzeichen eh kein platz mehr in der Zeile ist. Dann brauchst du nur einmal print();.

Danke Marcus,

das ist ein toller Ansatz!
Wie kann ich den Autolinebreak aktivieren?
Mein Display macht das nicht...

hmm... keine ahnung. normalerweise macht er das automatisch, allerdings nur wenn ich nur eine Zeile schreibe, wenn ich allerdings den Cursor händisch veränder, setzt er mir den fehlenden Text unter den Cursor.

Hi Marcus,
bei mir schreibt das Display alles in eine Zeile.
Aber das macht nichts, denn ich habe meinen Code jetzt einfach soweit verändert, das während der Fahrt nichts mehr verändert wird.
Außerdem habe ich die Zeilen zusammengefügt und habe nun nur noch 2 Printbefehle und somit auch kein LCD.clear() mehr. Fühlt sich so auch besser an, irgendwie...
Danke für deinen Wegweiser!

Ja... bei mir momentan irgentwie auch. Ich glaub bei ner alten Version der IDE war ne andere Version der Lib dabei - die hatte den Zeilenumbruch noch :frowning:

Aber ich würde an deiner stelle nicht komplett auf refresh verzichten während der Bewegung - sieht doch besser aus, wenn da Action auf dem Display ist - ich glaube dein Stocken rührte von dem clearen her. Versuch mal die ganze Geschichte mit 2 prints, ohne clear und alle 200ms. Ich glaube das sollte hinhauen...

Habe ich ausprobiert, funktioniert leider nicht.
Sobald ich das Display wärend der Fahrt aktiviere, ist das stocken da - selbst ohne LCD.clear().
Die Abstände zwischen dem Stocken kann ich dafür bequem über mein delay einstellen...

:smiley: