OLED Display An und Aus schalten

Hi , vielleicht kann mir ja jemand von euch helfen .
Ich habe bei meinem Projekt ein Display an einem Esp. Das Display zeigt Werte an und soll über Knopfdruck ausgeschaltet werden können .

Ich verwende ein ssd1306 Oled i2c mit Adafruit Bibliothek

Ich verstehe nicht , wie ich den Knopf in den Code integriere und das Display an , bzw aus geschaltet wird .

Ich weiß, der Code ist alles andere als schön :cold_sweat:

const char* host = "api.thingspeak.com";
String writeAPIKey = "XXXXX";

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 0  // GPIO0
Adafruit_SSD1306 display(OLED_RESET);


#define BLYNK_PRINT Serial    // Comment this out to disable prints and save space

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

#include <ESP8266mDNS.h>  // For OTA w/ ESP8266
#include <WiFiUdp.h>  // For OTA
#include <ArduinoOTA.h>  // For OTA

char auth[] = "XXXXXX";

char ssid[] = "XXXXX";
char pass[] = "XXXXXX";


BlynkTimer timer;

#define echoPin D8 // Echo Pin
#define trigPin D7  // Trigger Pin

int maximumRange = 13;
int minimumRange = 27;

double alertInMin = 0.5; //Alert time following water level alert being reached (0.5 = 30secs)
int alertLevelCounter = 0; //Counter starts at zero
const int alertDuration = 2;  //Alert sent every 2 minutes

long duration, distance; // Duration used to calculate distance

int volume;
int percent;
int levelAlert;
int wateralert = 0;


BLYNK_CONNECTED() {

Blynk.syncVirtual(V10); //sync level alert value
}
 
void MeasureCm()
{
  /* The following trigPin/echoPin cycle is used to determine the
 distance of the nearest object by bouncing soundwaves off of it. */ 

 
 digitalWrite(trigPin, LOW); 
 delayMicroseconds(2); 

 digitalWrite(trigPin, HIGH);
 delayMicroseconds(10); 
 
 digitalWrite(trigPin, LOW);
 duration = pulseIn(echoPin, HIGH);
 
 //Calculate the distance (in cm) based on the speed of sound.
 distance = duration/58.2;

  {
 
 if (distance >= 27 ){
  volume = (29200-(distance*((3.14159265359*(13*13)))))/1000;
  percent = ((float)volume/13)*100;
  
  } 
  
   else {
 
   if (distance < 27 ){
      volume = 13;
      percent = 100;
      }
   }
 }
Blynk.virtualWrite(V8, volume); // virtual pin
Blynk.virtualWrite(V9, percent); // virtual pin
Blynk.virtualWrite(V13, distance); // virtual pin
} 

void UpTime()
{
  Blynk.virtualWrite(2, (millis() / 1000));
  Blynk.virtualWrite(3, WiFi.RSSI());
 }


BLYNK_WRITE(V10) {levelAlert = param.asInt();} //level alert value
   
BLYNK_WRITE(V11) { //level alert button widget

  int alertOff = param.asInt();

  if (alertOff == 0){
    resetWaterLevelAlert();
    wateralert = 1;
  }
  else {
    resetWaterLevelAlert();
    wateralert = 0;
  }

  }

void checkWaterLevel() {
  if (volume < levelAlert && wateralert == 0) {
   //Serial.print("low water level.\r\n"); 
   alertLevelCounter += 1;
  // Serial.print(("alertLevelCounter:" + (String)alertLevelCounter + "\r\n").c_str());
  }

  if (alertLevelCounter > alertInMin * 60 && wateralert == 0) {
      
    Blynk.notify("Water Tank Level Alert"); // send push notification to blynk app
    wateralert = 1;
    resetWaterLevelAlert();
  }
       
 }

void resetWaterLevelAlert() {
  alertLevelCounter = 0;
  wateralert = 0;
}
  

void setup() {

 
 
 Serial.begin(115200);
 Blynk.begin(auth, ssid, pass);

 display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  // Cancellazione schermo e buffer
  display.clearDisplay();
  // Messaggio iniziale
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println(" Zisterne");
  display.setTextColor(BLACK, WHITE); // Inverte il colore del testo
  display.println(" Niklas V1  ");
  display.println(" HC-SR04  ");
  display.display();
  delay(2000);
 
 
 
 ArduinoOTA.setHostname("Water_Tank");  // For OTA - Use your own device identifying name
 ArduinoOTA.begin();  // For OTA

 Blynk.virtualWrite(0, BLYNK_VERSION);
 Blynk.virtualWrite(1, ESP.getCoreVersion());

 pinMode(trigPin, OUTPUT);
 pinMode(echoPin, INPUT);
 
   timer.setTimeout(100, [](){
     timer.setInterval(5000L, UpTime);
   });

   timer.setTimeout(300, [](){
     timer.setInterval(3000L, MeasureCm); //check water level every 5 min
   });

   timer.setTimer(1000L, MeasureCm, 1); //get a measurement straight up if the device was reset for some reason

    timer.setTimeout(500, [](){
         timer.setInterval(1000L, checkWaterLevel);
   });
}
 
