Hilfe Mit Animation bei Oled Display Start U8G2

Guten Tag,
bin der Manuel und Arduino Neuling, bin gerade an meinem ersten großen Projekt drann und würde eure hilfe benötigen.

Ich habe einen 1,5" OLED Display angeschlossen an einem Arduino Nano Board,
wo ich 3x NTC Sensoren, 1x Typ K Sensor und 1x einen 10 Bar Sensor laufen habe.

Das funktioniert alles so weit,

Beim Starten des Displays würde ich gerne eine Animation Abspielen und danach soll er wieder in das Hauptprogramm springen mit den Sensoren.

Ich habe es bis jetzt Nur Mit einem einzigen Bild zum Laufen gebracht und nicht mit einer Animation.

Ich benutze zum Betreiben des Displays die U8g2 Bibliothek.
vlt könnte mir jemand weiter Helfen. Danke

#include <Arduino.h>
#include <SPI.h>
#include <U8g2lib.h>
#include "max6675.h"
#include "Volvo_bild.h"

U8G2_SH1107_128X128_2_HW_I2C u8g2(U8G2_R0);

int thermoDO = 4;
int thermoCS = 5;
int thermoCLK = 6;
MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO);


#define coolantsensorDivider 10000   //defines the resistor value that is in series in the voltage divider
#define coolantsensorPin1 A0
#define coolantsensorPin2 A1         //defines the analog pin of the input voltage from the voltage divider
#define coolantsensorPin3 A2
#define NUMSAMPLES 5                //defines the number of samples to be taken for a smooth average


const float steinconstA1 = 0.00132775349985195;                 //steinhart equation constant A, determined from wikipedia equations
const float steinconstB1 = 0.000253553759466436;               //steinhart equation constant B, determined from wikipedia equations
const float steinconstC1 = 0.000000201514685565505;    //   //steinhart equation constant C, determined from wikipedia equations

const float steinconstA2 = 0.00132775349985195;                 //steinhart equation constant A, determined from wikipedia equations
const float steinconstB2 = 0.000253553759466436;               //steinhart equation constant B, determined from wikipedia equations
const float steinconstC2 = 0.000000201514685565505;

const float steinconstA3 = 0.00113023607410303000000;                 //steinhart equation constant A, determined from wikipedia equations
const float steinconstB3 = 0.00025359817622849800000;               //steinhart equation constant B, determined from wikipedia equations
const float steinconstC3 = 0.00000007377513607871290;


int samples1[NUMSAMPLES]; 
int samples2[NUMSAMPLES];                             //variable to store number of samples to be taken
int samples3[NUMSAMPLES]; 


const int sensorPin = A3;
const float alpha = 0.78; // Low Pass Filter alpha (0 - 1 )
const float aRef = 4.9; // analog reference
float filteredVal = 103; // midway starting point
float sensorVal;
float voltage;
float psiVal;
const int pressureZero = 102.4; //analog reading of pressure transducer at 0psi
const int pressureMax = 921.6; //analog reading of pressure transducer at 100psi
const int pressuretransducermaxBAR = 10.34 ; //psi value of transducer being used

float pressureValue = 0; //variable to store the value coming from the pressure transducer



