Reading CPU Temperature and Controlling LED with C++ via sysfs

thermometer

Let’s take a quick look at an example C++ program which reads CPU temperature and controls an LED using sysfs. This example is a bit specific in that it’s only been tested on our NXP i.MX6 powered TS-4900 or TS-7970 running Yocto Linux, but the principles could be applied to other embedded systems as well. If you’re interested in the nitty gritty details about sysfs, take a look at The sysfs Filesystem by Patrick Mochel. Suffice it to say for our purposes, sysfs makes it easy for us to interact with system hardware using plain text files located in the /sys/ directory. The file to control the red LED is /sys/class/leds/red-led/brightness. The file to read the CPU temperature is /sys/class/thermal/thermal_zone0/temp. If we want to turn the red LED on, we simply write a ‘1’ to the file, and not surprisingly, writing a ‘0’ will turn it off. If you’ve booted up your TS-4900 or TS-7970, you can see this by running the shell commands:    Home

echo 1 > /sys/class/leds/red-led/brightness
echo 0 > /sys/class/leds/red-led/brightness

The CPU temperature data is recorded as a 5 digit number. The first two digits represent the temperature in ºC and the remaining three digits are remainders for precision. So, a value of 54321 means 54.321 ºC. You can read the CPU temperature using the system command:

cat /sys/class/thermal/thermal_zone0/temp

Pro Tip: This five digit temperature reading is also known as millicelcius. Best practice would be to keep it in this format for any calculations or comparisons and display it as decimal when ready to display it to a human.

That’s all we need to know in order to create a C++ program, so let’s jump into the code. All of our development will be done onboard, so fire up your TS-4900 or TS-7970 in order to follow along. You can download a tarball of all the demo files here or clone the git repository here. After downloading and extracting, you’ll find a header file, two source files, and a makefile: imx6.h, imx6.cpp, main.cpp, and Makefile.

Pro Tip: Just use ‘wget’ to download the source files directly to the board. This is usually more convenient than using SCP to copy from your desktop to the board as it skips the transferring step.

There’s nothing too special about the files. The imx6.h header file contains all of our function and class declarations while the imx6.cpp source file contains the implementation of the functions and Imx6 class. As far as the implementation details, we’re simply using input and output file streams to write and read from the files in sysfs. For example, the following code block turns the red LED on or off, depending on the input variable:

int IMX6::setLed(int led) {
    ofstream ofile("/sys/class/leds/red-led/brightness");
    ofile << led; 
    ofile.close();
    return 0;
}

And the following code block reads the current LED status:

int IMX6::ledStatus() {
    string val;
    ifstream ifile("/sys/class/leds/red-led/brightness");
    ifile >> val;
    ifile.close();
    return std::stoi(val);
}

You could take it a step further from ofstream  and ifstream  and use a library like libudev, but this was beyond the scope of our simple program.

The main.cpp source file contains our main()  function and calls the functions within the Imx6 class and does something with them. First, we instantiate our Imx6 class using:        Home

IMX6* imx6 = new IMX6();

Then, we demonstrate the use of all the class functions (aka methods):

imx6->setLed(led);
imx6->ledStatus();
imx6->getCurrentTemperature();

Our main function turns on the red LED, reads the temperature for ten seconds, turns off the LED, turns the red LED on another time to demonstrate ledStatus() , and then restores initial LED state before exiting.

The Makefile is included to take the guesswork out of compiling. Simply run make  while in the imx6-demo directory to compile. You can see this in the terminal output below:

root@ts-imx6:~/imx6-demo# make && ./imx6-demo
g++ -std=c++11 -o imx6-demo imx6.cpp main.cpp
Turning on red LED to indicate temperature is being read...
Current temperature: 56.978
Current temperature: 55.894
Current temperature: 55.352
Current temperature: 54.810
Current temperature: 54.810
Current temperature: 54.810
Current temperature: 54.810
Current temperature: 54.268
Current temperature: 54.268
Current temperature: 54.810
Turning off red LED to indicate temperature is no longer being read...
Sleeping for a couple seconds for the next bit...
Turning red LED on for to demonstrate imx6->ledStatus()...
It's on!
Returning red LED to initial state and exiting.
root@ts-imx6:~/imx6-demo#

Running make clean  will delete the imx6-demo file.

Pro Tip: String two commands together by using ‘&&’ logical operator. This way, the second command will only run if the first succeeded. In the case above, imx6-demo  would not run if the make  command failed.

That concludes our simple C++ program to read and write to the sysfs in order to read CPU temperature and toggle the red LED on an NXP i.MX6 powered TS-4900 or TS-7970.

Anything we missed? Something you’d like to point out to the readers? We’d like to encourage you to leave your comments below. They’ll be appreciated!

Home

Downloads:

imx6-demo.tar
embeddedts/imx6-gpio-sysfs-demo

Leave a Reply

Your email address will not be published. Required fields are marked *