void loop() {
  Blynk.run(); // Initiates Blynk
  ArduinoOTA.handle();  // For OTA
  timer.run(); // Initiates SimpleTimer
display.clearDisplay();

  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println("      MESSUNG");
  
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 8);
  display.println("Abstand:");
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(60, 8);
  display.print(distance); display.println(" cm");
 
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 16);
  display.println("Volumen:");
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(60, 16);
  display.print(volume); display.println(" L");

  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 24);
  display.println("Fuellung:");
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(60, 24);
  display.print(percent); display.println(" %");
  
  display.display();
  //Delay 500ms before next reading.
  delay(5000);



//make TCP connections
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    return;
  }

  String url = "/update?key=";
  url+=writeAPIKey;
  url+="&field1=";
  url+=String(percent);
  url+="&field2=";
  url+=String(volume);
  url+="\r\n";
  
  // Request to the server
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" + 
               "Connection: close\r\n\r\n");
    delay(1000);
    }

Und warum möchtest du das Display ausschalten ? Setze die komplette Anzeige auf schwarz, dann sieht man nichts mehr.

HotSystems:
Und warum möchtest du das Display ausschalten ?
Setze die komplette Anzeige auf schwarz, dann sieht man nichts mehr.

Warum der OP das möchte ist doch eigentlich unerheblich. Zwar frisst so ein Display kaum etwas (meine brauchen < 1 mA), aber wenn man seine Bastelei auf den absolut minimalen Energiebedarf optimieren möchte, ist das Abschalten des Displays zumindest keine blöde Idee.

Finde ich.

Gruß

Gregor

Hi

Zumindest gibt es einen Aufruf in der Adafruit_SSD1306.ccp, Zeile 229: ssd1306_command(SSD1306_DISPLAYOFF); (erste Befehl in der Init-Sequenz) wobei

define SSD1306_DISPLAYOFF 0xAE

define SSD1306_DISPLAYON 0xAF

Ob man 'von Außen' diese Funktion (äh, Methode) aufrufen kann - kA, so weit bin ich noch nicht durchgestiegen.

Somit sollte sich das Display wohl auch ausschalten lassen (was Das im Endeffekt wirklich ist, sieht man dann ... oder befragt das Datenblatt zum Kontroller).

MfG

gregorss:
Warum der OP das möchte ist doch eigentlich unerheblich. Zwar frisst so ein Display kaum etwas (meine brauchen < 1 mA), aber wenn man seine Bastelei auf den absolut minimalen Energiebedarf optimieren möchte, ist das Abschalten des Displays zumindest keine blöde Idee.

Finde ich.

Naja…ich finde das nicht unerheblich, wenn es (theoretisch) keine direkte Möglichkeit gibt.
Oder darf ich das nicht hinterfragen ?
Wenn der TO schreibt, das es wegen Batteriebetrieb ist, dann ok. Nur wie schon geschrieben, einfach wird das nicht.
Aber er kann ja mal einen Hyperlink seines Displays posten, evtl. geht ja doch was.

HotSystems: Oder darf ich das nicht hinterfragen ?

Doch, natürlich. Es ist ja ziemlich üblich, dass sich die ursprüngliche Fragestellung im Verlauf eines Threads durch genau solche Fragen ändert.

@postmaster-ino: Diese Befehls-Bytes sind mir bekannt. In meiner eigenen Bibliothek bleiben die entsprechenden Befehle aber ohne Wirkung. Der Grund hierfür ist mir nicht bekannt.

Gruß

Gregor

Klar darf man fragen ;) @hotsystem , das Display einfach auf schwarz zu stellen wäre auch okay. Mir geht es weniger um den Energieverbrauch , sonder eher darum, dass ich die Lebensdauer des Displays verlängern will, da OLEDS nach einiger Zeit ihr Helligkeit verlieren und auch einbrennen könne.

xraptor92: ... einbrennen ...

