20 KiB
Užfiksuokite vaizdą - Wio Terminal
Šioje pamokos dalyje pridėsite kamerą prie savo Wio Terminal ir užfiksuosite vaizdus.
Aparatinė įranga
Wio Terminal reikia kameros.
Naudojama kamera yra ArduCam Mini 2MP Plus. Tai 2 megapikselių kamera, pagrįsta OV2640 vaizdo jutikliu. Ji perduoda duomenis per SPI sąsają, kad užfiksuotų vaizdus, ir naudoja I2C, kad sukonfigūruotų jutiklį.
Prijunkite kamerą
ArduCam neturi Grove jungties, vietoj to ji jungiasi prie SPI ir I2C magistralių per GPIO kaiščius ant Wio Terminal.
Užduotis - prijunkite kamerą
Prijunkite kamerą.
-
ArduCam apačioje esantys kaiščiai turi būti prijungti prie GPIO kaiščių ant Wio Terminal. Kad būtų lengviau rasti tinkamus kaiščius, uždėkite GPIO kaiščių lipduką, kuris yra komplekte su Wio Terminal:
-
Naudodami jungiamuosius laidus, atlikite šiuos sujungimus:
ArduCAM kaištis Wio Terminal kaištis Aprašymas CS 24 (SPI_CS) SPI Chip Select MOSI 19 (SPI_MOSI) SPI Valdiklio išvestis, periferijos įvestis MISO 21 (SPI_MISO) SPI Valdiklio įvestis, periferijos išvestis SCK 23 (SPI_SCLK) SPI Serijinis laikrodis GND 6 (GND) Žemė - 0V VCC 4 (5V) 5V maitinimo šaltinis SDA 3 (I2C1_SDA) I2C Serijiniai duomenys SCL 5 (I2C1_SCL) I2C Serijinis laikrodis GND ir VCC jungtys suteikia 5V maitinimą ArduCam. Ji veikia 5V, skirtingai nei Grove jutikliai, kurie veikia 3V. Šis maitinimas gaunamas tiesiai iš USB-C jungties, kuri maitina įrenginį.
💁 SPI jungčiai ArduCam ir Wio Terminal kaiščių pavadinimai, naudojami kode, vis dar naudoja seną pavadinimų konvenciją. Šios pamokos instrukcijos naudos naują pavadinimų konvenciją, išskyrus atvejus, kai kaiščių pavadinimai naudojami kode.
-
Dabar galite prijungti Wio Terminal prie savo kompiuterio.
Užprogramuokite įrenginį, kad jis prisijungtų prie kameros
Dabar Wio Terminal galima užprogramuoti naudoti prijungtą ArduCAM kamerą.
Užduotis - užprogramuokite įrenginį, kad jis prisijungtų prie kameros
-
Sukurkite naują Wio Terminal projektą naudodami PlatformIO. Pavadinkite šį projektą
fruit-quality-detector
. Pridėkite kodąsetup
funkcijoje, kad sukonfigūruotumėte serijinį prievadą. -
Pridėkite kodą, kad prisijungtumėte prie WiFi, su savo WiFi prisijungimo duomenimis faile, pavadintame
config.h
. Nepamirškite pridėti reikalingų bibliotekų įplatformio.ini
failą. -
ArduCam biblioteka nėra prieinama kaip Arduino biblioteka, kurią galima įdiegti iš
platformio.ini
failo. Vietoj to ją reikės įdiegti iš šaltinio jų GitHub puslapyje. Ją galite gauti:- Klonuodami repozitoriją iš https://github.com/ArduCAM/Arduino.git
- Apsilankę repozitorijoje GitHub adresu github.com/ArduCAM/Arduino ir atsisiųsdami kodą kaip zip failą iš Code mygtuko
-
Jums reikės tik
ArduCAM
aplanko iš šio kodo. Nukopijuokite visą aplanką įlib
aplanką savo projekte.⚠️ Visas aplankas turi būti nukopijuotas, kad kodas būtų
lib/ArduCam
. Nekopijuokite tikArduCam
aplanko turinio įlib
aplanką, nukopijuokite visą aplanką. -
ArduCam bibliotekos kodas veikia su kelių tipų kameromis. Kameros tipas, kurį norite naudoti, yra konfigūruojamas naudojant kompiliatoriaus vėliavėles - tai sumažina sukurtos bibliotekos dydį, pašalinant kodą kameroms, kurių nenaudojate. Norėdami sukonfigūruoti biblioteką OV2640 kamerai, pridėkite šiuos nustatymus į
platformio.ini
failo pabaigą:build_flags = -DARDUCAM_SHIELD_V2 -DOV2640_CAM
Tai nustato 2 kompiliatoriaus vėliavėles:
ARDUCAM_SHIELD_V2
, kad biblioteka žinotų, jog kamera yra ant Arduino plokštės, vadinamos "shield".OV2640_CAM
, kad biblioteka įtrauktų tik kodą OV2640 kamerai.
-
Pridėkite antraštės failą į
src
aplanką, pavadintącamera.h
. Jame bus kodas, skirtas bendrauti su kamera. Pridėkite šį kodą į šį failą:#pragma once #include <ArduCAM.h> #include <Wire.h> class Camera { public: Camera(int format, int image_size) : _arducam(OV2640, PIN_SPI_SS) { _format = format; _image_size = image_size; } bool init() { // Reset the CPLD _arducam.write_reg(0x07, 0x80); delay(100); _arducam.write_reg(0x07, 0x00); delay(100); // Check if the ArduCAM SPI bus is OK _arducam.write_reg(ARDUCHIP_TEST1, 0x55); if (_arducam.read_reg(ARDUCHIP_TEST1) != 0x55) { return false; } // Change MCU mode _arducam.set_mode(MCU2LCD_MODE); uint8_t vid, pid; // Check if the camera module type is OV2640 _arducam.wrSensorReg8_8(0xff, 0x01); _arducam.rdSensorReg8_8(OV2640_CHIPID_HIGH, &vid); _arducam.rdSensorReg8_8(OV2640_CHIPID_LOW, &pid); if ((vid != 0x26) && ((pid != 0x41) || (pid != 0x42))) { return false; } _arducam.set_format(_format); _arducam.InitCAM(); _arducam.OV2640_set_JPEG_size(_image_size); _arducam.OV2640_set_Light_Mode(Auto); _arducam.OV2640_set_Special_effects(Normal); delay(1000); return true; } void startCapture() { _arducam.flush_fifo(); _arducam.clear_fifo_flag(); _arducam.start_capture(); } bool captureReady() { return _arducam.get_bit(ARDUCHIP_TRIG, CAP_DONE_MASK); } bool readImageToBuffer(byte **buffer, uint32_t &buffer_length) { if (!captureReady()) return false; // Get the image file length uint32_t length = _arducam.read_fifo_length(); buffer_length = length; if (length >= MAX_FIFO_SIZE) { return false; } if (length == 0) { return false; } // create the buffer byte *buf = new byte[length]; uint8_t temp = 0, temp_last = 0; int i = 0; uint32_t buffer_pos = 0; bool is_header = false; _arducam.CS_LOW(); _arducam.set_fifo_burst(); while (length--) { temp_last = temp; temp = SPI.transfer(0x00); //Read JPEG data from FIFO if ((temp == 0xD9) && (temp_last == 0xFF)) //If find the end ,break while, { buf[buffer_pos] = temp; buffer_pos++; i++; _arducam.CS_HIGH(); } if (is_header == true) { //Write image data to buffer if not full if (i < 256) { buf[buffer_pos] = temp; buffer_pos++; i++; } else { _arducam.CS_HIGH(); i = 0; buf[buffer_pos] = temp; buffer_pos++; i++; _arducam.CS_LOW(); _arducam.set_fifo_burst(); } } else if ((temp == 0xD8) & (temp_last == 0xFF)) { is_header = true; buf[buffer_pos] = temp_last; buffer_pos++; i++; buf[buffer_pos] = temp; buffer_pos++; i++; } } _arducam.clear_fifo_flag(); _arducam.set_format(_format); _arducam.InitCAM(); _arducam.OV2640_set_JPEG_size(_image_size); // return the buffer *buffer = buf; } private: ArduCAM _arducam; int _format; int _image_size; };
Tai yra žemo lygio kodas, kuris konfigūruoja kamerą naudojant ArduCam bibliotekas ir ištraukia vaizdus, kai to reikia, naudojant SPI magistralę. Šis kodas yra labai specifinis ArduCam, todėl šiuo metu nereikia jaudintis, kaip jis veikia.
-
main.cpp
faile pridėkite šį kodą po kitaisinclude
teiginiais, kad įtrauktumėte naują failą ir sukurtumėte kameros klasės egzempliorių:#include "camera.h" Camera camera = Camera(JPEG, OV2640_640x480);
Tai sukuria
Camera
, išsaugančią vaizdus kaip JPEG failus 640x480 raiška. Nors palaikomos didesnės raiškos (iki 3280x2464), vaizdų klasifikatorius veikia su daug mažesniais vaizdais (227x227), todėl nėra reikalo fiksuoti ir siųsti didesnių vaizdų. -
Pridėkite šį kodą žemiau, kad apibrėžtumėte funkciją, skirtą kameros nustatymui:
void setupCamera() { pinMode(PIN_SPI_SS, OUTPUT); digitalWrite(PIN_SPI_SS, HIGH); Wire.begin(); SPI.begin(); if (!camera.init()) { Serial.println("Error setting up the camera!"); } }
Ši
setupCamera
funkcija pradeda konfigūruoti SPI chip select kaištį (PIN_SPI_SS
) kaip aukštą, padarydama Wio Terminal SPI valdikliu. Tada ji pradeda I2C ir SPI magistrales. Galiausiai ji inicializuoja kameros klasę, kuri konfigūruoja kameros jutiklio nustatymus ir užtikrina, kad viskas būtų tinkamai prijungta. -
Iškvieskite šią funkciją
setup
funkcijos pabaigoje:setupCamera();
-
Sukurkite ir įkelkite šį kodą, ir patikrinkite išvestį serijiniame monitoriuje. Jei matote
Error setting up the camera!
, patikrinkite laidus, kad įsitikintumėte, jog visi kabeliai jungia tinkamus ArduCam kaiščius su tinkamais GPIO kaiščiais ant Wio Terminal, ir visi jungiamieji laidai yra tinkamai prijungti.
Užfiksuokite vaizdą
Dabar Wio Terminal galima užprogramuoti, kad užfiksuotų vaizdą, kai paspaudžiamas mygtukas.
Užduotis - užfiksuokite vaizdą
-
Mikrovaldikliai vykdo jūsų kodą nuolat, todėl nėra lengva inicijuoti veiksmą, pvz., fotografavimą, nereaguojant į jutiklį. Wio Terminal turi mygtukus, todėl kamerą galima nustatyti taip, kad ją inicijuotų vienas iš mygtukų. Pridėkite šį kodą
setup
funkcijos pabaigoje, kad sukonfigūruotumėte C mygtuką (vieną iš trijų mygtukų viršuje, esantį arčiausiai maitinimo jungiklio).pinMode(WIO_KEY_C, INPUT_PULLUP);
INPUT_PULLUP
režimas iš esmės apverčia įvestį. Pavyzdžiui, paprastai mygtukas siųstų žemą signalą, kai nėra paspaustas, ir aukštą signalą, kai paspaustas. Kai nustatytasINPUT_PULLUP
, jis siunčia aukštą signalą, kai nėra paspaustas, ir žemą signalą, kai paspaustas. -
Pridėkite tuščią funkciją, kad reaguotų į mygtuko paspaudimą prieš
loop
funkciją:void buttonPressed() { }
-
Iškvieskite šią funkciją
loop
metode, kai mygtukas paspaustas:void loop() { if (digitalRead(WIO_KEY_C) == LOW) { buttonPressed(); delay(2000); } delay(200); }
Šis kodas patikrina, ar mygtukas paspaustas. Jei jis paspaustas, iškviečiama
buttonPressed
funkcija, o ciklas užlaikomas 2 sekundėms. Tai leidžia mygtukui būti atleistas, kad ilgas paspaudimas nebūtų užregistruotas du kartus.💁 Wio Terminal mygtukas nustatytas kaip
INPUT_PULLUP
, todėl siunčia aukštą signalą, kai nėra paspaustas, ir žemą signalą, kai paspaustas. -
Pridėkite šį kodą į
buttonPressed
funkciją:camera.startCapture(); while (!camera.captureReady()) delay(100); Serial.println("Image captured"); byte *buffer; uint32_t length; if (camera.readImageToBuffer(&buffer, length)) { Serial.print("Image read to buffer with length "); Serial.println(length); delete(buffer); }
Šis kodas pradeda kameros fiksavimą, iškviesdamas
startCapture
. Kameros aparatinė įranga neveikia grąžindama duomenis, kai jų prašoma, vietoj to siunčiate instrukciją pradėti fiksavimą, ir kamera fone dirba, kad užfiksuotų vaizdą, konvertuotų jį į JPEG ir išsaugotų vietiniame buferyje pačioje kameroje.captureReady
skambutis tada patikrina, ar vaizdo fiksavimas baigtas.Kai fiksavimas baigtas, vaizdo duomenys kopijuojami iš buferio kameroje į vietinį buferį (baitų masyvą) naudojant
readImageToBuffer
skambutį. Buferio ilgis tada siunčiamas į serijinį monitorių. -
Sukurkite ir įkelkite šį kodą, ir patikrinkite išvestį serijiniame monitoriuje. Kiekvieną kartą paspaudus C mygtuką, bus užfiksuotas vaizdas, ir serijiniame monitoriuje bus matomas vaizdo dydis.
Connecting to WiFi.. Connected! Image captured Image read to buffer with length 9224 Image captured Image read to buffer with length 11272
Skirtingi vaizdai turės skirtingus dydžius. Jie suspausti kaip JPEG failai, o JPEG failo dydis tam tikrai raiškai priklauso nuo to, kas yra vaizde.
💁 Šį kodą galite rasti code-camera/wio-terminal aplanke.
😀 Jūs sėkmingai užfiksavote vaizdus su savo Wio Terminal.
Pasirinktinai - patikrinkite kameros vaizdus naudodami SD kortelę
Lengviausias būdas pamatyti vaizdus, kuriuos užfiksavo kamera, yra įrašyti juos į SD kortelę Wio Terminal ir tada peržiūrėti juos savo kompiuteryje. Atlikite šį žingsnį, jei turite atsarginę microSD kortelę ir microSD kortelės lizdą savo kompiuteryje arba adapterį.
Wio Terminal palaiko tik microSD korteles iki 16GB dydžio. Jei turite didesnę SD kortelę, ji neveiks.
Užduotis - patikrinkite kameros vaizdus naudodami SD kortelę
-
Formatuokite microSD kortelę kaip FAT32 arba exFAT naudodami atitinkamas programas savo kompiuteryje (Disk Utility macOS, File Explorer Windows arba komandinės eilutės įrankius Linux).
-
Įdėkite microSD kortelę į lizdą tiesiai po maitinimo jungikliu. Įsitikinkite, kad ji visiškai įdėta, kol spragtelės ir liks vietoje, gali tekti ją stumti nagais arba plonu įrankiu.
-
Pridėkite šiuos
include
teiginiusmain.cpp
failo viršuje:#include "SD/Seeed_SD.h" #include <Seeed_FS.h>
-
Pridėkite šią funkciją prieš
setup
funkciją:void setupSDCard() { while (!SD.begin(SDCARD_SS_PIN, SDCARD_SPI)) { Serial.println("SD Card Error"); } }
Tai konfigūruoja SD kortelę naudojant SPI magistralę.
-
Iškvieskite tai iš
setup
funkcijos:setupSDCard();
-
Pridėkite šį kodą virš
buttonPressed
funkcijos:int fileNum = 1; void saveToSDCard(byte *buffer, uint32_t length) { char buff[16]; sprintf(buff, "%d.jpg", fileNum); fileNum++; File outFile = SD.open(buff, FILE_WRITE ); outFile.write(buffer, length); outFile.close(); Serial.print("Image written to file "); Serial.println(buff); }
Tai apibrėžia globalų kintamąjį failų skaičiui. Jis naudojamas vaizdo failų pavadinimams, kad būtų galima užfiksuoti kelis vaizdus su didėjančiais failų pavadinimais -
1.jpg
,2.jpg
ir t. t.Tada apibrėžiama
saveToSDCard
funkcija, kuri priima baitų duomenų buferį ir buferio ilgį. Failo pavadinimas sukuriamas naudojant failų skaičių, o failų skaičius padidinamas, pasiruošiant kitam failui. Tada binariniai duomenys iš buferio įrašomi į failą. -
Iškvieskite
saveToSDCard
funkciją išbuttonPressed
funkcijos. Skambutis turėtų būti prieš buferio ištrynimą:Serial.print("Image read to buffer with length "); Serial.println(length); saveToSDCard(buffer, length); delete(buffer);
-
Sukurkite ir įkelkite šį kodą, ir patikrinkite išvestį serijiniame monitoriuje. Kiekvieną kartą paspaudus C mygtuką, bus užfiksuotas vaizdas ir išsaugotas SD kortelėje.
Connecting to WiFi.. Connected! Image captured Image read to buffer with length 16392 Image written to file 1.jpg Image captured Image read to buffer with length 14344 Image written to file 2.jpg
-
Išjunkite microSD kortelę ir išimkite ją, šiek tiek paspausdami ir atleisdami, ir ji iššoks. Gali tekti naudoti ploną įrankį, kad tai padarytumėte. Įdėkite microSD kortelę į savo kompiuterį, kad peržiūrėtumėte vaizdus.
💁 Gali prireikti kelių vaizdų, kol fotoaparato baltos spalvos balansas prisitaikys. Tai pastebėsite pagal užfiksuotų vaizdų spalvą, pirmieji keli gali atrodyti netinkamos spalvos. Visada galite tai apeiti pakeisdami kodą, kad užfiksuotumėte kelis vaizdus, kurie ignoruojami funkcijoje
setup
.
Atsakomybės apribojimas:
Šis dokumentas buvo išverstas naudojant AI vertimo paslaugą Co-op Translator. Nors siekiame tikslumo, prašome atkreipti dėmesį, kad automatiniai vertimai gali turėti klaidų ar netikslumų. Originalus dokumentas jo gimtąja kalba turėtų būti laikomas autoritetingu šaltiniu. Kritinei informacijai rekomenduojama profesionali žmogaus vertimo paslauga. Mes neprisiimame atsakomybės už nesusipratimus ar klaidingus interpretavimus, atsiradusius dėl šio vertimo naudojimo.