Arduino UNO mit OLED RTC und DS18B20 Problem

Hallo,

ich habe ein UNO mit DS1307 RTC, zwei DS18B20 Temp Sensoren, einem SPI SD Card Modul und OLED Modul.

Als letztes wollte ich jetzt die Ausgabe über OLED realisieren. Leider funktioniert dies nicht.

Alle anderen Teile funktionieren soweit. Wenn ich das OLED Display anschließe, gibt es ein Problem. Wenn ich den UNO nur mit dem Code für das OLED bespiele, dann funktioniert es auch. Der Anschluss scheint daher zu passen. Es ist über I2C an SDA und SCL angeschlossen, genauso wie das RTC.
Das SD Card Modul hängt an CS 10; SCK an 13; Mosi und MISO 11,12.
Die DS18B20 Sensoren hängen am PIN 3.

Wenn ich den Code starte stoppt er immer mit “SSD1306 allocation failed”. Ich glaube irgendwas im Code scheint mit der Speicherbelegung nicht zu passen. Hat vielleicht jemand eine Idee?

//RTC DS1307
#include "RTClib.h"
//TempSensor DS18B20
#include <OneWire.h> 
#include <DallasTemperature.h>
//SD SPI Modul 
#include <SD.h>
//OLED
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

   
RTC_DS1307 rtc;

const int chipSelect = 10;
 
#define ONE_WIRE_BUS 3
#define DS18B20_Aufloesung 12
DeviceAddress DS18B20_Adressen;
 
OneWire oneWire(ONE_WIRE_BUS); 
DallasTemperature myDS18B20(&oneWire); 
#define Anzahl_Sensoren_DS18B20  2 // Anzahl der angeschlossenen Sensoren - Mögliche Werte: '0','1','2'
 
const float No_Val = 999.99;
float Temperatur[2] = {No_Val,No_Val};  
 
// Für beelogger-Solar: Aktivierung der Stromversorgung für Sensoren, Module und DS3231 
//#define Power_Pin 4 



void setup() {
 Serial.begin(9600);
   //OLED
  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }
  // Show initial display buffer contents on the screen --
  // the library initializes this with an Adafruit splash screen.
  display.display();
  delay(2000); // Pause for 2 seconds

  // Clear the buffer
  display.clearDisplay();

  // Draw a single pixel in white
  display.drawPixel(10, 10, SSD1306_WHITE);

  // Show the display buffer on the screen. You MUST call display() after
  // drawing commands to make them visible on screen!
  display.display();
  delay(2000);
  // display.display() is NOT necessary after every single drawing command,
  // unless that's what you want...rather, you can batch up a bunch of
  // drawing operations and then update the screen all at once by calling
  // display.display(). These examples demonstrate both approaches...
  display.clearDisplay();
 
  display.setTextSize(1);
  display.setCursor(0, 10);
  display.println("www.kollino.de"); //Textzeile ausgeben
  display.display();

  
  Wire.begin();
  rtc.begin();
  Serial.begin(9600);
    
  //RTC
  if (! rtc.isrunning()) {
    rtc.adjust(DateTime(__DATE__, __TIME__));
  }
  else Serial.println("RTC is running");
  
//  while (!Serial) {
//    ; // wait for serial port to connect. Needed for native USB port only
//  }
  Serial.println("DS18B20 Test");
  Serial.println();
  
  Serial.print("Initializing SD card...");
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1);
  }
  Serial.println("card initialized.");
  
  delay(1000);
 
  Serial.print("Anzahl aktivierter Sensoren: ");
  Serial.println(Anzahl_Sensoren_DS18B20);
 
  if ((Anzahl_Sensoren_DS18B20 > 0) and (Anzahl_Sensoren_DS18B20 < 3)) {
    myDS18B20.begin();
    Serial.print("Anzahl angeschlossener Sensoren: ");
    Serial.println(myDS18B20.getDeviceCount(), DEC);
    Serial.println();
 
    for(byte i=0 ;i < myDS18B20.getDeviceCount(); i++) {
      if(myDS18B20.getAddress(DS18B20_Adressen, i)) {
        myDS18B20.setResolution(DS18B20_Adressen, DS18B20_Aufloesung);
      }
    }
  }
   
   delay(1000);
   
}


