Własny internetowy termometr

Własny internetowy termometr

W swoim już drugim wpisie na Majsterkowo chciałbym pokazać Wam jak zrobić za pomocą Arduino (oczywiście następnie mikroprocesora) Internetowy termometr. Taki projekt może być przydatny dla Was i Waszych znajomych, w szczególności w miastach które nie mają swoich własnych stacji pogodowych. Termometr wyświetli na żywo aktualny podgląd temperatury oraz pokaże wykres jej zmian.

311317_145481232286174_801433871_n

Nie wszystkie z tych czynności będą realizowane przez układ, większość z nich wykona serwer PHP, gdyż lepiej się sprawdzi przy większych obciążeniach. Przykład działania można zobaczyć u mnie: podgląd temperatury & archiwum zmian temperatur & fanpage.

Potrzebne elementy

  • Płytka stykowa 400
  • LCD Kit 2×16 (możesz pominąć, jeśli nie chcesz widzieć podglądu fizycznie)
  • 2x Czujnik temperatury DS18B20 (działa na złączu OneWire i jego dokładność to 0,5 stopnia, analogowy sensor jest łatwiejszy do zakodowania, jednak o wiele mniej dokładny)
  • ATmega 328P-PU (w mniejszej nie zmieści się biblioteka OneWire wraz z biblioteką modułu Ethernet)
  • Moduł Ethernet ENC28J60 (np. z eBaya)
  • Rezystor 4,7k
  • Kawałek skrętki UTP lub innego kabla, tak aby móc wystawić termometr za okno
  • (opcjonalnie) 3 goldpiny aby łatwiej wtykać kabel w płytkę

Potrzebne biblioteki

Biblioteki należy umieścić w folderze libraries naszego Arduino IDE. Oczywiście umieszczamy je w folderach takich w jakich są, nie luzem.
UWAGA! Biblioteka ENC28J60 pokrywa się z funkcjami biblioteki Ethernet Shield, dlatego musimy ją najpierw usunąć z katalogu libraries!

Schemat podłączeń

Posiadamy już wszystkie potrzebne biblioteki oraz części, pora przejść do ich podłączenia. Zastosowałem 2 termometry gdyż docelowo mierzę temperaturę wewnętrzną oraz zewnętrzną. Oczywiście termometr mierzący temperaturę zewnętrzną nie jest wetknięty w płytkę, przylutowałem do niego 3 kabelki ze skrętki UTP i wystawiłem za okno. Po drugiej stronie kabla przylutowałem 3 goldpiny tak aby łatwiej móc podłączyć kabelek do płytki.

temperatury_okno_bb

 

Moduł ENCJ28J60 którego użyłem podłączyłem do zasilania 5V. Uczyniłem to dlatego, że model jaki posiadam toleruje takie napięcie i upraszcza to dalszą część czyli przenoszenie kodu na ATmegę, jednak według dokumentacji moduł ten powinno zasilać się napięciem 3,3V!

Kod dla mikroprocesora

Wyjaśnienia może wymagać tutaj kwestia odliczania między wysłaniem żądania pobrania temperatur a odczytaniem ich wyników. Otóż normalnie program po wysłaniu żądania oczekiwał by na jego zakończenie i dopiero przeszedł dalej. Jest to działanie niepożądane gdyż blokowało by możliwości przyjmowania w tym czasie połączeń internetowych. W związku z tym czujniki zostały ustawione tak, aby temperatura pobierana była w tle. Nie zmienia to jednak faktu, że zanim temperatura będzie do odczytania musi upłynąć pewien okres czasu, jest on ściśle określony w dokumentacji. Wewnątrz pętli sprawdzam, czy czas już upłynął, jeśli tak to odczytuję temperatury i wysyłam nowe żądanie. Dzięki temu moduł ethernet jest w stanie działać cały czas i przyjmować połączenia nawet w trakcie oczekiwania na dane.

Po uruchomieniu programu na wyświetlaczu powinna ukazać się aktualna temperatura wewnętrzna oraz zewnętrzna, możemy teraz przejść dalej.

Kod dla serwera WWW

Z uwagi na to, że taki serwer WWW jaki został stworzony w powyższym kodzie nie był by w stanie realizować bardziej zaawansowanych funkcji dalszą część zrealizowałem na normalnym serwerze WWW z PHP oraz MySQL. Skrypt PHP nawiązuje połączenie z układem i pobiera z niego temperaturę. Zastosowałem taką metodę dlatego, że między serwerem WWW a domem mam stały tunel VPN. W pozostałych przypadkach prawdopodobnie potrzebne okaże się przekierowanie jednego z portów na routerze na IP naszego układu. Oczywiście można było to zbudować w drugą stronę, aby to układ łączył się z serwerem.

