caricato da Utente7883

Scilab Arduino Temperature monitoring Tutorial

annuncio pubblicitario
Temperature monitoring Tutorial with Scilab/Xcos and Arduino Document version 1 – Yann Debray -­‐ Scilab Enterprises © -­‐ 08/11/2015 This tutorial aims at acquiring a temperature signal through a Arduino board. Configuration/Arduino Setup In order to follow this tutorial you need the following configuration: Software: -­‐
-­‐
-­‐
-­‐
-­‐
Scilab on Windows 32 or 64 bits (Version >= 5.5.2) Arduino IDE http://arduino.cc/en/Main/Software Serial toolbox http://atoms.scilab.org/toolboxes/serial Arduino toolbox http://atoms.scilab.org/toolboxes/arduino Help on the installation of the module: https://www.scilab.org/en/community/education/si/install Analog displays https://fileexchange.scilab.org/toolboxes/312000 Hardware: -­‐
-­‐
-­‐
Arduino Board (driver installation on http://www.arduino.cc/en/Guide/Windows#toc4 ) Breadboard, wires B & B Thermotechnik CON-­‐TF-­‐LM35DZ Temperature Sensor LM 35 DZ For Relative Humidity Detectors. -­‐55 -­‐ +150 °C http://www.conrad.com/ce/en/product/156600/ Hardware Set-­‐up Set up the following hardware configuration: Flash the firmware in the Arduino board Plug your Arduino Board to your PC, open the Arduino IDE and flash the file scilab_temp_reading.ino on the Arduino Board. 1.
2.
3.
4.
5.
6.
//TMP36 Pin Variables int sensorPin = 0; //the analog pin the TMP36's Vout (sense) pin is connected to //the resolution is 10 mV / degree centigrade with a //500 mV offset to allow for negative temperatures /* 7. * setup() -­‐ this function runs once when you turn your Arduino on 8. * We initialize the serial connection with the computer 9. */ 10. void setup() 11. { 12. Serial.begin(9600); //Start the serial connection with the computer 13. //to view the result open the serial monitor 14. } 15. 16. void loop() // run over and over again 17. { 18. //getting the voltage reading from the temperature sensor 19. int reading = analogRead(sensorPin); 20. 21. // converting that reading to voltage, for 3.3v arduino use 3.3 22. float voltage = reading * 5.0; 23. voltage /= 1024.0; 24. 25. // print out the voltage 26. Serial.print(voltage); Serial.println(" volts"); 27. 28. // now print out the temperature 29. float temperatureC = (voltage -­‐ 0.5) * 100 ; //converting from 10 mv per degree wit 500 mV offset 30. //to degrees ((voltage -­‐ 500mV) times 100) 31. Serial.print(temperatureC); Serial.println(" degrees C"); 32. 33. // now convert to Fahrenheit 34. float temperatureF = (temperatureC * 9.0 / 5.0) + 32.0; 35. Serial.print(temperatureF); Serial.println(" degrees F"); 36. 37. delay(1000); //waiting a second 38. } Scilab-­‐side script for temperature acquisition The temperature acquisition is directed through the serial communication from the Arduino board to the pc. The serial communication toolbox enables to get the data wired through this protocol in Scilab. The way to exchange data with the serial communication is the following: -­‐
-­‐
-­‐
Open serial communication Read/write on the serial communication Close the serial communication First we open the serial communication on the COM port 1 (example running on Windows OS). We have to enter the communication parameters, in the form "baud,parity,data_bits,stop_bits": -­‐-­‐>h=openserial(1,"9600,n,8,1") Second, we will in this case read the data on the serial port, coming from the temperature sensor on the Arduino board: -­‐-­‐>readserial(h) At last, as we have received the data, we have to close the serial communication: -­‐-­‐>closeserial(h) Graphical User Interface 1: instant temperature value visualization Cf. annexe 1 for the scilab code generating this graphical user interface Graphical User Interface 2: historical temperature values visualization Cf. annexe 2 for the scilab code generating this graphical user interface (with the serial communication) Alternative procedure with the Arduino toolbox for Xcos Go on the following website: http://www.demosciences.fr/projets/scilab-­‐arduino And download the following file: toolbox_arduino_v3.ino Plug your Arduino Board to your PC, open the Arduino IDE and flash the file toolbox_arduino_v3.ino on the Arduino Board. This sketch is based on the demo “potentiometre” of the Arduino toolbox: Start to build the Xcos schema, with the configuration blocks: This allows a serial communication between Arduino and Scilab. Double click on the block to let the following dialog box appear: Set the Serial com port number with the information acquired in the previous step. The sampling of the signal for the blocks of the model and the time of acquisition are configured by this block: The sampling period can be specified and has to be at least twice smaller than the period of evolution of the model (Nyquist-­‐Shannon sampling theorem) Sources Adafruit -­‐ Using a Temp Sensor https://learn.adafruit.com/tmp36-­‐temperature-­‐sensor/using-­‐a-­‐temp-­‐sensor Real-­‐time Temperature Monitoring and Control https://fileexchange.scilab.org/toolboxes/311000/1.0 More readings TP3 : Acquérir et piloter des systèmes à l'aide de cartes Arduino et d'une Toolbox Xcos dédiée -­‐ TP3 Démosciences 2012.pdf http://www.demosciences.fr/projets/scilab-­‐arduino Scilab / Xcos pour l’enseignement des sciences de l’ingénieur – © 2013 Scilab Enterprises chapitre « 4-­‐ acquisition et pilotage de moteur (module arduino) » -­‐ livret_Xcos.pdf www.scilab.org/fr/content/download/1017/9485/file/livret_Xcos.pdf Annexe 1: GUI 1 Scilab script //THIS FUNCTION WILL CREATE A THERMOMETER LIKE DISPLAY OF THE INPUT DATA
//
//var1: 1xn vector
--> data to be displayd
//var2: string
--> data unit
//var3: string
--> figure name
//var4: [1x2] matrix
--> figure position
//var5: integer
--> figure color
//var6: integer
--> display color
//var7: integer
--> the time pause [in milliseconds] after that the
//
next data point will be displayed.
function thermometer(data, unit, figname, figpos, figcolor, dispcolor, tstep)
CENTER = [0 0];
END = max(size(data));
fignr = 1002;
// use big numbers, so normal figures won't be affected
f = figure(fignr);
delmenu(fignr,'Datei');
delmenu(fignr,'Zusatzprogramme');
delmenu(fignr,'Editieren');
delmenu(fignr,'?');
toolbar(fignr,'off');
f.background
= figcolor;
f.figure_size
= [5 300];
f.figure_name
= figname;
f.figure_position = figpos;
// define the frame for the thermometer
rect=[-1,min(data),1,max(data)];
plot2d(0,0,0,rect=rect);
a = gca();
a.visible = "on";
a.box = "off";
a.margins = [0.1,0.4,0.1,0.1];
a.axes_visible = ["off","on","off"];
a.x_location = "middle";
a.y_location = "right";
y_label = a.y_label;
y_label.text = unit;
a.y_label.font_angle = 0;
a.y_label.position = [1.25 max(data)];
a.foreground
= dispcolor;
a.font_foreground
= dispcolor;
a.y_label.font_foreground = dispcolor;
plot(CENTER(1), CENTER(2),'ro');
e = gce();
p = e.children(1); // get the point as a handle
p.mark_style = 1;
p.mark_size = 6;
// display actual temperature
for i=1:END;
drawlater();
if data(i) == 0 then;
rect=[-0.5,data(i),1,abs(data(i))];
xrect(rect);
a = gca();
a.axes_visible = ["off","on","off"];
e = a.children(1);
e.background = 1;
e.thickness = 1;
elseif data(i) > 0;
rect=[-0.5,data(i),1,abs(data(i))];
xfrect(rect);
a = gca();
a.axes_visible = ["off","on","off"];
e = a.children(1);
e.foreground = 5;
e.background = 5;
e.thickness = 3;
else
rect=[-0.5,0,1,abs(data(i))];
xfrect(rect);
a = gca();
a.axes_visible = ["off","on","off"];
e = a.children(1);
e.foreground = 2;
e.background = 2;
e.thickness = 3;
end
drawnow();
xpause(tstep*1000); // xpause counts in microseconds, tstep is for milliseconds, thatswhy factor 1000
if i < END
delete(e);
end
end
endfunction
clc;
temp = [0 -5 -10 -15 -25 -40 -10 -5 0 5 10 15 18 20 22 24 26 28 30 35 20 10 5 4 3 2 1 0];
thermometer (temp,'°C','thermometer',[500 300],1,7,50);
Annexe 2: GUI 2 Scilab script + serial communication //
// Copyright (C) 2014 - A. Khorshidi <[email protected]>
//
// This file is distributed in the hope that it will be useful;
// It must be used under the terms of the CeCILL.
// http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
//
//
// The following work provided the inspiration for this challenge.
// https://www.scilab.org/content/view/full/847
//
// I owe thanks to Bruno Jofret, the author of the original GUI.
// https://fileexchange.scilab.org/toolboxes/270000
//
ind = x_choose(["RS-232" ;"USB"; "Ethernet" ;"Wireless"],["Please select the type of communication interface: ";"Just double-click on
its name. "],"Cancel");
if ind==0 then
msg=_("ERORR: No types of communication interfaces has been chosen. ");
messagebox(msg, "ERROR", "error");
error(msg);
return;
elseif ind==2
if (getos() == "Windows") then
if ~(atomsIsInstalled('serial')) then
msg=_("ERROR: A serial communication toolbox must be installed.");
messagebox(msg, "Error", "error");
error(msg);
return;
else
flag=1;
end
elseif (getos() == "Linux") then
if ~(atomsIsInstalled('serialport')) & ~(atomsIsInstalled('serial')) then
msg=_("ERROR: A serial communication toolbox must be installed.");
messagebox(msg, "Error", "error");
error(msg);
return;
elseif (atomsIsInstalled('serialport')) & (atomsIsInstalled('serial')) then
stoolbx = x_choose(['serialport';'serial' ],"Which serial ...
commiunication toolbox you prefer to use? "," Cancel ")
if stoolbx==1 then
flag=2;
elseif stoolbx==2 then
flag=3;
else
msg=_("ERROR: No serial toolbox has been chosen. ");
messagebox(msg, "Error", "error");
error(msg);
return;
end
elseif (atomsIsInstalled('serialport')) then
flag=2;
elseif (atomsIsInstalled('serial')) then
flag=3;
end
else
msg=_(["WARNING: This program has been tested and works under Gnu/Linux ...
and Windows."; "On other platforms you may need modify this script. "])
messagebox(msg, "WARNING", "warning");
warning(msg);
return;
end
else
error("Not possible yet.");
return;
end
//
if (getos() == "Linux") then
[rep,stat,stderr]=unix_g("ls /dev/ttyACM*");
if stderr ~= emptystr() then
msg=_(["No USB device found. ";"Check your USB connection or try ...
another port. "])
messagebox(msg, "ERROR", "error");
error(msg);
return;
end
ind = x_choose(rep,["Please specify which USB port you wanna use for ...
communication. ";"Just double-click on its name. "],"Cancel");
if ind==0 then
msg=_("ERORR: No serial port has been chosen. ");
messagebox(msg, "ERROR", "error");
error(msg);
return;
end
port_name = rep(ind);
end
if (getos() == "Windows") then
port_name=evstr(x_dialog('Please enter COM port number: ','13'))
if port_name==[] then
msg=_("ERORR: No serial port has been chosen. ");
messagebox(msg, "ERROR", "error");
error(msg);
return;
end
end
//
global %serial_port
if flag==2 then
%serial_port = serialopen(port_name, 9600, 'N', 8, 1);
while %serial_port == -1
btn=messagebox(["Please check your USB connection, and then click on ...
Try again. "; "To choose another port click on Change. "], "Error", ...
"error", [" Try again " " Change "], "modal");
if ~btn==1 then
[rep,stat,stderr]=unix_g("ls /dev/ttyACM*");
ind = x_choose(rep,["Please specify which USB port you wanna use...
for communication. ";"Just double-click on its name. "],"Cancel");
if ind==0 then
msg=_("ERORR: No serial port has been chosen. ");
messagebox(msg, "ERROR", "error");
error(msg);
return;
end
port_name = rep(ind);
end
%serial_port = serialopen(port_name, 9600, 'N', 8, 1);
end
elseif flag==1 | flag==3
%serial_port=openserial(port_name,"9600,n,8,1");
//error(999)
else
msg=_("ERROR: Could not specify which serial toolbox to use. ");
messagebox(msg, "Error", "error");
error(msg);
return;
end
//
// * Monitoring Phase:
//
global %MaxTemp
%MaxTemp = 35;
global %MinTemp
%MinTemp = 30;
f=figure("dockable","off");
f.resize="off";
f.menubar_visible="off";
f.toolbar_visible="off";
f.figure_name="Real-time Temperature Monitoring and Control";
f.tag="mainWindow";
bar(.5,0,'blue');
e = gce();
e = e.children(1);
e.tag = "instantSensor";
//
plot([0, 1], [%MinTemp, %MinTemp]);
e = gce();
e = e.children(1);
e.tag = "instantMinTemp";
e.line_style = 5;
e.thickness = 2;
e.foreground = color("orange");
//
plot([0, 3], [%MaxTemp, %MaxTemp]);
e = gce();
e = e.children(1);
e.tag = "instantMaxTemp";
e.line_style = 5;
e.thickness = 2;
e.foreground = color("red");
a = gca();
a.data_bounds = [0, 0; 1, 45];
a.grid = [-1, color("darkgrey")];
a.axes_bounds = [0.1, 0.2, 0.25, 0.85];
a.axes_visible(1) = "off";
a.tag = "liveAxes";
//a.title.text="Current Temperature";
//
f.figure_position = [0 0];
f.figure_size = [1000 700];
f.background = color(246,244,242) //color("darkgrey")
//
minTempSlider = uicontrol("style", "slider", "position", [60 30 30 440], ...
"min", 0, "max", 45, "sliderstep", [1 5], "value" , %MinTemp, ...
"callback", "changeMinTemp", "tag", "minTempSlider");
maxTempSlider = uicontrol("style", "slider", "position", [20 30 30 440], ...
"min", 0, "max", 45, "sliderstep", [1 5], "value" , %MaxTemp, ...
"callback", "changeMaxTemp", "tag", "maxTempSlider");
//
// Functions:
function changeMinTemp()
global %MinTemp
e = findobj("tag", "minTempSlider");
%MinTemp = e.value //45 - e.value;
e = findobj("tag", "instantMinTemp");
e.data(:,2) = %MinTemp;
endfunction
//
function changeMaxTemp()
global %MaxTemp
e = findobj("tag", "maxTempSlider");
%MaxTemp = e.value //45 - e.value;
e = findobj("tag", "instantMaxTemp");
e.data(:,2) = %MaxTemp;
endfunction
//
function closeFigure()
stopSensor();
global %serial_port
if flag == 2 then
serialclose(%serial_port);
elseif flag == 1 | flag == 3 then
closeserial(%serial_port);
end
f = findobj("tag", "mainWindow");
delete(f);
endfunction
//
function stopSensor()
global %Acquisition
%Acquisition = %f;
endfunction
//
function launchSensor()
global %MaxTemp
global %serial_port
global %Acquisition
%Acquisition = %t;
global %fanStatus
%fanStatus = 0;
// Arduino toolbox
values=[];
value=ascii(0);
while %Acquisition
while(value~=ascii(13)) then
if flag == 2 then
value=serialread(%serial_port,1);
elseif flag == 1 | flag == 3 then
value=readserial(%serial_port,1);
end
values=values+value;
v=strsubst(values,string(ascii(10)),'')
v=strsubst(v,string(ascii(13)),'')
data=evstr(v)
end
//
xinfo("Temperature = "+v+"°C");
values=[]
value=ascii(0);
updateSensorValue(data);
//
global %RegulationEnable
if %RegulationEnable == 1 then
if data > %MaxTemp then
enableFan();
else
disableFan();
end
end
updateFanValue(%fanStatus);
end
endfunction
//
function updateSensorValue(data)
global %MaxTemp
global %MinTemp
e = findobj("tag", "instantSensor");
e.data(2) = data;
if data > %MaxTemp then
e.background = color("red");
else
if data > %MinTemp then
e.background = color("orange");
else
e.background = color("green");
end
end
//
e = findobj("tag", "minuteSensor");
lastPoints = e.data(:, 2);
e.data(:, 2) = [lastPoints(2:$) ; data];
e = findobj("tag", "hourSensor");
lastPoints = e.data(:, 2);
e.data(:, 2) = [lastPoints(2:$) ; data];
endfunction
//
// * Regulation Phase:
//
global %RegulationEnable
%RegulationEnable = 1;
global %PController
%PController = 0;
global %PIController
%PIController = 0;
global %PIDController
%PIDController = 0;
//
top_axes_bounds = [0.25 0 0.8 0.5];
bottom_axes_bounds = [0.25 0.5 0.8 0.5];
minTempDisplay = 20;
maxTempDisplay = 45;
minRegulationDisplay = -0.2;
maxRegulationDisplay = 1.2;
// Temperature variations in the last 5 minutes
timeBuffer = 300;
subplot(222);
a = gca();
a.axes_bounds = top_axes_bounds;
a.tag = "minuteAxes";
plot2d(0:timeBuffer, zeros(1,timeBuffer + 1), color("red"));
a.title.text="Temperature variations in the last 5 minutes";
a.data_bounds = [0, minTempDisplay; timeBuffer, maxTempDisplay];
e = gce();
e = e.children(1);
e.tag = "minuteSensor";
// adding a second vertical axis on the right side ...
// to show the On/Off status of the DC Fan.
a = newaxes();
a.y_location = "right";
a.filled = "off"
a.axes_bounds = top_axes_bounds;
plot2d(0:timeBuffer, zeros(1,timeBuffer + 1), color("blue"));
a.data_bounds = [0, minRegulationDisplay; timeBuffer, maxRegulationDisplay];
a.axes_visible(1) = "off";
a.foreground=color("blue");
a.font_color=color("blue");
e = gce();
e = e.children(1);
e.tag = "minuteRegulation";
// Temperature variations in the last hour
timeBuffer = 4000;
subplot(224);
a = gca();
a.axes_bounds = bottom_axes_bounds;
a.tag = "hourAxes";
plot2d(0:timeBuffer, zeros(1,timeBuffer + 1), color("red"));
a.title.text="Temperature variations in the last hour";
a.data_bounds = [0, minTempDisplay; timeBuffer, maxTempDisplay];
e = gce();
e = e.children(1);
e.tag = "hourSensor";
// 2nd vertical axis
a = newaxes();
a.y_location = "right";
a.filled = "off"
a.axes_bounds = bottom_axes_bounds;
a.axes_visible = "off";
plot2d(0:timeBuffer, zeros(1,timeBuffer + 1), color("blue"));
a.data_bounds = [0, minRegulationDisplay; timeBuffer, maxRegulationDisplay];
a.axes_visible(1) = "off";
a.foreground=color("blue");
a.font_color=color("blue");
e = gce();
e = e.children(1);
e.tag = "hourRegulation";
//
// Functions:
function resetDisplay()
e = findobj("tag", "instantSensor");
e.data(:, 2) = 0;
e = findobj("tag", "minuteSensor");
e.data(:, 2) = 0;
e = findobj("tag", "hourSensor");
e.data(:, 2) = 0;
e = findobj("tag", "minuteRegulation");
e.data(:, 2) = 0;
e = findobj("tag", "hourRegulation");
e.data(:, 2) = 0;
endfunction
//
function changeRegulationStatus()
global %RegulationEnable
e = findobj("tag", "enableRegulationCBO");
%RegulationEnable = e.value;
if %RegulationEnable == 0 then
disableFan();
end
endfunction
//
function updateFanValue(data)
e = findobj("tag", "minuteRegulation");
lastPoints = e.data(:, 2);
e.data(:, 2) = [lastPoints(2:$) ; data];
e = findobj("tag", "hourRegulation");
lastPoints = e.data(:, 2);
e.data(:, 2) = [lastPoints(2:$) ; data];
endfunction
//
function enableFan()
global %serial_port
if flag == 2 then
serialwrite(%serial_port,'H');
elseif flag == 1 | flag == 3 then
writeserial(%serial_port,ascii(72));
end
global %fanStatus
%fanStatus = 1;
endfunction
//
function disableFan()
global %serial_port
if flag == 2 then
serialwrite(%serial_port,ascii(76));
elseif flag == 1 | flag == 3 then
writeserial(%serial_port,"L");
end
global %fanStatus
%fanStatus = 0;
endfunction
//
// Buttons:
// * Main Panel
mainFrame = uicontrol(f, "style", "frame", "position", [15 560 305 80], ...
"tag", "mainFrame", "ForegroundColor", [0/255 0/255 0/255],...
"border", createBorder("titled", createBorder("line", "lightGray", 1)...
, _("Main Panel"), "center", "top", createBorderFont("", 11, "normal"), ...
"black"));
//
startButton = uicontrol(f, "style", "pushbutton", "position", ...
[20 595 145 30], "callback", "launchSensor", "string", "Start Acquisition", ...
"tag", "startButton");
//
stopButton = uicontrol(f, "style", "pushbutton", "position", ...
[170 595 145 30], "callback", "stopSensor", "string", "Stop Acquisition", ...
"tag", "stopButton");
//
resetButton = uicontrol(f, "style", "pushbutton", "position", ...
[20 565 145 30], "callback", "resetDisplay", "string", "Reset", ...
"tag", "resetButton");
//
quitButton = uicontrol(f, "style", "pushbutton", "position", ...
[170 565 145 30], "callback", "closeFigure", "string", "Quit", ...
"tag", "quitButton");
//
RegulationFrame = uicontrol(f, "style", "frame", "position", [15 490 305 65]...
,"tag", "mainFrame", "ForegroundColor", [0/255 0/255 0/255],...
"border", createBorder("titled", createBorder("line", "lightGray", 1), ...
_("Regulation Mode"), "center", "top", createBorderFont("", 11, "normal"),...
"black"));
//
// * Regulation Mode
enableRegulation = uicontrol(f, "style", "checkbox", "position", ...
[20 520 140 20],"string", "ON/OFF", "value", %RegulationEnable, ...
"callback", "changeRegulationStatus", "tag", "enableRegulationCBO");
//
enableP = uicontrol(f, "style", "checkbox", "position", [20 500 140 20], ...
"string", "P Controller", "value", %PController, ...
"callback", "", "tag", "");
//
enablePI = uicontrol(f, "style", "checkbox", "position", [170 520 140 20], ...
"string", "PI Controller", "value", %PIController, ...
"callback", "", "tag", "");
//
enablePID = uicontrol(f, "style", "checkbox", "position", [170 500 140 20], ...
"string", "PID Controller", "value", %PIDController, ...
"callback", "", "tag", "");
//
Scarica