duminică, 12 iunie 2016

Server de temperatura cu Python si Arduino

Pentru inceput...

     Daca in articolul trecut ne-am familiarizat cu capabilitatile NodeMcu-ului in cele ce urmeaza voi incerca sa prezint o noua abordare a modului de integrare in Internet of Things (IOT). 

     Desi NodeMcu ofera o oarecare libertate si simplitate in proiecatrea sistemelor integrate in IOT, datorita limitarilor impuse de catre arhitectura,  posibilitatile de dezvoltare sunt relativ reduse. 
     Se poate considera, de exemplu, cazul in care serverul (NodeMcu) ar trebui sa trimita clientului niste fotografii, sau niste scripturi mai complexe. In fiecare din cele doua cazuri enumerate mai sus sunt necesare  artificii suplimentare: gazduirea fotografiilor pe un server extern sau lucrul cu memoria ROM a controller-ului. In plus numarul de conexiuni (clienti) este realtiv  limitat.

     Avand in vedere cele enumerate mai sus, am inceput sa ma gandesc la un sistem in care controller-ul sa fie comadat de catre computer si care  totodata sa joace  si  rolul de  web-server. Tot scotocind am descoperit Python-ul, un limbaj de programare interpretat, usor de invatat si de utilizat,  cu o groaza de librarii printre care si "Flask" - un excelent server web. 
  Cu problema serverului odata rezolvata, mai ramane doar problema comunicatiei seriale cu Arduino. Si aici popularitatea Python-ului si-a spus cuvantul, deoarece fara prea mare dificultate am gasit libraria "pySerial", exact ce trebuie pentru a stabilii conexiunea cu Arduino.
    Cu un pic de HTML si jQuery si utilizand ca senzor "batranul" DS18B20 am injghebat un mic server de temperatura:
   


Toate puse cap la cap...

     Pentru oricine este interesat de realizarea practica a acestui proiect pasii de urmat sunt urmatorii:

  1. Se instaleaza Python 3 un bun ghid de instalare pentru Windows se poate gasi aici. Va recomand sa instalati limbajul e programare intr-un loc cat mai usor de accesat cu putiinta, de exemplu "C:\Pyhton3";
  2. Se instaleaza rand pe rand urmatoarele librarii: FlaskpySerial, colorama, termocolor;
  3. Deoarece instalarea librariilor in Python poate da unui incepator destule batai de cap va propun o alterantiva de instalare mai simpla, utilizand PIP (un manager care instaleaza automat  pachete si librarii pentru Python). Daca ati instalat Python3, atunci acest manager este deja disponibil. Tot ceea ce trebuie sa faceti este sa navigati pana in folderul in care ati instalat Python3 sa dati click pe bara de adrese (cea care contine locatia in care va aflati) si sa copiati adresa locatiei. Deschideti o noua fereastra "CMD", tastati "cd" urmat de spatiu, click dreapta alegeti "Paste" dupa care tastati "Enter". Din acest moment tot ce aveti de facut este sa tastati "pip3 install" urmat de numele librariei dorite. In cazul meu Flask era deja instalat, in cazul vostru libraria se va instala fara prea mari dureri de cap.                                                                                                                                                                    

     
     
  4. Se descarca arhiva cu codul sursa de aici.

Cum functioneaza...

    Simplu :) . Pe langa libraria ce serveste comunicatiei seriale am scris o clasa care ajuta la conectarea cu Arduino. Aceasta clasa se gaseste in fisierul arduinoSerial.py si  este apelata inainte de prima conectare a clientului la server:


Cand clientul incearca sa se conecteze in fereastra deschisa de server va trebui introdus numarul portului la care este conectat Arduino. In cazul meu portul este 7. Serverul se va conecta la Arduino iar clientul isi va primi pagina:


     Pagina este "relativ" simpla. Practic sunt prezentate 3 indicatoare analogice, unul cu minimul temperaturii inregistrate, altul cu temperatura curenta si in fine cel de-al treilea cu temperatura maxima inregistrata de-a lungul masuratorilor. Pentru reprezentarea indicatoarelor a fost utilizata libraria pentru javascript "justGage".

     Cheia intregului sistem este codul pentru server:




  
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import arduinoSerial
import time
import atexit
from flask import Flask,request, redirect, url_for, send_from_directory
app = Flask(__name__,static_url_path='')

