Elektroda.pl
Elektroda.pl
X
Sklep HeluKabel
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Moduł kamery OV7670, uruchomienie, testy z Arduino

TechEkspert 19 Sie 2018 10:08 3804 12
  • Moduł kamery OV7670, uruchomienie, testy z Arduino
    Stosując moduł kamery OV7670 możemy w naszym projekcie przetwarzać obraz o rozdzielczości 640x480. Rozdzielczość VGA może wydawać się obecnie śmiesznie mała, jednak niskim kosztem możemy wzbogacić nasz projekt o możliwość przetwarzania obrazu z kamery. Wspomniana rozdzielczość 640x480 dla np. modułu Arduino nano może okazać się zaskakująco duża w porównaniu do zasobów mikrokontrolera. Wiedza z eksperymentów z kamerą niskiej rozdzielczości może przydać się przy próbach z droższymi modułami o wyższej rozdzielczości. W przypadku nowszych modułów kamer warto zajrzeć do projektu ArduCAM.

    Próbowałem przebrnąć przez konfigurację rejestrów, jednak muszę przyznać, że to zadanie pokonało mnie czasowo. Ilość zależności między rejestrami jest spora, opisy niektórych opcji dość enigmatyczne. Praca z rejestrami to dobre pole do eksperymentów i można sporo wycisnąć z modułu kamery, jednak wymaga to czasu. Udało mi się potwierdzić działanie następujących rejestrów:
    -Zapis pod adres 0x12 wartości 0x80 resetuje wartości w rejestrach do domyślnych.
    -Rejestr 0x0C umożliwia włączenie skalowania obrazu (bit 3), natomiast zapis odpowiednich wartości do rejestru 0x12 pozwala na ustawienie rozdzielczości QCIF, CIF, VGA oraz włączenie trybu przesyłania danych o kolejnych pikselach jako RGB (np. RGB565). Kamera może wysyłać dane w formacie YUV/YCbCr (4:2:2) gdzie kolejne bajty nie są wartościami 1:1 kolejnych pikseli link (tak jak jest to np. w trybie RGB).
    -Zapis do rejestru 0x15 wartości 0x20 spowoduje generowanie sygnału PCLK tylko wtedy gdy są wysyłane dane pikseli.
    -Rejestry 0x11 i 0x6B pozwalają na ustawienie dzielników i PLL dla sygnału zegarowego.
    -Rejestr 0x1B pozwala na wprowadzanie opóźnienia w wysyłaniu danych, co czasem może przydać się przy przetwarzaniu danych

    Ponieważ pokonała mnie własnoręczna konfiguracja rejestrów, skorzystałem z gotowego kodu:
    https://github.com/indrekluuk/LiveOV7670
    który pozwala na wyświetlanie obrazu z kamery na wyświetlaczu 128x160 TFT SPI.

    Podgląd na żywo z OV7670 na TFT 128x128 ILI9163.

    Na filmie poniżej efekt działania podglądu na żywo z kamery, który pozwolił stwierdzić prawidłowe działanie modułu kamery, oraz ustawić ostrość obiektywu:


    Moduł wykorzystuje dużą ilość linii sygnałowych, gdyby dane o obrazie były przekazywane np. magistralą szeregową SPI, ilość wykorzystanych linii byłaby mniejsza, natomiast sprzętowa obsługa SPI może ułatwić pobieranie danych.

    Moduł kamery OV7670, uruchomienie, testy z Arduino

    Uruchomienie zgodnie z opisem autora:
    -pobranie plików z github
    -skopiowanie "src/lib/LiveOV7670Library" i "src/lib/Adafruit_GFX_Library" do Arduino folder "libraries"
    -otwarcie "src/LiveOV7670/LiveOV7670.ino" w Arduino IDE i skompilowanie oraz wgranie do płytki Arduino

    Aby uniknąć stosowania konwerterów poziomów logicznych, wykorzystałem Arduino mini pro z rezonatorem 16MHz jednak zasilone napięciem 3.3V. Zgodnie z notą ATmega328 mikrokontroler przy napięciu 3.3V nie powinien być taktowany częstotliwością 16MHz (np. powinna być to wersja Arduino mini pro 3.3V 8MHz), jednak na potrzeby testu taki zestaw upraszczał połączenia i działał prawidłowo.

    Autor zastosował wyświetlacz TFT 128x160, podczas testów podłączyłem wyświetlacz TFT 128x128 ze sterownikiem IL9163.
    W wyświetlanym obrazie zamieniony był kolor czerwony z niebieskim. Do celów testowych, sprawdzenia czy moduł kamery działa, oraz ustawienia ostrości - zamienione kolory nie są problemem. Jeżeli chcecie uzyskać właściwe kolory zmieniając kolejność z RGB z BRG można np. na szybko w pliku Adafruit_ST7735_mod.cpp zmienić wartość w rejestrze MADCTL:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    na
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Według dokumentacji kamery OV7670 moduł zasilany jest napięciem 3.3V, przy podłączaniu do Arduino 5V należy zadbać o konwersję poziomów napięć. Moduł posiada wyprowadzenia SIO_C, SIO_D będące magistralą SCCB o działaniu zbliżonym do I2C, magistrala szeregowa wykorzystywaną w konfiguracji kamery. Moduł odpowiada na magistrali I2C pod adresem 0x21. Wejścia RESET (stan wysoki praca kamery) i PWDOWN (stan niski praca normalna). Wejście sygnału zegarowego XCLK, oraz wyjście PCLK do synchronicznego pobierania danych z równoległej 8bitowej magistrali D7-D0. Wyjścia HREF i VSYNC synchronizujące pobieranie danych z magistrali równoległej (odpowiednia konfiguracja umożliwia zrezygnowanie z sygnału HREF - sygnał linii, wykorzystując wyłącznie VSYNC - synchronizacja ramki).

    Podstawą uruchomienia modułu jest odpowiednia konfiguracja rejestrów magistralą SCCB. Linie interfejsu SCCB należy podciągnąć do + zasilania rezystorami 4.7-10kom. Istotne aby moduł kamery posiadał stabilne zasilanie 3.3V. Aby magistrala działała poprawnie należy podać sygnał zegarowy na wejście XCLK, wg. noty aplikacyjnej częstotliwość sygnału wejściowego powinna wynosić 10-48MHz (eksperymentalnie sprawdziłem, że przy częstotliwości wejściowej na XCLK=4MHz interfejs SCCB odpowiada prawidłowo). Testowany kod generował częstotliwość taktującą XCLK=8MHz. Częstotliwość sygnału PCLK taktującego zmiany danych na liniach D7-D0 (dane należy zczytywać na zboczu narastającym) zależy od ustawionych dzielników i PLL. W przypadku testowanego kodu, na PCLK otrzymujemy zegar o częstotliwości 2MHz.

    Moduł kamery OV7670, uruchomienie, testy z Arduino

    Odstęp czasowy między impulsami VSYNC (odstęp między ramkami) to 100ms czyli mamy ~10FPS:
    Moduł kamery OV7670, uruchomienie, testy z Arduino

    Odstęp między impulsami HREF (jedna linia) to około 800us:
    Moduł kamery OV7670, uruchomienie, testy z Arduino

    Czas transmisji jednej linii z OV7670 to ~156us, transmisji towarzyszy stan wysoki na linii HREF oraz sygnał zegarowy na linii PCLK:
    Moduł kamery OV7670, uruchomienie, testy z Arduino

    Między kolejnymi transmisjami linii OV7670, dane przesyłane są do wyświetlacza TFT po magistrali SPI, towarzyszy temu sygnał zegarowy na linii SCK, transmisja trwa ~484us:
    Moduł kamery OV7670, uruchomienie, testy z Arduino

    Samo wyświetlanie obrazu z kamery na wyświetlaczu jest mało praktyczne, chyba że prześlemy dane cyfrowe na większą odległość transmisją przewodową lub bezprzewodową. Ciekawszym zastosowaniem byłoby zapisanie danych z modułu kamery na kartę SD uzyskując fotopułapkę lub kamerę timelaps np. do obserwacji przyrody. Rozdzielczość plików zapisanych przez taką kamerę będzie dość beznadziejna, ale za to całość byłaby dość tania i miałaby wartość eksperymentalną.

    Zapis obrazu z OV7670 na karcie SD

    Na stronie link znajdziemy pomysł na sposób zapisania danych z kamery na karcie SD. Okazuje się, że autor wybrał rozdzielczość 320x240 niższą niż maksymalna 640x480. Dodatkowo wybrał format odczytu danych z kamery YUV i zapisuje na kartę tylko dane o luminancji czego efektem będzie czarnobiały obraz. Na koniec aby uzyskać plik BMP pliki przetwarza skryptem python. Mało efektowne i wygodne, dlaczego zapis kolorowego (RGB565) pliku BMP na karcie SD sprawia problemy? Otóż zapis danych do wyświetlacza TFT był sekwencyjny i nie wymagał potwierdzeń i dodatkowych operacji, natomiast na karcie SD obsługujemy system plików. Niezbyt wydajna biblioteka Arduino obsługująca karty SD, oraz zmienne zachowanie karty SD utrudnia szybkie i sekwencyjne zapisywanie danych z kamery do pliku na karcie. Ograniczenie rozdzielczości z 640x480 do 320x240 wynika z pozostałej pamięci na zmienne po zaimportowaniu biblioteki obsługi kart SD. Jedna linia 320px mieści się w pozostałej pamięci, natomiast z 640px 16b kolor jest już problem.

    Podsumowanie
    Moduł OV7670 jest tani i pozwala na wiele eksperymentów z odczytem obrazu i jego przetwarzaniem. Spore ograniczenia modułu mogą zniechęcać mniej wytrwałe osoby. Można spróbować zbudować tanie, proste, małe urządzenia do eksperymentów z timelaps/fotopułapka do obserwacji przyrody. Aby swobodnie eksperymentować z przetwarzaniem danych z kamery można wybrać:
    -platformę, która ma wystarczającą ilość RAM aby zmieścić całą ramkę z obrazem (lub w wersji oszczędnościowej pojedynczą linię)
    -moduł kamery posiadający bufor pamięci FIFO do której zostaną zapisane dane obrazu, natomiast odczyt może zostać wykonany z dowolną szybkością
    -moduł kamery wysyłający dane obrazu magistralą szeregową (mniejsza ilość przewodów łączących)
    -moduł z dobrą dokumentacją, bibliotekami/api/przykładami do konfiguracji, aby nie walczyć z uzyskaniem pierwszej klatki obrazu z kamery
    -platformę z odpowiednio szybkimi interfejsami, oraz zasobami obliczeniowymi aby odpowiednio szybko przetwarzać dane

    Niskopoziomowe eksperymenty z próbami przechwycenia obrazu VGA 640x480 pozwalają docenić aparaty fotograficzne i kamery wbudowane w nasze smartfony, oraz samodzielne aparaty i kamery 4K :)


    Fajne! Ranking DIY
  • Sklep HeluKabel
  • #2 20 Sie 2018 17:16
    Mscichu
    Poziom 15  

    Swojego czasu testowałem OV7670 z ATMega8A która służyła tylko jako wysterowanie nowej ramki LCD na sterowniku SSD1963 i wystartowanie kamerki. Śmigało elegancko z rozdzielczością maksymalną 640x480 nie było żadnych przycięć ale jak sam napisałeś nie było tutaj zastosowania innego jak super tani elektroniczny wizjer do drzwi. Szukałem też jakiegoś serializera aby puścić obraz po skrętce UTP ale zaprzestałem tego projektu.

    Natomiast wróciłem do sprawy z kamerkami tylko w innej formie, którą w sumie polecam każdemu. ESP32 + OV2640 (bez żadnego bufora) i można streamować do sieci jako podgląd, chociaż przy rozdzielczości 800x600 przycina tak jak w Twoim nagraniu gdy obraz zmienia się szybko (format jpeg). Zrobiłem też zapis na serwer zewnętrzny w sieci LAN może działać jako foto-pułapka. Link do projektu z którego korzystałem: https://github.com/igrr/esp32-cam-demo

    Swoją drogą omnivision olewa typowe pytania techniczne. Zapytałem o oficjalny datasheet lub podpowiedź jak w OV2640 uruchomić funkcję STROBE (w innych modułach jest dostępny rejestr a tutaj nie znalazłem żadnych danych) i odpisali, że nie mają czasu zająć się tą sprawą...

  • #3 20 Sie 2018 20:45
    TechEkspert
    Redaktor

    @Mscichu jeżeli miałbyś ochotę i czas to zapraszam do przedstawienia swoich osiągnięć w DIY lub Artykułach.

    Jaki zegar na PCLK użyłeś przy OV7670 + SSD1963 w trybie 640x480?

    W OV2640 widzę niepokojąco podobny interfejs sprzętowy jak w OV7670, czy w kwestii konfiguracji rejestrów też jest taka zabawa jak w OV7670?

    OV2640 posiada w sobie "kodek" jpeg?

    Widzę że są dwie wersje:
    bez dodatkowych modułów:
    https://botland.com.pl/kamery-do-arduino-i-ra...ry-arducam-ov2640-2mpx-1600x1200px-60fps.html
    https://botland.com.pl/kamery-do-arduino-i-ra...200px-60fps-z-obiektywem-hx-27227-m12x05.html
    oraz z dodatkowym układem na płytce:
    https://botland.com.pl/kamery-do-arduino-i-ra...1200px-60fps-spi-modul-kamery-do-arduino.html
    który komunikuje się szeregowo.
    Jest też wersja z ESP8266:
    https://botland.com.pl/kamery-do-arduino-i-ra...a-arducam-ov2640-2mpx-modul-wifi-esp8266.html

  • Sklep HeluKabel
  • #4 21 Sie 2018 14:43
    Mscichu
    Poziom 15  

    Co do projektu na OV7670 to stary projekt i zostały mi tylko szczątki. Ze schematu jednej z pierwszych wersji widzę, że na XCLK miałem wejście z zewnętrznego generatora i zamawiałem różne od 8 przez 16, 20 i 24MHz (jeszcze mam w szufladkach;) ) i z tego co pamiętam to działo na 24MHz. Wyjście z kamerki podałem na przerzutnik SN74HC109D który najpierw uruchamiał pierwszą bramkę SNJ54AC573W, a następnie następną (kodowanie RGB565) i przy drugim takcie zegara uruchamiał wyjście bufora oraz zapis kolejnego pixela na ekranie LCD (szyna 16bit). Dodatkowo po pełnej ramce gdy pojawiał się sygnał na VSYNC który był odczytywany z uC wysyłałem do SSD1963 położenie następnego pixela na 0.0 i tak w kółko.
    To było na początku 2014r. i mam spory bałagan, szczególnie z projektami testowymi więc nie ma co pokazywać. Jak ktoś będzie chętny i będzie chciał przejrzeć ten "worek" odnośnie OV7670 to mogę wrzucić tylko będę musiał pousuwać biblioteki od Kardasia.
    Z kolei jeżeli chodzi o projekt na OV2640 i ESP32 to jest to projekt na zlecenie i nie mogę ujawniać dokumentacji, chociaż służę pomocą.

    Jeżeli chodzi o rejestry na OV2640 to nawet do nich się nie zabierałem. Projekt na którym się wzorowałem już był poustawiany i nie wgryzałem się w same rejestry. Jedyne co zrobiłem to obracałem obrazem i tutaj jest niespodzianka bo po obróceniu obrazu o 180st zaczyna łapać zielony odcień. Nie na jednej bo testowałem już chyba z 10szt. i nie tylko u mnie bo na necie też mają problemy. OV2640 ma wbudowany kodek JPEG, dlatego wykorzystałem akurat tę kamerkę, jednak można pobrać obraz niekodowany w standardowych formatach.

    Co do wyboru OV2640 to dla mnie zależało aby jak najbardziej ograniczyć koszty przyszłej produkcji więc zamawiałem z chin same kamerki bez płytek (coś jak ten pierwszy link w którym masz również zasilanie czujnika i logiki kamery). ArduCam byłby najprostszym rozwiązaniem ale jest różnica 20pln za kamerę, a 140pln;)
    Ta wersja z ESP8266 i ta wersja po 140zł mają wbudowany procesor który najpierw łapie ramkę, a potem puszcza szeregowo i do zdjęć się będzie nadawać ale nie do filmów. Na ESP32 bez żadnych pośrednich procesorów jedną ramkę 800x600 łapię w 200-300ms. Jak ktoś chce złapać 1600x800 to trzeba zwiększyć kodowanie i obraz wygląda dość tragicznie, ale jest taka możliwość. Trzeba by dodać RAM'u do ESP32 ;)

  • #5 21 Sie 2018 16:26
    TechEkspert
    Redaktor

    Ciekawe eksperymenty.
    Czyli do strumieniowania na ESP32 odczytywane są z OV2640 ramki "raw", a później kompresowane i wysyłane po TCP?

    Gdy OV2640 wysyła ramkę skompresowaną, to wysyła jakiś znacznik końca danych? (być może rozmiar po kompresji może być różny i zależny od treści ?).

    Czy dane jpg z OV2640 można wykorzystać do strumieniowania np. w mjpg?

  • #6 21 Sie 2018 17:25
    Mscichu
    Poziom 15  

    Możesz odebrać jako RAW albo już skompresowane, przy czym możesz sam szybko wybrać jakość kompresji. Kamera zawsze po skończonej ramce czy to jest RAW czy JPEG zmienia sygnał na VSYNC, a samą kompresją zajmuje się już procesor wbudowany w moduł kamery. Oczywiście pliki JPEG pomimo tej samej rozdzielczości mogą mieć różne wielkości (u mnie od 30 do 60kb).
    Moduł kamery OV7670, uruchomienie, testy z Arduino

    Na ESP32 można też wykorzystać wbudowaną pamięć jako dysk twardy aby zapisać zdjęcie i odczytać w innym czasie. W standardowym ESP-WROOM32 mamy 4mb flash z czego przynajmniej połowę można zużyć na system plików (to około 50 zdjęć).
    Co do odtwarzania MJPEG to jest już nawet taka funkcja która w kółko wysyła i odświeża stronę. Próbowałem zapisać i zapisuje jako film - nieskończenie długi ;) Ogólnie tematyka ciekawa, chociaż wgryźć się aby wszystko zacząć samemu od zera byłoby ciężko.

  • #7 21 Sie 2018 19:41
    TechEkspert
    Redaktor

    Sprytne z tym wykorzystaniem VSYNC do poinformowania o końcu skompresowanych danych jpg. Rozumiem, że w tym przypadku HREF nie niesie żadnej informacji?

    Co jest w stanie odtworzyć ten "film" w postaci zapisanej odświeżającej się strony?

    Przykład tych kamer pokazuje, że niby znikome rozdzielczości, ale aby to łatwo obsłużyć powstają bardzo złożone platformy wykorzystujące FPGA:
    https://botland.com.pl/arducam-kamery-do-ardu...-v2-dla-arduino-modul-kamery-ov2640-2mpx.html

    Znalazłem jeszcze jeden moduł wspierający kompresję:
    https://botland.com.pl/kamery-do-arduino-i-ra...x-640x480px-30fps-z-obiektywem-hq-m12x05.html

  • #8 21 Sie 2018 19:53
    Mscichu
    Poziom 15  

    Odtwarzałem tym co miałem na kompie, pewnie był to VLC lub dziobas. Postaram się jutro coś nagrać i sprawdzę dokładnie co i jak. Co do informacji o końcu za[isu JPEG to widzę w kodzie, że jest porównanie odebranego buforu do SIZE_MAX ale SIZE_MAX nie znalazłem nigdzie w kodzie, nawet jak używam grep. HREF przy jpeg wydaje się być nieużywane.

    Tą kamerkę też widziałem ale musiałem wszystko miniaturyzować więc u mnie wybór padł na kamerki OV :)

  • #9 25 Sie 2018 11:55
    Mscichu
    Poziom 15  

    Trochę mi zajęło aby zebrać wszystko do kupy (a w szczególności aby wygrzebać działający program do ESP).

    Po zaprogramowaniu ESP32 w linii komend dostajemy wiadomość o poprawnym uruchomieniu kamery oraz podłączeniu do sieci, co potwierdza przydzielenie IP i podanie przez ESP32 linków do podglądu:
    Moduł kamery OV7670, uruchomienie, testy z Arduino

    Po skopiowaniu adresu i wklejeniu do przeglądarki dostajemy zdjęcie oraz informacje o połączeniu i czasu odczytu ramki:
    Moduł kamery OV7670, uruchomienie, testy z ArduinoModuł kamery OV7670, uruchomienie, testy z Arduino

    Gdy skopiujemy link ze streamem to dostajemy dość dobry obraz (niestety nagrywany zewnętrznym programem bo nie pamiętam już dokładnie jak zapisywałem/odtwarzałem). Film robiony pod światło ponieważ nie mam gdzie skierować kamery. Ogólny bałagan i projekty których nie mogę pokazywać. Chcę tylko pokazać jak wygląda ruch w samej kamerze:

    Oraz prędkość generowania klatek w streamingu:
    Moduł kamery OV7670, uruchomienie, testy z Arduino

    Teraz parę ciekawostek które przychodzą mi na myśl i które przerabiałem:
    1. Można podłączyć kartę SD i szybko zapisywać zdjęcia do pamięci przy podłączeniu SDIO
    2. Zapis do wbudowanej pamięci flash zajmuje wieczność bo ok 3s.
    3. Wysłanie zapisanego zdjęcia (wewnętrzny flash) na zewnętrzny serwer zajmuje mniej niż 1s
    4. Kamera OV2640 ma wbudowany pin sterujący diodą flash, jednak nie ma żadnych opisów jak nią terować. Można natomiast odczytać z rejestru urządzenia pod adresem 0x2F natężenie światła i terować np pinem ESP32
    5. Kamera ov2640 ma 2 rejestry - Gdy do komórki 0xFF zapiszemy 1 lub 0. Rejestry są opisane w DS dość dokładnie.

  • #10 25 Sie 2018 15:57
    TechEkspert
    Redaktor

    Bardzo ciekawy efekt przy wykorzystaniu tanich podzespołów. Przy uporządkowaniu i poszerzeniu materiału można spokojnie umieścić jako samodzielny artykuł lub projekt w DIY.

  • #11 26 Sie 2018 21:29
    Mscichu
    Poziom 15  

    ESP32 ogólnie jest bardzo ciekawym produktem. Całkiem niedawno uruchamiałem jako MP3 dekoder. Sama biblioteka działa jako odtwarzacz internetowego radia ale można uruchomić aby odtwarzał z zewnętrznej karty SD. Link do projektu: https://github.com/MrBuddyCasino/ESP32_MP3_Decoder

    Co do pisania artykułu to faktycznie byłby ciekawy jednak ja nie mam smykałki do opisów. Każdy zawsze mi mówił, że nie potrafię opisać tego co chcę ;) Ale jak by komuś potrzeba było pomocy to chętnie pomogę.

  • #12 26 Sie 2018 21:57
    TechEkspert
    Redaktor

    Sprawne pisanie to kwestia wprawy, z komentarzy można się bardzo dużo nauczyć, tak jak właśnie w przypadku tego materiału.

    Testowałem radio internetowe na ESP32, bez zewnętrznego DAC efekt średni, ale przy tak małych kosztach eksperyment ciekawy. Jakość dźwięku bez DAC pewnie można określić jako zbliżona do małych trzeszczących radyjek FM.

    ESP32 to ciekawy produkt i przy mniejszych seriach ESP8266 traci sens?

  • #13 26 Sie 2018 23:01
    Mscichu
    Poziom 15  

    Według mnie ESP8266 nadaje się do prostych rzeczy przy seryjnych produkcjach ponieważ dalej jest tańszy od ESP32 więc nie ma sensu przy sterowaniu np przekaźnikiem przepłacać. Dla hobbysty lepiej zakupić ESP32 ponieważ za kilka złotych więcej mamy dużo większą wydajność, możliwości i większą ilość pinów. Dodatkowym atutem przemawiającym za używanie ESP32 przez amatorów jest wykorzystanie jednego rdzenia tylko dla wifi w arduino więc wifi nie będzie się zacinać i rwać. Tutaj chciałbym tylko dodać, że pisząc program jak np wspomniane radio internetowe można włączyć lub wyłączyć dostęp do dwóch rdzeni (dekodowanie MP3 wykorzystuje oba rdzenie, inaczej nie chce działać), tak więc mamy naprawdę mocny moduł za niewielkie pieniądze.