OLED Display ist zu langsam (Anfänger)

Hi, ich lerne gerade Arduino und will ein Sonar Bauen das die Entfernung auf einem OLED Display Anzeigt. Aber wenn die Zahlen sich ändern geht das viel zu langsam und es kommen Pixelfehler aber ich verstehe nicht warum könnte mir bitte irgendjemand helfen.
Ich weiß es ist wahrscheinlich nicht der beste Code aber ich lerne ja noch:)
In den Internationalen Chanel antwortet mir keiner deswegen hoffe ich jemand kann mir hier weiterhelfen bin echt am verzweifeln verstehe einfach nicht warum es nicht funktioniert bitte hilft mir jemand.

#include "U8g2lib.h"
#define Echopin 13
#define Trigpin 12
#define SERVOPIN 10
#include "Servo.h"
#include "HCSR04.h"
#define Buzzer 9

// 1,3 Zoll SH1106
 U8G2_SH1106_128X64_NONAME_F_HW_I2C oled(U8G2_R0);
UltraSonicDistanceSensor Abstandssensor (Trigpin,Echopin);


Servo Servomotor;
byte Servowinkel = 0;
int Serv = 0;
unsigned long previousMillis = 0;//für den Timer
const long intervall = 30;//für den Timer

void setup() 
{
  oled.setBusClock(100000);
  oled.begin();
  oled.clearBuffer();
  Serial.begin(9600);
  Servomotor.attach(SERVOPIN);
  pinMode(Buzzer,OUTPUT);
  digitalWrite(Buzzer,0);
  Servomotor.write (0);
}

void loop() 
{
 
 
  //Zeichnen der Benutzeroberfläche OLED:

  oled.setDrawColor(1);// Farbe weiß
  
   
  oled.firstPage();
  do 
  {
  
   oled.drawRFrame(0, 0, 128, 64, 3); //Rahmen
   oled.setFont(u8g2_font_helvB12_tf); //12 px
   oled.drawStr(2,15,"Sonar:");
   oled.drawLine(3,18,51,18); //Unterschrift von "Sonar"

   //Radar:
   oled.drawCircle(65,62, 34, U8G2_DRAW_UPPER_RIGHT);//Großer Kreis Rechts
   oled.drawCircle(63,62,34,U8G2_DRAW_UPPER_LEFT); //Großer Kreis Links

   oled.drawCircle(65,62, 24, U8G2_DRAW_UPPER_RIGHT); //Mittlerer Kreis Rechts
   oled.drawCircle(63,62,24,U8G2_DRAW_UPPER_LEFT);//Mittlerer Kreis Links

    oled.drawCircle(65,62, 14, U8G2_DRAW_UPPER_RIGHT);//Kleiner Kreis Rechts
   oled.drawCircle(63,62,14,U8G2_DRAW_UPPER_LEFT);//Kleiner Kreis Rechts

   oled.drawLine(64,62,64,25);//Mittlere Linie
   oled.drawLine(64,62,36,36);//Linke Linie
   oled.drawLine(64,62,92,36);//Rechte Linie

   oled.drawFrame(79,3,46,15);//Rechteck cm anzeige
   
   //damit cm immer direkt eine Freizeile hinter der entfernung steht 
  unsigned long currentMillis = millis();
  if((currentMillis-previousMillis)>= intervall){//delay
  previousMillis = currentMillis;
   int Abstand = Abstandssensor.measureDistanceCm();
   oled.setFont(u8g2_font_ncenB08_tr);
   if(Abstand<=99){
   if(Abstand<10){
   oled.drawStr(88,14,"cm");
   }
   else{
   oled.drawStr(94,14,"cm");
   }
   }
   else{
   oled.drawStr(82,14,"no");
   }
  }
  // x Koordinaten Radar OLED Display Start: 31 Ende: 99
  // y Koordinaten Radar OLED Display Start: 25 Ende: 62

  for(int Serv= 0; Serv<= 165;Serv++) // Servomotor geht nur dreht nur bis 165 alles danach ist quasi wie delay
{
Servomotor.write(Serv);
delay(10);
unsigned long currentMillis = millis();
if((currentMillis-previousMillis)>= intervall){//delay
previousMillis = currentMillis;
int Abstand = Abstandssensor.measureDistanceCm();
if(Abstand<30){
oled.setCursor(82,14);
oled.setFont(u8g2_font_ncenB08_tr);
oled.print(Abstand);
Serial.print(Abstand);
Serial.println();
}
}
}


for(int Serv=165; Serv>0;Serv--) //for schleife wird solange ausgeführt bis sie false ist dann geht es erst weiter
{
Servomotor.write(Serv);
delay(10);
unsigned long currentMillis = millis();
if((currentMillis-previousMillis)>= intervall){//delay
previousMillis = currentMillis;
int Abstand = Abstandssensor.measureDistanceCm();
if(Abstand<30){
oled.setCursor(82,14);
oled.setFont(u8g2_font_ncenB08_tr);
oled.print(Abstand);
Serial.print(Abstand);
Serial.println();
}
}
}


   
    
  


  
  }
  while (oled.nextPage());
  
}