Das ist allerdings auch ein guter Grund. Dafür dürfte es tatsächlich genügen, einfach alle Pixel „auszuschalten“.

Gruß

Gregor

das funktioniert auch , mit dem Befehl " display.clearDisplay();" , aber ich bekomme das nicht in meinen Code eingebaut. Beim Betätigen von einem Taster soll einfach das Display gelöscht werden, beim nächsten betätigen soll es die Werte wieder anzeigen. Vielleicht könnte mir jemand von euch helfen , wie ich das Feature in den Code einbaue .

xraptor92: ... Vielleicht könnte mir jemand von euch helfen , wie ich das Feature in den Code einbaue .

Räume dazu am besten den Code auf und formatiere ihn so, dass er lesbar ist, ohne sich anstrengen zu müssen. Es würde mich nicht wundern, wenn Du die Lösung dann selbst finden würdest. Das Aufräumen beginnst Du am besten mit Strg-T.

Gruß

Gregor

Ich habe den Code etwas aufgeräumt . Aber komme bei meinem Problem leider immer noch nicht weiter . Ich verstehe leider nicht , wie ich den Knopf in den Code , einbaue , damit er das Display schwarz stellt, bzw löscht .

const char* host = "api.thingspeak.com";
String writeAPIKey = "XXXXX";

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 0  // GPIO0
Adafruit_SSD1306 display(OLED_RESET);


#define BLYNK_PRINT Serial    // Comment this out to disable prints and save space

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

#include <ESP8266mDNS.h>  // For OTA w/ ESP8266
#include <WiFiUdp.h>  // For OTA
#include <ArduinoOTA.h>  // For OTA

char auth[] = "XXXXX";

char ssid[] = "XXXXX";
char pass[] = "XXXXX";


BlynkTimer timer;

#define echoPin D8 // Echo Pin
#define trigPin D7  // Trigger Pin

int maximumRange = 13;
int minimumRange = 27;

double alertInMin = 0.5; //Alert time following water level alert being reached (0.5 = 30secs)
int alertLevelCounter = 0; //Counter starts at zero
const int alertDuration = 2;  //Alert sent every 2 minutes

long duration, distance; // Duration used to calculate distance

int volume;
int percent;
int levelAlert;
int wateralert = 0;


BLYNK_CONNECTED() {

  Blynk.syncVirtual(V10); //sync level alert value
}

void MeasureCm()
{
  /* The following trigPin/echoPin cycle is used to determine the
    distance of the nearest object by bouncing soundwaves off of it. */


  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);

  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);

  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);

  //Calculate the distance (in cm) based on the speed of sound.
  distance = duration / 58.2;

  {

    if (distance >= 27 ) {
      volume = (29200 - (distance * ((3.14159265359 * (13 * 13))))) / 1000;
      percent = ((float)volume / 13) * 100;

    }

    else {

      if (distance < 27 ) {
        volume = 13;
        percent = 100;
      }
    }
  }
  Blynk.virtualWrite(V8, volume); // virtual pin
  Blynk.virtualWrite(V9, percent); // virtual pin
  Blynk.virtualWrite(V13, distance); // virtual pin
}

void UpTime()
{
  Blynk.virtualWrite(2, (millis() / 1000));
  Blynk.virtualWrite(3, WiFi.RSSI());
}


BLYNK_WRITE(V10) {
  levelAlert = param.asInt(); //level alert value
}

BLYNK_WRITE(V11) { //level alert button widget

  int alertOff = param.asInt();

  if (alertOff == 0) {
    resetWaterLevelAlert();
    wateralert = 1;
  }
  else {
    resetWaterLevelAlert();
    wateralert = 0;
  }

}

void checkWaterLevel() {
  if (volume < levelAlert && wateralert == 0) {
    //Serial.print("low water level.\r\n");
    alertLevelCounter += 1;
    // Serial.print(("alertLevelCounter:" + (String)alertLevelCounter + "\r\n").c_str());
  }

  if (alertLevelCounter > alertInMin * 60 && wateralert == 0) {

    Blynk.notify("Water Tank Level Alert"); // send push notification to blynk app
    wateralert = 1;
    resetWaterLevelAlert();
  }

}

void resetWaterLevelAlert() {
  alertLevelCounter = 0;
  wateralert = 0;
}


