Sunday, March 19, 2017

Real-Time Temperature Monitoring using MATLAB & Python

Hello! Everyone, in this post i will show you how to plot temperature data in real time using MATLAB and Python.
The temperature sensor which we are going to use in this project is LM35 and the PIC18F4550 micro-controller is used to measure the temperature using the LM35 sensor which then transmit/send the data to MATLAB/Python for plotting purpose.
For this project i am going to use mikroC for PIC compiler, as this compiler is very easily to use and it has extensive set of libraries for rapid development, so for both case i.e. MATLAB or Python the PIC firmware remains same.

Introduction:
LM35 outputs a voltage with respect to change in temperature, this output is measured using PIC18F4550 micro-controller's analog to digital converter, and then converted into temperature value, which is then displayed on 16x2 lcd (mikroC has inbuilt library for lcd and Analog to Digital Converter), and this value is also transmitted to MATLAB/Python.
As i am using Proteus simulation environment for this project, that's why to send data from Proteus to MATLAB/Python, we need to use Elitma Virtual Serial port software, by using this software we can create two virtual communication port and connect them, after doing this, whatever we send on first port will get received on second port and vice versa.
The following figure shows the connection diagram, as you can see we are using COMPIM in Proteus to send data from Proteus to MATLAB/Python.
Connection Diagram
You can watch the following video to see the working demo of Real-Time Plot in MATLAB.



You can watch the following video to see the working demo of Real-Time Plot in Python.




Software:
The following software is of mikroC, as already described in Introduction section, this measure the temperature value and then display these value on lcd and it also transmit these value on communication port, which is then processed by MATLAB/Python.
#include <stdint.h>
// LCD module connections
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;
sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
// End LCD module connections

void main()
{
  Adc_Init();
  UART1_Init(9600);
  TRISA.F0 = 1;                      // Input Pin
  Lcd_Init();
  Lcd_Cmd(_LCD_CLEAR);               // Clear display
  Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off
  Lcd_Out(1,1, "Embedded");
  Lcd_Out(2,1, "      Laboratory");
  Delay_ms(2000);
  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Out(1,1, " Temperature:");
  while(1)
  {
    char lcd_text[16] = {0};
    float voltage = 0.0;
    uint16_t adc_data = Adc_Read(0);
    voltage = adc_data * 5000.0/1023.0;
    sprintf( lcd_text, "%2.2f", voltage/10.0);
    Lcd_Out(2,1, lcd_text);
    Lcd_Chr(2, 6, 0xDF);
    Lcd_Chr(2, 7, 'C');
    UART1_Write_Text(lcd_text);
    UART1_Write(10);
    UART1_Write(13);
    Delay_ms(1000);
  }
}

Note: The code written is not optimized, i used float data types and sprintf functions to make my life easy and that's why this simple project is taking too much space, you can easily optimize this code, for me this is fine as my main objective of this post is to display real time plotting of temperature values. But if still you guys wants me to write smaller footprint code, please mention in comment section and i will update the code as per request, which is pretty easy.

MATLAB:
Now coming to the MATLAB software, in MATLAB, we received the data coming from serial port, and plot that data on graph, the span of graph is 100, which means only 100 values can be displayed on graph, you can modify these values to 1000 or any other number you want.
Once the span get completed the old data is re-written by the incoming new data, this is done by implementing a circular array in MATLAB.
One important thing is that, the data we are receiving from serial port is in string format and we need to update that in double format before plotting, which is quite obvious because no one can plot strings.
The following is the MATLAB Code.
clc;
clear;
% Delete Opened Ports in MATLAB
delete(instrfind)
% Create a Serial Object
ser = serial('COM5', 'BaudRate',9600, 'Timeout', 10);


DATA_SIZE = 100;
temperature = zeros(DATA_SIZE, 1);
index = 1;


% Open Communication Port
fopen(ser);
while true
    temp = fscanf(ser);
    if size(temp) == [0][0]
        disp 'Timeout Occurs'
        disp 'Check Connections'
        fclose(ser);
        delete(ser);
        break
    else
        if index <= DATA_SIZE
            temperature(index) = str2double(temp);
            index = index+1;
        else
            % Reset Subscript Index
            index = 1;
        end
        plot(temperature, 'r', 'LineWidth',2)
        grid on;
        ylim([0,50])
        xlabel('Time \rightarrow')
        ylabel('Temperature ^\circ(C)\rightarrow');
        title('Real-Time Temperature Plot');
        drawnow
    end
