Raspberry Pi temperature reading with nodejs

http://raspberrypi.org

In the previous post about Raspberry Pi I’ve showed what is needed to be done to install an OS with a mini www server on it ( as easy nodejs script).

RPI is not just a miniature version of a standard PC, where you can test applications or web pages. For this, you can use the VM (at the same time allocate more resources). Raspberry has something more – a built-in GPIO expansion port, with which we can interact with external electronic devices. Starting from a simple lighting a LED diodes, through reading the value of the devices to more advanced control possibilities.

In this post I will show you one of those options – the temperature reading from the 1-wire Dallas 18B20 sensor.

System update

Unfortunately, in the available in July Debian image, there were no 1-wire module, the kernel was in 3.1.9 version.

vokiel@rpi ~$ uname -a
Linux raspberrypi 3.1.9+ #168 PREEMPT Sat Jul 14 18:56:31 BST 2012 armv6l GNU/Linux

Work on the RPI is still going on, so the new updates, additions appear very often. In this case we need a system upgrade. There are a plenty instructions avalible on the net, such as: http://elinux.org/RPi_Kernel_Compilation, http://www.bootc.net/projects/raspberry-pi-kernel/. The easiest onve (if you do not want to compile the kernel yourselfs) is Hexxeh’s easy updater tool, the use of which boils down to three commands:

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 #memory split 240MB for CPU / 16MB for GPU

Given solution does not not update the kernel to the latest available version, but it is sufficient to run the 1-wire:

vokiel@rpi ~ $ uname -a
Linux rpi 3.2.18+ #20 Mon May 28 17:27:57 EDT 2012 armv6l GNU/Linux

1-wire module

Forum Thread on RPI forum about 1-wire is quite extensive: http://www.raspberrypi.org/phpBB3/viewtopic.php?t=6649, one is important for us – enabling the kernel module.

Let’s see first if we have the w1 (1-wire) device visible:

vokiel@rpi ~ $ ls /sys/bus/
amba  hid  mmc  platform  scsi  sdio  spi  usb

As we see – we don’t, so we need to add the module, and reboot the Raspberry

root@rpi:~# modprobe w1-gpio

After reboot everything seems to be ok:

vokiel@rpi ~ $ ls /sys/bus/
amba  hid  mmc  platform  scsi  sdio  spi  usb  w1

Our thermometer will appear in the /sys/bus/w1/devices/ directory, under it’s own id, for example: 28-00000249bf39. But for this to happen, we need to get on with a small soldering.

Electronics

Dallas 18B20

Dallas 18B20

In the picture on the right you can see how the Dallas 18B20 looks like. It is very small and compact, suitable for miniaturization of the RPI.

Next diagram shows pin marks: 0V (GND), DQ, V + – ground, the signal. power. We need a resistor with a resistance of 4.7kΩ, which need to be inserted between 2-3 pin.

Example schema: (To be sure of right connection, check manufacturer’s datasheet.)

http://nathan.chantrell.net/

To finish the project, set of cables will be needed yet. A good source might be an old pc, from which we can take out front panel to the motherboard connection cables. The advantage of such is that, they are ready to connect them to the GPIO pins. Another useful thing can be shrink tubs, to have the termometer not look so tragic like mine – isolated with the tape.

RPI_DS18B20

Since this is not an electronics blog, I will not be showing here the soldering process, it is not complicated, or even interesting. Ready, connected set looks as follows:

The doubled plug (blue + grey wire) is doubled just because I’ve lacked of single;), gray wire in this case is unnecessary.

Temperature reading

By default w1-wire for RPi operates on GPIO4 (pin 7) – the blue wire on the photo above. I suggest you refer to the system of pins and their markings, convenient schedule is available at http://www.raspberrypi-spy.co.uk/2012/06/simple-guide-to-the-rpi-gpio-header-and-pins/. The white wire visible in the picture, is connected to P1 – Power 3.3 V, black on the back – to the GND.

If everything is connected correctly, you should see the device in the system:

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

We can see couple files and folder in the device directory:

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

The most important for us is the w1_slave, from which we will be reading current tempreature. It can be done jus by using cat program:

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

As it is not difficult to guess, t=28187 is the current temperature from the sensor (28.187 °C). Of course, this figure is not very suitable for further use. Ways to read the temperature in a more readable format is as many as programmers, my looks as follows:

vokiel@rpi /sys/bus/w1/devices/28-00000249bf39 $ \
> cat ./w1_slave | grep t= | cut -f2 -d= | awk '{print $1/1000}'
28.125

Node

