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

The ADS1115 AD-converter and the 16x2 LCD are using the same i2C connections (SDA: A4, SCK: A5). The SD card reader uses the SPI protocol. The start and stop buttons are connected to the interrupt pins (D1, D2). The LEDs are used to provide visual f…

The ADS1115 AD-converter and the 16x2 LCD are using the same i2C connections (SDA: A4, SCK: A5). The SD card reader uses the SPI protocol. The start and stop buttons are connected to the interrupt pins (D1, D2). The LEDs are used to provide visual feedback for the user. The four LM335 thermometer chips are connected to the inputs of the ADS1115 AD-converter. The AD converter is used in single-ended mode, so we can use all 4 channels.



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); 
}

Previous
Previous

Testing different Peltier coolers by cooling/freezing water - Part 1 - Introduction

Next
Next

Reasons why you CANNOT use Peltier for air conditioning