Struktura bazy danych

Pobieranie danych

Jak już wspominałem celem przeniesienia obsługi żądań na normalny serwer WWW było odciążenie układu z serwowania dużej ilości zapytań. W związku z tym nie miało by sensu aby każde zapytanie do strony z temperaturą odpytywało układ. Z tego powodu zdecydowałem się na napisanie pliku pobierającego dane do bazy i umieszczenie go w crontabie wykonywanym co 5 minut:

W linii 6 temperatura mnożona wcześniej w układzie jest teraz dzielona tak aby otrzymać normalny wynik. Niestety bez takiego zabiegu nie udało się uzyskać temperatury z miejscami po przecinku. Linia 8 zabezpiecza nas przed pobraniem wartości zaraz po uruchomieniu układu, gdy jeszcze nie ma aktualnych danych o temperaturze.

Wyświetlanie danych

Do wyświetlania danych zastosowałem prosty skrypt PHP który następnie obsadziłem na blogu za pomocą iframki:

Rysowanie wykresów

To najbardziej złożona część tego projektu. Wykresy są rysowane za pomocą JavaScript przez przeglądarkę po otrzymaniu odpowiednich danych przez PHP. Plik ten docelowo również został wstawiony jako iframka na blogu.

Z uwagi na to, że listing kodu od wykresów jest długi, zamiast wstawiać go tutaj przygotowałem paczkę która zawiera zarówno powyższe kody, jak i kod wykresów oraz niezbędne do jego działania biblioteki JavaScript: kliknij aby pobrać.

Finalizacja projektu

Jak to na koniec realizowania projektu przystało, pora teraz przenieść się z Arduino na czystą ATmegę, tak aby Arduino mieć do kolejnych zabaw. Programujemy mikroprocesor oraz zmieniamy podłączenia kabelków na następujące:

temperatury_okno_atm_bb

Na sam koniec

Internetowy termometr to tylko jedno z przykładowych zastosowań, można go np. przerobić aby był bezprzewodowy, lub też np. zrobić tak aby zapalać sobie światło w pokoju przez Internet (ja tak zrobiłem) – całkiem fajny efekt gdy można zapalić światło bez wstawania od komputera lub przez telefon (zostało to opisane we wpisie “Lampka zapalana przez Internet“) oraz wiele wiele innych. Jeżeli macie jakieś fajne pomysły – podzielcie się w komentarzach :)

Ocena: 4.62/5 (głosów: 58)

Podobne posty

