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
- 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!
8 comments
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
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
Hi Nicolas, sorry for the delay. I have uploaded code to the article now. I will be interested in hearing how you get on. Cheers & 73 Ade
Hi Adrian
Did you ever post the code for
MULTI-SENSOR REAL-TIME TEMPERATURE MONITORING AND LOGGING SYSTEM USING ARDUINO
Thanks
John
Hi John,
I have updated the article with version 9 of my code. Please check the article now. I will be interested in hearing how you get on.
73 Adrian
Hi Adrian
Thanks,I managed to upload the code and displayed on the LCD very impressed
Regards
John
That’s great John. Pleased you found it helpful.
73 Ade
How many thermal sensors can be used with this? I’m looking to log about 50 simultaneously at roughly 1hz