Das bremst schon mal.

Welche Pixelfehler? Wo? Kannst Du mal ein Foto machen?
Kann es eventuell sein das da Teile einer vorherigen Ausgabe noch sichtbar sind?

Gruß, Jürgen

In der ersten Zeile steht das "_F_" für full page, was nicht zur zweiten Zeile - seitenweise - paßt.

Für seitenweise paßt U8G2_SH1106_128X64_NONAME_1_HW_I2C.

Schau mal in die Beispiele, da siehst Du das :slightly_smiling_face:

Es sind keine Pixelfehler, es sind die ineinander geschachtelten schleifen, ich würde empfehlen, sich erstmal mit der grundlegenden Funktionsweise vertraut zu machen und sich dann mit einer statemachine auseinander zu setzen. Der Ablauf sollte so sein:
in setup() :

  1. Servo auf erste position setzen

in loop():

  1. Abstand einlesen
  2. display-Ausgabe
  3. Servo auf nächste Position setzen

Dabei muss halt Berücksichtigt werden, in welche Richtung der Servo sich gerade bewegt und wo die Umkehrpunkt der Richtung sind.

Was ich so garnicht verstehe ist die verwendung von firstPage() und nextPage() in Schleife, sehe ich jetzt schon zum zweiten Mal, hab ich bei meinen OLED nicht gebraucht, einfach die Mal-Funktionen aufgerufen und dann einmal an das display gesendet....

Das ist eine pfiffige Lösung von Oli Kraus, um Speicher zu sparen. In RAM schwache AVRs können so den Displayinhalt zwischenspeichern.

Da nicht angegeben ist, welcher Arduino verwendet wird, kann ich leider keinen Rat geben. Reicht der Speicher, ist fullpage schneller :slightly_smiling_face:

Ah, ok, hab ich auch noch was dazu gelernt :wink:
Ich hab die OLED's an ESP8266 D1 Mini hängen, wo ich aber nur gerade die Temperatur und Verbindungsstatus anzeige, also nur ein paar ASCII-Zeichen. Aber das ist jetzt nebensache, hilft dem TO erstmal nicht viel. Er müsste zumindest mal die forschleifen aus der while-schleife extrahieren, so lässt sich schwer sagen, was das display denn letztendlich wann wie anzeigt.

Genügend Speicher für fullpage :grinning:

puh, da hab ich ja nochmal schwein gehabt... :joy:

Ja, genau da sind noch Teile von der vorherigen Zahl da

Ich habe einen Arduino UNO R3

Ich weiß das hört sich evtl dumm an aber ich verstehe nicht ganz wo sind die forschleifen in einer whileschleife

Naja also theoretisch hab ich ja auch diesen Ablauf zuerst in setup() lass ich den Servo auf 0 fahren dann in loop() fährt er zwischen 0 und 165 hin und her während dessen will ich dass der Sensor den Abstand misst was er auch macht dann sollte eigentlich das Display den abstand anzeigen und danach soll der Servo 1++ in die nächste Position fahren dass funktioniert ja eigentlich alles auch einwandfrei bloß verstehe ich nicht warum genau diese anzeige nicht funktioniert vielen dank euch beiden schonmal ihr seid mir eine große Hilfe :slight_smile:

