Poniżej opisany projekt przedstawia “wrap” biblioteki EtherCard https://github.com/njh/EtherCard.
Biblioteka EtherCard bardzo ładnie rozwiązuje konfigurację modułu ethernet opartego na układzie ENC28J60, pozwala ona m.in. na zestawienie połączenia ze statycznym IP lub uzyskanym poprzez DHCP.
Dzięki bibliotece EtherCard w łatwy sposób można zrobić aplikację serwer/klient obsługującą powiadomienia lub dostarczającą dane telemetryczne, a nawet prostą aplikację IoT.
Brakowało mi jednak przejrzystości w sketch-u i prostoty obsługi żądań HTTP. Bazując na przykładach udostępnionych przez EtherCard i ogólnodostępnej wiedzy, dopisałem wrap tej biblioteki i nazwałem ją EtherDevice.
Spis treści:
- Opis nagłówka
- Przykładowe użycie
- Sposób połączenia modułu ethernet i arduino
- Sketch z komentarzami
- Sketch bez komentarzy
- Wady/Zalety
- Załączniki
1. Opis nagłówka
Na początku postanowiłem zamknąć fragmenty kodu, które pierwotnie zmniejszały czytelność sketch-a właściwego.
Utworzyłem klasę EtherDevice dziedziczącą publicznie po EtherCard, a w niej zawarłem poniżej opisane metody.
Inicializacja z adresem IP przydzielanym przez DHCP:
Inicializacja z adresem IP ustawionym statycznie:
Metoda ipconfig:
Metoda statycznej odpowiedzi – staticHttpServerReply:
Powyższa metoda ta wymaga zdefiniowanych stałych łańcuchów, zdefiniowałem typowe odpowiedzi HTTP (200, 401, 404, 405, 406), przydatne w dalszej części usprawnienia biblioteki EtherCard:
Następnie napisałem metodę, ułatwiającą parsowanie argumentów żądania HTTP, np:
po wpisaniu w przeglądarce http: //ip_urządzenia/?arg_1=val_1&arg_2=val_2& … &arg_C=val_C
jest C niewygodnych do sparsowania argumentów oddzielonych znakiem “&”.
Powyższa metoda wymaga zdefiniowanej struktury dla argumentów argv:
Kolejno dopisałem metodę pozwalającą w przyjazny sposób wypisać w Serial wszystkie argumenty żądania, mając już je sparsowane przy użyciu metody getTask:
Nie mogło zabraknąć też metody wyszukującej czy dany argument zaistniał w żądaniu i zwracającej jego wartość:
Dodatkowo napisałem metodę sprawdzającą i porównującą czy istnieje dany argument o danej wartości:
Wewnątrz klasy jest zadeklarowana metoda webPage służąca wygenerowaniu odpowiedzi na żądanie:
Natomiast definicja powyższej metody jest realizowana w sketch-u, po to by użytkownik opisywanego tutaj wrap-a nie musiał grzebać w kodzie nagłówka.
Cały plik nagłówkowy “EtherDevice.h” prezentuje się następująco:
2. Przykładowe użycie
Poniżej przedstawiony zostanie schemat połączeń oraz sketch z komentarzami i bez, aby ukazać zaletę wrap-a, jaką jest przejrzystość sketcha przy nieco rozbudowanej funkcjonalności.
Założenia do przykładu użycia:
- W przykładzie przyjęte jest założenie, że ktoś kto nie zna “tajnego klucza”, nie może ani odczytać nic z Arduino za pomocą protokołu HTTP, ani nic zmienić w jego ustawieniach.
- Jako przykład wyobraźmy sobie wentylator sterowny PWM, wraz z termometrem podpiętym do pinu A0 Arduino – taka “wentylacja IoT”.
- W kodzie temperaturę reprezentuje zmienna “int temperatura”, obroty wiatraka zmienna “int pwm_wentylatora”.
- Chcielibyśmy po wpisaniu w przeglądarce IP urządzenia i odpowiedniego klucza zobaczyć aktualną temperaturę (0-100 stopni) i obecne obroty wiatraka (0-255) podane w formacie “temperatur|pwm_wentylatora”.
- Wpisanie w przeglądarce samego adresu IP powinno zwrócić komunikat 401 Unauthorized.
- Dopiero wpisanie adresu IP opatrzonego w secretKey
np. http://192.168.0.10/?secretKey=7rHvCGd59C
wyświetli stan temperatury odczytanej z pinu analogowego A0 i aktualnie ustawione PWM wentylatora. - Natomiast dopisanie do adresu cmd=changepwm i pwm=255 ustawi zmienną pwm_wentylatora na 255.
http://192.168.0.10/?secretKey=7rHvCGd59C&cmd=changepwm&pwm=255 - Wyzerowanie pwm_wentylatora mogłoby być poprzez dopisanie cmd=resetpwm do adresu IP
np. http://192.168.0.10/?secretKey=7rHvCGd59C&cmd=resetpwm
Wybrany sposób łączności z urządzeniem jest ze względu na łatwość pobrania stanu urządzenia i jedno czesne sterowanie z innego urządzenia (np. NanoPi) za pomocą linuksowego polecenia wget. Z myślą o Arduino jako element większego systemu IoT.
2.1. Sposób połączenia modułu ethernet i Arduino
Schemat połączeń jest taki sam jak oryginalnie w bibliotece EtherCard https://github.com/njh/EtherCard
Dla Arduino UNO:
ENC28J60 | Arduino Uno | Adnotacje |
---|---|---|
VCC | 3.3V | |
GND | GND | |
SCK | Pin 13 | |
MISO | Pin 12 | |
MOSI | Pin 11 | |
CS | Pin 10 | Modyfikowalny przez eth.init() |
ENC28J60 | Arduino Mega | Adnotacje |
---|---|---|
VCC | 3.3V | |
GND | GND | |
SCK | Pin 52 | |
MISO | Pin 50 | |
MOSI | Pin 51 | |
CS | Pin 53 | Modyfikowalny przez eth.init() |
Odpowiednio zgodnie do przykładu użycia, do pinu A0 czujnik temperatury np. analogowy czujnik temperatury LM35 i do wybranego pinu PWM sterowanie wentylatora.
2.2. Sketch z komentarzami
2.3. Sketch bez komentarzy
Jak widać sketch bez komentarzy jest już bardzo czytelny a zawiera logikę główną i obsługę ethernet.
3. Zalety/Wady
Do zalet należy:
- ułatwiona obsługa modułu ethernet do poziomu “instant”;
- przejrzystość kodu, w sketch-u można się skupić na obsłudze zadań/czujników;
- gotowe parsowanie argumentów przychodzących w żądaniu;
- kilka gotowych odpowiedzi (HTTP 401, 404, 405, 406) na błędnie wpisany w pasku adresu IP z argumentami.
Do wad należy:
- zabezpieczenie secretKey jest na laików bo i tak wszystko po http leci plain-text, więc ktoś z Wireshark-iem od razu znajdzie klucz, ale jest to możliwe do załatania/usprawnienia;
- jak na programowanie mikrokontrolera trochę za bardzo obiektowo;
- z wielu metod HTTP obsłużone tylko część GET https://pl.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Metody_HTTP;
- waga sketch-a:
- podobne funkcjonalnie sketch-e z przykładów EtherCard zajmują średnio (na dzień dobry) około 30% pamięci programu i około 40% pamięci dynamicznej;
- sketch po owrapowaniu już jako EtherDevice zajmuje 38% pamięci programu i 48% pamięci dynamicznej.
4. Załączniki
Do wpisu załączam paczuszkę z sketch-em (.ino) i plikiem nagłówkowym (.h).
Bardzo dokładny i ładny opis. Ocena 5*.
Dziękuję :)
Mimo małego projekciku, starałem się go dobrze opisać, aby każdy mógł zrozumieć, użycie moich dopisanych metod do biblioteki EtherCard.
Sam zrobiłem kilka projektów z ENC28J60 i mimo że działają już ponad dwa lata – to nie jest to najlepszy wybór – są ciągłe problemy ze stabilnością modułu. Ostatnio wypróbowałem USR-ES1 na chipie W5500 i bibliotekę Ethernet3 https://github.com/sstaub/Ethernet3 – jest to dużo lepsze rozwiązanie niż ENC28J60.
Witam,
jak osiągnąć “narastanie” / “opadanie” PWM na sztyno o okresie np 1 sek ? lub – co było by najmilsze, jako parametr, coś na wzór z kit AVT1825 (niestety to nie jest superkonstrukcja, wiesza się)