Show system temperature on a mini i2c (9E6018A0) screen via Arduino Nano
Table Of Contents
Introduction
This is a project showing
- How to wire the I2C display to an Arduino
- How to retrieve the CPU temperature (or other values) from Linux’s sysfs
- How to use the RS232 library by wjwwood
- How to connect to the Arduino Nano and send data
- How to receive data in Arduino
- How to display data through the nice graphics library by Adafruit —— (also how to scribble with that library)
We will build a minimal C++ console application that retrieves a temperature value from Linux’s sysfs and sends it to a serial port. Then we will see how to wire the I2C screen to an Arduino Nano where we’ll upload our own sketch that reads the incoming value from the serial stream and renders it, with the help of some Adafruit’s libraries, to the 9E6018A0 screen. Moreover we will fill the screen with useless but cool looking graphics.
Requirements
- A Linux system
- Arduino Nano
- I2C Display 9E6018A0 *
- 4 wires
- USB cable
- Breadboard
*: Can be sourced at AliExpress but many other screens are compatible with the Adafruit library, including excellent Adafruit ones.
Prerequired Knowledge
- Basic C++
- Arduino programming
- A sprout of confidence with Linux
Part 1: retrieving system information
sysfs
The principle behind retrieving hardware information is extremely simple in Linux where, in case you haven’t been told enough already, everything is a file. Even the CPU temperature or the system fan’s speed.
From Wikipedia: sysfs is a pseudo file system provided by the Linux kernel that exports information about various kernel subsystems, hardware devices, and associated device drivers from the kernel’s device model to user space through virtual files.[1] In addition to providing information about various devices and kernel subsystems, exported virtual files are also used for their configuration.
Interesting locations to find such informative files are /proc and /sys/class/. If you take a moment to explore these directory trees, you should have at least an intuition on what information each file contains and what device they refer to. Of course you’ll find some cryptic naming but in general, you should have a grasp on how it works.
For example /sys/class/thermal/thermal_zone0/temp is the 1st CPU’s current temperature.
Simply using cat
, we can print the file’s contents and thus get one read of the current CPU temperature.
cat /sys/class/thermal/thermal_zone0/temp
If we want a recurrent reading, the command watch
can be of great help.
watch cat /sys/class/thermal/thermal_zone0/temp
Note: watch
will also be extremely useful later to quickly find out if our program is printing out the correct values.
Links
Reading files in C++
Opening a file for reading
|
|
Reading a value from a file
|
|
Resetting the reading to the start of the file
|
|
Part 2: Temperature reading and serial communication in C++
RS232 library
There’s many serial libraries around and many of them are good. The one developed by GitHub’s user wjwwood seems to be one of the most widely adopted.
Links
Opening a serial port
In the following example I use the ttyUSB0 port but your serial device might be connected to a different one. To find out which is the right one these commands can be useful:
lsusb
ls /dev/tty*
|
|
Sending a byte to serial device
|
|
And that’s all we need for now.
C++ full code
|
|
Building the C++ application
To build you need g++
and optinally make
Build with the following command
g++ SerialDisplaySysInfo.cpp rs232.c -o SerialDisplaySysInfo
where SerialDisplaySysInfo.cpp is the main file containing the code above.
or create the following makefile
|
|
and launch make
.
The rs232.h and .c must be in the same folder as the SerialDisplaySysInfo.cpp.
Part 3: Wiring Screen to Arduino Nano
Remember: i2c standard pins, SDK (aka SDL) and SDA are respectively on A5 (clock) and A4 (data)
Wiring Pins
Screen | Nano |
---|---|
GND | GND |
VDD | 5V |
SDK | A5 |
SDA | A4 |
Part 4: Adafruit graphics library
These Adafruit libraries for Arduino do a lot of magic for us. They hide all technicalities letting us skip the technical documentation while leaving us with an elegant set of functions to easily draw graphic elements on screen.
SSD1306’s (very) technical documentation by Adafruit
Include files and initialization
At the start of our Arduino sketch:
|
|
In this article we don’t use the GFX core library.
To initialize our library we create a display
object:
|
|
In the setup
function:
|
|
We can now use the functions to draw on the screen. For example:
|
|
and then there’s drawLine
, drawCircle
, fillCircle
, setFont
to change the current text font, println
to write text, and on and on. Exploring the Adafruit_SSD1306.h file will give you a good overview of all available methods.
Part 5: Arduino Coding
Finding the i2c address
The Arduino IDE, as you know comes with a big set of examples and a few of them do serve an actually useful purpose.
To find the I2C address of an I2C device that’s connected to the Arduino we can use a very handy I2C scanner that can be found in File > Examples > Wire > i2c_scanner
If you upload this sketch to the Arduino and let it run from a serial terminal, assuming all is wired correctly, you’ll see the addresses of all I2C connected devices.
Arduino full sketch
The following example should work on all SSD1306 screens. It would have to be adapted for screens with different resolutions.
The code is a merge of examples I found online and code I did for this tutorial. Part of the code is made by InterlinkKnight. You can find more of his stuff in his website.
I intentionally left a lot of commented out calls so one can have more handy examples to play with.
|
|
Conclusions
We took a good little journey touching the different areas that this kind of prototyping requires: serial communication between a C++ application and an Arduino including the use of Adafruit libraries to obtain some cool graphics on such a cool little, cheap screen such as the 9E6018A0. We used it to show the current temperature of one of the CPU cores. Much more can be done with different values coming from your Linux system and sensors. I hope you felt at least as satisfied as I was in putting this simple project together and I wish you to be inspired to do more.
Please, if you want to show appreciation or found something that should be improved in the article, have your say using the Contact form.
Of course if you’d like to share this article with your communities, more good wishes to you!
Thanks for reading.
Further reading
Troubleshooting
Cannot open serial port / Permission denied
By default, if you try non-root access to any device in /dev, you’ll be denied permission. That’s because by default, non-root users are not part of the dialout group. dialout is the group that allows access to modems and all serial interfaces. The solution is to add your current user to the group.
sudo usermod -a -G dialout $USER
Restart the system.
See also: https://askubuntu.com/questions/133235/how-do-i-allow-non-root-access-to-ttyusb0