Sunday, November 03, 2019

USB temperature measurement with LM35 and Arduino

Just needed a way to output temperate measurement from an LM35 on the serial or USB port.

Nothing fancy here, some code on the Arduino to read an analog input from the sensor and output it on the USB, the usb connection on the Arduino will also take care of powering the circuit.

The output temperature range will be a limited due to max power supply (5v) and of the gain stage (5x) to "increase" resolution of the Arduino ADC and reduce uncertain on the ADC conversion. In practice temperature range will be around 0 to 70 C positive.

Finished, boxed product, just one cable to the sensor and the Arduino inside:



Code running and pooling data to the desktop:

Inside:


Circuit:



Opamp gain stage (5x) for the LM35:


 There's a second opamp in the LM358 that could be used for a second sensor.

Input (10mv per *C, so that is 20.9 *C) and output after opamp:








5.018 gain in practice (1049mv/209mv) and 5.1 in theory. I used a 8.2k and 2K resistors so the gain will be 4.1 + 1

I also created some code to read the values on the desktop using python:

Could be handy for OSD display/overlay on video but mostly will be used for automation measurement.
You can use also any terminal program reading /dev/ttyUSB0 (or other device where the Arduino/circuit is connected):


 By adding the gain stage the fluctuation on the reading is mostly reduced (as image above), much less as when the LM35 output is directly connected to the ADC, could  see around 1 *C or more variance in the initial testing.

[Arduino code]:

 // read temperature from an LM35 sensor
// there is external opapmp with 5x gain to compensate Arduino ADC resolution.
// CT2GQV 2019
// based on code for the LM35 sensor read and adapted to external opapmp
// if no amp on the signal from LM35 then remove lines:   temp_val1 = temp_val1/5;


int lm35_1 = A1;  
int lm35_2 = A2;


void setup() {
  Serial.begin(9600);
}

void loop() {
  int temp_adc_val1;
  int temp_adc_val2;
  float temp_val1;
  float temp_val2;
  temp_adc_val1 = analogRead(lm35_1);    // read sensor 1

// debug
//Serial.print("ADC:"); Serial.print(temp_adc_val1);

  temp_adc_val2 = analogRead(lm35_2);  // read sensor 2
 
  temp_val1 = (temp_adc_val1 * 4.88);    /* Convert adc value to equivalent voltage */
  temp_val1 = temp_val1/5; // we scale the voltage by 5 times with external opamp
  temp_val1 = (temp_val1/10);    /* LM35 gives output of 10mv/°C */


// For second sensor on A2 uncoment the next 4 lines line
//  temp_val2 = (temp_adc_val2 * 4.88);    /* Convert adc value to equivalent voltage */
//  temp_val2 = temp_val2/5;  // scaling by 5 since the opamp will amplify 5x
//  temp_val2 = (temp_val2/10);    /* LM35 gives output of 10mv/°C */
// Serial.print("T2:"); Serial.println(temp_val2);

  Serial.print(temp_val1); Serial.println(" *C");
  delay(1000);
}


[Python code for screen display]:

#!/usr/bin/python
from serial import *
from Tkinter import *
# adaptation from here:
# http://robotic-controls.com/learn/python-guis/tkinter-serial

serialPort = "/dev/ttyUSB0"
baudRate = 9600
ser = Serial(serialPort , baudRate, timeout=0, writeTimeout=0) #ensure non-blocking

#make a TkInter Window
root = Tk()
root.wm_title("- Temperature -")

label = Label(root,text="waiting data...", fg="light green", bg ="dark green", font = "Helvetica 18 bold italic")
label.pack()

serBuffer = ""

def readSerial():
    while True:
        c = ser.read() # attempt to read a character from Serial
       
        #was anything read?
        if len(c) == 0:
            break
       
        # get the buffer from outside of this function
        global serBuffer
       
        # check if character is a delimeter
        if c == '\r':
            c = '' # don't want returns. chuck it
           
        if c == '\n':
            serBuffer += "\n" # add the newline to the buffer

            label.config(text=serBuffer)           

            #add the line to the TOP of the log
#            log.insert('0.0', serBuffer)
            serBuffer = "" # empty the buffer
        else:
            serBuffer += c # add to the buffer
   
    root.after(10, readSerial) # check serial again soon

# after initializing serial, an arduino may need a bit of time to reset
root.after(100, readSerial)

button = Button(root, text=' EXIT ', width=35, command=root.destroy)
button.pack()

root.mainloop()
# end code

--
Have a nice week!