problem combining digital thermometer with sd card and oled on uno

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();
}
}

temp sensor to oled and sd card.jpg

digital_temp_sensor_to_oled_with_sd_logging_not_working.ino (3.11 KB)

temp sensor to oled and sd card.jpg

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

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.

TEST.TXT (9.64 KB)

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.

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

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.

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.

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.

pj3:
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.

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

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/

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();
}
}

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.

pj3:
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.

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.

You might be able to begin the OLED display at full size before you being the SD instance, that might then allow you to blank the whole display before ending the display instance, opening the SD and the smaller OLED part. Just an idea

OK so I did the following
1 Used integer for temperature so ditched the decimal places
2 reduced the sensor resolution to 9 bit
3 Changed the display to 126 x 24
4 Used a text size of 3 for temperature and 2 for "(C)" getting rid of Ist line

I now have a usable display and SD logging correctly. Still have the odd random dots in last column to work on. I could possibly steal some from the library files but out of my depth at the moment. Will look at your suggestion. :slight_smile:

I don’t know what it is, but I think there is something else going on. If that display and an SD card can’t work together on a Uno in the manner you, and everybody else, would expect, we would all know about it by now. In short, your original project is normal, and the compromises you have made are unreasonable.

The only thing I can suggest is that I think you are wasting memory and processing grunt by using a graphics library to produce text. This might help
https://forum.arduino.cc/?topic=510106#msg3601641
I don’t know how much difference it actually makes to resources demand. It is the only method I have used.

Thanks Nick looks like a good avenue to investigate. Good learning exercise for me all round.