Na wstępie chciałbym się przywitać, gdyż jest to mój pierwszy artykuł.
Od dłuższego czasu byłem zainteresowany napisaniem programu który by odczytywał dane wysłane z mikrokontrolera. Dzisiaj przedstawię wam bardzo prosty program napisany w Visual C#, który będzie odczytywał dane z czujnika DHT11 i odpowiednio wyświetlał.
Podłączenie czujnika do arduino
DHT11 to cyfrowy czujnik temperatury i wilgotności powietrza. Jego zalety to bardzo łatwe podłączenie, niska cena i brak kalibracji. Jego wady to słaba dokładność, mierzy tylko dodatnie temperatury. Czujnik posiada 4 nóżki, z czego tylko 3 są używane. Pierwsza nóżka to zasilanie 5v, druga to wyjście sygnałowe, które podłączamy do pinu cyfrowego w Arduino (w moim przypadku był to pin 2) oraz do 5V przez rezystor o wartości 10kΩ. Ostatnia nóżka to GND.
Schemat:
Wyjście sygnałowe czujnika (na schemacie zielony przewód) dodatkowo podłączamy do 5V przez rezystor o wartości 10kΩ.
Programowanie Arduino
Program który tutaj zastosuje to zmodyfikowany program przykładowy czujnika który dostarczony jest wraz z biblioteką obsługującą czujniki DHTxx.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
#include "DHT.h" #define DHTPIN 2 // pin do którego podłączyliśmy dane z czujnika #define DHTTYPE DHT11 // typ czujnika DHT dht(DHTPIN, DHTTYPE); void setup() { Serial.begin(9600); // inicjujemy połączenie szeregowe Serial.println("DHTxx test!"); dht.begin(); // włączamy czujnik } void loop() { float h = dht.readHumidity(); // odczyt wilgotności float t = dht.readTemperature(); // odczyt temperatury if (isnan(t) || isnan(h)) { Serial.println("Failed to read from DHT"); } else { Serial.println(t); // Wyświetlenie linijki z temperaturą Serial.println(h); // Wyświetlenie linijki z wilgotnością } } |
Następnie wgrywamy program do Arduino i włączamy monitor portu szeregowego. Jak wszystko poprawnie zrobiliśmy to powinniśmy zobaczyć coś takiego:
28.00 to temperatura w stopniach Celsjusza, a 34.00 to wilgotność powietrza w procentach.
Visual C# 2010 Express
Visual C# 2010 Express można ściągnąć z tej strony. Na początku tworzymy nowy projekt i wybieramy Windows Forms Application.
Przed nami ukaże się ekran w którym będziemy tworzyć cały interface. Przeciągając odpowiednie elementy z lewej części ekranu tworzymy mniej więcej coś takiego:
Należy pamiętać aby dodać także komponent portu szeregowego.
Napisy przycisków zmieniamy w prawej części ekranu w menu “properties” po zaznaczenu danego elementu (wartość “text”). Dla ułatwienia po zmieniam sobie nazwy pól tekstowych na coś bardziej czytelnego (wartości “name”).
Trzeba pamiętać żeby nie pomylić wartości “name” z wartością “text” !
Ogólnie cały kod programu prezentuje się jak poniżej. Konkretne kawałki kodu opiszę komentarzami.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form { string temperatura; // deklaracja zmiennej temperatury string wilgotnosc; // deklaracja zmiennej wilgotności public bool parz = true; // deklaracja zmiennej boolean public Form1() { InitializeComponent(); button_stop.Enabled = false; // zablokowanie przycisku stop w momencie uruchomienia programu. } private void button_start_Click(object sender, EventArgs e) // w momencie kliknięcia przycisku Start zostaną wykonane następujące instrukcje. { if (!serialPort1.IsOpen) // Jeżeli port nie jest otwarty, otwieramy go { serialPort1.PortName = "COM3"; // nazwa portu gdzie jest Arduino podłączone serialPort1.BaudRate = 9600; // predkosc transmisji szeregowej serialPort1.Open(); // otwarcie portu pole_status.Text = "Otwarto port " + serialPort1.PortName; // wyświetlenie informacji o otwarciu portu w polu 'stan' button_start.Enabled = false; // zablokowanie przycisku Start button_stop.Enabled = true; // odblokowanie przycisku stop } } private void button_stop_Click(object sender, EventArgs e) // przycisk stop { serialPort1.Close(); // zamkniecie portu pole_status.Text = "Zamknieto port " + serialPort1.PortName; // informacja o zamknięciu portu button_start.Enabled = true; // odblokowanie przycisku Start button_stop.Enabled = false; // zablokowanie przycisku Stop } private void Form1_FormClosed(object sender, FormClosedEventArgs e) // instrukcje jakie mają się wykonac w przypadku wyłączenia okna programu { serialPort1.Close(); } private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) // Instrukcje jakie mają się wykonac w momencie odebrania danych z portu szeregowego. { if (parz == true) // sprawdzenie którą wartośc z kolei odbiera { temperatura = serialPort1.ReadLine(); // odczyt linii - temperatura this.Invoke(new EventHandler(DisplayText_temp)); // wywołanie metody wyświetlania temperatury parz = !parz; // negacja zmiennej boolean } else { wilgotnosc = serialPort1.ReadLine(); // odczyt linii - wilgotnośc this.Invoke(new EventHandler(DisplayText_wilg)); // wywołanie metody wyświetlania wilgotności parz = !parz; } } private void DisplayText_temp(object sender, EventArgs e) // metoda wyświetlania temperatury { pole_temp.Text = temperatura + " °C"; // wstawienie wartości do pola tekstowego } private void DisplayText_wilg(object sender, EventArgs e) { pole_wilg.Text = wilgotnosc + " %"; } } } |
Jako, że Arduino wysyła dwie zmienne (temperatura i wilgotność) program zbudowałem tak, by na zmianę odczytywał wartość temperatury i wilgotności (do tego służy zmienna ‘parz’). Pewnie jest to nie do końca poprawne ale jak na pierwszy program proszę mi to wybaczyć.
Jest to też mój pierwszy artykuł więc za wszelkie błędy stylistyczne proszę mi wybaczyć. :)
Schemat schemat.. nie wiem czy ten zielony ma sie stykac z + czy nie.
Faktycznie mi umknęło.
Zielony (sygnałowy) ma byc podłączony dodatkowo do 5V przez rezystor 10k ohm
Jezusie …
Czy atmega / arduino sprowadza się tylko do termometrów ?!
Jest to już 3?4? poradnik o termometrach, konstrukcja nie zaskakująca…
Zastosowanie Visual odróżnia od reszty…
Jeżeli wykorzystałbyś Visual do sterowania przekaźnikami lub np. robotem uwierz mi 5tki by leciały :)
4 i nic więcej
Od czegoś trzeba zacząć, a na 5-tkach mi nie zależy, bo nie robie to dla statystyk, tylko żeby się podzielić informacjami. Mam nadzieje, że komuś po prostu się to przyda i zainspiruje do bardziej skomplikowanych zastosowań Visuala
A mnie się właśnie to przydało. Jest to dokładnie to czego szukałem i wielkie dzięki za ten poradnik !
Mi się to bardzo przydało, szczególnie program w Visual Studio, wielkie dzięki kolego !!! Do tego komentarze, cud, miód ;)
plus obsługa joysticka, gamepada ;) np. directx
Ta termometrowa seria ma jedną wielką zaletę – pokazuje początkującym użytkownikom, na jak wiele sposobów można podejść do tego samego problemu :)
Przede wszystkim cieszę się, że majsterkowo.pl istnieje – niesamowicie przyjemnie się go czyta, choć nie mam warunków, żeby te cuda robić u siebie.
Mam natomiast pytanie dotyczące termometrów podłączanych do ARDUINO – na ile one są dokładne?
Pozdrawiam
Zależy od termometru, ale większość tak około 0,5 – 1 *C.
Ciekawe połączenie Arduino z PC ;)
Plus dla Ciebie za komentarze w kodzie :) Ode mnie 5 :)
BTW, ostatnio bawiłem się trochę mikrokontrolerami i powstał sterownik zasłaniania/odsłaniania żaluzji lub rolet (albo na czujnik zmierzchowy albo ręcznie), dodatkowo zegar i kalendarz, wszystko wyświetlane na LCD 2×16. Zbudowałem to na Atmedze8. Jeżeli kogoś interesowałoby powyższe urządzenie, to może bym się zebrał i opisał to na Majsterkowie ;) Z tym że na razie jest sam sterownik, części mechanicznej (silnik i jego mocowanie) nie ma :(
W tym projekcie chodziło głównie o tym, żeby zrobić aplikacje, która będzie współpracować z Arduino/Atmega. Dlatego wybrałem coś prostego (czujnik temperatury) by skupić się na samym C#.
Mam plany by w przyszłości zbudować większy projekt wykorzystując Visual C# :)
Fajnie było by zobaczyć artykuł o tym sterowniku.
Sam sterownik jest banalny do wykonania, ale wyzwaniem (jak dla mnie) jest część mechaniczna). Chętnie bym zobaczył Twoje rozwiązanie.
Fajny temat, ale poruszę kilka kwestii kodu c#.
Po pierwsze załącz cały projekt. Każdy kto zna c# potrafi sobie to sam zrobić a reszta nie skorzysta ponieważ podałeś tylko część kodu. Wklejenie go nie zadziała ponieważ trzeba powiązać zdarzenie z odpowiednią metodą (EventHandler). Tak jak np button_stop_Click jest tylko metodą którą trzeba powiązać z button_stop.Click. Robi się to na kilka sposobów (najlepiej w Properties w zakładce Events – ikona z błyskawicą)
Dobrze wyuczyć w sobie takie nawyki jak obsługa błędów – otwarcie portu zawsze może się nie udać (np zajęty). Zobacz jak brzydko wywala się Twoja aplikacja a wystarczy użyć try catch.
Jeszcze jedna rzecz – moje arduino Leonardo nie działa dopóki nie włączę DTR (serialPort1.DtrEnable = true;). Opcja ta zgłasza gotowość trerminala odczytującego dane z serial portu. Bez tego arduino w ogóle nie wysyła danych – widać to po diodzie TX.
Daję 4 na zachętę.
Hej,
program w C# ma błędny algorytm odczytu danych z czujnika. Wystarczy, że chociaż jeden odczyt się nie uda, aby odczyt temperatury był zamieniony z odczytem wilgotności.
W skrócie to ja bym to rozwiązał chociażby tak
W Arduino:
a w C#:
No, coś w ten deseń. Chociaż można całą tę komunikację rozwiązać na 100 innych sposobów :)
Jak już wspomniałem w artykule, zapewne cały algorytm jest źle wykonany. Myślałem, żeby wykonac to tak, żeby przed wysłaniem temperatury arduino dodawało jakiś przedrostek, który potem program odczyta i za pomocą którego będzie wiedział jaki to odczyt.
Proponuję zatem aby arduino wysyłało te dane w jednej linii rozdzielone znakiem np #. A jeszcze lepiej aby oznaczyć początek i koniec linii. Arduino mogłoby wysyłać coś takiego: @b#24.00#34.00#@e
I teraz:
Przy danych bardziej wrażliwych mogę sprawdzać czy np temperatura jest w odpowiednim formacie, a w danych super wrażliwych sprawdzać sumę kontrolną bądź całego ciągu bądź samych wartości.
I do tego sprawdzanie czy odczyt z czujnika się udał jak napisał kolega kr0nos.
Pamiętajmy, że zawsze może się coś nie udać i róbmy tak aby wykluczyć te możliwości. O ile w wyświetlaniu nic się takiego nie stanie program się wysypie o tyle w danych zapisywanych np do bazy danych wywalić może się całkiem sporo włącznie z położeniem całej bazy.
Hej,
ten fragment:
oryginalnego kodu już załatwia problem poprawności samego odczytu. Dlaczego? Otóż funkcja isnan() sprawdza, czy jej argument jest poprawną liczbą, czy nie. Jeżeli jest – zwraca 1, jeżeli nie, zwraca 0. Jeżeli jeden z odczytów, czy to temperatury, czy wilgotności nie zwróci liczby, generowany jest sygnał błędu. Problemem jest parsowanie w “odbiorniku”.
Zaproponowany przez Ciebie sposób wysyłki danych od strony pomysłu jest oczywiście poprawny. Można by polemizować z jego czytelnością i wydajnością (zapewne można użyć po prostu znacznie mniejszej ilości wysyłanych danych), ale nie o tym ten temat ;).
Cześć,
Masz u mnie 5 za te komentarze w kodzie C#.
Dwie uwagi:
– nazwa zmiennej ‘parz’ jest mało czytelna w przeciwieństwie do ‘temperatura’ i ‘wilgotnosc’
– na Visual Express świat C# się nie kończy. Można wykorzystać np. SharpDevelop czy MonoDevelop, ( z tych dwóch korzystam akurat w pracy).
ogolnie to fajny wstep do arduino no i podlaczenie tego do PC. niemniej za komentarze w kodzie to u mnie jest pala u wujka boba tez:) bo komentarze mowia jedno, kod sam w sobie napisany niejasno. po jakims czasie jak sie nanosi poprawki w kodzie, komentarze sie rozjerzdzaja, bo oczywiscie ich czasem zapomni sie poprawic, potem jak sie do niego siada za pol roku i patrzy, to nie wiadomo czym sie sugerowac, komentarzem czy kodem… polecam clean code – robert c martin.
Ciekawe podejście. Brakuje mi zawsze tylko przy takich projektach, realizacji bez płytki Arduino. Takie samodzielne rozwiązanie ma dopiero sens użycia wykonania.
Tu jest Spoleto bajer z dht I przesylaniem danych ale do arduino: http://www.jarzebski.pl/blog/2013/05/24/dalsze-zabawy-z-monitino-uno.html
Mam takie pytanie. Jak to zrobić bez Arduino? Przykładowo na ATtiny2313 (chodzi mi głównie o to jak podłączyć do mikrokontorlera kabel usb)
użyj konwentera ttl-usb szukaj na allegro “usb ttl”
Obsługa DHT11 jest banalna, więc korzystanie z gotowych bibliotek to czyste lenistwo. Ogólnie nie polecam tego czujnika, ma straszną bezwładność a wskazywana wilgotność powietrza to czysta abstrakcja (w praktyce jest to zwykle wartość 60-80%, czujnik pokazuje 30-40).
Nie ma co marudzić na czujnik. Nie o to autorowi chodziło. Ja akurat zgłębiam Arduino od prawie miesiąca i bardzo mi się artykuł przydał bo widzę że można pisać oprogramowanie na kompa do obsługi Arduino. Akurat teraz robię maszynkę której by się przydał taki interfejs na PCta żeby sterować silnikiem krokowym
“Obsługa DHT11 jest banalna, więc korzystanie z gotowych bibliotek to czyste lenistwo. “. Po to są biblioteki, żeby z nich korzystać. Świat idzie do przodu a nie stoi w miejscu. Obudź się.
gdzie ten kod wrzucić? Wytlumacz
Witam,
Postanowiłem zrobić podobny projekt jak autor, lecz zakupiłem wcześniej inny czujnik temperatury (choć to nie problem i wszystko działa od tej strony).
Program działa bez problemu jeśli chodzi o odczytanie danych z portu COM5 (nie mam COM3 jako USB w laptopie), ale tylko w programie Arduino. Jak zrobiłem już program w VS2013 to kompiluje bez problemu, otwiera port, ale nie otrzymuje żadnych danych. Bardzo proszę o pomoc. Oto kod z C#
A oto z Arduino (dodałem jeszcze wyświetlacz LCD ale to chyba nie problem)
Jestem zielony w programowaniu na wstępie mówiąc, ale miałem ten sam problem i irytowałem się przy tym nie wyobrażalnie :) ale rozwiązaniem problemu było dodanie do public Form1() danych o serial porcie oraz ” serialPort1.DataReceived += serialPort1_DataReceived; ” serialPort1.Open(); podpiąłem dopiero pod przycisk start. ogólnie to wygląda tak:
public Form1()
{
InitializeComponent();
button_stop.Enabled = false; // zablokowanie przycisku stop w momencie uruchomienia programu.
serialPort1.PortName = “COM6”;
serialPort1.BaudRate = 9600;
serialPort1.DtrEnable = true;
//serialPort1.Open();
serialPort1.DataReceived += serialPort1_DataReceived; // to jest ważne bez tego nie odczyta danych z seriala
}
Kurcze zastanawia mnie to, jak by to ugryźć aby zrobić coś takiego, tylko termometr, jest w jednym miejscu (np. na baterię 9V) i wysyła dane do płytki umieszczonej w innym pokoju podłączonej do komputera, i bezprzewodowo można wyświetlać odebrane dane przez drugą płytkę. Tylko nie wiem co zastosować żeby wysłać dane, no i oczywiście czy takie coś jest w ogóle możliwe :)
Nie ma problemu żeby zrealizować takie coś o czym mówisz. Poszukaj na elektrodzie tematu o bezprzewodowym czujniki temperatury :)
https://www.youtube.com/watch?v=yKJ8Lk4OS3o
https://www.youtube.com/watch?v=yKJ8Lk4OS3o
skopiowalem i nie dziala