Backyard Meteorological Instrumentation

Raspberry Pi 4 Set Up

CPU Temperature Monitor

The objective of this program is to measure the temperature of a computer's CPU and record it to a database. This is primarily of interest for the Raspberry Pi that is mounted in an external enclosure that is exposed to direct sun and possibly air temperatures over 45C in summer.

To allow this data to be analysed, the timestamped temperature readings are stored in a database. This allows the data to be analysed using SQL commands, or the data exported from the database to be graphed for a visual analysis.

The use of this program has two components. The first part is the two database tables used to hold the information about the nodes that may be monitored, and the second part is the program that will run on the node. The two (2) tables were installed in the setup database page.

Database Table Definitions

-- WeatherStation.ws_nodes definition

CREATE TABLE `ws_nodes` (
node_index` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
node_name` varchar(100) NOT NULL,
varchar(100) NOT NULL,
varchar(100) NOT NULL,
varchar(100) DEFAULT NULL,
varchar(100) DEFAULT NULL,
varchar(100) DEFAULT NULL,
PRIMARY KEY (`node_index`),
UNIQUE KEY `node_name` (`node_name`),
UNIQUE KEY `nod_fdn` (`node_fdn`),
UNIQUE KEY `node_ip_address` (`node_ip_address`),
UNIQUE KEY `node_fdn_2` (`node_fdn_2`),
UNIQUE KEY `node_ip_address_2` (`node_ip_address_2`)
0 DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
This table defines the nodes that the system knows about. Only the field names highlighted in purple will be used by this program.

For this program the objective of this table is to map each node name to a unique number. By doing this, testing for a node can be done with a simple number test, rather than having to test all the characters in the a name. It also reduces the amount of data that needs to be stored for each reading, since the  number is generally smaller than the text name.

node_name must match what will be returned if hostname is run from the command line on the node in question.

Below is an example of nodes would be entered into the database. REplace the node-one and node-two with the names of your nodes. If the system does not use an FDN  (Fully Qualified Domain Name), simply repeat the
node_name in the node_fdn. The IP address of the node can be found by running ifconfig.

If you do not want to put in a description, such has the example 'Backyard Meteorological Sensor', you can replace the name with NULL.

INSERT INTO WeatherStation.ws_nodes (node_name,node_fdn,node_ip_address,node_fdn_2,node_ip_address_2,Description) VALUES
'node-one','node-one.development.local','',NULL,NULL,'Main Linux Server, Webserver, RAID'),
'node-two','node-two.development.local','',NULL,NULL,'Backyard Meteorological Sensor');

The table below defines how the observations will be stored in the database.
-- WeatherStation.ws_node_obs definition

CREATE TABLE `ws_node_obs` (
bigint(20) unsigned NOT NULL,
  `date_utc` datetime
tinyint(3) unsigned DEFAULT NULL,
PRIMARY KEY (`obs_index`)
0 DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;

obs_index. A unique index of the observations (not used for this program);

node_index. The node identifier defined in the ws_nodes table.

date_utc. The date the observation was taken. UTC is used because it does not suffer the confusion that can arise with local times when daylight saving is starts or ends.

cpu_temperature. The temperature of the CPU as measured by the chip itself.

fans_enabled.  Active fans bit-mapped into this variable to show what CPU fans are active.

cputempmonitor Program

The cputempmonitor program is written using the Qt development environment which means that the source code can be written that is independent of many of the variations between operating systems - as long as the source code is compiled for the operating system in question. In this case, different operating systems store the file holding the CPU temperature in different files. For a truly general solution, this program should check the type of operating system and adjust that file accordingly, but because this local network only using the Fedora operating system with X86-64 computers and the Raspberry Pi OS with the Raspberry Pis, this program using the CPU type as an analogue of the operating system type.

Since the code uses the name of the computer to determine where the temperature data should be stored, it can be installed on any computer of the type for which it was compiled without any modification, although the fan control software in conjunction with the I/O module should be disabled to prevent unforeseen side effects.

When the fan control hardware and software is being used, the program initcontrolport is used to initialise the I/O control ports when the computer boots. On interest to this program, it sets two pins to control the two Raspberry Pi cooling fans via the O/C Darlington pairs.

The source code for the program can be found here, however, in a nutshell, the program looks up its own name and asks the database for its id number. It then reads the temperature and save its id number, the current datetime (timestamp) and the temperature to the database. When compiled, the program is copied into the directory

This version of
cputempmonitor does not include any timing, so an external method must be used to periodically trigger the process. In this case, it is the ubiquitous cron to the rescue. For the Raspberry Pi in the outside enclosure, the following crontab entry is being used to record the temperature every minute

To start the editing process on each  node in turn:

sudo crontab -e

For the outside Raspberry Pi add the following line to the bottom of the file and save. For all other nodes replace the first
* with */10 so that recording is done every 10 minutes. If the program does not use the fan control, the @reboot line should be omitted.

* * * * * /usr/local/sbin/cputempmonitor

@reboot /usr/local/sbin/initcontrolport

Licenced under Creative Commons Attribution Share Alike 4.0 International or better by Mark Little (2022 - 2023)