Multi-sensor real-time temperature monitoring and logging system using Arduino

In March 2018 I designed and built a multi-sensor, real-time temperature monitoring and logging system using Arduino.

Having built a liquid cooled RF amplifier for 23cm earlier in the year (find the article here), I wanted to build a solution that will enable me to view real-time temperatures and analyse the efficiency of the cooling system using logged data.

KEY REQUIREMENTS

  • Read temperatures from multiple temperature sensors at a pre-defined frequency
  • Apply a software corrective calibration value to each temperature sensor (if required)
  • Display ambient temperature and temperature from each sensor on an LCD display
  • Sound an alarm if one or more temperatures is equal to or greater than a pre-defined temperature value
  • Log ambient temperature, temperature from each sensor and date & time to an SD card at a pre-defined frequency

MY PARTS LIST

Below is  list of parts required for this project:

  • Ardunino UNO board
  • DS3231 Real Time Clock (RTC)
  • Micro SD card module
  • Buzzer
  • Push to make Switch
  • 5 x DS18B20 temperature sensors
  • 4.7K resistor
  • 20 x 4 LCD – I2C version that works using only 4 wires – VCC GND SDA and SCL
  • Female housing connector pins
  • Telephone extension cable wire
  • Nylon M3 spacers and screws
  • 2 x PCB – one to piggy back on the Arduino UNO and the other to mount the components in the box
  • Plywood
  • Breadboard
  • Double sided foam tape
  • Project box
  • Arduino PCB pins
  • Bezel – I obtained the laser cut Bezel from a supplier in the US. It comes complete with clear facia, nuts and bolts. Find the link to this supplier here
  • Heat shrink
  • 2 x pan head screws
  • 2 x raw plugs

CIRCUIT DESIGN USING FRITZING

Fritzing is a fantastic free open source application that I used for designing my Arduino temperature logging application. More information here

My Fritzing file coming soon.

DESIGN LAYOUT USING BREADBOARD

After designing the circuit in Fritzing I built it using a breadboard. At this stage I made a few modifications so it was much easier to do this using the breadboard.

ARDUINO LIBRARIES

Prior to starting development I looked at functionality of the built-in libraries in the Arduino IDE. I found that both Wire.h and SD.h met requirements and could be used as standard with no modification.

This meant I still needed something to communicate to the LCD, OneWire devices, DS18B20 temperature ICs and the RTC. I searched the Internet for libraries that any of the Arduino developer community had developed and shared. I wasn’t long before I found four additional libraries that met the requirements of what I wanted to do so I downloaded and installed these in the Arduino IDE. Thank you to those that developed and shared the code.

WIRE LIBRARY

Standard wire library installed as part of Arduino IDE. Allows you to communicate with I2C / TWI devices.

SD CARD LIBRARY

Standard wire library installed as part of Arduino IDE. For reading and writing SD cards.

LIQUID CRYSTAL LIBRARY

Find the library here. Derivative of the original LiquidCrystal Library. Faster and supports I2C.

ONEWIRE LIBRARY

Find the library here. Lets you access 1-wire devices made by Maxim (previously Dallas).

DALLAS TEMPERATURE LIBRARY

Find the library here. For Maxim (previously Dallas) DS18B20  temperature ICs.

REAL TIME CLOCK LIBRARY

Find the library here. To easily interface and use the DS3231 RTC.

CODE VERSIONS

[code language="csharp"]

Temperature logging application for 23cm liquid cooled RF amplifier

Version 9

Created April 2018

By Adrian Leggett - amateur radio callsign M0NWK

This example code is in the public domain.

Using Arduino UNO, 4 x DS18B20 temperature sensors,DS3231 Real Time Clock (RTC), Micro SD card module
and 20 x 4 Liquid Crystal Display (LCD) this sketch:

- Calibrates all four sensors individually
- Calibrates all four sensors globally to align to alternative calibrated temperature sensor
- Reads temperatures from all four sensors at a frequency specified
- Displays all four temperatures on the LCD simulaneously
- Writes all four temperatures to the serial monitor with date and time stamp
- Writes all four temperatures to the SD card (if inserted and initialised) with date and time stamp
- Set overheat temperature for each sensor
- Warning alarm if specified overheat temperature exceeded - auto on / off

