2014 m. lapkričio 26 d., trečiadienis

Temperatūros stebėjimas ir atvaizdavimas

Šį savaitgalį leidau sau užsiimti tuo, kas patinka, į šalį nustumiant tikrai reikalingus darbus. Na, darbas, kad ir reikalingas, į mišką nepabėgs, o va malonumams paskui galiu ir neberast laiko :) Todėl išsitraukiau keletą anksčiau planuotų projektėlių, tikėdamasis juos sujungti į vieną, bandomąją versiją.
Pagrindinis šio projekto įrenginys - prieš pusantrų metų nusipirktas "Raspberry Pi" minikompiuteris. Jo per daug neaptarinėsiu, nes arba būsite apie jį girdėję, arba labai nesunkiai susirasite informacija apie jį, nes toks produktas už 35 dolerių kainą - pirmas atvejis.

Taigi. Projekto tikslas - nuskaityti temperatūrą iš dviejų skaitmeninių temperatūros jutiklių DS18B20 (kodėl dviejų? Tiesiog tiek jų teturiu :) ), ir nuskaitytas temperatūras nusiųsti į interneto serverį, kuris iš tų temperatūrų nupieš gražius grafikus.  Toks tad greitas aprašymas, toliau pabandysiu kiek pasigilint. Šio projekto privalumas - reikės labai nedaug programavimo. Tiesą sakant, tikėjausi, kad jo visai nereikės, bet visos rastos internete instrukcijos man netiko - vienos neveikė, kitų nenorėjau. Todėl teko vėl prisiliesti prie Python programavimo kalbos.
 Viso šito grožio struktūra tokia:

 Temperatūros stebėjimas atliekamas (mano atveju) dviejų skaitmeninių jutiklių Dallas Semiconductors DS18B20 pagalba. Šie įrenginukai nėra brangūs, gana tikslūs. Taip pat privalumas - vienu kabeliu galima prijungti keletą jutiklių (kiekvienas jų turi unikalų adresą, pagal kuriuos sistema juos atskiria), o kabelio ilgis gali viršyti 100 metrų. Šioje schemoje pavaizduotas atskiras jų maitinimas +5V įtampa, tačiau jie turi galimybę jungtis dviejų gyslų kabeliu, kas čia nebus aprašoma. Jutikliai siunčia duomenis 1-WIRE protokolu.
Sekantis įrenginukas - DS2480 mikroschema - signalų lygių keitimui iš 1-WIRE protokolo į TTL UART protokolą. Tiek 1-WIRE, tiek UART veikia įtampomis nuo 0 iki +5 V, kas supaprastina schemą.
Svarbu: čia  pavaizduota ne visa schema. Reikia dar mažiausiai vieno 0,1 uf kondensatoriaus ant maitinimo laido, jei daugiau - galima pridėti ir apsaugantį nuo elektrostatinio krūvio diodą ir dar RC granfinę filtravimui. Tačiau veiks ir be to.
DS2480 mikroschema jungiama į TTL - USB keitiklį, kurių porą turiu parsisiuntęs iš e-bay. Jeigu tokį temperatūros stebėjimą realizuoti su paprastu kompiuteriu, galima naudoti COM prievadą, tačiau tokiu atveju vietoj TTL - USB keitiklio reiktų naudoti MAX232 mikroschemą. TTL - USB keitiklis pagamintas Prolific2303 mikroschemos pagrindu - tai svarbu, nes kita mikroschema, naudojama tokiuose keitikliuose (FT232) su RaspberryPi kompiuteriu veikė netinkamai.
Keitiklis jungiamas į Raspberry Pi USB prievadą. Kadangi kompiuteryje - linuksas, papildomai jokių valdiklių diegti nereikia.
Eilinį kartą noriu pastebėti, kad jei rasite klaidų ar kitokių nesklandumų - prašau nepykti, o pastebėti tai komentaruose :)

Programinė dalis

