Budowa stacji zainspirowana by?a prostymi aplikacjami pomiaru temperatury za pomoc? digitemp.
W miar? jedzenia okaza?o si?, ?e digitemp to tylko wst?p do tematu a dalej potoczy?o si? samo.
http://meteo.tytanos.pl
Sprz?t:
1. Router z portem USB i mo?liwo?ci? wgrania OpenWrt lub jaka? inna platforma PC z systemem linux. Ja przetestowa?em najpierw WRT160NL z OpenWrt a potem przeszed?em na T5710 i Ubuntu.
2. Konwerter USB-1Wire MP00200A.
3. Czujnik temperatury DS18B20 (2szt).
4. Czujnik wilgotno?ci HIH-4000-002.
5. Czujnik ci?nienia atmosferycznego bezwzgl?dnego MPX4115A.
6. Konwerter napi?cie na 1-Wire DS2450.
7. Opcjonalnie polecam pendrive i hub USB.
8. Troch? przewodu (mo?e by? skr?tka).
Oprogramowanie:
1. W zale?no?ci od potrzeb najciekawiej b?dzie pod OpenWrt ale mo?e by? te? inny równie wspania?y system linux ;)
2. Pakiet oprogramowania owfs, bc, rrdtool, php z bibliotekami filtrów graficznych.
Sposób dzia?ania systemu:
Konwerter USB-1Wire stanowi pomost sprz?towy dla pod??czenia urz?dze? pracuj?cych na szynie 1-Wire tj. DS2450 i DS1820. Te elementy pod??czone s? równolegle do konwertera.
DS2450 jest to cztero-wej?ciowy przetwornik: napi?cie na szyn? 1-Wire. DS1820 to znana czujka temperatury.
Od razu mo?na zaznaczy? ?e czujek DS1820 mo?e by? wi?cej bez wielkiego wp?ywu na stopie? skomplikowania uk?adu.
Taki uk?ad zapewnia przetworzenie trzech ró?nych sygna?ów pomiarowych warunków pogodowych na transmisj? USB. (ja pod??czy?em dwie czujki temperatury)
Najciekawszym dla mnie jest wykorzystanie pakietu [b]owfs[/b] który na nasze potrzeby zapewni komunikacj? systemu operacyjnego z czujkami.
Owfs to specjalizowany ale bardzo prosty w u?yciu system plików który zapewnia przekazywanie danych w dwóch kierunkach (my wykorzystamy jeden).
Za odczyt danych z owfs odpowiada skrypt ?aduj?cy baz? danych rrdtool oraz generuj?cy wykresy.
Pomocniczym jest php u?yte na potrzeby generowania "odjazdowych" zegarów b?d? po prostu termometru s?upkowego.
Etap 1.
Do DS2450 pod??czymy czujniki które przetwarzaj? parametr mierzony na napi?cie (czujka ci?nienia i wilgotno?ci).
Równolegle do DS2450 po??czamy DS1820. Oba elementy pod??czamy do konwertera MP00200A. DS2450 wymaga jeszcze zasilania wi?c podpinamy trzeci przewód do konwertera gdzie mamy wyj?cie napi?cia 5V. Konwerter wpinamy do naszego rz?dzenia.
Instalujemy pakiet owfs. Na openwrt jest on dost?pny w repozystoriach w Ubuntu musia?em kompilowa? ze ?róde?.
Instalujemy rrdtool - pakiet spe?niaj?cy rol? bazy danych a jednocze?nie rysuj?cy wykresy.
Budujemy system plików:
Przygotowujemy malutki dysk wirtualny w pami?ci systemu (starczy z 5MB). Na dysku przechowywane b?d? dynamicznie zmienne dane.
W OpenWrt wykorzystujemy gotowy dysk /tmp a w innym systemie dopisujemy do /etc/rc.local :
/home/user/skrypty/ramdysk.sh
mkdir /mnt/ram/owfs
/opt/owfs/bin/owfs -u /mnt/ram/owfs
skrypt ramdysk tylko gdy nie mamy /tmp w ramie (zapewne mo?na te? inaczej):
dd if=/dev/zero of=/dev/ram0 bs=1k count=32768
mkfs.ext3 -m 0 /dev/ram0 15000
mount -t ext3 /dev/ram0 /mnt/ram
chmod 0777 /mnt/ram
Wpisy i skrypt powinny po restarcie systemu stworzy? nam w ramie katalog owfs gdzie wewn?trz utworozny zostanie automatycznie system plików odzwierciedlaj?cy liste czujników 1-Wire podpi?tych do konwertera USB/1-Wire.
Zasadniczym wpisem jest tu montowanie systemu plików owfs z automatycznym wykryciem konwertera na USB /opt/owfs/bin/owfs -u /mnt/ram/owfs
?cie?k? prowadz?c? do programu owfs nale?y dostosowa? do w?asnego systemu.
W katalogu owfs powinni?my zobaczy? co? podobnego:
ls
01.AA5FF7050000
28.5DF4FA010000
alarm
settings
statistics
system
20.CC350A000000
28.92FCFA010000bus.0
simultaneous
structure
uncached
Pisa? mo?na o tym du?o ale naprawd? u?ycie jest proste. Katalogi s? odzwierciedleniem wykrytych urz?dze?. Zawarto?? poszczególnych plików to wielko?ci odczytane/odczytywane z naszych czujek. Cze?? z nich jest z buforem domy?lnie 15s inne s? bezpo?rednio zwi?zane z urz?dzeniem, tzn. czytaj?c z nich inicjujemy odczyt konkretnej czujki. My wykorzystamy pliki z buforem. Niektóre pliki maja podobn? zawarto??. Ró?ni? si? dok?adno?ci? odczytu. Je?li czujka ma pami?? alarmu oraz mo?liwo?? sterowania ni? znajdziemy obok inne odpowiadaj?ce za to pliki (my ich nie u?yjemy).
Etap 2.
Zak?adamy baz? danych:
#rrdtool create ./pomiary.rrd -s 60 DS:temp_out:GAUGE:180:U:U DS:temp_in:GAUGE:250:U:U DS:presure:GAUGE:180:U:U DS:higrometr:GAUGE:180:U:U RRA:MIN:0.5:4:44640 RRA:AVERAGE:0.5:4:44640 RRA:MAX:0.5:4:44640
pomiary.rrd to miejsce bazy danych. Ja baz? umie?ci?em na zamontowanym pendrivie którego mi nie szkoda gdy? zapisy b?d? odbywa?y si? co jedn? minut? (ja tak robi?- mo?na rzadziej).
Uwaga: je?li kto? zapisze to do skryptu koniecznie po wygenerowaniu bazy niech zakomentuje wywo?anie polecenia - wiadomo czym to grozi :)
Baza rrdtool jest przesuwn? czyli nigdy jej nie zapchamy. W momencie zak?adania bazy musimy zdecydowa? si? ile (na jak d?ugi okres) danych ma przechowywa?.
Etap 3.
Skrypt ?aduj?cy baz? i generuj?cy wykresy:
#!/bin/bash
RRD=/mnt/meteo/www/pomiary.rrd
TOOL='/usr/bin/rrdtool'
NOW=`date -u +%s`
TEMPOUT=`sed 's/^[ ]*//' /mnt/ram/owfs/28.92FCFA010000/temperature`
TEMPIN=`sed 's/^[ ]*//' /mnt/ram/owfs/28.5DF4FA010000/temperature`
VOLTA=`sed 's/^[ ]*//' /mnt/ram/owfs/20.CC350A000000/volt.A`
VOLTB=`sed 's/^[ ]*//' /mnt/ram/owfs/20.CC350A000000/volt.B`
#A=4.935
#A=4.825
####### obliczenie cisnienia
A=4.959
B=0.095
C=0.009
E=`echo $VOLTA/$A+$B | bc -l`
PRESURE=`echo $E/$C*10 | bc -l`
########
####### obiczenie wilgotnosci
G=4.935
H=`echo $VOLTB/$G-0.16 | bc -l`
HIGRO=`echo $H/0.0062 | bc -l`
#######
#petla
if [ -n "$TEMPOUT" ];
then
################ LCD ##########
echo "$TEMPOUT" > /mnt/ram/temp_out.txt
echo "$TEMPIN" > /mnt/ram/temp_in.txt
pres=`echo $PRESURE*100 | bc -l`
pres2=`echo $pres | cut -d"." -f1`
pres3=`echo $pres2/100 | bc -l`
pres4=`echo $pres3 | cut -d"." -f1`
#echo "$pres4" > /mnt/ram/presure.txt
echo "$PRESURE" > /mnt/ram/presure.txt
echo "$HIGRO" > /mnt/ram/higro.txt
##################
$TOOL update $RRD $NOW:$TEMPOUT:$TEMPIN:$PRESURE:$HIGRO;
rrdtool graph /mnt/ram/temp13.png --lazy -a PNG -n TITLE:12 -t 'Temperatura w pomieszczeniu' \
-A -l 18 -u 24 -r -W 'Testowy pomiar w domu' -w 600 -h 200 --vertical-label 'Stopnie Celsjusza' --end now -s end-24h --slope-mode \
DEF:t=$RRD:temp_in:AVERAGE LINE1:t#00bf00:Temperatura \
DEF:tmax=$RRD:temp_in:MAX DEF:tmin=$RRD:temp_in:MIN \
'GPRINT:t:LAST:Ostatni pomiar\: %2.1lf C\j' \
'GPRINT:tmin:MIN:Minimum \: %2.1lf C' \
'GPRINT:tmax:MAX:Maximum \: %2.1lf C\j';
rrdtool graph /mnt/ram/temp12.gif -t 'Temperatura na dworze - 24 godziny' \
-A -w 600 -h 200 --vertical-label 'Temperatura [C]' -Y -s end-24h -E \
DEF:t=$RRD:temp_out:AVERAGE LINE1:t#00af00:Temperatura \
DEF:tmax=$RRD:temp_out:MAX DEF:tmin=$RRD:temp_out:MIN \
'GPRINT:t:LAST:Ostatni pomiar\: %2.1lf C\j' \
'GPRINT:tmin:MIN:Minimum \: %2.1lf C' \
'GPRINT:tmax:MAX:Maximum \: %2.1lf C\j';
rrdtool graph /mnt/ram/temp12t.gif -t 'Temperatura na dworze - 7 dni' \
-A -w 600 -h 200 --vertical-label 'Temperatura [C]' -Y -s end-168h -E \
DEF:t=$RRD:temp_out:AVERAGE LINE1:t#00af00:Temperatura \
DEF:tmax=$RRD:temp_out:MAX DEF:tmin=$RRD:temp_out:MIN \
'GPRINT:t:LAST:Ostatni pomiar\: %2.1lf C\j' \
'GPRINT:tmin:MIN:Minimum \: %2.1lf C' \
'GPRINT:tmax:MAX:Maximum \: %2.1lf C\j';
rrdtool graph /mnt/ram/temp12a.gif -t 'Ci?nienie atmosferyczne na wysoko?ci poziomu morza' \
-A -l 980 -u 1040 -L 8 -W 'POMIAR W LUBLINIE h=195m n.p.m.' -w 600 -h 250 --vertical-label 'Cisnienie [hPa]' -Y --end now -s end-168h -E \
DEF:t=$RRD:presure:AVERAGE LINE1:t#00af00:hPa \
DEF:tmax=$RRD:presure:MAX DEF:tmin=$RRD:presure:MIN \
'GPRINT:t:LAST:Ostatni pomiar\: %2.1lf hPa\j' \
'GPRINT:tmin:MIN:Minimum \: %2.1lf hPa' \
'GPRINT:tmax:MAX:Maximum \: %2.1lf hPa\j';
rrdtool graph /mnt/ram/temp12b.gif -t 'Wilgotno?? w pomieszczeniu test bez kalibracji' \
-A -l 25 -u 60 -W 'POMIAR HIGRO' -w 600 -h 250 --vertical-label 'Higrometr [%]' -Y --end now -s end-48h -E \
DEF:t=$RRD:higrometr:AVERAGE LINE1:t#00af00:% \
DEF:tmax=$RRD:higrometr:MAX DEF:tmin=$RRD:higrometr:MIN \
'GPRINT:t:LAST:Ostatni pomiar\: %2.1lf procent\j' \
'GPRINT:tmin:MIN:Minimum \: %2.1lf procent' \
'GPRINT:tmax:MAX:Maximum \: %2.1lf procent\j';
mv -f /mnt/ram/temp12.gif /mnt/ram/atemp12.gif
mv -f /mnt/ram/temp12a.gif /mnt/ram/atemp12a.gif
mv -f /mnt/ram/temp12b.gif /mnt/ram/atemp12b.gif
mv -f /mnt/ram/temp12t.gif /mnt/ram/atemp12t.gif
mv -f /mnt/ram/temp13.png /mnt/ram/atemp13.png
else
echo "koniec bez roboty";
Gdzie w skrypcie:
Katalog i plik ze wskazaniem temperatury: 28.92FCFA010000/temperature
Katalog i plik ze wskazaniem temperatury: 28.5DF4FA010000/temperature
Katalog i plik z napi?ciem odczytanym z czujki ci?nienia 20.CC350A000000/volt.A
Katalog i plik z napi?ciem odczytanym z czujki wilgotno?ci 20.CC350A000000/volt. B
Nale?y tu wiedzie? o tym, ?e ka?da czujka b?d? przetwornik DS2450 ma fabrycznie nadany indywidualny identyfikator.
Nazwy katalogów/identyfikatorów nale?y w skrypcie zmieni? wed?ug odczytów z zamontowanego katalogu owfs.
W sekcjach obliczenia ci?nienia i wilgotno?ci warto?? A i G dobieramy eksperymentalnie w okolicach 5.
Parametry te wskazuj? na wielko?? napi?cia zasilania czujników-zmieniamy je tak aby osi?gn?? wskazanie ci?nienia i wilgotno?ci zgodne z realiami.
Sekcja LCD s?u?y?a mi okresowo gdy na breloku chcia?em mie? wskazania parametrów z czujek.
Obecnie wykorzystuj? tworzone pliki na potrzeby generowania zegarów.
Poni?szy wpis to ?adowanie bazy danych.
"$TOOL update $RRD $NOW:$TEMPOUT:$TEMPIN:$PRESURE:$HIGRO;"
Uwaga: Do?wiadczy?em, ?e baz? nale?y zape?nia? rzeczywistymi danymi gdy? przy braku danych z czujnika mog? powsta? b??dy.
P?tla zapewnia mi ?adowanie bazy tylko wtedy gdy uk?ad odczyta wskazania z konwertera. Gdy nie mamy której? czujki baz? mo?na stworzy? mniejsz? ale mo?na te? okresowo na sztywno w skrypcie wskaza? brakuj?c? warto?? odczytu.
Sekcje "rrdtool graph ..." odpowiadaj? za czytanie danych z bazy i jednocze?nie generowanie wykresów w postaci plików graficznych.
Wpisy "mv -f /mnt/ram/temp..." na ko?cu skryptu zapewniaj? szybkie podstawienie wygenerowanych wykresów w miejsce poprzednich wykorzystywanych bezpo?rednio do prezentacji na WWW.
Skrypt odpalamy co minut? wpisem w crontab:
* * * * * /mnt/meteo/www/tempera.sh > /dev/null 2>&1
U?rednione dane gromadzone s? w bazie z rozdzielczo?ci? 4 minuty.
Na potrzeby sprawdzenia poprawno?ci zapisów w bazie mo?emy u?y? kodu:
W baza.txt znajdziemy wykaz danych za ostatnie 12 godzin.
W wyniku dzia?ania g?ównego skryptu otrzymujemy podobne wykresy jak ten:
ETAP 4.
Generowanie zegara w php (w skrypcie nale?y doda? nag?ówek i zako?czenie php)
header('Content-Type: image/png');
$img = imagecreatefrompng('strzalka_th.png');
$img2 = imagecreatefrompng('higrometr.png');
$col = imagecolorallocate($img, 255, 255, 255);
$black = imagecolorallocate($img, 0, 0, 0);
$width = 300;
$height = 300;
$xa = 430;
$ya = 430;
$tlo = imagecreatetruecolor($width, $height);
$tlo = imagecolorallocatealpha($tlo, 255, 255, 255, 100);
$plik=fopen("http://127.0.0.1/meteo/www/ram/higro.txt", "r");
$higro=fgets($plik, 10);
fclose($plik);
###tester
#$higro=80;
###
$angle = -360/133*($higro-43.89);
#obracanie strza?ki
$coltrans = imagecolorallocatealpha($img, 255, 255, 255, 100);
$img = imagerotate($img, $angle, $coltrans);
imagesavealpha($img, true);
$xb = $xa*abs(sin(deg2rad($angle)))+$xa*abs(cos(deg2rad($angle)));
$yb = $xb;
$punktx = ($xb-$width)/2+0;
$punkty = ($yb-$height)/2+0;
imagecopy($img2, $img, 0, 0, $punktx, $punkty, 300, 300);
imagesavealpha($img2, true);
imagepng($img2);
W wyniku odpalenia takich kodów otrzymujemy:
Plik strza?ka_th.png przedstawia na rysunku wskazówk? z przezroczystym t?em.
Plik higrometr.png to tarcza zegara otoczona równie? przezroczystym t?em.
Generowanie obrazków w php znacz?co obci??a router dlatego proponuj? nie wstawia? bezpo?rednio php na www tylko wynikowe obrazki otrzymane poprzez pobranie php wget-em (kolejny wpis w cronie).
Zapraszam na forum: http://openrouter.info/forum/viewtopic.php?f=30&t=111
Powodzenia w oswajaniu owfs ;)
Pomocne linki:
http://www.meraprojekt.com.pl/mp00200a.html
http://datasheets.maxim-ic.com/en/ds/DS18B20.pdf
http://mijagi.vot.pl/index.php/2009/08/obrobka-obrazkow-w-php-biblioteka-gd/
http://www.freescale.com/files/sensors/doc/data_sheet/MPX4115A.pdf
http://datasheet.octopart.com/HIH-4000-002-Honeywell-datasheet-62840.pdf
http://www.howtoforge.com/recompiling-php5-with-bundled-support-for-gd-on-ubuntu