The circuit:
- Details on website. URL below.

Full details of this project here:

http://www.m0nwk.co.uk/workshop/multi-sensor-temperature-logging-application-using-arduino
*/

/*-----( Import libraries )-----*/

#include <Wire.h> // Standard with Arduino IDE
#include <LiquidCrystal_I2C.h> // Developed by Francisco Malpartida
#include <OneWire.h> // 
#include <DallasTemperature.h> // Developed by Miles Burton
#include <SD.h> // Standard with Arduino IDE
#include <DS3231.h>
#include <SPI.h>

// Set the 20x4 LCD I2C address
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

#define ONE_WIRE_BUS 7 // Data wire from DS18B20 1-Wire Digital Thermometer Sensor

OneWire oneWire(ONE_WIRE_BUS); // Setup oneWire instance to communicate with OneWire devices

DallasTemperature temp_sensors(&oneWire); // Pass Dallas Temperature oneWire reference of temp_sensors

DS3231 rtc(SDA, SCL);

/*-----( Declare Constants )-----*/

const int warning_alarm = 9; // Overheat warning alarm set to use arduino pin 9
const int chipSelect = 10; // Set arduino pin 10 as the Micro SD card adaptor CS pin

/*-----( Temperature sensor calibration constants )-----*/

const float temp_calibration_1 = 1; // Individual temperature sensor calibration value - must be 1 if not required
const float temp_calibration_2 = 1; // Individual temperature sensor calibration value - must be 1 if not required
const float temp_calibration_3 = 1; // Individual temperature sensor calibration value - must be 1 if not required
const float global_calibration = 1; // Global temperature sensor calibration value that will apply to all calibrated sensors - for calibrating using known good sensor

/*-----( Warning alarm array )-----*/

double warningAlarm[4] = {26, 27, 28, 29};

/*-----( Setup - runs once on Arduino power up or press of reset button )-----*/

void setup() 
{

/*-----( Initialisations )-----*/

Serial.begin(9600); // Start the serial port
lcd.begin(20,4); // initialize the lcd for 20 chars 4 lines
rtc.begin(); // Initialise the DS3231 RTC AT24C32 I2C precision real-time clock 

/*-----( Set DS3231 date / time - uncomment lines if required )-----*/

//rtc.setDOW(SATURDAY); // Set Day-of-Week DDD
//rtc.setTime(06, 44, 00); // Set the time to HH:MM:SS (24hr format)
//rtc.setDate(16, 6, 2018); // Set the date to DD.MM.YYYY

/*-----( Initialisation messages )-----*/

Serial.println("Liquid cooled 23cm RF amplifier temperature logger started"); // Print start message
Serial.println();
Serial.println("Version 9 - June 2018");
Serial.println();
Serial.println("By Adrian Leggett - amateur radio callsign M0NWK");

lcd.setCursor(2,1); // Set cursor position on LCD
lcd.print("Temp Logger v9"); // Print msg to LCD
delay(1000); // Wait 1000ms
lcd.clear(); // Clear the LCD

lcd.setCursor(4,0); // Set cursor position on LCD
lcd.print("By A Leggett"); // Print msg to LCD
lcd.setCursor(3,2); // Set cursor position on LCD
lcd.print("Callsign M0NWK"); // Print msg to LCD
delay(1000); // Wait 1000ms
lcd.clear(); // Clear the LCD

lcd.setCursor(0,0);
lcd.print("Date:");
lcd.setCursor(6,0); // Set cursor position on LCD
lcd.print(String(rtc.getDateStr()));
lcd.setCursor(0,2);
lcd.print("Time:");
lcd.setCursor(6,2); // Set cursor position on LCD;
lcd.print(String(rtc.getTimeStr()));
delay(5000);
lcd.clear();

/*-----( Check SD card is present and can be initialised )-----*/

lcd.setCursor(2,1); // Set cursor position on LCD
lcd.print("Checking SD Card"); // Print msg to LCD
delay(1000); // Wait 1000ms
lcd.clear(); // Clear the LCD

/*-----( SD card initialisation failure )-----*/

if (!SD.begin(chipSelect)) // If SD card NOT initialised 
{
Serial.println(); // Print blank line 
Serial.println("** SD card failed, or not present **"); // Print failure message to log
lcd.setCursor(1,1); // Set position of cursor to 0,0 on LCD // Set cursor position on LCD
lcd.print("SD card not found!"); // Print failure message to LCD
delay(1000); // Wait 3000ms
lcd.clear(); // Clear the LCD
return; // Terminate the function 
}
/*-----( SD card initialisation success )-----*/ 
Serial.println();
Serial.println("SD card ready!"); // Print success message to log
lcd.setCursor(3,1); // Set position of cursor to 0,0 on LCD // Set position of cursor on LCD
lcd.print("SD card ready!"); // Print success message to LCD
delay(1000); // Wait 3000ms
lcd.clear();

// Clear the LCD
temp_sensors.begin(); // Start the library up
pinMode(warning_alarm, OUTPUT); // Set warning_alarm - pin 9 as an output // Sets the warning alarm pin to 9 as output
}

