Go Down

Topic: problem combining digital thermometer with sd card and oled on uno (Read 380 times) previous topic - next topic

pj3

Hi all if anyone can help I would appreciate it.  I have a one wire digital temperature sensor.   I want to display the temperature onto an 0.9 "OLED display whilst recording the readings to an SD card.  I have compiled programs independently to get each working successfully but when I try to combine them  I get an allocation error from the oled.  Is it a memory problem or comms messing up?

 /**************************************************************************
    This is an example for our Monochrome OLEDs based on SSD1306 drivers
 
    Pick one up today in the adafruit shop!
    ------> http://www.adafruit.com/category/63_98
 
    This example is for a 128x64 pixel display using I2C to communicate
    3 pins are required to interface (two I2C and one reset).
 
    Adafruit invests time and resources providing this open
    source code, please support Adafruit and open-source
    hardware by purchasing products from Adafruit!
 
    Written by Limor Fried/Ladyada for Adafruit Industries,
    with contributions from the open source community.
    BSD license, check license.txt for more information
    All text above, and the splash screen below must be
    included in any redistribution.
   **************************************************************************/
  #include <OneWire.h>
  #include <SPI.h>
  #include <SD.h>
  int chipSelect = 6;
  File mySensorData;
  #include <Wire.h>
 
  #include <Adafruit_GFX.h>
  #include <Adafruit_SSD1306.h>
  #define ONE_WIRE_BUS 2
  OneWire oneWire(ONE_WIRE_BUS);
  #include <DallasTemperature.h>
  DallasTemperature sensors(&oneWire);
  #define SCREEN_WIDTH 128 // OLED display width, in pixels
  #define SCREEN_HEIGHT 64 // 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);
 
 
  void setup() {
    Serial.begin(9600);
    sensors.begin();  // Start up the library
    SD.begin(chipSelect);
    // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
 if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3c)) { // Address 0x3D for 128x64
   Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
 
  }
    display.clearDisplay();
 
    display.display();
    delay(2000);
  }
 
 
 
  void loop() {
 
 
    sensors.requestTemperatures();
    //Serial.print("Temperature: ");
    mySensorData = SD.open("test.txt", FILE_WRITE);
    if (mySensorData) {
      //Serial.print(sensors.getTempCByIndex(0));
      //Serial.print((char)176);//shows degrees character
     // Serial.print("C  |  ");
 
      //print the temperature in Fahrenheit
      //Serial.print((sensors.getTempCByIndex(0) * 9.0) / 5.0 + 32.0);
      //display.println(sensors.getTempCByIndex(0));
     // Serial.print((char)176);//shows degrees character
      //Serial.println("F");
 
      delay(500);
     display.clearDisplay();
      sensors.requestTemperatures();
    display.setTextSize(2);      // Normal 1:1 pixel scale
    display.setTextColor(SSD1306_WHITE); // Draw white text
    display.setCursor(15, 0);
      display.println("Temp (C)");
     display.setTextSize(4);
    display.setCursor(5, 30);
     display.println(sensors.getTempCByIndex(0));
 
      display.display();
      mySensorData.println(sensors.getTempCByIndex(0));
    mySensorData.close();
  }
}








Nick_Pyner

No 4k7 pullup for DS18B20? What is the real address of the display? Ox3D?

pj3

#2
Nov 24, 2020, 11:38 am Last Edit: Nov 24, 2020, 02:17 pm by pj3 Reason: showing oled working
Hi Nick thanks for your reply.  The digital thermometer works great reporting to the OLED until I include code for the SD card.  Also the SD  works great saving temperatures etc till I include code for the OLED.   I try to marry the 2 codes and get  the allocation error.


countrypaul

What Arduino are you using this with? The Oled display requires 1KB ram and the SD card will require at least 512B, that leaves only 512KB for everything else assuming your Arduino has 2KB.  Can you post up the output that shows the error message there should be a button at the rhs of the IDE to copy the serial output so you can post it on here.

Nick_Pyner