void setup() {
  Serial.begin(9600); 
  u8g2.begin();
  u8g2.setContrast(400);                              
u8g2.firstPage();
    do {
    
u8g2.drawXBMP( 0, 28, 128, 71, epd_bitmap_vectordesign2);
delay(10);

    } while ( u8g2.nextPage() );
    
    delay(3000);

}
void loop() {

  uint8_t i;                                          //integer for loop
  float average1; 
  float average2;                                    //decimal for average
  float average3;


  for (i=0; i<NUMSAMPLES; i++) {                      
    samples1[i] = analogRead(coolantsensorPin1);        //takes samples at number defined with a short delay between samples
    delay(10);
  }

for (i=0; i<NUMSAMPLES; i++) {                      
    samples2[i] = analogRead(coolantsensorPin2);        //takes samples at number defined with a short delay between samples
    delay(10);
  }

for (i=0; i<NUMSAMPLES; i++) {                      
    samples3[i] = analogRead(coolantsensorPin3);        //takes samples at number defined with a short delay between samples
    delay(10);
  }

  average1 = 0;
  for (i=0; i< NUMSAMPLES; i++) {
    average1 += samples1[i];                            //adds all number of samples together
  }
  average1 /= NUMSAMPLES;  
  
   average2 = 0;
  for (i=0; i< NUMSAMPLES; i++) {
    average2 += samples2[i];                            //adds all number of samples together
  }
  average2 /= NUMSAMPLES;                            //divides by number of samples to output the average

  average3 = 0;
  for (i=0; i< NUMSAMPLES; i++) {
    average3 += samples3[i];                            //adds all number of samples together
  }
  average3 /= NUMSAMPLES;  


  //Serial.print("Average Analog Coolant Reading1 = ");
  //Serial.println(average1);                                        //analog value at analog pin into arduino
  average1 = (coolantsensorDivider*average1)/(1023-average1);        //conversion equation to read resistance from voltage divider
  //Serial.print("Coolant Sensor Resistance1 = ");
  //Serial.println(average1);

   //Serial.print("Average Analog Coolant Reading2 = ");
  //Serial.println(average2);                                        //analog value at analog pin into arduino
  average2 = (coolantsensorDivider*average2)/(1023-average2);        //conversion equation to read resistance from voltage divider
  //Serial.print("Coolant Sensor Resistance2 = ");
  //Serial.println(average2);

  //Serial.print("Average Analog Coolant Reading3 = ");
  //Serial.println(average3);                                        //analog value at analog pin into arduino
  average3 = (coolantsensorDivider*average3)/(1023-average3);        //conversion equation to read resistance from voltage divider
  //Serial.print("Coolant Sensor Resistance3 = ");
  //Serial.println(average3);

  float steinhart1;                              //steinhart equation to estimate temperature value at any resistance from curve of thermistor sensor
  steinhart1 = log(average1);                     //lnR
  steinhart1 = pow(steinhart1 ,3);                 //(lnR)^3
  steinhart1 *= steinconstC1;                     //C*((lnR)^3)
  steinhart1 += (steinconstB1*(log(average1)));    //B*(lnR) + C*((lnR)^3)
  steinhart1 += steinconstA1;                     //Complete equation, 1/T=A+BlnR+C(lnR)^3
  steinhart1 = 1.0/steinhart1;                    //Inverse to isolate for T
  steinhart1 -= 273.15;                          //Conversion from kelvin to celcius

  float steinhart2;                              //steinhart equation to estimate temperature value at any resistance from curve of thermistor sensor
  steinhart2 = log(average2);                     //lnR
  steinhart2 = pow(steinhart2 ,3);                 //(lnR)^3
  steinhart2 *= steinconstC2;                     //C*((lnR)^3)
  steinhart2 += (steinconstB2*(log(average2)));    //B*(lnR) + C*((lnR)^3)
  steinhart2 += steinconstA2;                     //Complete equation, 1/T=A+BlnR+C(lnR)^3
  steinhart2 = 1.0/steinhart2;                    //Inverse to isolate for T
  steinhart2 -= 273.15;

    float steinhart3;                              //steinhart equation to estimate temperature value at any resistance from curve of thermistor sensor
  steinhart3 = log(average3);                     //lnR
  steinhart3 = pow(steinhart3 ,3);                 //(lnR)^3
  steinhart3 *= steinconstC3;                     //C*((lnR)^3)
  steinhart3 += (steinconstB3*(log(average3)));    //B*(lnR) + C*((lnR)^3)
  steinhart3 += steinconstA3;                     //Complete equation, 1/T=A+BlnR+C(lnR)^3
  steinhart3 = 1.0/steinhart3;                    //Inverse to isolate for T
  steinhart3 -= 273.15;

  sensorVal = (float)analogRead(sensorPin); // Read pressure sensor val (A0)
  filteredVal = (alpha * filteredVal) + ((1.0 - alpha) * sensorVal);// Low Pass Filter
  voltage = (filteredVal / 1024.0) * aRef; // calculate voltage


  pressureValue = filteredVal; //reads value from input pin and assigns to variable
  pressureValue = ((filteredVal-pressureZero)*pressuretransducermaxBAR)/(pressureMax-pressureZero); //conversion equation to convert analog reading to psi
  


  //Serial.print("ECT = ");
  //Serial.print(steinhart1);                      //prints final temp in celcius
  //Serial.println(" *C");

  //Serial.print("OILT = ");
  //Serial.print(steinhart2);                      //prints final temp in celcius
  //Serial.println(" *C");
  
  //Serial.print("RCT = ");
  //Serial.print(steinhart3);                      //prints final temp in celcius
  //Serial.println(" *C");

  //Serial.print("Öldruck = ");
  //Serial.print(pressureValue, 1); //prints value from previous line to serial
  //Serial.println(" Bar"); //prints label to serial
  //Serial.print("voltage = ");
  //Serial.println(voltage,2);

    u8g2.firstPage();
  do {
    u8g2.setFont(u8g2_font_crox4hb_tf);
  

    u8g2.drawStr(0,20,"RCT:");
    u8g2.setCursor(55,20);
    u8g2.println(steinhart3,1);
    u8g2.drawCircle(110,6,2);
    u8g2.drawStr(112,20, "C");

    u8g2.drawStr(0,47,"OILT:");
    u8g2.setCursor(55,47);
    u8g2.println(steinhart2,1);
    u8g2.drawCircle(110,33,2);
    u8g2.drawStr(112,47, "C");

    u8g2.drawStr(0,74,"OILP:");
    u8g2.setCursor(53,74);
    u8g2.println(pressureValue, 1);
    u8g2.drawStr(92,74, "Bar");

  u8g2.drawStr(0,101,"ECT:");
    u8g2.setCursor(55,101);
    u8g2.println(steinhart1,1);
    u8g2.drawCircle(110,87,2);
    u8g2.drawStr(112,101, "C");

    u8g2.drawStr(0,128,"EGT:");
    u8g2.setCursor(53,128);
    u8g2.println(thermocouple.readCelsius(),1);
    u8g2.drawCircle(110,114,2);
    u8g2.drawStr(112,128, "C");

  } while ( u8g2.nextPage() );

  delay(200);                                  //delay between readings
}