/*-----( loop - program runs until Arduino power down )-----*/

void loop(void)
{
temp_sensors.requestTemperatures(); // Get temperatures from sensors serial

double tempID[4] = {};
String warnAlarmCondition = " ";
Serial.println();
Serial.print(String(rtc.getDateStr()) + String(" ") + String(rtc.getTimeStr() + String(" ")));
int y=0;

for (y = 0; y < 4; y++)
{
tempID[y]=temp_sensors.getTempCByIndex(y);
if (y==0){
tempID[y]=(tempID[y] * global_calibration);
}

else
{
tempID[y]=((tempID[y] * temp_calibration_1) * global_calibration);
}

Serial.println();
Serial.print(String("Temp ") + (y + 1) + String(":") + tempID[y]);
lcd.setCursor(0,y); // Set position of cursor to 0,0 on LCD
lcd.print(String("Temp ") + (y+1) + (": ") + tempID[y] + ((char)223) + String("C")); // Write Temp: XX.XX deg C to LCD

/*-----( Warning alarm if temperature sensor of any sensor exceeds set value )-----*/

if (tempID[y] > warningAlarm[y]){
lcd.setCursor(17,y); // Set position of cursor to 0,0 on LCD
lcd.print(String("*")); // Write Temp: XX.XX deg C to LCD
warnAlarmCondition="true";
}

else{
lcd.setCursor(17,y); // Set position of cursor to 0,0 on LCD
lcd.print(String(" ")); // Write Temp: XX.XX deg C to LCD
}
}

Serial.print(warnAlarmCondition);
if (warnAlarmCondition == "true"){
tone(warning_alarm, 1000); 
}

else{
noTone(warning_alarm);
delay(5000);
}

lcd.clear();
lcd.setCursor(0,0);
lcd.print("Temp 5:");

lcd.setCursor(0,1);
lcd.print("Temp 6:");
lcd.setCursor(6,1); // Set cursor position on LCD;

delay(3000);
lcd.clear();

lcd.setCursor(0,0);
lcd.print("Date:");
lcd.setCursor(6,0); // Set cursor position on LCD
lcd.print(String(rtc.getDateStr()));
lcd.setCursor(0,2);
lcd.print("Time:");
lcd.setCursor(6,2); // Set cursor position on LCD;
lcd.print(String(rtc.getTimeStr()));

File dataFile = SD.open("temp_log.txt", FILE_WRITE);

if (dataFile) {
dataFile.print(String(rtc.getDateStr()) + String(" ") + String(rtc.getTimeStr() + String(" ")));
dataFile.print(String("Temp 1: ") + String((temp_sensors.getTempCByIndex(0)* global_calibration) + String(" ")));
dataFile.print(String("Temp 2: ") + String(((temp_sensors.getTempCByIndex(1)* temp_calibration_1) * global_calibration) + String(" ")));
dataFile.print(String("Temp 3: ") + String(((temp_sensors.getTempCByIndex(2)* temp_calibration_2) * global_calibration) + String(" ")));
dataFile.print(String("Temp 4: ") + String(((temp_sensors.getTempCByIndex(3)* temp_calibration_3) * global_calibration) + String(" ")));
dataFile.println();
dataFile.close();
}

else {
Serial.println();
Serial.println("** Error - cannot write to SD card **");
}
Serial.println();
delay(3000);
}