@app.before_first_request
def setupSerial():
 global arduino
 arduino=arduinoSerial.Arduino(57600,'*',0)
  
@app.route("/")
def page():
 if arduino.getConnStatus()==True:
  return app.send_static_file('temp.html')
 
@app.route('/state') 
def getState():
 arduino.serWrite('get')
 a=arduino.serRead()
 print(a)
 return a

@atexit.register
def disconnect():
 arduino.closePort()
 print('Port closed !!!')
 
@app.route('/')
def sendPage():
 return app.send_static_file('temp.html')
 
if __name__ == "__main__":
 app.run(debug=True,host='192.168.0.39')


      Fiecarei actiuni pe care serverul trebuie sa o execute ii este ascociata o functie. De exemplu inainte de prima conectare se apeleaza functia setupSerial(). Aceasta functie practic face posibila conectarea cu Arduino. Obiectul "arduino" este creat utilizand constructorul clasei arduinoSerial si are ca parametrii baudrate-ul, caracterul pana la care Arduino citeste sirul e caractere trimis de server si daca se doreste (1) sau nu (0) conectarea automata.
       Browserul web va trimite un 'request' catre server la fiecare doua secunde, utilizand Ajax. Prin request se va cere '/state'. Cand serverul a primit aceasta comanda va solicita la randul lui temperatura catre Arduino. Arduino ii va da server-ului un sir de caractere separat prin ":" care va contine temperatura curenta, cea mimina si maxima. Serverul va trimite clientului sirul primit. Clientul (browser-ul), dupa ce va prelucra sirul de caractere va afisa temperatura pe pagina web.

Pheeeeeeewwwww :)!!!

Acum sa aruncam un ochi si pe codul pentru Arduino (care a fost scris compilat si upload-at utilizand Arduino Create, al carui betatester fericit sunt):



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <OneWire.h>
#include <DallasTemperature.h>
 
// Data wire is plugged into pin 12 on the Arduino
#define ONE_WIRE_BUS 12
 
// Setup a oneWire instance to communicate with any OneWire devices 
// (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
 
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
float current;
float min;
float max;
boolean firstRead=true;

void setup(void)
{
  // start serial port
  Serial.begin(57600);
  // Start up the library
  sensors.begin();
}
void sendData(){
    String g="";
    g=String(current)+':'+String(min)+":"+String(max)+":";
    
    Serial.println(g);
} 
 
void loop(void)
{
  sensors.requestTemperatures();
  current=sensors.getTempCByIndex(0);
  if(firstRead){
    min=current;
    max=current;
    firstRead=false;
      
  }
  else{
    if(current<min){
        min=current;
    }
    if(current>max){
        max=current;
    }
  }
  delay(100);
  if(Serial.available()>0){
      String g=Serial.readStringUntil('*');
      if(g.indexOf("get")!=-1){
         sendData(); 
      }
  }
}

Dupa cum se observa nu este nimic special. Arduino va citi tot ceea ce primeste pe portul serial pana cand va primi caracterul "*". Apoi daca primeste comanda "get" va trimite datele inapoi catre server despartite intre ele prin caracterul ":".

Epilog...

Metoda descrisa mi se pare foarte avantajoasa. Oricine dispune de un computer mai vechi  poate realiza un server permanent ce indeplineste functii complexe, Arduino devinind practic un periferic al acestuia.

Pana data viitoare sa auzim de bine. Daca doriti mai multe detalii nu va sfiiti sa ma contactati!

Succes!


Un comentariu:

  1. Computer mai vechi am , Arduino este ,cunostinte minime am ,deci pot sa ma apuc sa realizez practic acest proiect.Astept cu nerabdare articolul urmator !

    RăspundețiȘtergere