void loop() {
    //RTC abrufen
    DateTime now = rtc.now();
    //RTC Zeit ausgeben
    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(" ");
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();

    // Zeit in String
    char buf1[] = "hh:mm";
    Serial.println(now.toString(buf1));
    char buf4[] = "MM-DD-YYYY";
    Serial.println(now.toString(buf4));


    //Schreibe das Datum und Uhrzeit auf SD KArte 
    File dataFile = SD.open("datalog.csv", FILE_WRITE);
    // if the file is available, write to it:
    if (dataFile) {
      dataFile.print(buf4);
      dataFile.print(";");      
      dataFile.print(buf1);
      dataFile.print(";"); 
      }    
    dataFile.close();     


  //Wieviel Sensoren sind angeschlossen   
  if ((Anzahl_Sensoren_DS18B20 > 0) and (Anzahl_Sensoren_DS18B20 < 3)) {
    myDS18B20.requestTemperatures();
    
    //Schleife für Messung aller Sensoren
    for(byte i=0 ;i < Anzahl_Sensoren_DS18B20; i++) {
      if (i < myDS18B20.getDeviceCount()) {
    
        Serial.print("Sensor ");
        Serial.print(i+1);
        Serial.print(": "); 
    
        Temperatur[i] = myDS18B20.getTempCByIndex(i);

        // make a string for assembling the data to log:
        String dataString = "";
   
        dataString += String(Temperatur[i]);
        // open the file. note that only one file can be open at a time,
        // so you have to close this one before opening another.
        File dataFile = SD.open("datalog.csv", FILE_WRITE);
    
        //Schreibe die Temp - Werte auf die SD Karte
        if (dataFile) {    
          dataFile.print(dataString);
          dataFile.print(";");  
          if (i == 1){
            dataFile.println("");  
            }    
          dataFile.close();
          // print to the serial port too:
          Serial.println(dataString);
        }
        // if the file isn't open, pop up an error:
        else {
          Serial.println("error opening TempDataLog.csv");
        }

        
        if (Temperatur[i] == DEVICE_DISCONNECTED_C) {
            Temperatur[i] = No_Val;
          Serial.println("Fehler");
       }
            else {
              Serial.print(Temperatur[i]);
              Serial.println(" 'C");
            }        
      }
    }
  }
 Serial.println();

  delay(900000);
}
SSD1306 allocation failed
RTC is running
DS18B20 Test

Initializing SD card...card initialized.
Anzahl aktivierter Sensoren: 2
Anzahl angeschlossener Sensoren: 2

2020/1/24 12:43:5
12:43
01-24-2020
Sensor 1: 23.94
23.94 'C
Sensor 2: 24.31
24.31 'C

2020/1/24 12:58:7
12:58
01-24-2020
Sensor 1: 23.63
23.62 'C
Sensor 2: 24.19
24.19 'C

Hast du dein Display mal allein (eigener Sketch) am Arduino getestet ?

Und prüfe mit einem I2C-Scanner mal die angeschlossenen I2C-Adressen.

HotSystems:
Hast du dein Display mal allein (eigener Sketch) am Arduino getestet ?

Und prüfe mit einem I2C-Scanner mal die angeschlossenen I2C-Adressen.

Hallo Dieter,

ja das habe ich getestet und es läuft super. Die Adresse passt mit 3C auch. Ich glaube das Problem liegt am Speicher. Weiß nur nicht wie ich das Problem löse.

