Termometr na Raspberry Pi

Od jakiegoś czasu latał mi po głowie pomysł zrobienia termometru z zapisem temperatury, aby po latach móc porównywać np. czy lato w tym roku jest wyjątkowo upalne. Okazja przyszła gdy spalił się stary termometr i trzeba było kupić nowy. Wybór padł na Raspberry Pi 2 B…

System operacyjny postawiony na mojej malince to Raspbian i tego systemu będzie dotyczył poradnik. Zakładam że masz już odpalone połączenie sieciowe i zainstalowany zestaw LAMP (Linux, Apache, MySQL, PHP).

Do budowy wykorzystałem chyba najpopularniejsze w tym temacie czujki czyli DS18B20. Schemat podłączenia wygląda następująco:

  • zasilanie czyli czerwony kabel łączymy z +3,3V (pin 1)
  • masę czyli czarny kabel łączymy z GND (pin 6)
  • dane czyli żółty kabel łączymy z GPIO 4 (pin 7)
  • zasilanie i dane łączymy dodatkowo rezystorem 4,7 kΩ

Po podłączeniu wszystkiego czas odpalić obsługę magistrali 1Wire w naszej malince. Do pliku /etc/modules dopisujemy

w1-gpio
w1-therm

oraz do /boot/config.txt

dtoverlay=w1-gpio,gpiopin=4

i restartujemy naszą malinkę. W katalogu /sys/bus/w1/devices/ powinniśmy zobaczyć nasze czujki. Aby odpytać czujki używamy pierwszego lepszego czytacza plików tekstowych (np. cat) i czytamy plik /sys/bus/w1/devices/ID_CZUJKI/w1_slave czyli w moim przypadku:

pi@malwina ~ $ cat /sys/bus/w1/devices/28-0315047a0cff/w1_slave

44 01 55 00 7f ff 0c 10 94 : crc=94 YES
44 01 55 00 7f ff 0c 10 94 t=20250

„CRC=XX YES” oznacza że transmisja przeszła bez błędów, a „t” to nasza temperatura w stopniach miliCelsjusza i należy ją podzielić przez 1000. W tym przypadku to 20,25°C.

Skoro czujki już działają to czas zrobić skrypt do zrzutu danych i ich prezentowania. W tym celu wykorzystałem bazę MySQL i PHP.

MySQL to proste kilka tabelek:

CREATE TABLE IF NOT EXISTS `pogoda` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`czujka` int(11) NOT NULL,
`data` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`data_unix` int(11) NOT NULL,
`wartosc` decimal(3,1) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

do zrzucania danych do bazy napisałem prosty skrypt w PHP:

<?php
// blokujemy dostęp z zewnątrz
if ($_SERVER["REMOTE_ADDR"] != "127.0.0.1") { die("Dostęp zabroniony"); }
// Tutaj podmieniamy swoje dane MySQL na swoje
$mysqli = new mysqli("localhost", "LOGIN_MYSQL", "HASLO_MYSQL", "BAZA_MYSQL");
if ($mysqli->connect_errno) {
echo "Błąd połaczenia z MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}
// Podmieniamy numer czujki na własny
$czujka1 = system("cat /sys/bus/w1/devices/28-0315047a1bff/w1_slave | grep t= | cut -f2 -d= | awk '{print $1/1000}'"); // czytamy dane z czujki
$komenda1 = "INSERT INTO pogoda VALUES (NULL , '1',CURRENT_TIMESTAMP , '".time("U")."', '".$czujka1."')"; // generujemy dane do MySQL
$mysqli->query($komenda1); // wrzucamy dane do MySQL
// Koniec pierwszej czujki i początek drugiej. Jeśli mamy tylko jedną czujkę możemy ten kod usunąć. Jeśli mamy ich więcej kopiujemy wedle zasady.
$czujka2 = system("cat /sys/bus/w1/devices/28-0315047a0cff/w1_slave | grep t= | cut -f2 -d= | awk '{print $1/1000}'");
$komenda2 = "INSERT INTO pogoda VALUES (NULL , '2',CURRENT_TIMESTAMP , '".time("U")."', '".$czujka2."')";
$mysqli->query($komenda2);
// Koniec drugiej czujki
?>

Aby całość była automatycznie odpalana robimy wpis do Crona (w tym przypadku zrzut danych będzie co 5 minut).

pi@malwina ~ $ crontab -e

*/5 * * * *      wget -O /dev/null http://127.0.0.1/NASZ_SKRYPT.php

Strona do sprawdzenia ostatnich odczytów sprowadza się do odpytania wiersza ID o najwyższym numerze:

<?php
$mysqli = new mysqli("localhost", "LOGIN_BAZY", "HASLO_BAZY", "NAZWA_BAZY");
if ($mysqli->connect_errno) {
    echo "Błąd połaczenia z MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}
$res = mysqli_query($mysqli, "SELECT * FROM pogoda WHERE czujka='1' ORDER BY `pogoda`.`id` DESC LIMIT 0,1");
$pokoj = mysqli_fetch_assoc($res);
echo("Ostatnia aktualizacja: ".$pokoj['data']."
");
echo("Opis czujki 1: ".$pokoj['wartosc']."°C
");
$res = mysqli_query($mysqli, "SELECT * FROM pogoda WHERE czujka='2' ORDER BY `pogoda`.`id` DESC LIMIT 0,1");
$pokoj = mysqli_fetch_assoc($res);
echo("Opis czujki 2: ".$pokoj['wartosc']."°C");
?>

Pozostało tylko wygenerować jakiś ładny wykres, ale to już temat na osobny wpis. 🙂