Neaprašinėsiu Raspberry Pi diegimo, tačiau komandas, reikalingas šiam projektui, parašysiu. Juo labiau, kad jos tiks ir tai atliekant su bet kokiu kompiuteriu, įdiegus į jį DEBIAN OS.
Prisijungus root teisėmis, ir įvedus komandą lsusb, parodomi visi esantys USB įrenginiai.

Paskutinėje eilutėje matosi PL2303 keitiklis.
Norint, kad kompiuteris matytų prijungtą 1-WIRE įrenginį, reikia specialios programinės įrangos. OWFS (One-Wire-File-System) butent tokia programinė įranga ir yra. Ją instaliavus reikia sukurti katalogą /mnt/1wire, kuriuo bus galima pasiekti jutiklių siunčiamą informaciją.
 OWFS diegiama šitaip:

sudo apt-get install owfs ow-shell

Kadangi DS2480 - ne vienintelė mikroschema, galinti 1-WIRE protokolą siųsti per USB, reikia pakoreguoti konfigūracijos failą, kuriame nurodomas keitiklio tipas ir kiti duomenys. Prieš konfigūruojant reikia sukurti katalogą /mnt/1wire. Mano atveju konfigūracija tokia:

######################## SOURCES ########################
#
# With this setup, any client (but owserver) uses owserver on the
# local machine...
! server: server = localhost:4304
#
# ...and owserver uses the real hardware, by default fake devices
# This part must be changed on real installation
#server: FAKE = DS18S20,DS2405
#
# USB device: DS9490
#server: usb = all
#
# Serial port: DS9097
server: device = /dev/ttyUSB0
#
# owserver tcp address
#server: server = 192.168.10.1:3131
#
# random simulated device
#server: FAKE = DS18S20,DS2405
#
######################### OWFS ##########################
#
mountpoint = /mnt/1wire
allow_other
#
####################### OWHTTPD #########################

http: port = 2121

####################### OWFTPD ##########################

ftp: port = 2120

####################### OWSERVER ########################

server: port = localhost:4304

Po konfigūracijos pakeitimo reikia perkrauti servisusowserver ir owhttpd. (service owserver restart ir service owhttpd restart). Jeigu iškart nepavyks pasiekti temperatūros, gali būti, kad owfs sistema neprisijungė katalogo (nežinau, kodėl, nesu baisiai linux specialistas). Tokiu atveju padės komanda owfs -c /et/owfs.conf -m /mnt/1wire
Pagrindinė temperatūros nuskaitymo sistema jau veikia - tereikia nueiti adresu http://[kompiuterio su owfs IP]:2121 , ir pamatysime paprastą sistemos puslapiuką su visa gauta iš jutiklių informacija.

Pirmos dvi eilutės lentelėje - jutiklių adresai, ant kurių paspaudus galima rasti daugiau informacijos:

Mano atveju svarbiausias dydis - temperature10. Tai 10 bitų tikslumo temperatūra (iki 2 skaičių po kablelio). Tačiau norint gauti ir apdoroti duomenis automatiškai, toks stebėjimo būdas netinka. Kadangi OWFS sistema sukuria failų sistemą, tuos pačius duomenis galima "pasiimti" ir komandinės eilutės pagalba, naudojant komandą "cat" :

cat /mnt/1wire/28.C514BD030000/temperature10

18.5

PYTHON SKRIPTAS IR SERVERIS

