ESP8266 robi zdjęcia – ArduCam na ESP8266
ArduCam Mini jest dość niszowym produktem. Mała kamerka która możesz podłączyć do Arduino lub ESP8266. Dlaczego to jest możliwe? Otóż ArduCam to nie tylko układ optyczny i przetwornik. To również dedykowany układ CPLD, który zajmuje się obróbką obrazu. Dzięki temu nawet Arduino może przez SPI i I2C odebrać dane z kamery. Przetworzyć to już pewnie nie da rady, ale na kartę SD to może zapisać. ESP8266 ma nieco większe możliwości.
Gdy wpadł nam w ręce testowy układ ArduCam Mini 2 MP postanowiłem przetestować kamerę – podłączając ją do ESP8266 i udostępniając obraz przez WWW. Dla jasności – ESP ma nieco większe możliwości niż Arduino, ale nadal za wolne i za mało pamięci by robić jakiś zaawansowany streaming. Dlatego tylko kilka zdjęć na sekundę (jeżeli będzie rozdzielczość mała).
Cały proces nie jest skomplikowany – jak już się dojdzie do finału. Ja, niestety wpadłem w dwie pułapki, które mnie kosztowały stracony czas, ale w końcu po to piszę, byście Wy mogli uniknąć takiego losu.
Nim jednak ruszymy, przyda się płytka deweloperska dla ESP. Ja wyrwałem ja z projektu, który powstał w ramach cyklu ESP8266 i IoT (to nie koniec do niego jeszcze wrócę, tylko skończmy z tą kamerą). Warto sobie taką zbudować (koszt 9-13 zł w zależności ile części typu złącza masz na stanie). Jak ją zrobić – to było opisane w części trzeciej przewodnika ESP8266 i IoT. Tam też lista elementów.
Nim zaczniemy coś programować, musimy przygotować Arduino IDE do pracy z ESP8266. Jeśli już masz to gotowe, do ściągnij i zainstaluj trzy biblioteki: ArduCAM, ESP8266_websocket oraz UTFT4ArduCAM_SPI (co za nazwa…). Możesz te biblioteki zainstalować przez manager (Sketch/Include Library/Library Manager
) ale… ja osobiście nie przepadam, zainstalowałem ręcznie.
Ok, sprzęt gotowy, to zaczynamy podpinać. I tu pierwszy wilczy dół, w który wpadłem. Otóż chyba wszystkie diagramy (łącznie z oficjalną dokumentacją) wskazują pin CS/SS na GPIO15 na płytce. Przykład, który jest dołączony również w komentarzu mówi o GPIO15, choć w kodzie był 16. Dlatego, zmieniłem w kodzie GPIO na 15 i do podłączania. Po wpięciu kabelków do SPI zdziwienie – ESP2866 zaczęło zachowywać się co najmniej dziwnie.
Wgranie programu jeszcze się udało, ale potem zwis totalny, zazwyczaj reset nawet nie pomagał, trzeba było wyłączać układ. I tutaj nakłada się druga historia, w tym samym czasie robię testy innych urządzeń z ESP8266. One też korzystają z SPI i tam były pewne problemy ze stabilnością. Dlatego, pierwsze podejrzenia poszły w kierunku podobnych problemów z SPI – oscyloskop i szukanie sygnałów. Jednak w miarę szybko okazało się, że odpięcie właśnie CS przywracało po resecie ESP8266 do życia. W końcu – zmieniłem CS na pin GPIO16 i ESP zaczęło normalnie funkcjonować.
Sęk w tym, że tak się na SPI zafiksowałem, że wpadłem w drugi „wilczy dół” :) Wstyd się przyznać, ale ArduCam potrzebuje zarówno SPI jak I2C jednocześnie, a jak się okazało nie było dla mnie to dostatecznie dużymi literami napisane. Co z tego, że wszystkie schematy mówią wyraźnie, że SDA/SCL też trzeba podłączyć, gdzieś się zapisało w głowie że albo SPI albo I2C. Prawda jest taka, że po SPI jest dostęp do CPLD Altery, który dokonuje obróbki danych z czujnika kamery. Sam czujnik kamery jest dostępny po I2C i potrzeba obu by całość mogła być sterowana.
Czyli, niezależnie od doświadczenia, zawsze można zrobić głupi błąd :) który kosztować będzie Was trochę straconego czasu. Jeśli coś nie działa zupełnie (a powinno), to warto zostawić na chwilę wszystko i z otwartym umysłem podejść jeszcze raz do tematu, ale zweryfikować wszystkie swoje wstępne założenia.
Jak już CS został zmieniony na GPIO16 a piny SDA/SCL zostały podłączone (GPIO4 i GPIO5 – uwaga sprawdź dobrze, niektóre moduły ESP8266-07 i -12 miały zamienione te dwa wyprowadzenia), to wszystko zaczęło działać jak należy:
Na zdjęciu jest złącze ArduCAM. Łączymy z ESP8266-12:
CS -> GPIO16
MOSI -> GPIO13
MISO -> GPIO12
SCK -> GPIO14
GND -> GND
VCC -> VCC
SDA -> GPIO4
SCL -> GPIO5
Do działania potrzebny nam jest szkic, na początek nie wybiegniemy poza przykład dostępny z ArduCam. W menu File/Examples/ArduCAM/ESP8266/ArduCAM_Mini_OV2640_websocket_server
jest tym czego szukamy. Otwieramy przykład, odnajdujemy miejsce w którym jest ustawiane SSID i hasło sieci WiFi (u mnie są to linie 42 i 43 szkicu – jeśli nie masz jeszcze to włącz sobie numerowanie linii w IDE – Ctrl+,
i opcja Display line numbers
), wpisz właściwe SSID i hasło do Twojej sieci WiFi.
Wgraj szkic na ESP (pamiętaj o zwarciu do GND pinu GPIO0), korzystając z jakiegoś konwertera USB/Serial. Zajrzyj na konsolę, by zobaczyć jaki adres IP otrzymało ESP. Teraz, co robi ten szkic? Otóż udostępnia tak zwany WebSocket – jest to standard zapewniający komunikację w dwie strony przez jeden kanał TCP i jest zaimplementowany przez współczesne przeglądarki. Jako taki nadaje się świetnie do transmisji danych z kamery. Po nawiązaniu połączenia, przeglądarka w każdej chwili może wysłać do ESP komendę capture
, która spowoduje zrobienie zdjęcia i odesłanie go przez kanał WebSocket.
Do tego potrzebny jest HTML – aby już nie kombinować z równoległa obsługą WebSocket i HTML na ESP, dla wygody skorzystamy z lokalnego HTML. Do szkicu jest dołączony katalog html
(tam gdzie jest przykład). Możesz dogrzebać się do niego na swoim dysku, albo po prosty ściągnij ArduCAM websocket HTML – archiwum ZIP będące jego kopią.
Rozpakuj zip i otwórz plik html w przeglądarce. Otworzy się taka strona ze zdjęciem przygotowanym przez autora ArduCAM.
W polu Location
wpiszcie adres IP waszego ESP (zachowując ws://
z przodu) i kliknijcie Connect
. Po chwili powinien wyskoczyć pop-up z informacją o nawiązaniu połączenia.
Wtedy można wysłać komendę capture
by otrzymać zdjęcie. Tutaj zobaczyć możecie jak dziś rano widok za oknem się prezentował. Może niezbyt pięknie, ale heh, taka rzeczywistość :)
Klikając kolejny raz Send
możecie uaktualnić zdjęcie. Ale na takim gotowcu nie poprzestaniemy. Jak działa ten szkic?
W pętli loop znajdziecie kod:
WiFiClient client = server.available(); if (webSocketServer.handshake(client)) { while (client.connected() ) { //KOD }
Zmienna client
zostanie „wypełniona” jeżeli przyjdzie połączenie z przeglądarki. Następnie, jeżeli połączenie jest zidentyfikowane jako poprawna komunikacja w ramach WebSocket (sprawdza to
webSocketServer.handshake
) to następuje obsługa połączenia. Po odebraniu danych od przeglądarki, są one umieszczane w łańcuchu znakowym i przekazywane do funkcji handleClientData
. I tam, jeśli został odebrany łańcuch capture
zostaje uruchomiona kamera.
Co można poprawić? Na szybko – może dodamy obsługę różnych rozdzielczości. W tym celu modyfikujemy funkcję handleClientData
dając dwa ify, a przed wywołaniem start_capture
ustawiamy wybraną rozdzielczość. Całość wygląda tak:
void handleClientData(String &dataString) { if (dataString.startsWith("capture1")) { myCAM.OV2640_set_JPEG_size(OV2640_640x480); Serial.println(dataString); start_capture(); } if (dataString.startsWith("capture2")) { myCAM.OV2640_set_JPEG_size(OV2640_320x240); Serial.println(dataString); start_capture(); } }
Prawda, że proste? Od teraz w zależności czy wyślecie tekst capture1
czy capture2
to otrzymacie zdjęcie w różnej rozdzielczości.
Przy produkcji wpisu ucierpiały (albo i nie) następujące części:
- kamera ArduCAM Mini 2MP
- ESP8266-12E
- kable, przewody, stripboard – jak opisane w przewodniku ESP8266 i IoT cz 3
- zawsze przydatny jakiś konwerter USB/Serial
Co dalej z ArduCAM?
Jak na wstępie napisałem, ArduCAM jest w mojej opinii produktem niszowym. Jego niewątpliwą zaletą jest stosunkowy niewielki rozmiar.
Gdy myślisz o obróbce obrazu czy bardziej o video streamingu to raczej Twoje myśli powinny kierować się w stronę rozwiązania opartego o jakieś Rasbperry Pi i kamer dedykowanych do Raspberry lub nawet zwykłe kamerki na USB.
Jeśli chcesz zrobić coś użytecznego z tą kamerą, to na myśl przychodzi mi scenariusz w którym chcesz robić zdjęcie po jakimś zdarzeniu. Czy to będzie wyzwolenie z czujnika PIR czy może odczyt karty RFID (kontrola wejść) to już nie ma znaczenia.
Czy chcielibyście tutaj zobaczyć taki gotowy projekt?
Super projekt
jak możesz jeszcze do kompletu schemat połączeń dołożyć było by super
@gregorR
Dodałem zdjęcie złącza i listing jak połączyć z ESP
dzięki