4 channel temperature logger with Arduino, SD card, LM335 and ADS1115
I improved my previous thermometer - datalogger circuit. Previously, I made a similar circuit, but just for to demonstrate how easy to collect the data of a sensor and write the data on a SD card. Now, there was a real demand for a 4 channel thermometer. My Peltier experiments need several thermometers, because I want to get the readings from different areas/zones of the experimental setup. So, I found some sensors laying around and I decided to build this equipment. It turned out great at the end.
Wiring diagram
Arduino source code
/* PIN LAYOUT FOR SD CARD READER * CS = 4 * SCK = 13 * MOSI = 11 * MISO = 12 * VCC = 5V (Make sure that your module is 5V and not 3.3V * GND = GND * ------------------------------------------------------- * PIN LAYOUT FOR LM335Z * Flat part is facing you! * 1 2 3 * ADJ OUT GND * ------------------------------------------------------- * WIRING FOR LM335Z * * Arduino pins resistor LM335Z Chip * (+5V)-------------[ 2k ]---/-------------[OUT] * (A0)----------------------/ * (GND)------------------------------------[GND] * [ADJ] //NOT CONNECTED * ------------------------------------------------------- * PIN LAYOUT FOR LCD SCREEN * VIN = 5V * GND = GND * SCL/SCK = A5 * SDA = A4 * * PIN LAYOUT FOR ADS1115 * V = 5V * G = GND * SCL/SCK = A5 * SDA = A4 * ADDR = GND */ #include <SD.h> // SD library #include <Wire.h> //I2C #include <Adafruit_ADS1015.h> #include <LiquidCrystal_I2C.h> //ADS and LCD Adafruit_ADS1115 ads; LiquidCrystal_I2C lcd(0x27, 16, 2); 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 int analogBit; //raw analog data from the ads1115 float tempKelvin; //Temperature in Kelvin float tempCelsius; //Temperature in Celsius float T1, T2, T3, T4; // these are the 4 channels const byte FileStartButton = 2; //attachinterrupt button for starting the measurement (red) const byte FileStopButton = 3; //attachinterrupt button for stopping the measurement (black) const byte GreenLED = 5; //Status LEDs const byte RedLED = 6; bool WritingEnabled = false; //we switch the status of this with the buttons unsigned long startTime; unsigned long elapsedTime; void setup() { //Defining the LEDs' functions pinMode(GreenLED, OUTPUT); pinMode(RedLED, OUTPUT); digitalWrite(GreenLED, LOW); digitalWrite(RedLED, HIGH); Serial.begin(9600); // start serial //Attachinterrupt pins pinMode(FileStartButton, INPUT_PULLUP); pinMode(FileStopButton, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(FileStartButton), FileStart, CHANGE); attachInterrupt(digitalPinToInterrupt(FileStopButton), FileStop, CHANGE); //ADC setup ads.setGain(GAIN_TWOTHIRDS); // Gain - multiplier for the bit = 0.1875 mV //ads.setGain(GAIN_ONE); //0.125 mV //ads.setGain(GAIN_SIXTEEN); // 0.0078125 mV ads.begin(); //------------------------------------- //-----------------Taking care of LCD------------------- //NOTE: if you cannot see the text on the LCD, try to change the potmeter on the back of it. //Sometimes you just have wrong contrast settings and nothing shows up on the screen because of it. lcd.begin(); lcd.backlight(); //initialize backlight //------------------------------------------------------ lcd.clear(); //clear the LCD lcd.setCursor(0, 0); //Defining positon to write from first row,first column . lcd.print("LM335Z Sensor"); //some message lcd.setCursor(0, 1); //Cursor is moved to the 2nd line of the LCD lcd.print("Temperature"); //You can write 16 Characters per line . delay(1000); //wait 3 sec //-------------------------------- //SD card module pinMode(CS, OUTPUT); // chip select pin is set as OUTPUT if (!SD.begin(CS)) { // Initialize SD card Serial.println("Could not initialize SD card."); // if return value is false, something went wrong. } 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() { //Calculate elapsed time elapsedTime = millis() - startTime; readADS(); delay(1000); //update and writing intervall basically. Change this for slower/faster acquisition printLCD(); LEDControl(); writeFile(); } void writeFile() //writing something to the SD card { if(WritingEnabled == true) { file = SD.open("Temp.txt", FILE_WRITE); // open "file.txt" to write data; make sure that you want to write in the same file that you created in the setup() 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.print(tempCelsius, 2); // debug output: show written number in serial monitor //you can write as much as you want, just make sure that you have a consistent formatting! Serial.println("Success"); } else { Serial.println("Could not open file (writing)."); } } else { // } } void LEDControl() { if(WritingEnabled == true) { digitalWrite(GreenLED, HIGH); digitalWrite(RedLED, LOW); lcd.setCursor(15, 1); //Defining positon to write from second row,first column . lcd.print("!"); //You can write 16 Characters per line } else { digitalWrite(GreenLED, LOW); digitalWrite(RedLED, HIGH); lcd.setCursor(15, 1); //Defining positon to write from second row,first column . lcd.print("."); //You can write 16 Characters per line } } void FileStart() { //Serial.println("red"); //do not use serial.print() or digitalwrite() in the attachinterrupt! WritingEnabled = true; } void FileStop() { //Serial.println("black"); //do not use serial.print() or digitalwrite() in the attachinterrupt! WritingEnabled = false; } void readFile() { //Reading //You can read the content of the file and print it on the serial. //This is not explained in the tutorial video because I was only focusing on the writing file = SD.open("Temp.txt", FILE_READ); // open "file.txt" to read data if (file) { Serial.println("--- Reading start ---"); char character; while ((character = file.read()) != -1) { // this while loop reads data stored in "file.txt" and prints it to serial monitor Serial.print(character); } file.close(); Serial.println("--- Reading end ---"); } else { Serial.println("Could not open file (reading)."); } } void readADS() { Serial.println(elapsedTime); analogBit = ads.readADC_SingleEnded(0); //read A0, store it in the analogBit variable tempKelvin = (analogBit*0.1875)/10; T1 = tempKelvin - 273.15; Serial.print("Celsius1: "); Serial.println(T1); analogBit = ads.readADC_SingleEnded(1); //read A1, store it in the analogBit variable tempKelvin = (analogBit*0.1875)/10; T2 = tempKelvin - 273.15; Serial.print("Celsius2: "); Serial.println(T2); analogBit = ads.readADC_SingleEnded(2); //read A2, store it in the analogBit variable tempKelvin = (analogBit*0.1875)/10; T3 = tempKelvin - 273.15; Serial.print("Celsius3: "); Serial.println(T3); analogBit = ads.readADC_SingleEnded(3); //read A3, store it in the analogBit variable tempKelvin = (analogBit*0.1875)/10; T4= tempKelvin - 273.15; Serial.print("Volt4: "); Serial.println(tempKelvin); Serial.print("Celsius4: "); Serial.println(T4); } //------------------------------------------------------------------------------------------------------------- //Small explanation //1024 comes from the resolution of the ADC. 2^10 = 1024. If you use different ADC, change the value. //4876 (mV) comes from the measured voltage on the 5V rail. //Example: (analogBit/1024.0) * 4876 /10; //To have precise data, measure the 5V rail when everything is connected to the arduino (screen, modules, etc) and they are running //use the measured voltage in mV (millivolts) in the formula // division by 10 comes from the gain of the LM335Z chip which is G=10 mV/K. void printLCD() { //-------------LCD Printout------------------ lcd.clear(); //clear LCD lcd.setCursor(0, 0); //Defining position to write from first row,first column . lcd.print("1: "); lcd.setCursor(2, 0); lcd.print(T1, 1); lcd.setCursor(7, 0); lcd.print("2: "); lcd.setCursor(9, 0); lcd.print(T2, 1); //------------------------------------------- lcd.setCursor(0, 1); lcd.print("3: "); lcd.setCursor(2, 1); lcd.print(T3, 1); lcd.setCursor(7, 1); lcd.print("4: "); lcd.setCursor(9, 1); lcd.print(T4, 1); }