void setup() {



  Serial.begin(115200);
  Blynk.begin(auth, ssid, pass);

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

  display.clearDisplay();

  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println(" Zisterne");
  display.setTextColor(BLACK, WHITE);
  display.println(" Niklas V1  ");
  display.println(" HC-SR04  ");
  display.display();
  delay(2000);



  Blynk.virtualWrite(0, BLYNK_VERSION);
  Blynk.virtualWrite(1, ESP.getCoreVersion());

  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);

  timer.setTimeout(100, []() {
    timer.setInterval(5000L, UpTime);
  });

  timer.setTimeout(300, []() {
    timer.setInterval(3000L, MeasureCm); //check water level every 5 min
  });

  timer.setTimer(1000L, MeasureCm, 1); //get a measurement straight up if the device was reset for some reason

  timer.setTimeout(500, []() {
    timer.setInterval(1000L, checkWaterLevel);
  });
}

void loop() {
  Blynk.run(); // Initiates Blynk

  timer.run(); // Initiates SimpleTimer
  display.clearDisplay();

  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println("      MESSUNG");

  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 8);
  display.println("Abstand:");
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(60, 8);
  display.print(distance); display.println(" cm");

  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 16);
  display.println("Volumen:");
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(60, 16);
  display.print(volume); display.println(" L");

  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 24);
  display.println("Fuellung:");
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(60, 24);
  display.print(percent); display.println(" %");

  display.display();
  //Delay 500ms before next reading.
  delay(5000);



  //make TCP connections
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    return;
  }

  String url = "/update?key=";
  url += writeAPIKey;
  url += "&field1=";
  url += String(percent);
  url += "&field2=";
  url += String(volume);
  url += "\r\n";

  // Request to the server
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "Connection: close\r\n\r\n");
  delay(1000);
}

xraptor92:   //Delay 500ms before next reading.   delay(5000);

Finde ich irgendwie witzig :-)

Problematisch sind die vielen delay()s, denn die verhindern, dass quasi „gleichzeitig“ ein Taster abgefragt werden kann. Probiere am besten, Deinen Sketch als „endlichen Automaten“ zu formulieren. Dabei läuft loop ständig und so gut wie ungebremst durch (vor allem keine delay()s!). Ein Teil des Programms fragt dabei in jedem loop()-Durchgang, ob der Taster gedrückt ist und setzt ein „flag“, das dann darüber entscheidet, ob etwas angezeigt wird.

Zum Verständnis, wie ein endlicher Automat funktioniert, kannst Du einen Blick in mein Geschreibsel werfen. Die dort erwähnte „Nachtwächter-Erklärung“ (IIRC Kasten ganz unten) ist sehr gut. Die Nachtwächter-Erklärung müsstest Du auch über die Forensuche finden.

Gruß

Gregor

Danke für die Infos, ich werde mich noch einmal dransetzen !

xraptor92: Danke für die Infos, ich werde mich noch einmal dransetzen !

Viel Erfolg! Gib Bescheid, ob es geklappt hat. Beim „Umstricken“ des Codes auf einen endlichen Automaten kann man sich Knoten ins Hirn denken. Aber wenn man verstanden hat worum es geht, hat man eine Art schweizer Offizierstaschenmesser für einen Haufen von Anwendungsfällen.

Gruß

Gregor

Hi

Löscht die Funktion clearDisplay() den Inhalt des Display-Puffer (wahrscheinlich), oder gibt Diese nur Leer-Pixel ans Display? Bei Ersterem musst Du den kompletten Display-Inhalt erneut erzeugen, da der Inhalt halt weg ist.

Letzteres wäre eine Erweiterung der Lib wert, also ein/zwei Funktionen, Die ein Flag setzen/löschen, ob aus dem Puffer gelesen werden soll, oder Nullen ans Display geschickt werden sollen. OLED leuchtete aktiv, also ohne Backlight? Sonst müsste man Das auch noch abschalten.

Das müsste sich doch relativ einfach realisieren lassen. Einwände?

MfG

postmaster-ino: ... eine Erweiterung der Lib ... Einwände?

Meiner Erfahrung nach fährt man am besten, wenn man sich nur den Code zur Initialisierung und zur Manipulation einzelner Pixel abguckt und den Rest selbst programmiert - wenn man sich also eine eigene Bibliothek schreibt. Die Vorteile wiegen IMO schwer. Man kennt z. B. die Bibliothek „bis aufs letzte Bit“ und kann implementieren, was auch immer man braucht. Und was Zeichensätze angeht: Einer genügt vollkommen. Ich schraube mir mit meiner eigenen Bibliothek eine Grafik zusammen, die mir ständig anzeigt, was die Uhr meint und ob ich ungelesene E-Mails habe:

Das sieht vielleicht nicht ganz so hui aus, ist als reines „Kurzinfo-Display“ vollkommen ausreichend.

Gruß

Gregor