Bist du denn auf den Treiber von Adafruit angewiesen oder geht es auch mit einem anderen, z.B. den von olikraus ?
Mit dem habe ich bisher sehr gute Erfahrungen gemacht und gelesen.

Da wird Dir wohl evtl. ein effektiver Umgang mit dem Speicher (z.B. F-Macro für konstante Texte) oder evtl. auch nur ein Prozessor mit mehr RAM helfen.

Brauchst Du unbedingt Grafik auf dem Display oder genügt auch Text?

Das Display braucht 624 Byte, die SD 512 Byte und dann wird es für den Rest eng.

Gruß Tommy

Hallo,
das Display alleine funktioniert ja anscheinend auch, dann würde ich jetzt mal step by step die Hardware erweitern und imme wieder testen.

wo ist die Zeile display.begin() ich denke die fehlt

Nachtrag hab sie gefunden sorry

Heinz

Nein, auf Grafik bin ich nicht wirklich angewiesen. Fände es zwar nett das Adafruit Logo beim Bootvorganganzuzeigen, letztlich soll allerdings nur Text ausgegeben werden.

@Tommy: Genau das habe ich vermutet, konnte das Problem aber nicht alleine lösen. Warum braucht die SD 512 Byte?

Kann ich eventuell bei den Variablen irgendetwas vereinfachen?

char buf1[] = "hh:mm";
char buf4[] = "MM-DD-YYYY";
String dataString = "";

Hi,

wenn nur ASCII für Dich keine Einschränkung ist, dann probiere mal die Lib hier, benutze ich für die SSD1306 Dinger:


https://github.com/greiman/SSD1306Ascii

Gruß André

SpaghettiCode:
Hi,

wenn nur ASCII für Dich keine Einschränkung ist, dann probiere mal die Lib hier, benutze ich für die SSD1306 Dinger:


https://github.com/greiman/SSD1306Ascii

Gruß André

Habe ich denn keine Chance das über die ADAfruit Lib zu machen. Warum reicht der Speicher des restlichen Programms nicht?

petzlrun:
.....Warum reicht der Speicher des restlichen Programms nicht?

Das hatte dir Tommy doch schon in Post #4 geschrieben.
Evtl. kannst du ja einen anderen Controller verwenden. Z.B. den Wemos D1 mini o.ä.

HotSystems:
Das hatte dir Tommy doch schon in Post #4 geschrieben.
Evtl. kannst du ja einen anderen Controller verwenden. Z.B. den Wemos D1 mini o.ä.

Ich weiß, hatte es allerdings nicht ganz nachvollziehen können.

Das OLED braucht wohl 624 bytes of RAM for its internal buffer (128 * ((32 + 7) / 8)).
Weshalb benötigt das SD Modul 512 bytes?
Der Atmega hat doch 2048? Weshalb reicht der Rest dann nicht?

petzlrun:
Weshalb benötigt das SD Modul 512 bytes?

Weil ein Sektor der SD 512 Byte groß ist. Das kannst Du übrigens alles im Netz finden.
Tipps zum Speichersparen hatte ich Dir auch schon gegeben.

Umsetzen und lernen musst Du allerdings selbst.

Gruß Tommy

Tommy56:
Weil ein Sektor der SD 512 Byte groß ist. Das kannst Du übrigens alles im Netz finden.
Tipps zum Speichersparen hatte ich Dir auch schon gegeben.

Umsetzen und lernen musst Du allerdings selbst.

Gruß Tommy

Mit der Lib von Spagetti Code funktioniert es super. Vielen Dank dafür schon einmal.

Der ATmega hat 2048 bytes zur Verfügung. 624 + 512 = 1136 bytes. Müssten also 912 bytes übrig bleiben.

Diese bleiben für die restlichen Datentypen. Und ich frage mich wo ich am meisten verschwende, um den Rest von 912 bytes zu überschreiten.

Bei ATmega memory use könntest Du etwas lesen und den freien Speicher anzeigen lassen.