Sekanti užduotis - vykdyti Python programavimo kalboje parašytą skriptą, kuris paimtų temperatūros duomenis ir juos išsiųstų į tam skirtą serverį internete. Toks serveris yra Xively.com - jis leidžia iš įvairių įrenginių siųsti duomenis, juos saugo ir atvaizduoja grafiniu formatu. Šis serveris per specialų PYTHON modulį xively-python leidžia norimu intervalu siųsti, pavyzdžiui, temperatūrą.
Norint naudotis serverio paslaugomis (kurių dalis, reikalina mums, yra nemokama) reikia užsiregistruoti, pridėti įrenginį ir duomenų srautą. Tai nėra sunku, juo labiau, kad viskas yra paaiškinta registruojantis - vakar tai dariau pirmą kartą, ir sunkumų tai nesudarė.
Pradžioje instaliuojame būtent tą modulį, xyvely-python. Nuorodos, kaip tai padaryti yra pačiame Xively.com tinklapyje https://xively.com/dev/tutorials/pi/. Turiu pasakyti, kad šio modulio diegimas užėmė daugiausiai laiko, o to priežastis - neperskaičiau ten pateiktos informacijos iki galo, t.y. žioplumas ir skubėjimas :)
Sekantis žingsnis - parašyti PYTHON programą, kuri "paims" temperatūrą iš jutiklių ir išsiųs į xively.com. Sukuriame tuščią failą:

nano temp.py

Štai mano programos tekstas:
#!/usr/bin/pythonimport datetimeimport xivelydef read_temperature1():  tfile = open("/mnt/1wire/28.C514BD030000/temperature10")  text = tfile.read()  tfile.close()  temp=text.strip()  temp=float(temp)  return tempdef read_temperature2():  tfile = open("/mnt/1wire/28.DF2ABD030000/temperature10")  text = tfile.read()  tfile.close()  temp=text.strip()  temp=float(temp)  return tempcurrent_temp1 = read_temperature1()current_temp2 = read_temperature2()# temperatura perskaityta, siunciama i xivelyapi=xively.XivelyAPIClient("[---jums suteiktas API numeris---]")feed = api.feeds.get([duomenų srauto numeris])now=datetime.datetime.utcnow()feed.datastreams = [  xively.Datastream(id=''pirmas_jutiklis'', current_value=current_temp1, at=now),  xively.Datastream(id=''antras_jutiklis'', current_value=current_temp2, at=now)  ]feed.update()

Štai ir visas gudrumas. Šis skriptas taip, kaip skaitytų iš failo, nuskaito abiejų jutiklių temperatūras ir priskiria jas kintamiesiems. Sekantis etapas - naudojantis xively-python moduliu duomenys nusiunčiami į serverį. Rezultatą galima pamatyti iškart, prisijungus prie savo Xively.com paskyros.
Paleisti skriptą vykdymui galima komanda "python temp.py".
Tačiau paleidus skriptą duomenys bus nusiųsti vieną kartą. Norint, kad tai vyktų nuolat (mano atveju - kas minutę), reikia sukurti cron užduotį. Cron - programa, kuri paleidžia nustatytą programą nustatytais laiko intervalais. Ši programa yra linux dalis, todėl tereikia tik pridėti naują užduotį:

crontab -e

pridėti tokį tekstą:

* * * * * /usr/bin/python /home/pi/temp.py

Uždarius teksto rašyklę (mano atveju Nano uždarius klavišų kombinacija ctrl+x) kas minutę bus vykdomas parašytas skriptas.
Mano rezultatas - https://xively.com/feeds/2104719994 , karšto vandens vamzdžio temperatūra. Nors ją matuoti pradėjau atsitiktinai - tiesiog reikėjo pritvirtinti prie ko nors jutiklį, pasirodo, tokia informacija gali būti visai naudinga. Pagal higienos normas (yra internete) karšto vandens temperatūra negali būti žemiau 50 laipsnių. Tai va, pasirodo, mes turim per šaltą vandenį.
--------------
Nuorodos:
 http://datasheets.maximintegrated.com/en/ds/DS18B20.pdf - DS18B20 dokumentacija
http://en.wikipedia.org/wiki/1-Wire 1-WIRE protokolo aprašymas
http://datasheets.maximintegrated.com/en/ds/DS2480B.pdf DS2480 dokumentacija
http://www.gaggl.com/2013/01/accessing-1-wire-devices-on-raspberry-pi-using-owfs/
http://owfs.sourceforge.net/WRT54G.html
http://wannabe.guru.org/scott/hobbies/temperature/
http://xively.github.io/xively-python/

Komentarų nėra:

Rašyti komentarą