/* ( END ) */

/code]

PCB DESIGN

After finalising the circuit design, I designed a PCB to piggy back onto the Arduino UNO board using Adobe Photoshop.

PCB DOWNLOAD

Below is link to a PDF of my PCB design:

m0nwk_temp_PCB_v1.0_20180620.pdf

ETCHING THE PCB

I etched the PCB using a press-n-peel film technique. In March 2017 I made a YouTube video that shows how this technique works.

The picture below shows my etched PCB. I used a metal file to clean up the edges.

WIRING THE CIRCUIT

I started out using 28 AWG rainbow ribbon wire but the wire diameter was too small and I found it broke easily after being soldered. I had a length of telephone extension cable with six wires of small gauge in my workshop so used this instead. This proved to be perfect because it was flexible, can be twist easily and is strong.

Once all of the soldering was finished I lacquered the PCB.

FINALISED DESIGN LAYOUT

With all of the wires soldered to the PCB I crimped on female housing connector pins, inserted them to the housing and connected everything up. I retained the reset switch, buzzer and temperature sensors on the breadboard because they will be installed later. Using double sided foam tape I fastened each of the components to a piece of plywood.

Below is a photo of  the Micro SD card module.

And one of the RTC (Real Time Clock).

This is a close up photo of the PCB piggy backed onto the Arduino with wires soldered in place.

And finally one of the reset switch, buzzer and temperature sensors on the breadboard.

PREPARING THE CASING

The first thing I needed to do was to make a cut out for the LCD display. I measured the size of the LCD and marked the box using a vernier caliper. I then placed the box in my vice, ensuring the alloy was protected with thin cardboard. Using a 10mm drill I made a number of holes in the alloy.

I used a hacksaw to remove the majority of the alloy before using a file to file the edges.

The photo below shows the completed cut-out.

I centralised the bezel and marked the four corner holes. Using an M3 drill bit I drilled the holes and then fastened the LCD, clear plastic screen and outer bezel in place.

This photo shows how the LCD is mounted on the inside.

My project box has inner slots for inserting PCB. I measured the internal dimensions using a vernier caliper before cutting a piece of single sided PCB to size.

I then etched the PCB to remove all copper.

Using double sided foam tape I attached all of the components to the PCB.

When I cut the PCB I made sure it was exact, finishing off with a metal file to ensure a tight fit.

I then cut out a hole for the Arduino USB connector using a drill and jewellers files.

This photo shows the PCB containing all of the components inserted into the box and both ends attached.

With all of the components in place I decided on a location for the buzzer and marked two holes for the pins using a marker pen.

Using a pin vice and small drill bit I drilled the two holes and using double sided foam tape attached it to the PCB.

I then soldered on the alarm wires from the PCB before heat shrinking the connections.

I added a push to make switch for the reset. Pushing it will temporarily connect the reset pin to ground and restart code loaded on the Arduino.

The project box has a sliding cover which I decided to use as the back. After measuring the head and shank of the screw I was using to mount the box to the wall, I drilled holes slightly larger than the head and then filed slots to slide the shank into.

Using my Vernier caliper and spirit level I measured the position of the holes ensuring they were level. I then drilled the holes, inserted a raw plug and inserted the pan head screws.

More to come soon!

 

You may also like

8 comments

  1. Hi,

    Nice project ! I would realize exactly the same to check the temperature in heating system in my multi appartment building.

    Where can I download the code ?

    Many, many thanks !!!

    Nicolas

    1. Hi Nicolas, thanks for your message. I thought I had uploaded the code but appears I didn’t do it. Please give me a day or so and I will add it and let you know. Cheers Ade

  2. Hi Adrian
    Did you ever post the code for
    MULTI-SENSOR REAL-TIME TEMPERATURE MONITORING AND LOGGING SYSTEM USING ARDUINO
    Thanks
    John

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.