4 channel temperature logger based on the DS18B20 sensors
In this video I show you my recent build which is a 4 channel temperature logger based on the DS18B20 sensor. The full system consists of an Arduino Nano, a micro SD card slot, 4x DS18B20 thermometers, a toggle switch and a 128x32 OLED display. It was relatively easy to build and program the circuit, however, I was struggling a bit with the boxing. It was a bit too crowded in the enclosure due to the large amount of cables.
Wiring diagram
The connections are fairly simple. The SD card reader used the SPI protocol and the OLED display uses the i2C protocol. Their connections are shown on the image. The four DS18B20 thermometer chips are connected parallel to the same input pin (D5) on the Arduino. They also need a pull-up resistor (4.7 kOhm). The toggle switch is used to switch between two modes: writing the data on the SD card or not.
Arduino source code
#include <OneWire.h> #include <DallasTemperature.h> #include <SD.h> // SD library #include "SSD1306Ascii.h" #include "SSD1306AsciiAvrI2c.h" #define I2C_ADDRESS 0x3C //Address #define RST_PIN -1 //For OLED with no reset pin // Data wire is plugged into digital pin 5 on the Arduino #define ONE_WIRE_BUS 5 //The parallel wires are connected to D5 // Setup a oneWire instance to communicate with any OneWire device OneWire oneWire(ONE_WIRE_BUS); // Pass oneWire reference to DallasTemperature library DallasTemperature sensors(&oneWire); int deviceCount = 0; float T1, T2, T3, T4; //Variables for the 4 thermometers const byte FileOnOffButton = 10; //toggle switch (ON-ON) for starting and stopping the logging bool WritingEnabled = false; //we switch the status of this with the buttons bool SwitchStatus = false; //by default, this is false that means that the switch is OFF (no logging) unsigned long startTime; unsigned long elapsedTime; SSD1306AsciiAvrI2c display; int CS = 4; //chip select pin for the MicroSD Card Adapter, This is the CS Pin File file; // file object that is used to read and write data void setup(void) { sensors.begin(); // Start up the library Serial.begin(9600); sensors.setResolution(10); //10 bit resolution (0.25°C step) // locate devices on the bus Serial.print("Locating devices..."); Serial.print("Found "); deviceCount = sensors.getDeviceCount(); Serial.print(deviceCount, DEC); Serial.println(" devices."); Serial.println(""); //Pin for the switch pins pinMode(FileOnOffButton, INPUT); //OLED part----------------------------------------------------------------------------------- #if RST_PIN >= 0 display.begin(&Adafruit128x32, I2C_ADDRESS, RST_PIN); #else // RST_PIN >= 0 display.begin(&Adafruit128x32, I2C_ADDRESS); #endif // RST_PIN >= 0 //Call oled.setI2cClock(frequency) to change from the default frequency. display.setFont(System5x7); display.set1X(); //set2x() is too large display.clear(); //--endofOLED---- //SD card module----------------------------------------------------------------------------------- pinMode(CS, OUTPUT); // chip select pin is set as OUTPUT if (!SD.begin(CS)) { // Initialize SD card Serial.println("No SD card found. Reset the device after inserting an SD card."); // if return value is false, something went wrong. } /* //We skip this part if (SD.exists("Temp.txt")) { // if "Temp.txt" exists, fill will be deleted Serial.println("File exists."); if (SD.remove("Temp.txt") == true) { Serial.println("Successfully removed file."); } else { Serial.println("Could not removed file."); } } */ //Starting timer for the elapsed time startTime = millis(); } void loop() { ReadSwitchState(); ReadSensors(); PrintSerial(); PrintOLED(); WriteSD(); delay(300); } void ReadSensors() { elapsedTime = millis() - startTime; //Collect the values for each sensors sensors.requestTemperatures(); //request the temperature //Filling up the variables T1 = sensors.getTempCByIndex(0); T2 = sensors.getTempCByIndex(1); T3 = sensors.getTempCByIndex(2); T4 = sensors.getTempCByIndex(3); } void PrintOLED() { //128x32 OLED //1st line of the OLED display.clear(); display.setCursor(0, 0); //The cursor's unit is in pixels and not in blocks as in the case of the 16x2 LCD display.print("1: "); display.print(T1,1); display.print(" 2: "); display.println(T2,1); if(WritingEnabled == true) { display.setCursor(120, 0); //this display has to be positioned by pixel value and not block value! display.print("W"); // W = writing is in progress } else { display.setCursor(120, 0); display.print("0"); // 0 = no writing at the moment } //2nd line display.setCursor(0, 1); display.print("3: "); display.print(T3,1); display.print(" 4: "); display.println(T4,1); //3rd line display.setCursor(0, 2); display.print("t: "); display.print(elapsedTime/1000); display.print(" s"); } void PrintSerial() { Serial.print(elapsedTime); //time in ms Serial.print(" "); //space Serial.print(T1,2); //temperature, 2 digits (i.e. 28.12) Serial.print(" "); Serial.print(T2,2); Serial.print(" "); Serial.print(T3,2); Serial.print(" "); Serial.println(T4,2); } void WriteSD() { if(WritingEnabled == true) { file = SD.open("Temp.txt", FILE_WRITE); // open "Temp.txt" to write data; make sure that you want to write in the same file that you created in the setup() file.seek(EOF); //This goes to the End Of (the) File and _continues_ writing from there if (file) { file.print(elapsedTime); file.print(" "); file.print(T1); file.print(" "); file.print(T2); file.print(" "); file.print(T3); file.print(" "); file.print(T4); file.println(" "); file.close(); // close file Serial.println("Success"); //we print on the serial port, so we see that the writing to SD was OK. You can remove this } else { Serial.println("Could not open file (writing)."); } } else { // } } void ReadSwitchState() { if(digitalRead(FileOnOffButton) == HIGH) //if the button is high { if(SwitchStatus == false) //if the previous status was false, we restart the timer to 0 by resetting the startTime. { SwitchStatus = true; //flip the state startTime = millis(); //reset the timer to zero } WritingEnabled = true; //enable the writing Serial.println("ON"); //message for checking the things out } else //in this case, the FileOnOffButton is LOW, which means, we don't write the SD card { SwitchStatus = false; //Switch status is off WritingEnabled = false; //we do not write on the SD card Serial.println("OFF"); //message on the serial, to see what is happening } }