Du könntest dir abspeichern ob du gerade die Animation anzeigen musst und in welchem Frame du bist.

bool isAni = true;
uint32_t aniFrame = 0;

void doAnimation(){
  drawFrame(aniFrame);
  delay(200);
  aniFrame++;
  if (aniFrame > 100){
    isAni = false;
  }
}

void loop(){
  if(isAni){
    doAnimation();
  } else {
    doNormal();
  }
}

Unter Animation meinst Du verschiedene Grafiken (bilder) nacheinander oder Geometrische Zeichnungen die sich nacheinander aufbauen?

Bilder brauchen viel Speicher. Da ist es möglich daß schnell der Speicher fertig ist.

Grüße Uwe

Das volvo_h wird das Bild enthalten. Man kann sicherlich einen Teil auch "onthefly" berechnen, zb. drehende Räder oder sowas, aber dazu müsstest Du schon etwas mehr Infos geben. Und vor allem alles was Du hast, da es schlecht nachzuvollziehen ist, was Du verwendest.

Hallo Rintin:
danke für deine Beschreibung, funktioniert das Mit der U8g2 Bibliothek?

Hallo Uniform: ich würde beim Start des Bildschirms 3-5 Grafiken abspielen mit jeweils einem Delay von zb. 1000ms

Hallo mein_xy_Projekt:
Ja genau in der Volvo_bild.h sind verschiedene Bitmap Grafiken abgespeichert die ich gerne abspielen würde.

Youtube Link

Es sollte beim Start so etwas abgespielt werden und dann soll in die Sensoroberfläche gewechselt werden.

Lege ich richtig wenn ich meine Das diese Bildreihenfolge in den void setup teil gehört und nicht in den void loop teil?

Lg Manuel

Dann im setup() einfach so wie die erste aufgerufen wird, die nächsten hinterher.
Vielleicht mit einem kurzen delay() nach jeder Grafik.
Das kannst Du ggfls. auch in einer Schleife innerhalb des setup mehrfach abspielen.

Achte auf den Speicher! Der wird recht schnell knapp.
Ggfls. könnte man versuchen alles mit progmem() auszulagern.

Ja, musst halt drawFrame() so implementieren, das U8g2 benutzt wird.

Vielleicht so ungefähr:

void drawFrame(uint32_t aniFrame){
  u8g2.firstPage();
  do {
    switch(aniFrame){
    	case 0:
    	  u8g2.drawXBMP( 0, 28, 128, 71, bitmap1);
          break;
    	case 1:
    	  u8g2.drawXBMP( 0, 28, 128, 71, bitmap2);
          break;
    	case 2:
    	  u8g2.drawXBMP( 0, 28, 128, 71, bitmap3);
          break;
        ...
    };
  } while ( u8g2.nextPage() );
}