ich schicke gleich mal ein bild rein


das kommt wenn die zahlen wechseln und ist dann da für so 3 sek und danach kommt erst die andere zahl

oh ok hab das gemacht weil so läuft das Display flüssiger

Also ich hab den code jetzt nochmal überarbeitet des läuft zwar alles also Zahlen werden jetzt angezeigt aber die Zahlen ändern sich immer noch zu langsam

#include "U8g2lib.h"
#include "Servo.h"
#include "HCSR04.h"

#define Echopin 13
#define Trigpin 12
#define SERVOPIN 10

// 1,3 Zoll SH1106
U8G2_SH1106_128X64_NONAME_1_HW_I2C oled(U8G2_R0);
UltraSonicDistanceSensor Abstandssensor(Trigpin, Echopin);


Servo Servomotor;
int Serv = 0;

void setup() {
  oled.setBusClock(400000);
  oled.begin();
  oled.clearBuffer();
  Serial.begin(9600);
  Servomotor.attach(SERVOPIN);
  Servomotor.write(0);
}

void loop() {


  //Zeichnen der Benutzeroberfläche OLED:

  oled.setDrawColor(1);  // Farbe weiß


  oled.firstPage();
  do {

    oled.drawRFrame(0, 0, 128, 64, 3);   //Rahmen
    oled.setFont(u8g2_font_helvB12_tf);  //12 px
    oled.drawStr(2, 15, "Sonar:");
    oled.drawLine(3, 18, 51, 18);  //Unterschrift von "Sonar"

    //Radar:
    oled.drawCircle(65, 62, 34, U8G2_DRAW_UPPER_RIGHT);  //Großer Kreis Rechts
    oled.drawCircle(63, 62, 34, U8G2_DRAW_UPPER_LEFT);   //Großer Kreis Links

    oled.drawCircle(65, 62, 24, U8G2_DRAW_UPPER_RIGHT);  //Mittlerer Kreis Rechts
    oled.drawCircle(63, 62, 24, U8G2_DRAW_UPPER_LEFT);   //Mittlerer Kreis Links

    oled.drawCircle(65, 62, 14, U8G2_DRAW_UPPER_RIGHT);  //Kleiner Kreis Rechts
    oled.drawCircle(63, 62, 14, U8G2_DRAW_UPPER_LEFT);   //Kleiner Kreis Rechts

    oled.drawLine(64, 62, 64, 25);  //Mittlere Linie
    oled.drawLine(64, 62, 36, 36);  //Linke Linie
    oled.drawLine(64, 62, 92, 36);  //Rechte Linie

    oled.drawFrame(79, 3, 46, 15);  //Rechteck cm anzeige




    // x Koordinaten Radar OLED Display Start: 31 Ende: 99
    // y Koordinaten Radar OLED Display Start: 25 Ende: 62

    for (int Serv = 0; Serv <= 165; Serv++)  // Servomotor geht nur dreht nur bis 165 alles danach ist quasi wie delay
    {
      Servomotor.write(Serv);
      delay(10);
      int Abstand = Abstandssensor.measureDistanceCm();
      if (Abstand < 30) {
        oled.setFont(u8g2_font_ncenB08_tr);
        if (Abstand <= 99) {
          if (Abstand < 10) {
            oled.drawStr(88, 14, "cm");  //damit cm immer direkt eine Freizeile hinter der entfernung steht
          } else {
            oled.drawStr(94, 14, "cm");
          }
        } else {
          oled.drawStr(82, 14, "no");
        }

        oled.setCursor(82, 14);

        oled.print(Abstand);
        Serial.print(Abstand);
        Serial.println();
      }
    }


    for (int Serv = 165; Serv > 0; Serv--)  //for schleife wird solange ausgeführt bis sie false ist dann geht es erst weiter
    {
      Servomotor.write(Serv);
      delay(10);
      int Abstand = Abstandssensor.measureDistanceCm();
      oled.setFont(u8g2_font_ncenB08_tr);
      if (Abstand < 30) {
        if (Abstand <= 99) {
          if (Abstand < 10) {
            oled.drawStr(88, 14, "cm");  //damit cm immer direkt eine Freizeile hinter der entfernung steht
          } else {
            oled.drawStr(94, 14, "cm");
          }
        } else {
          oled.drawStr(82, 14, "no");
        }

        oled.setCursor(82, 14);

        oled.print(Abstand);
        Serial.print(Abstand);
        Serial.println();
      }
    }







  }

  while (oled.nextPage());
}

