OLED Display Problem..

Hallo zusammen...

Ich verwenden einen 128x32 pixel I2C OLED Display (ohne Reset Pin) am Arduino Nano und zeige damit Sensorwerte von DS18B20 Temperatursensoren an.

Die Anzeige im Display wechselt alle paar Sekunden von einem Sensor auf den anderen..

Das Ganze funktioniert hervorragend & sehr stabil...

Nun ist da allerdings das Problem das nach ein paar Stunden Laufzeit der Display auf einmal dunkel bleibt und nix mehr anzeigt...
Das ist sofort behoben wenn ich mal eben den Arduino neu starte, es reicht sogar schon mich mit dem Rechner anzuklemmen & den Seriellen Monitor zu öffnen... Display ist dann sofort wieder da...

Um das zu umgehen, hab ich einen reset des Arduinos nach x Stunden einprogrammiert, aber auch das tut nicht was es soll...

Hat Jemand das selbe Problem & evtl ne Lösung dazu?

LG

Der Fehler ist in Zeile 42 deines Sketches.
Heißt zu viele Strings.

Zu viele Strings? :relaxed:

Wie ist das lösbar ohne die Funktion zu beeinflussen?

Zeig doch mal deinen Sketch, dann können wir mehr sagen.

Der Sketch:

// Integrierte Libarys
#include <avr/wdt.h>
#include <SPI.h>
#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
//Display Settings
#define col 1
#define col_degree 90
#define row_first_line  1
#define row_second_line 16
//Globale Settings
#define ONE_WIRE_BUS 2   // OneWire Bus Pin
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
#define OLED_RESET -1     // OLED Reset Pin
#define TEMPERATURE_PRECISION 12  // Präzisionseinstellung Temperatursensoren
// Timing Settings
#define INTERVALL 3 //20  // Umschaltung der Anzeigen, alle X Sekunden.
#define RESET_INTERVALL 300 // = 5h //Reset alle x minuten
#define SWITCH_INTERVALL INTERVALL * 1000
unsigned long RESET_INTVAL = RESET_INTERVALL * 60000; // Hochrechnen auf milisek.
#define calibration_mode 0  // Kalibrierung der Sensoren 1 = aktiv, 0 = inaktiv
//float temp_average;
//char temp_display;

// Sensorendaten & Kalibrierungswerte
DeviceAddress Sensor_1 = {0x28, 0xFF, 0xCA, 0xA2, 0xA4, 0x16, 0x04, 0x36}; //Innentemperatur
#define Sensor1_Offset +00.00 // Differenz der Sensormessung zum Realen Wert
DeviceAddress Sensor_2 = {0x28, 0xFF, 0x72, 0xB8, 0xA4, 0x16, 0x05, 0x3A}; //Aussentemperatur
#define Sensor2_Offset +00.00 // Differenz der Sensormessung zum Realen Wert
DeviceAddress Sensor_3 = {0x28, 0xFF, 0x22, 0x30, 0xA4, 0x16, 0x05, 0x6A}; // Eingehängter Kalibriersensor
#define Sensor3_Offset +00.00
//DeviceAddress Sensor_4 = { }; // Zusatzsensor spätere Verwendung?
//#define Sensor4_Offset +00.00

//Meldungen 
#define kb "K" "\x81" "hlboxtemperatur:"
#define sensor_def "Fehler"