Since we can read the temperature from the sensor, it’s time to combine it with nodejs.

For start we will need child_process module by which we call systems command and pick the result of its action.

#!/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 );

We lauch the script and every 10 seconds will se current temperature readings, which could be saved into a database to draw some pretty chart.

Started node-temp
-----------------
Current temperature: 22.50°C
Current temperature: 22.50°C
Current temperature: 24.19°C

After some small modyfications ( github – rpi-node-temp ) the effect looks a little better. I’ve added one threshold that separates “safe” temperature from the critical and colors them respectively. Touching RPi chip with the thermometer shows the effect of colours:

rpi-node-temp

 

Przeczytaj także

Komentarze: 40

Dodaj komentarz »

 
 
 

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

 

Reply

 

Ruszyło dopiero po załadowaniu kolejnego modułu:
modprobe w1-therm

mój system to też rasbian

 

Reply

 

Proponuję dodanie obu modułów do /etc/modules:

#echo "w1-gpio" >> /etc/modules
#echo "w1-therm" >> /etc/modules

da to pewność, że będą ładowane przy starcie systemu.
AK

 

Reply

 

@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.

 

Reply

 

Wie ktoś jak to obsłużyć z poziomu C/C++? Coś bardziej eleganckiego niż cat /sys/bus/w1/…

 

Reply

 

@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

 

Reply

 

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.

 

Reply

 

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.

 

Reply

 

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?

 

Reply

     

    Czasem pojawiają się błędne odczyty, ale zwykle przy nich jest też niepoprawny CRC (pierwsza linia odczytu).

    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

    Zatem trzeba przerobić trochę skrypt odczytu, tak aby brał pod uwagę sumę kontrolną i odrzucał wpisy, gdzie jest niepoprawna.

     

    Reply

 

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?

 

Reply

 

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.

 

Reply

 

1) czy mogę zamotować 5 takich czujników ?
2) ile max metrów może mieć kabel łączący gpioczujnik ?

 

Reply

     

    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.

     

    Reply

       

      podłączyłem 5 czyhbników równolegle z rezystorem 2.5k i wszystko jest ok. Kabele do czujników maja około 4m.

       

      Reply

       

      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.

       

      Reply

 

Jak zmienić domyślny pin GPIO4(7) na inny ?

 

Reply

 

chyba “wykorzystując po prostu program cat”

 

Reply

 

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!

 

Reply

 

Witam, mógłbyś wrzucić schemat podłączenia? Byłbym wdzięczny.

 

Reply

Raspberry Pi computer
 

I learnt a lot from you guys. Thanks for this discussion.

 

Reply

 

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 …)

 

Reply

 

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/ …

 

Reply

 

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

 

Reply

     

    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.

     

    Reply

 

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 🙂

 

Reply

     

    Najprościej zrobić to chociażby w sqlite3, chociaż do node bardziej by pasował jakiś nosql.

    Tworzenie bazy:

    #!/usr/bin/env node
     
    var sqlite3 = require('sqlite3').verbose();
    var db;
     
    console.log("Creating database temps.sqlite3...");
     
    db = new sqlite3.Database('temps.sqlite3',function(){
        db.run("CREATE TABLE IF NOT EXISTS readings (id INTEGER PRIMARY KEY, term_id TEXT, temperature REAL, timestamp INTEGER)", function(){
            console.log('Database created');
        });
    });
     
    console.log('Done.');

    Odczyt temp z zapisem do bazy:

    #!/usr/bin/env node
     
    var exec = require('child_process').exec
        sqlite3 = require('sqlite3'),
        db = new sqlite3.Database('temps.sqlite3'),
        stmt = db.prepare("INSERT INTO readings (term_id, temperature, timestamp) VALUES(?, ?, ?)");
     
    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" );
     
            var now = Math.round(+new Date()/1000);
     
            stmt.run(tempId, temp, now, function ( err ) {
                if ( err ){
                    console.log('Query error: ' + err);
                }
            });
     
        });
    }
     
    console.log( 'Started node-temp');
    console.log( '-----------------');
     
    /* Start interval */
    dispTempInterval = setInterval( function(){
      dispTemp();
    }, dispTempIntervalClock*1000 );
     

    Reply

       

      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.

       

      Reply

 

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ł?

 

Reply

 

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ę?

 

Reply

 

Dodaj komentarz

 
(nie będzie publikowany)
 
 
Komentarz
 
 

Dozwolone tagi XHTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

 
© 2009 - 2016 Vokiel.com
WordPress Theme by Arcsin modified by Vokiel