OK, I could have just bought something already. In the end, it is just a thermometer :)
Nevertheless, it happens that I bought in the recent past a few random pieces for my Arduino, just to fill some dead time in my days eventually.
So, today I wanted to continue my data logger project by adding an OLED screen to visualise temperature and humidity in real-time. To do that, I went through some challenges:
My Arduino UNO has limited memory, so I couldn't allocate memory for the OLED screen initially.
Then I moved some string onto the Arduino flash memory but wasn't enough. Then, I found an alternative library that uses less memory, but now I had some issues with the RTC library; specifically, the date and time were reset :(
Once I made it past these two points, I noticed that the log file on my Windows system was reporting the wrong date and time of creation!
Here is the solution I came up with (thanks google).
The wiring
But first, as usual, here is the wiring for this project:
Move strings to flash memory and use a light library for the OLED screen
When we print something onto the serial monitor through the "Serial.print()" function, the string is normally saved in the RAM memory (). If we print many strings, our microcontroller RAM can run out of space. We can decide to save those strings in the FLASH memory. To do that, we can use the F() macro. Hence:
from: Serial.print("I'm printing into the RAM")
to: Serial.print(F("I'm printing into the FLASH memory"));
This can help to free a bit of RAM, but in my case, I still couldn't allocate enough memory for my OLED screen functioning. In the end, I ended up using the U8x8 library. Let's install it: Sketch â include library â manage libraries â type U8g2 in the search bar and install it.
When using U8x8lib, my data logger lost date and time
Per se, the library was really easy to use for my purpose. I just wanted to display the current temperature, humidity, date, and time.
// for oled - library that uses reduced memory
#include <U8x8lib.h>
U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8( /* reset=*/ U8X8_PIN_NONE);
void setup() {
// initialise the oled
u8x8.begin();
}
void loop() {
// now set the font and then
// the cursor position
// and print the text and variables to the OLED
u8x8.setFont(u8x8_font_amstrad_cpc_extended_r);
u8x8.setCursor(0, 0); // col, raw
u8x8.print("Temp:");
u8x8.setCursor(6, 0);
u8x8.print(t);
u8x8.setCursor(0, 2);
u8x8.print("Hum:");
u8x8.setCursor(6, 2);
u8x8.print(h);
u8x8.setCursor(0, 5);
u8x8.print("Date:");
u8x8.setCursor(6, 5);
u8x8.print(current_date_oled);
u8x8.setCursor(0, 7);
u8x8.print("Time:");
u8x8.setCursor(6, 7);
u8x8.print(current_time);
}
Pretty neat; after importing the library, and initialising it, we use "u8x8.setCursor(col_no, raw_no)" to get to the "writing position". Then through the "u8x8.print("text_or_variable")" command, we write what we want to display on the OLED screen.
For some reason though, the date and time I set in the previous example, was getting lost every time I flashed the new script (btw, you can find it here). Honestly, I don't remember what I did to make it not working :) it was late, but I know how it is working now.
Basically, in my setup() loop, the first time I flashed the new program I also added these lines:
rtc.begin();
rtc.adjust(DateTime(__DATE__, __TIME__));
In this way, I set on my Arduino the current date and time as it appears on my PC OS. Soon after, I flash again the script by changing the above lines like so:
rtc.begin();
if (!rtc.isrunning()) {
Serial.println("RTC is NOT running!");
rtc.adjust(DateTime(__DATE__, __TIME__));
}
In this way, I check if there is already a real-time clock running, and only if not, I update the date and time (well, probably I could have removed all the "if" directly). This is because otherwise, every time that I plug my device somewhere, the time would mess up. Is it the best way? Don't know đ€, but it works đ!
Correct log file creation date
After these troubles, my data logger was logging the data as I wanted, my display was displaying the data as I wanted, but I noticed that the log file data and time creation was missing; the log file/s were dated at a very early night somewhere in the year 2000.
I solved it by adding this function before the setup() loop:
void dateTime(uint16_t* date, uint16_t* time) {
DateTime now = rtc.now();
// return date using FAT_DATE macro to format fields
*date = FAT_DATE(now.year(), now.month(), now.day());
// return time using FAT_TIME macro to format fields
*time = FAT_TIME(now.hour(), now.minute(), now.second());
}
and then by calling it before creating the file log:
SdFile::dateTimeCallback(dateTime);
Basically, the SD.h library I am using to log data onto the SD doesn't set the attributes of the log file because it doesn't have a way to know the date and time. With that callback, we set the attributes with the correct date and time.
In my case, I call the dateTime() function only once, before creating the log file the first time, because, as I open it, modify it, and close it every 1 second, it would always record the latest date and time. I want to only see when the log file was created the first time (and yes, I do have the first and last date and time anyway logged into the log file).
OK, so finally, there is everything, and it is working đ„ł
ăłăĄăłă