// Declaration for an SSD1306 display connected to I2C (SDA (Pin A4), SCL (Pin A5) pins)
Adafruit_SSD1306 display (SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
int sensorCount, next_step, error;
unsigned long current_millis, prevous_millis;

void setup() 
{
  Serial.begin(9600);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  sensors.begin();
  sensorCount = sensors.getDS18Count();
  sensors.setResolution(Sensor_1, TEMPERATURE_PRECISION);
  sensors.setResolution(Sensor_2, TEMPERATURE_PRECISION);
  if(calibration_mode == 1)
   {
     sensors.setResolution(Sensor_3, TEMPERATURE_PRECISION);
    // sensors.setResolution(Sensor_4, TEMPERATURE_PRECISION);
   }
 
  display.clearDisplay();
  current_millis = millis();
  next_step = 1;
  error = 0;
}

void loop() 
{
  sensors.requestTemperatures();
  temperatur(next_step);
  if((millis() - prevous_millis > SWITCH_INTERVALL))
   {
    //temperatur(next_step);
    prevous_millis=millis();
    if(next_step < 3)
     {
       next_step++;  // Hochzählen des Zählers
     }
    else
     {
      next_step = 1; // Rücksetzen des Zählers auf 1
     }
   }
  // resetschaltung

  if(millis() >= RESET_INTVAL)
   {
     Serial.println(F("Now Resetting.."));
     reset_now();
   }
}

void temperatur(int value)
 {
  //Serial.print("Fehlerstatus: ");
  //Serial.println(error);
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(col, row_first_line);
    if(value == 1)
      {
          display.println("Innentemperatur");
      }
    else if(value == 2)
      {
          display.print("Au");
          display.print(char(224));
          display.println("entemperatur");
      }
    else
      {
        if(calibration_mode == 1)
         {
           display.println("Kalibriertemperatur");
         }
        else
         {
              display.println("Differenztemperatur");
         }
       
      }
  display.setTextSize(2);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(col, row_second_line);
    if(value == 1)
      {
        if(sensors.isConnected(Sensor_1))
          {
            display.print(sensors.getTempC(Sensor_1)+Sensor1_Offset);
            error=0;
          }
        else
          {
            display.print(sensor_def);
            error=1;
          }
        
      }
    else if (value == 2)
      {
        if(sensors.isConnected(Sensor_2))
          {
            display.print(sensors.getTempC(Sensor_2)+Sensor2_Offset);
            error=0;
          }
         else
          {
            display.print(sensor_def);
            error=1;
          }
       }
    else
      {
        if (calibration_mode == 1)
          {
            if(sensors.isConnected(Sensor_3))
              {
                display.print(sensors.getTempC(Sensor_3)+Sensor3_Offset);
              }
          }
        else
          {
            if((sensors.isConnected(Sensor_1)) && (sensors.isConnected(Sensor_2)))
              {
               display.print((sensors.getTempC(Sensor_2)+Sensor2_Offset) - (sensors.getTempC(Sensor_1)+Sensor1_Offset));
               error=0;
              }
            else
              {
               display.print(sensor_def);
               error=1;
              }
          }
      }
  if(error == 0)
   {
     display.setCursor(col_degree, row_second_line);
     display.print(char(247));
     display.println("C");
   }
  display.display();
 }

//Resetfunktion..
void reset_now()
 {
  wdt_enable( WDTO_15MS);
 }

(deleted)

Hallo Skipper_Do,

die von dir verwendete Methode der Umschaltung ist schon etwas merkwürdig.
Du solltest dabei berücksichtigen, dass die Sensoren eine gewisse Zeit zum Messen benötigen. Auch würde ich besser die Sensoren "ständig" messen lassen und nur die jeweilige Variable mit den Messdaten umschalten.
Somit ist dein Sketch sicher verbesserungswürdig.
Allerdings Strings wie vermutet, kann ich nicht finden. Somit muss das Problem anderswo gesucht werden.

Wozu nutzt du den Watchdog ? Evtl. dein Problem.

Hallo,

ich hätte da mal zwei Vorschläge

  1. mach mal aus der

#define SWITCH_INTERVALL INTERVALL * 1000SWITCHINTERVALL

Compiler Anweisung eine richtige Variable

uint32_t const swichintervall =3000UL;

die Textausgaben mit dem F Makro ändern macht speicher frei.

display.println("Innentemperatur") // andern in 

display.println(F("Innentemperatur"));

Heinz

@ HotSystems: Die Sensoren messen bei jedem Schleifendurchlauf, Ansonsten währe die Temperaturanzeige bei jedem Wechsel Statisch und ändert sich innerhalb der Umschaltzeit zum Anderen Sensor nicht mehr..

void loop()
{
  sensors.requestTemperatures();
[...]

Der Watchdog wird für den Reset nach Zeit benötigt...

//Resetfunktion..
void reset_now()
 {
  wdt_enable( WDTO_15MS);
 }

Das Problem verursacht er nicht... Das Problem war schon vorher da, das war nur ein Lösungsversuch.. - der leider nicht geklappt hat..
Die Umschaltung des Displays hab ich so gelöst um den Loop möglichst klein zu halten & ich nicht "1000 Unterfunktionen" Schreiben wollte... Daher wird der Status ("next_step=x") des Loops (gesteuert nach Zeit) an die Temp Funktion übergeben & die macht dann den Rest... Programmiertechnisch wohl nicht perfekt aber ich fand's clever...
Ich bin auch kein Profi-Programmierer... Ich lerne noch... Meist Autodidaktisch mit Foren-, Internet- Unterstützung & Projektbezogen... Also learning by doing...

@ Rentner:
was heißt das UL nach der Zahl?

Die Compileraneisungen (ich nehme an Du meinst die " #define") hab ich gewählt um weit oben im Sketch die wichtigsten Einstellungen beisammen zu haben... Und das ganze "human readable" daher die anschließenden Berechnungen...
Verbesserungsvorschläge die das besser machen, nehm ich gern an...
Ich möchte da nur nicht diverse Zeitverzögerungen (die in ms angegeben werden müssen) bei jeder Konfigurationsänderung händisch neu errechnen... (Bin Faul ;D )

@ Peter... Ich gelobe Besserung...

was heißt das UL nach der Zahl?

Das ist ein Literal Suffix

combie:
Das ist ein Literal Suffix

Verstehe. Steht für Unsigned Long... Wieder was gelernt ;D

Skipper_Do:
.....
Die Umschaltung des Displays hab ich so gelöst um den Loop möglichst klein zu halten & ich nicht "1000 Unterfunktionen" Schreiben wollte...

Was hast du gegen Funktionen ?
Diese machen deinen Sketch übersichtlicher, auch für dich.
Damit ist dieser besser lesbar und für dich auch später noch besser verständlich.

Zudem lassen sich Fehler besser einkreisen.
Somit nur Vorteile und es gibt sicher noch mehr positive Gründe, Funktionen zu verwenden.

Dann würde ich auch verstehen, warum du den Sketch so merkwürdig aufgebaut hast.
Den Sinn warum das so ist, verstehe ich leider immer noch nicht.
Aber egal, Hauptsache du versteht es.

Ich hab absolut nix gegen Funktionen... Zumal ich diese gerade für mich "entdeckt" habe....
Aber offensichtlich hab ich wohl noch nicht so ganz verstanden wie diese "richtig" eingesetzt werden..

Aber das Kommt noch... :grin:

Die Schleife im Loop erzeugt Zeitgesteuert die Zahl 1, 2 oder 3 und dann von vorn...
Diese Zahl wird an die Temp Funktion übergeben und weiter verarbeitet...
Je Nachdem welche Zahl übergeben wurde Zeigt der Display dann die Außentemperatur, die Innentemperatur oder die Differenztemperatur zwischen innen & aussen an, incl. Passendem Schriftzug...

Die Temp Funktion ist unterteilt in "1. Displayzeile" mit keiner Schriftgröße wo Innen- Außen & Differentemp. & "2. Displayzeile" mit etwas größerer Schrift wo die Sensorwerte angezeigt werden...

So schwer sollte der Sketch doch nicht zu durchschauen sein, oder?

Skipper_Do:
So schwer sollte der Sketch doch nicht zu durchschauen sein, oder?

Für dich vielleicht.
Aber deine zahlreichen if-Verschachtelungen machen den Sketch für externe unlesbar.
Zumal da jegliche nützliche Kommentare fehlen.

Ich hätte noch eine kleine Anmerkung zum Sketch - aber das wird wohl nicht Dein Problem lösen.
Du schreibst mit println() auf das Display:

display.println("Innentemperatur");

Das ist nicht erforderlich, denn der Cursor wird ja positioniert. print() sollte reichen:

display.setCursor(col, row_first_line);
...
display.print("Innentemperatur");

@ wno158: ja da hast Du absolut recht...

Löst das Problem nicht, ist aber bessere syntax... Werd es so mal abändern...

(die F Macros hab ich bereits eingearbeitet...)

@Skipper_Do

ich habe mir deinen Sketch jetzt noch mal in Ruhe angesehen und kann leider keinen direkten Fehler erkennen.

Da ich schon mehrere dieser Sensoren verbaut habe und diese auch problemlos über Monate bzw. Jahre funktionieren, kann ich mir nur vorstellen, dass es an deiner, mir unergründlichen Art der Auslesung der Sensoren liegt.

Allerdings habe ich da keinen weiteren Tipp, als den schon genannten.

Oder evtl. I2C, hast du da Pullup-Widerstände dran ?
Länge der I2C-Leitung ?

@ HotSystems:

PullupResistoren sind verbaut, die Leitungslänge zum Display beträgt ca 300 - 400mm..

Die Ausleseart ist wohl der gängige Standard für diese Sensoren... Zumindest hab ich noch keine andere art der Auslesung zu Gesicht bekommen...
Im Loop werden sie ja ausgelesen & in der Temp Funktion verarbeitet...

Update...

Seit dem letzten Flashen Läuft es bereits seit 8 tagen durchgehend ohne Ausfall...
Ich habe lediglich die Codezeilen

display.println("....");

in

display.print(F("..."));

geändert, und bin somit dem Tipp von Rentner & wno158 gefolgt..

Ich gehe zwar aktuell nicht davon aus, das es nochmal ausfallen wird, aber sollte das Teil jetzt 2 Wochen ohne Ausfall durchhalten (das ist im Regelfall die Dauer die das Gerät im schnitt am Stück betrieben wird) werd ich die Resetschaltung nach x stunden mal Entfernen & mal schauen was passiert...

Ich Danke für eure Hilfe & Tipps, wenn gewünscht erzähle ich euch noch das Ergebnis der oben beschriebenen Vorgehensweise...

LG