
2012
Raspberry Pi odczyt temperatury przez nodejs
W poprzednim wpisie dotyczącym Raspberry Pi pokazałem co należy zrobić aby uruchomić na nim system oraz mini-server www w postaci prostego skryptu nodejs.
RPi nie jest tylko miniaturową wersją zwykłego komputera, na którym można testować aplikacje czy strony www. Do tego można przecież użyć VM (przy tym przydzielić więcej zasobów). Malina ma coś więcej – wbudowany port rozszerzeń GPIO, za pomocą którego możemy wchodzić w interakcje z zewnętrznymi urządzeniami elektronicznymi. Począwszy od prostego świecenia diodami LED, przez odczytywanie wartości z urządzeń aż po bardziej zaawansowane możliwości sterowania.
W tym wpisie pokażę jedną z możliwości – odczyt temperatury z czujnika 1-wire Dallas 18B20.
Aktualizacja systemu
Niestety, w dostępnym w lipcu obrazie Debiana nie było modułu 1-wire, jądro było w wersji 3.1.9.
vokiel@rpi ~$ uname -a Linux raspberrypi 3.1.9+ #168 PREEMPT Sat Jul 14 18:56:31 BST 2012 armv6l GNU/Linux |
Prace przy RPi ciągle trwają, zatem nowe aktualizacje, dodatki pojawiają się bardzo często. W związku z tym potrzebna jest aktualizacja systemu. Dostępnych jest wiele instrukcji, m.in.: http://elinux.org/RPi_Kernel_Compilation, http://www.bootc.net/projects/raspberry-pi-kernel/. Najłatwiejszą wersją (jeśli nie chcecie sami kompilować jądra) jest Hexxeh’s easy updater tool, którego użycie sprowadza się do trzech komend:
wget http://goo.gl/1BOfJ -O /usr/bin/rpi-update && chmod +x /usr/bin/rpi-update |
sudo apt-get install ca-certificates |
rpi-update 240 #podział pamięci na 240MB CPU / 16MB GPU |
Podany sposób nie aktualizuje nam jądra do najnowszej dostępnej wersji, ale jest ona wystarczająca do uruchomienia 1-wire:
vokiel@rpi ~ $ uname -a Linux rpi 3.2.18+ #20 Mon May 28 17:27:57 EDT 2012 armv6l GNU/Linux |
Moduł 1-wire
Wątek na forum RPi dotyczący 1-wire jest dość obszerny: http://www.raspberrypi.org/phpBB3/viewtopic.php?t=6649, ważne jest dla nas jedno – włączenie modułu jądra.
Sprawdźmy najpierw, czy mamy widoczne urządzenie w1 (1-wire):
vokiel@rpi ~ $ ls /sys/bus/ amba hid mmc platform scsi sdio spi usb |
Jak widać nie, zatem musimy dodać moduł, a następnie zrestartować Malinę
root@rpi:~# modprobe w1-gpio |
Po restarcie jest ok:
vokiel@rpi ~ $ ls /sys/bus/ amba hid mmc platform scsi sdio spi usb w1 |
Nasz termometr pojawi się w katalogu /sys/bus/w1/devices/
pod swoim id, np.: 28-00000249bf39
. Ale aby to się stało, musimy zabrać się za małe lutowanie.
Elektronika

Dallas 18B20