end


Note: As you can see in graphs that, on X-axis we are getting some values (which are sample values), not the time, this is because we are not transmitting time from PIC as that requires Real-Time Clock, in my future post i will time-stamp the time from MATLAB and display that time on X-axis.


Temperature Plot

LCD Display
The MATLAB and PIC code can be downloaded by clicking here.

If you are new to serial communication using MATLAB, then i would suggest you to read the post "Serial Communication Using MATLAB"

Python:
Now coming to the Python software, in Python, we received the data coming from serial port, and plot that data on graph, the span of graph is 100, which means only 100 values can be displayed on graph, you can modify these values to 1000 or any other number you want.
Once the span get completed the old data is re-written by the incoming new data, this is done by implementing a circular array in Python.
One important thing is that, the data we are receiving from serial port is in string format and we need to update that in double format before plotting, which is quite obvious because no one can plot strings.
Python requires matplotlib library for plotting graphs and this project requires numpy library and of-course serial library also. So before proceeding further i will tell you, how to install these libraries.


PySerial Library:
  • Open Command Prompt and type
    pip install pyserial
    This command will download and install the PySerial package from internet.

Once the PySerial package is installed, open the python GUI (IDLE) and type the command "import serial", if it doesn't give any error, then it means PySerial library is successfully installed.

Matplotlib Library:
  • Open Command Prompt and type
    pip install matplotlib
    This command will download and install the complete Matplotlib package from internet.
Once the Matplotlib package is installed, open the python GUI (IDLE) and type the command "import matplotlib", if it doesn't give any error, then it means Matplotlib library is successfully installed.

NumPy Library:
  • Open Command Prompt and type
    pip install numpy
    This command will download and install the complete NumPy package from the internet.
Once the NumPy package is installed, open the python GUI (IDLE) and type the command "import numpy", if it doesn't give any error, then it means NumPy library is successfully installed.
Now you use the following is the Python Code to plot the Real-time temperature graph.

import matplotlib.pyplot as plt
import numpy as np
import serial
DATA_SIZE = 100
temperature = np.zeros(DATA_SIZE, dtype=np.float32)
index = 0
samples = range(0, DATA_SIZE)

fig = plt.figure()
ax = fig.gca()
ax.set_ylim([0, 60])
ax.set_title('Real-Time Temperature Monitoring')
ax.set_xlabel('Time->')
ax.set_ylabel('Temperature(C)->')

# Enable Interactive Plotting, use plt.ioff() to turn off
plt.ion()

# Open Serial Port
ser = serial.Serial('COM5',baudrate=9600,timeout=10
                    ,parity=serial.PARITY_NONE,
                    stopbits=serial.STOPBITS_ONE,
                    bytesize=serial.EIGHTBITS
                    )
try:
    while True:
        temp = ser.readline()
        if index < DATA_SIZE:
            # Convert String to a Number
            temperature[index] = float(temp)
            # Clear the Old Plot from Screen
            ax.cla()
            ax.grid(True)
            ax.set_ylim([0, 60])
            ax.set_title('Real-Time Temperature Monitoring')
            ax.set_xlabel('Samples ->')
            ax.set_ylabel('Temperature$^\circ$(C) ->')
            ax.plot(samples, temperature,'b')
            plt.pause(0.01)
            index +=1
        else:
            index = 0
        
except KeyboardInterrupt:
    print ('Exiting Program')

except:
    print ('Error Occurs, Exiting Program')

finally:
    plt.ioff()
    plt.show()
    ser.close()

The following figure shows the graph.
Python Real-Time Plot
The Python and PIC code can be downloaded by clicking here.
Get Python code from GitHub, the file name is "05-Real Time Temperature Plot.py"

If you are new to serial communication using Python, then I would suggest you to read the post "Serial Communication Using Python"

If you guys have any problem, please write in the comment section and I will try to help you guys as soon as possible.


3 comments:

  1. very nice demonstrated the real time temperature monitoring graph.If you are interested in wifi temperature sensor then you can contact with Ubibot.

    ReplyDelete
  2. The best way to monitor environmental is using of Smart Wireless Sensor WS1. You can manage the temperature and humidity data every time and everywhere on your mobile, this is very easy to use. Thanks

    ReplyDelete