mein_xy_Projekt:

das mit dem delay und dannach eine zweite grafik im setup modus habe ich schon probiert hat leider nicht funktioniert.

Rintin:

ich Habe es jetzt so versucht,
leider wird mir so jetzt Keine grafik Angezeigt.



void setup() {
  Serial.begin(9600); 
  u8g2.begin();
  u8g2.setContrast(400);
}   
  void drawFrame(uint32_t aniFrame){
  u8g2.firstPage();
  do {
    switch(aniFrame){
    	case 0:
    	  u8g2.drawXBMP( 0, 28, 128, 71, epd_bitmap_vectordesign2);
          break;
          delay(1000);
    	case 1:
    	  u8g2.drawXBMP( 0, 18, 128, 92, epd_bitmap_volvo740test);
          break;
          delay(1000);
  
    };
  } while ( u8g2.nextPage() );
}                           

void loop() {

Hast du auch Code in der Loop() der drawframe() aufruft?

Ähmmm...

Ein Delay, nach einem break?

Vielleicht solltest du mal schauen, was ein break da so tut!

Tipp:
Das steht in deinem C++ Grundlagen Buch.

Drück mal STRG-T in der IDE.

drawFrame() ist eine Funktion - die will auch aufgerufen werden.
Ich würde die delay()ganz aus der Funktion entfernen. Das Warten (wie lange soll das Bild stehen bleiben) hat ja mit dem Zeichnen (draw) nix zu tun.

Dann könnte das ungefähr so aussehen:

void setup() {
  Serial.begin(9600); 
  u8g2.begin();
  u8g2.setContrast(400);
  
  drawFrame(0);
  delay(1000);
  drawFrame(1);
  delay(1000);
} 

void drawFrame(uint32_t aniFrame) {
  u8g2.firstPage();
  do {
    switch(aniFrame) {
    	case 0:
    	  u8g2.drawXBMP( 0, 28, 128, 71, epd_bitmap_vectordesign2);
          break;
    	case 1:
    	  u8g2.drawXBMP( 0, 18, 128, 92, epd_bitmap_volvo740test);
          break;
    };
  } while ( u8g2.nextPage() );
}                           

Ob es jetzt ein uint32_t für die Auswahl des Bildes braucht und die Namen der Bilddaten hart kodiert sein müssen (oder besser außerhalb in einem Array, ggf. von Strukturen zusammen mit den Koordinaten und Abmessungen, verwaltet werden), ist nochmal eine andere Geschichte.

Vielleicht so:


void setup()
{
  Serial.begin(9600);
  u8g2.begin();
  u8g2.setContrast(400);
  const uint8_t allFrames = 2;  // Hier festlegen, wieviele Bilder gezeigt werden

  // Variante 1 - 1 Durchlauf
  for (byte b = 0; b < allFrames; b++)
  {
    drawFrame(b);
    delay(100);
  }

  // Variante 2 - mehrere Durchläufe
  for (byte c = 0; c < 5; c++)        // Festlegung wieviele Wiederholungen
  {
    for (byte b = 0; b < allFrames; b++)
    {
      drawFrame(b);
      delay(100);
    }
  }
}

void drawFrame(const uint8_t aniFrame)
{
  u8g2.firstPage();

  do
  {
    switch (aniFrame)
    {
      case 0:
        u8g2.drawXBMP( 0, 28, 128, 71, epd_bitmap_vectordesign2);
        break;

      case 1:
        u8g2.drawXBMP( 0, 18, 128, 92, epd_bitmap_volvo740test);
        break;
    };
  } while ( u8g2.nextPage() );
}

Wie viel: Hallo ich bin kein Profi, mache nur learning by doing

wno158: Hallo und vielen Dank für deine Hilfe, genau so wollte ich es haben, es funktioniert. :smiley: :smiley: :+1:
mein_xy_projekt: Hallo, auch dir danke, deine Variante funktioniert auch nur schneller, eher für die Variante "onthefly" Simulation, werde ich mir abspeichern:

vielen Dank für eure Hilfe :heart:

In vielen Lebensbereichen mag das funktionieren.
In der Programmierung eher nicht.
Und mit C++ schon gar nicht.

Du kannst das delay() für Dich anpassen.

Das ist Unsinn.
Du schiesst über den gültigen Wertebereich hinaus und erzeugst damit einen Überlauf.

void setContrast(uint8_t value)