77 komentarzy do “Własny internetowy termometr

  • Fajny projekt. Sam chciałem taki zrobić i jestem w trakcie tylko zastój mi się zrobił :D Mam już prawie gotowy skrypt PHP + highcharts.com wyświetlający statystyki ale nie miałem czasu się za niego wziąć bo mam milion pomysłów na minutę :D Mam tą samą płytkę modułu ethernet kupioną na allegro i chodzą po ok. 30zł. co jest ceną dość przystępną w porównaniu z jakimiś dedykowanymi shieldami pod Arduino :D Może w niedługim czasie się za to zajmę i dodam własny poradnik ale to zobaczymy :) Jeśli nie to polecam zainetersowanie się skryptem highcharts.com bo jest naprawdę fajny i gdzieś znalazłem nawet kod wraz z php i mysql tylko już nie pamiętam gdzie ale mam go na dysku :D

    Odpowiedz
  • Pomysł trafiony w 10! Gratuluję!

    Jestem ciekaw opisów Twoich projektów, o których wspominałeś powyżej (w połączeniu z internetem i via telefon – o tym chyba jeszcze nie było na Majsterkowie).

    Tak z innej beczki – jest opcja, żeby zbudować analogiczne rozwiązanie, ale np. z czujnikiem dymu (o ile takie w ogóle są do zamontowania) albo czymś w ten deseń?

    No i przy okazji choć to trochę OT – jak wygląda kwestia domontowania do tego, ale i do innych projektów, modułu GSM, który wysyłałby np. smsa z jakąś informacją lub dzwonił na podany numer np. włączając mikrofon?

    Odpowiedz
    • Dzięki ;)

      Z Internetem i telefonem to chodziło o jedno – przeglądarkę ale w sumie mam możliwości zrobić to SMSem tylko, że opis jak zrobić to SMSem nie był by dla nikogo przydatny – mam własne SMSC i własne API do tego, czyli ja sobie to mogę zrobić ale nikt nie będzie w stanie powielić tego pomysłu.
      Niektóre serwisy typu smsapi.pl oferują odbiór SMSów ale jest to kosmiczna cena jak do stosowania w takich zabawkach.

      Co do czujnika dymu to szczerze mówiąc nie wiem, nie spotkałem się z takowym nigdzie.

      Modułu GSM nie testowałem, jest on też dość drogi i jego stosowanie w tego typu projektach mija się z celem. W przypadku wysyłki SMS to jeszcze można by to obejść wysyłając przez API jakiegoś serwisu (albo tak jak ja przez swoje własne) – ale już z rozmowami telefonicznymi i podsłuchem gorzej ;)

      Odpowiedz
  • Mam jedno pytanie:
    W opisach katalogowych czujnika DS18S20 (np. http://nettigo.pl/products/321) podano, że dokładność czujnika to “0.5 stopnia w zakresie od -10 do 85 stopni”.
    Tymczasem, na Twojej stronie można zobaczyć np. temperaturę -2.75 °C (dane z 2013-03-10 12:55:02)
    Jak udało Ci się osiągnąć dokładność 0.01°C ?

    Odpowiedz
    • W dokumentacji do DS18B20 masz ładnie opisane dlaczego tak, a nie inaczej ;P (Strona 3 – “OPERATION — MEASURING TEMPERATURE”).

      Wynika to z ustawienia rozdzielczości. W kodzie przedstawionym przez autora, komentarz do linii 35. jest błędny. Ustawiasz rozdzielczość pomiaru, a nie dokładność. Dokładność jest prawie niezmienna w zakresie od -10 do 85 stopni i wynosi 0,5 stopnia o czym zapewnia producent ;P

      Odpowiedz
      • Dzięki za informację. Teraz dopiero doczytałem w pedeefie.
        Duży szacun dla Autora za kompleksową realizację projektu od sprzętowej bazy do webowego frontendu. Mnie by się nie chciało – kiedyś robiłem rejestrację temperatury odczytywanej z czujnika na procesorze przez lmtools i skończyło się na instalacji i konfiguracji mrtg + rrdtool. :^)
        No ale wtedy wystarczyła rejestracja temperatury w komputerze, nie było mowy o stacji pogodowej.
        BTW, do takiej stacji warto by było dodać odczyt/rejestrację napięcia pochodzącego np. z ogniwa baterii słonecznej (do wymontowania z lampy ogrodowej dostępnej w hipermarkecie za ok 10zł).

        Odpowiedz
  • Miałem pisać podobny tutorial, ale widzę że już jest ;) Z kumplem stworzyłem coś podobnego, a wykorzystaliśmy do tego komputerek HP T5500 z Debianem, ręcznie wykonany moduł 1-wire na RS232 i bibliotekę RDDtool to generowania wykresów ;) Muszę się w końcu zebrać i to opisać :D

    Odpowiedz
    • Czy mógł byś opisać swoje rozwiązanie? Mam moduł 1-Wire na RS232 i też HP T5000 leży nieużywany. Nie mam jednak zbyt dużego doświadczenia z linuxem i opis by się przydał.

      Odpowiedz
  • Kurde, co tu wejdę to Twoje pomysły mnie po prostu zabijają. Termometr fajna sprawa, a ja ciągle cierpię na brak czasu, bo chętnie bym sobie przećwiczył te wasze pomysły. Tak więc proszę – o artykuł, w którym zaprogramujesz mnie bym miał więcej czasu – nawet przez internet ;P

    Odpowiedz
  • Właśnie sam próbuje zrobić taki termometr tylko że z wysyłaniem danych a nie odbiorem przez skrypt php. Minusem, dość dużym dla mnie jest tutaj to że musimy mieć obsługę crone’a na serwerze a nie każdy ma taką możliwość. Polecam pobranie biblioteki z tego poradnika http://www.blue17.elektroda.eu/mikrokontrolery-avr/1618 i użycie example “etherShield_client” który wysyła dane na serwer i w php już możemy sobie zrobić aby albo zapisywał dane do bazy danych albo do pliku .txt
    Tutaj gotowy kod php http://www.mercenarymind.com/arduino/463-ethernet-shield-for-arduino-a-web-client-example

    Póki co działa i zapisuje ale przydało by się poprawić trochę ten przykładowy kod :) Na plus jest to że cały kod z biblioteką etherShield zajmuje tylko 5 854 bytes także możemy wykorzystać Atmega8 w końcowym układzie :)

    Odpowiedz
    • Jednak gdzieś jest błąd bo po jakimś czasie przestaje zapisywać do tego pliku a i z komunikacją z zewnętrznym serwerem też jest jakiś problem także działa tylko na serwerze postawionym u siebie. Jak ktoś się lepiej zna to może poprawić :D

      Zdecydowałem się jednak na Twój skrypt i kod bo u mnie na serwerze jest CRON ale niestety działa tylko co godzinę :( No ale do wykresów wychodzi w sam raz :)

      Dodam jeszcze że masz drobny błąd w index.php jest $czas = $l[‘czas’]; a powinno być $czas = $l[‘time’]; a właściwie to powinno być $czas = date( ‘Y-m-d H:i:s’, $l[‘time’]); aby wyświetliło poprawnie datę i czas ;)
      Jeśli chcemy samą godzinę (00:00:00) to $czas = date( ‘H:i:s’, $l[‘time’]);

      Odpowiedz
      • Nope. Bootloader w Arduino nie robi nic, oprócz udostępnienia funkcji wgrywania wsadu. Nie udostępnia żadnych funkcji systemowych, wsad skompilowany w Arduino IDE (C++ + plik Arduino.h) będzie poprawnie działał na “czystym” procesorze.

        Odpowiedz
  • Pomysł termometru rewelacja.
    Właśnie testuję Twój układ.
    Mam tylko pytanie o wyświetlanie temperatury na stronie WWW (nie używam serwera SQL ani PHP – interesuje mnie jedynie wyświetlenie wartości na stronie)
    Temperatura podawana jest bez przecinka. Da się jakoś go wstawić do wartości temperatury na stronie WWW?

    Odpowiedz
  • Witam mam problem z tym projektem. Pobiera mi temperaturę na serwer ale tylko raz potem nie da rady pobrać jej na nowo gdyż ENC28J60 się chyba ścina i nie da rady wejść nawet lokalnie sprawdzić jaka jest temperatura.

    Odpowiedz
  • Bardzo fajny projekcik dla początkujących i właśnie od niego zaczynam przygode z Arduino ale jest tu masa błędów i początkujący nie uruchomi układu.
    moduł lan – źle podpięte GND
    moduł LCD – pin 5 podpięty do VCC zamiast GND
    pin 4 i 6 ma być podpięty do ATmegi do 5 i 6
    sygnał z czujników DS ma być podpiety do pinu 4 Atmegi
    wszystko to można wywnioskować z kodu programu
    no i w kodzie PHP trzeba zwrócić uwage na ujednolicenie adresów IP oraz definicja czasu o której już wspomniano w komentarzach.

    Układ nie ruszył mi też na wewnętrzym oscylatorze Atmegi (działał na zewnętrznym 16MHz) ale to dlaczego to musze się dokształcić.

    Odpowiedz
    • No i według “rysunku” zasilanie czujników temperatury jest odwrotnie. Kiedy trzymamy DS18B20 płaską stroną do siebie masa jest po lewej stronie, a “+” po prawej!!! Bez karty katalogowej ani rusz, prawie usmażyłem palec dotykając czujnika po kilku sekundach takiego odwrotnego podłączenia – nauczka na przyszłość żeby nie ufać ślepo wszystkiemu co mądrze wygląda.

      Odpowiedz
  • Witam majsterkowiczów! Rozpocząłem pracę z tymże termometrem, i wszystko szło dobrze. Aż do momentu podłączenia modułu Ethernet. Wszystkie biblioteki i inne rzeczy zaimplementowałem dobrze, lecz gdy podpinam gotowy projekt pod router, nie ma żadnego efektu. Na adresie ( 192.168.1.15 ) nic się nie pokazuje. Czy mógłby ktoś mi pomóc z tym? Pilne. Z góry dzięki ;)

    Odpowiedz
  • Witam

    Mam poważny problem. Mianowicie ma zrobiony taki termometr, także na pc (webserv) serwer i bazę danych i wszystko ładnie pracuje. Chciałem Zrobić serwer na raspberry pi i tu zonk. Serwer apache, mysql, phpadmin to samo co na windowsie ale odczytuje dane tylko raz, zapisuje do bazy danych i zawiesza połączenie z modułem ethernet w arduino. Kombinuje już parę dni i nie mogę dojść do skutku co jest przyczyną. Może ktoś podrzuci jakiś pomysł bo mi się już wyczerpały.
    Pozdrawiam

    Odpowiedz
    • Jako ze nie udało mi się rozwiązać tego problemu, to zrobiłem w drugą stronę. Arduino wysyła dane do serwera, a serwer już zapisuje w bazie mysql. A dalej to tak samo jak w tym projekcie.

      Odpowiedz
  • Dzięki za dobry poradnik. Będę próbować połączyć termometr z systemem powiadamiania o listach w skrzynce pocztowej, a wszystko wysyłane bezprzewodowo za pomocą nRF24L01 do arduino, który te informacje będzie wysyłać i na LCD i do internetu.

    Odpowiedz
  • czy coś ja źle widzę czy nie doczytałem ale czujniki DS są źle podłączone na schemacie – prawa nóżka (jedynka) powinna iść do masy a idzie do +5 ? prawie spaliłem czujnik gdyby nie to że przypadkowo dotknąłem go bo nie widziałem pomiarów i szybko odłączyłem zasilanie. Aż mi wyskoczył pęcherz ta palcu :)

    Odpowiedz
  • Witam.
    Mam problem. Jak wejdę na stronę wypuszczoną przez arduino to wyświetla mi się temperatura. Ale jeśli zrobię to przez PHP z wykorzystaniem file_get_contents układ na arduno wysyła raz temperaturę i się zawiesza.
    Gdzie szukać przyczyny.

    Odpowiedz
  • Witam. Czy jest w stanie pomoc mnie z tym plikiem cron. Strona i baza jest na udu.pl. Komunikacja miedzy strona a baza jest oraz miedzy arduino a wyjsciem. Dane jednak gina przed myql. Podejrzewam problem z crone. Nie jestem specialista ..wiec potrzebuje pomocy step by step z tym plikiem Dzieki

    Odpowiedz
  • Cześć
    Mam taki błąd podczas kompilacji

    Documents/Arduino/libraries/etherShield/etherShield.h:34:76: error: ISO C++ forbids declaration of ‘progmem_s’ with no type [-fpermissive]
    uint16_t ES_fill_tcp_data_p(uint8_t buf,uint16_t pos, const prog_char progmem_s);

    Odpowiedz
  • Witam,

    Zazdroszczę talentu programisty :P. Chciałbym się zapytać w jaki sposób adres IP 192.168.1.15 z routera domowego udało Ci się zamienić na adres lokalny 10.3.1.2:8888 i odebrać dane temperatury ? Z góry dzięki za odpowiedź.

    Odpowiedz
  • In file included from C:\Program Files (x86)\Arduino\libraries\etherShield/etherShield.h:25:0,
    from sketch_dec19d.ino:1:
    C:\Program Files (x86)\Arduino\libraries\etherShield/ip_arp_udp_tcp.h:32:66: error: ‘prog_char’ does not name a type
    extern uint16_t fill_tcp_data_p(uint8_t buf,uint16_t pos, const prog_char progmem_s);
    ^
    Hej, wrzucam do Arduino Twój kod i wywala mi IDM taki problem:

    C:\Program Files (x86)\Arduino\libraries\etherShield/ip_arp_udp_tcp.h:32:77: error: ISO C++ forbids declaration of ‘progmem_s’ with no type [-fpermissive]
    extern uint16_t fill_tcp_data_p(uint8_t buf,uint16_t pos, const prog_char progmem_s);
    ^
    In file included from sketch_dec19d.ino:1:0:
    C:\Program Files (x86)\Arduino\libraries\etherShield/etherShield.h:34:65: error: ‘prog_char’ does not name a type
    uint16_t ES_fill_tcp_data_p(uint8_t buf,uint16_t pos, const prog_char progmem_s);

    Odpowiedz
  • Witam Koledzy!
    Czy może ktoś narysować i zamieścić chemat ideowy tego ostatniego układu na samodzielnym kontrolerze. Ten widok na płytce stykowej nie za bardzo przemawia. Pozdrawiam, i z góry dziekuję.

    Odpowiedz
  • Witam
    Super termometr czegoś takiego właśnie szukałem, jestem trochę zielony w sprawach Arduino, czy może mi ktoś łopatologicznie wytłumaczyć krok po kroku co zrobić z bibliotekami, co z wycinkami kodów umieszczonych powyżej w ramkach, a może podeśle mi ktoś sklejony plik do kompilacji ?
    z góry dziękuję za pomoc
    Pozdrawiam Robert

    Odpowiedz
  • Program działa w wersji 1.0.5 r2, biblioteki należy rozpakować do katalogu libraries w Arduino, należy również skasować starą bibliotekę Ethernet

    Odpowiedz

Odpowiedz

anuluj

Masz uwagi?