Ich glaube ich verstehe solangsam meinen fehler den der Befehl dass die Zahlen geschrieben werden sollen wir erst nach der while schleife ausgeführt also aktuallisiert der bildschirm erst ganz am ende.
könnte das sein ?

Da sollte man jetzt nochmal jemand haben wo sich mit den Ausgabe auf Displays auskennt.
Ich habe da irgendwann vor rund 3 Jahren mal was gemacht...
Mit Servos und mit Ultraschallsensor noch nie etwas. :slight_smile:

Was mir aber so auffällt ist z.B.:

Sind bei 166 Wiederholungen schon 1,66 Sekunden

Du setzt in der for Schleife 166 mal die Schriftart neu. Das dauert bestimmt auch.

Du gibst laufend die Werte bei 9600 Baud aus. Die darfst Du gerne erhöhen, bringt dann auch was. Aber natürlich im Sketch und in der IDE, sonst hagelt es seltsame Zeichen im Monitor!

Ob das zusammenfassen oder verketten von Variablen was bringt, ob das überhaupt funktioniert / möglich ist bei der Bibliothek, weiß ich nicht. Ich kann es nicht testen.
Also z.B. statt

dann so:

oled.drawStr(82, 14, Abstand);

Oder statt zuerst "cm" an eine bestimmte Position zu schreiben und dabei noch nach Länge der Zahl zu unterscheiden einfach

oled.drawStr(82, 14, Abstand + " cm");

Wie gesagt, ich kann es nicht testen und habe auch keine hnung ob die Bibliothek die Verkettung mitmacht.

Gruß, Jürgen

Schau mal, ich habe die ganzen Ausgaben mal weg gelassen, damit du die Schleifen besser erkennen kannst.

void loop() {



  oled.firstPage();
  do {


    for (int Serv = 0; Serv <= 165; Serv++)  // Servomotor geht nur dreht nur bis 165 alles danach ist quasi wie delay
    {
    }


    for (int Serv = 165; Serv > 0; Serv--)  //for schleife wird solange ausgeführt bis sie false ist dann geht es erst weiter
    {
    }

  }

  while (oled.nextPage());
}

du hast für die Anzeige eine do...while Schleife, in dieser Schleife hast du zwei for-Schleifen, bei der ersten fährst du den Servo von 0 bis 165 und in der zweiten von 165 nach 0, demzufolge läuft der Servo einmal komplett von rechts nach links und wieder zurück, bevor dann letztendlich der screen vollständig geschrieben wurde. Und du musst beachten, dass loop() ja selber eine schleife ist, sonst wäre dein Programm ja nach einem Durchlauf zu ende.

Versuch mal, dein Programm wie folgt zu gliedern, dann fallen die beiden for-schleifen schon mal weg

int position = 0;
int schritt = 1;

void setup()
{
	//bringe Servo in definierte Ausgangsstellung 'position'
}

void loop()
{
	//lese Abstand vom Sensor
	
	//Gib den Abstand auf dem OLED aus
	
	if(position + schritt > 165)
		schritt = -1;
    else if(position + schritt < 0)
		schritt = 1;
		
	position = position + schritt;
	
	//bringe Servo in Stellung 'position'
}

Ah ok vielen dank der Tipp mit den cm ist echt gut wäre ich nie drauf gekommen das mit dem print befehl muss tatsächlich so gemacht werden da mit drawStr nur Wörter geschrieben werden können so wie ich das jetzt verstanden hab vielen dank für deine Hilfe falls ich falsch liege korigiert mich gern