Dallas 18B20
Na zdjęciu obok widać jak wygląda Dallas 18B20. Jest bardzo mały i poręczny, pasuje do miniaturyzacji samego RPi.
Obok zdjęcia widać schemat oznaczenia nóżek: 0V (GND), DQ, V+ – masa, sygnał, zasilanie. Potrzebujemy jeszcze rezystora o oporności 4,7kΩ, który wstawiamy pomiędzy nóżki 2-3.
Przykładowy schemat: (Dla pewności podłączenia sprawdzajcie datasheet producenta.)
Do ukończenia zestawu potrzebne będą jeszcze kabelki. Dobrym źródłem może być stary pc, z którego możemy wymonotować taśmy łączące przedni panel z płytą główną. Zaletą takich kabli są gotowe końcówki, które możemy od razu podpinać do pinów GPIO. Przydadzą się jeszcze rurki termokurczliwe, żeby całość nie wyglądała tak tragicznie jak u mnie – izolowanie za pomocą taśmy.
Jako, że nie jest to blog elektronika, nie będę tu przedstawiał procesu lutowania, w zasadzie nie jest on skomplikowany, ani nawet interesujący. Gotowy zestaw po podłączeniu wygląda następująco:
Podwójna wtyczka (niebieski + szary kabelek) jest podwójna tylko dlatego, że zbrakło mi pojedynczych ;), siwy kabelek jest w tym przypadku niepotrzebny.
Odczyt temperatury
Domyślnie w1-wire dla RPi działa na GPIO4 (pin 7) – niebieski kabelek na zdjęciu powyżej. Proponuję zapoznać się z układem pinów i ich oznaczeniami, wygodny schemat dostępny jest na stronie http://www.raspberrypi-spy.co.uk/2012/06/simple-guide-to-the-rpi-gpio-header-and-pins/. Widoczny na zdjęciu biały kabelek podpięty jest do P1 – zasilanie 3,3V, czarny z tyłu to GND.
Jeśli wszystko zostało podpięte poprawnie, powinniśmy zobaczyć urządzenie w systemie:
vokiel@rpi ~ $ ls -l /sys/bus/w1/devices/ razem 0 lrwxrwxrwx 1 root root 0 wrz 16 08:16 28-00000249bf39 -> ../../../devices/w1_bus_master1/28-00000249bf39 lrwxrwxrwx 1 root root 0 wrz 16 13:04 w1_bus_master1 -> ../../../devices/w1_bus_master1 |
W katalogu urządzenia zobaczymy kilka plików i katalogów:
vokiel@rpi ~ $ cd /sys/bus/w1/devices/28-00000249bf39 vokiel@rpi /sys/bus/w1/devices/28-00000249bf39 $ ls -la razem 0 drwxr-xr-x 3 root root 0 wrz 16 08:16 . drwxr-xr-x 4 root root 0 wrz 16 08:16 .. lrwxrwxrwx 1 root root 0 wrz 16 13:52 driver -> ../../../bus/w1/drivers/w1_slave_driver -r--r--r-- 1 root root 4096 wrz 16 13:52 id -r--r--r-- 1 root root 4096 wrz 16 13:52 name drwxr-xr-x 2 root root 0 wrz 16 13:52 power lrwxrwxrwx 1 root root 0 wrz 16 13:52 subsystem -> ../../../bus/w1 -rw-r--r-- 1 root root 4096 wrz 16 13:52 uevent -r--r--r-- 1 root root 4096 wrz 16 08:16 w1_slave |
Najważniejszy dla nas to w1_slave
, z którego odczytamy aktualną temperaturę. Możemy to zrobić wykorzystując po prostu program cat
:
vokiel@rpi /sys/bus/w1/devices/28-00000249bf39 $ cat w1_slave c3 01 4b 46 7f ff 0d 10 2f : crc=2f YES c3 01 4b 46 7f ff 0d 10 2f t=28187 |
Jak się nie trudno domyśleć, t=28187
to aktualna temperatura z czujnika (28.187 °C). Oczywiście ta postać nie bardzo nadaje się do dalszego użycia. Sposobów na pobranie temperatury w bardziej czytelnym formacie jest tyle ilu programistów, mój wygląda następująco:
vokiel@rpi /sys/bus/w1/devices/28-00000249bf39 $ \ > cat ./w1_slave | grep t= | cut -f2 -d= | awk '{print $1/1000}' 28.125 |
Node
Skoro potrafimy już odczytywac temperaturę z czujnika, czas najwyższy połączyć to z nodejs.
Na początek przyda nam się moduł child_process
, przy pomocy którego wywołamy sytemową komendę i odbierzemy wynik jej działania.
#!/usr/bin/node var exec = require('child_process').exec; var tempId = '28-00000249bf39', dispTempInterval, dispTempIntervalClock = 10; //sec var dispTemp = function(){ exec( "cat /sys/bus/w1/devices/" + tempId + "/w1_slave | grep t= | cut -f2 -d= | awk '{print $1/1000}'", function( error, stdout, stderr ){ if ( error != null ){ console.log( "Error: " + error); } var temp = parseFloat(stdout).toFixed(2); console.log ( "Current temperature: " + temp + "°C" ); }); } console.log( 'Started node-temp'); console.log( '-----------------'); /* Start interval */ dispTempInterval = setInterval( function(){ dispTemp(); }, dispTempIntervalClock*1000 ); |
Uruchamiamy skrypt i co 10 sekund otrzymujemy aktulane odczyty temperatury, które możemy zapisać w bazie danych i zrobić z nich ładny wykres.
Started node-temp ----------------- Current temperature: 22.50°C Current temperature: 22.50°C Current temperature: 24.19°C
Po drobnych modyfikacjach ( github – rpi-node-temp ) efekt wygląda troszeczkę lepiej. Dodałem jeden próg, który oddziela „bezpieczną” temperaturę od krytycznej i odpowiednio sygnalizuje to kolorem. Przyłożenie termometru do czipa pokazuje efekt kolorów:
Hej właśnie podłączam ten czujnik według twojego opisu i nie pojawia mi się plik w1_slave. Katalog czujnika pojawia się po podłączeniu.
po wykonaniu: #ls /sys/bus/
amba event_source hid i2c mmc platform scsi sdio spi usb w1
Ruszyło dopiero po załadowaniu kolejnego modułu:
modprobe w1-therm
mój system to też rasbian
Proponuję dodanie obu modułów do /etc/modules:
da to pewność, że będą ładowane przy starcie systemu.
AK
@ZuKo dzięki za tip.
Pewnie się przyda, później, bo jeszcze nie restartowałem jeszcze RPi od czasu tego wpisu;)
edit: po restarcie trzeba było dodać oba moduły. Dopisane do /etc/modules, dzięki za komentarze.
Wie ktoś jak to obsłużyć z poziomu C/C++? Coś bardziej eleganckiego niż cat /sys/bus/w1/…
@guzik nie wiem jak odczyt wartości sensora, ale może dasz radę przez obsługę samego GPIO: http://elinux.org/RPi_Low-level_peripherals#GPIO_Driving_Example_.28C.29
Witam, czy nie masz może skryptu do publikowania odczytu temperatury. Może zamiast wysyłania odczytu do konsoli zapis byłby do pliku lub na stronkę web.
Mam prosty skrypt zapisujący odczyty do sqlite3, ale jeszcze wymaga dorpacowania. W najbliższym czasie planuję kolejne wpisy o RPi, więc pewnie niedługo się pojawi.
Witam, mam jeszcze jedno pytanko: co jakiś czas otrzymuje błędny odczyt temperatury np. w pomieszczeniu mam temp. 22.5 C a czasmi mam odczyt na poziomie -0.012 C. Nie wiem z czego to wynika. Masz moze pomysł co może być źle?
Czasem pojawiają się błędne odczyty, ale zwykle przy nich jest też niepoprawny CRC (pierwsza linia odczytu).
Zatem trzeba przerobić trochę skrypt odczytu, tak aby brał pod uwagę sumę kontrolną i odrzucał wpisy, gdzie jest niepoprawna.
Hej. Próbowaliście podłączać 2 czujniki do jednego gpio? Mi po podłączeniu zaczęły pojawiać się błędy, że jest niewłaściwe CRC. Otrzymuję coś w rodzaju:
zawsze mam ff na początku, złe crc, ale temperatura jest podawana dobra np. tak jak powyżej wyszłoby 28.187
ff ff ff ff ff ff ff ff ff : crc=2f NO
c3 01 4b 46 7f ff 0d 10 2f t=-0.62
jaką macie wartość w pliku w1_master_pullup?
Błędy mogą wynikać z niewłaściwego pull up . Wartość 4k7 jest dla 5V i przy 1 czujniku pewnie jest OK nawet z napięciem 3V. Przy 3V dałem 3k0 i nie ma problemu z 3 czujnikami.
1) czy mogę zamotować 5 takich czujników ?
2) ile max metrów może mieć kabel łączący gpioczujnik ?
1. Możesz zamontować tyle czujników ile pinów GPIO zmusisz do obsługi
2. Testowane przez kumpla na 4m kabla telefonicznego – działa bardzo dobrze. Myślę, że do 10m nie powinno być problemów, powyżej trzeba by policzyć spadki napięcia i rezystancję i ewentualnie skorygować parametry rezystora.
podłączyłem 5 czyhbników równolegle z rezystorem 2.5k i wszystko jest ok. Kabele do czujników maja około 4m.
podłączyłem 5 czujników równolegle, z 1 rezystorem 2.5k i wszystko jest ok(wykorzystałem 3 piny na gpio). Kabele do czujników maja około 4m.
Jak zmienić domyślny pin GPIO4(7) na inny ?
Zobacz w tych wątkach: http://www.raspberrypi.org/phpBB3/viewtopic.php?f=44&t=11127, http://www.raspberrypi.org/phpBB3/viewtopic.php?f=72&t=17975.
Funkcje „General purpose Clock” można uzyskać też na innych pinach: http://elinux.org/RPi_BCM2835_GPIOs#GPCLK0
No to jak dla mnie lipa, bo moduł działa na alternatywnej funkcji GPIO, a nie bezpośrednio na sterowanym pinie GPIO4. Próbowałeś napisać własny program obsługi protokołu 1-wire ??
chyba „wykorzystując po prostu program cat”
Tak, jasne, thx.
Jako zapalony Arduinowiec już od dawna czaiłem się na zakup rPi, ale cały czas powstrzymywał mnie kompletny brak polskich stron poświęconych początkowym boją z tym maleństwem. Mam nadzieję, że szybko się nie poddasz i będziesz kontynuował swoje dzieło 🙂
Pozdrawiam serdecznie!
I tak w ogóle, to skądś Cię kojarzę. Z Blipa? 😉
Może z WordCamp’a 2011 ?
Chyba gdzieś wcześniej już widywałem tego nicka i avatara… No nieważne 🙂
A tak w ogóle, to od kilku dni http://blog.vokiel.com/raspberry-pi-pierwsze-starcie/ zwraca 404…
Dzięki za info, w3 total cache potrafi wyświetlić stronę dla zalogowanego użytkownika, ale dla anonymous już sypie 404.
Witam, mógłbyś wrzucić schemat podłączenia? Byłbym wdzięczny.
@Gizmor jasne, dodałem schemat w treści wpisu.
I learnt a lot from you guys. Thanks for this discussion.
Hej,
jednak uwaga, w tekscie piszesz opernik 47 Ohm
o oznaczenia wskazują na 4.7 kOhm i tak też na schemacie!
to jest roznica 100x i nie wiem czy czegoś ktoś nie usmaży (chyba nie jak podłączy do 3.3V, ale jakby tak do 5V …)
Racja, urwało
k
, dzięki za uwagę.Wpis poprawiony.
Super artykuł! Abstrhując od porządnej treści merytorycznej to czytając czułem się jak w latach 80-tych majstrując interfejs oparty o centroniks w oparciu o artykuł z bajtka. Rozumiem, że nodejs to taki dodatkowy bajer, bo odczyt można zrobić z dowolnego języka pozwalającego na dostęp do systemu plików z /sys/bus/w1/devices/ …
Bardzo pomocny artykuł.
Czy próbował ktoś podłączyć do pojedynczego RPi więcej niż jeden taki termometr? Niestety nie udało mi się znaleźć w Sieci opisów takich konstrukcji
[…] Raspberry Pi odczyt temperatury przez nodejs […]
Witam udało się odczytać 9 termometrów, chodziły w miarę stabilnie, długość kabla ok 20mb z jednym rezystorem 4.7 k napięcie 3,3V kabel skrętka kat 5, powyżej tej 20 m lub większej liczbie czujników albo wyświetla czujniki z wartością 0.0 stopnia lub ich nie widzi. Jestem w trakcie prób może na 5 V lub z rezystorem na końcu lini będzie jakaś poprawa.
Piękna sprawa z tym czujnikiem. A jak zapisywać dane z czujnika do bazy danych? Byłoby o wiele wygodniej z nich korzystać.
Pozdrawiam Autora 🙂
Najprościej zrobić to chociażby w sqlite3, chociaż do node bardziej by pasował jakiś nosql.
Tworzenie bazy:
Odczyt temp z zapisem do bazy:
Dzięki za odpowiedź, niestety nie moge poeksperymentować, bo mój termometr się nie pojawia, wygląda to tak:
pi@raspberrypi ~ $ ls -la /sys/bus/w1/devices/
razem 0
drwxr-xr-x 2 root root 0 mar 19 19:13 .
drwxr-xr-x 4 root root 0 mar 19 19:13 ..
pi@raspberrypi ~ $
sprawdzam jeszcze:
pi@raspberrypi ~ $ ls /sys/bus/
i mam
amba container hid mmc sdio w1
czyli wygląda że dotąd jest ok, połączenia sprawdziłem 10 razy, łącznie z pomiarami napiecia na DS18B20. Szukając przyczyny znalazłem niespójność w schemacie i na zdjęciu. Na chemacie jest podłączone napięcie 5V, a na zdjęciu 3,3V. W necie znalazłem że dla 5V należy zastosować rezystor 4,7kΩ, ale dla 3,3V – 2,7kΩ., Może tu mam przyczynę. Zmieniałem rezystor na 3,67kΩ, potem na 2,8kΩ i nadal nic. Następnym krokiem byłoby podłączenie na 5V z rezystorem 4,7kΩ, ale ponieważ zauważyłem w/w niespójność, a nie chcę zniszczyć malinki pochpnym działaniem (bo nie wiem czy to nie zaszkodzi) wolę się upewnić jak powinno być. Skoro to działa u Ciebie i u wielu innych osób to znaczy że ja coś źle robię, tylko nie wiem co. Proszę o pomoc, pozdrawiam.
Witam. Jest możliwość wystosowania jakichś alertów np. sms czy mail po przekroczeniu danej wartości? Znaczy na RaspberryPi postawić serwer który to będzie obsługiwał?
Odsyłam tutaj – http://www.ematador.pl/pl/p/Modul-Raspberry-Pi-GPIO-Breakout-40-pin/788
Jak się sprawuje, kto go posiada i czy polecacie? Ewentualnie co innego za podobną kasę?