What I was commenting on was
Code: [Select]
if(!display.begin(SSD1306_SWITCHCAPVCC, [b]0x3c[/b])) { // Address [b]0x3D[/b] for 128x64which may not be relevant(!).

pj3

Hi 

Its not a compile error since it compiles and uploads.  I first tried it on a NANO  then tried a UNO  but both compile and upload but no flashing sensor,  showing its not sending data.   Check with Monitor and it shows "SSD1306 allocation failed".   So it appears that its not allocating memory and failing early on in the program.  I have googled this and it would seem no-one has put the two devices together.  I wanted to make a temperature display on my shed visible from the house with data logged to SD for future analysis.   I have sent for a weather station kit but cant help feeling frustrated with it. 


  

countrypaul

The buffers are quite likely to be allocated dynamically in the class constructor, and 126x64/8 would be 1024 bytes out of the 2048 a Nano or Uno has. The SD card buffer if I recall is 512 bytes, and there will be buffers for the SPI and onewire also required which can easily top the 2048 bytes you have. Put a call into the memory functions to tell you how much is free just before you try and begin the display.

pj3

This is the compile report.  Not sure how to check free memory before display begin.




Sketch uses 26064 bytes (80%) of program storage space. Maximum is 32256 bytes.
Global variables use 1256 bytes (61%) of dynamic memory, leaving 792 bytes for local variables. Maximum is 2048 bytes.

Nick_Pyner

Hi

Its not a compile error since it compiles and uploads.   
I'm not talking about compile error. If you call the wrong address, no compiler will save you.

If you are running out of memory at compile time, the IDE will tell you that - and it hasn't.

pj3

Nick the 3C address works on the stand alone sketch 3D doesn't.   Is that what you mean?

countrypaul

Since you only have 792 bytes free that won't be enough to allocate the 1024 needed by the display.begin call. You could try changing
#define SCREEN_WIDTH 128
to say 16 just to see whether it can then pass that point.

There is a library for looking at the meory usage at runtime, have a read of this article: https://forum.arduino.cc/index.php?topic=551905.0

Also look at this: https://playground.arduino.cc/Code/AvailableMemory/

pj3

Genius Country Paul  great thinking.   I actually got to SCREEN_WIDTH 80,   SCREEN_HEIGHT 32 with text sizes of 1 and 2 to give a usable display and logging to SD.   Now if anyone can scavenge a bit more memory  I will be on a winner.  Thanks all.  Solution below.  Could use smaller display I suppose but I have this one available and OLED is bright.

 
  /**************************************************************************
    This is an example for our Monochrome OLEDs based on SSD1306 drivers
  
    Pick one up today in the adafruit shop!
    ------> http://www.adafruit.com/category/63_98
  
    This example is for a 128x64 pixel display using I2C to communicate
    3 pins are required to interface (two I2C and one reset).
  
    Adafruit invests time and resources providing this open
    source code, please support Adafruit and open-source
    hardware by purchasing products from Adafruit!
  
    Written by Limor Fried/Ladyada for Adafruit Industries,
    with contributions from the open source community.
    BSD license, check license.txt for more information
    All text above, and the splash screen below must be
    included in any redistribution.
   **************************************************************************/
  #include <OneWire.h>
  #include <SPI.h>
  #include <SD.h>
  int chipSelect = 4;
  float temp=0;
  File mySensorData;
  #include <Wire.h>
  
  #include <Adafruit_GFX.h>
  #include <Adafruit_SSD1306.h>
  #define ONE_WIRE_BUS 2
  OneWire oneWire(ONE_WIRE_BUS);
  #include <DallasTemperature.h>
  DallasTemperature sensors(&oneWire);
  #define SCREEN_WIDTH 80 // 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     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
  
  
  void setup() {
    Serial.begin(9600);
    sensors.begin();  // Start up the library
    SD.begin(chipSelect);
    // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
 if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
   Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
  
  }
    display.clearDisplay();
  
    display.display();
    delay(2000);
  }
  
  
  
  void loop() {
  
  
    sensors.requestTemperatures();
    //Serial.print("Temperature: ");
    mySensorData = SD.open("test.txt", FILE_WRITE);
    if (mySensorData) {
      //Serial.print(sensors.getTempCByIndex(0));
      //Serial.print((char)176);//shows degrees character
     // Serial.print("C  |  ");
  
      //print the temperature in Fahrenheit
      //Serial.print((sensors.getTempCByIndex(0) * 9.0) / 5.0 + 32.0);
      //display.println(sensors.getTempCByIndex(0));
     // Serial.print((char)176);//shows degrees character
      //Serial.println("F");
  Serial.print(temp);
      delay(500);
     display.clearDisplay();
      sensors.requestTemperatures();
    
    display.setTextSize(1);      // Normal 1:1 pixel scale
    display.setTextColor(SSD1306_WHITE); // Draw white text
    display.setCursor(15, 0);
      display.println("Temp (C)");
     display.setTextSize(2);
    display.setCursor(15, 10);
     //display.println(sensors.getTempCByIndex(0));
  temp=sensors.getTempCByIndex(0);
     display.println(temp);
      display.display();
     // mySensorData.println(sensors.getTempCByIndex(0));
    mySensorData.println(temp);
    
    mySensorData.close();
  }
}

countrypaul

You might gain a little by dropping the Dallas temperature library and just reading the ds18B20 yourself: https://playground.arduino.cc/Learning/OneWire/
No idea if it is worthwhile or not though.


Nick_Pyner

Nick the 3C address works on the stand alone sketch 3D doesn't.   Is that what you mean?
Yes. I was just pointing out that you might have called the wrong address. Since they are on different buses, there should be no clash between SD and OLED.

pj3

Countrypaul  I will look into your ideas thanks.  One thing I notice is that I now get random pixels lit up in the unassigned screen area.   Looking at how to clean it up.

Go Up