Toto je starší verze dokumentu!
Vytvořil: Martin Kráčala, 17.1.2015
Tento projekt se zabývá využitím CMOS kamerového modulu OV7670 firmy OmniVision s FIFO bufferem AL422 ve spojení s mikrokontroléry s architekturou ARM. Projekt byl realizován na platformě FRDM-KL25Z od firmy Freescale s mikroprocesorem ARM Cortex-M0+ ve vývojovém prostředí mbed. Obrazová data jsou KL25Z postupně vyčítána z FIFO bufferu a posílána sériovou komunikací do PC. V rámci tohoto projektu byla dále vytvořena aplikace v prostředí MATLAB, která umožňuje připojení k sériovému portu a zpracování přijímaných obrazových dat.
Projekt je založen na „ultra-low-cost“ vývojové desce FRDM-KL25Z firmy Freescale s mikroprocesorem ARM® Cortex™-M0+. Základní charakteristiky desky KL25Z jsou následující:
Použitou periferií pro snímání obrazu je modul kamery OV7670 firmy OmniVision s integrovaným FIFO bufferem AL422, konkrétně se jedná o verzi CF76700-V3. Tato kamera je vybavena CMOS senzorem schopným zaznamenávat snímky s rozlišením VGA (640×480, 0.3 Mpx) při obnovovací frekvenci až 30 fps společně s dalšími periferiemi zajišťujícími obrazové předzpracování a externí konektivitu. Kamera díky vnitřnímu zpracování obrazu podporuje VGA i CIF rozlišení a jejich podvzorkované varianty.
Výstupem senzoru je 8-bitová datová sběrnice přenášející následující obrazové formáty:
Kamera je taktována oscilátorem s frekvencí 24 MHz. Ovládá se prostřednictvím SCCB sběrnice. Jedná se o I2C rozhraní s maximální hodinovou frekvencí 400 kHz, v projektu je použito 100 kHz.
Celý firmware byl tvořen SDK mbed.org. Projekt se do značné míry inspiruje pracemi OV7670 Camera (by Martin Smith) a OV7670 Camera + mbed LPC1768 over USB od (by Edoardo De Marchi) včetně v obou případech použité knihovny ov7670. Kromě ní bylo využito ještě knihovny BufferedSerial, rozšiřující možnosti běžného Serial interface definovaného v knihovně mbed o softwarový TX a RX buffer.
Firmware pro KL25Z je k dispozici na stránkách mbed.org KL25Z_OV7670.
Na začátku výkonu programu je inicializováno sériové rozhraní spolu s modulem kamery OV7670.
BufferedSerial pc(USBTX, USBRX); // PTA2,PTA1 OV7670 camera ( PTC9,PTC8, // SDA,SCL(I2C) PTA13,NC,PTE2, // VSYNC,HREF,WEN(FIFO) PortB,0x00000F0F, // PortIn data PTB<0-3>,PTB<8-11> PTE3,PTE4,PTE5 // RRST,OE,RCLK );
Program využívá nejvyšší podporovanou přenosovou rychlost, baudrate 921600. Program záhy zapadne do nekonečné smyčky, ve které čeká na povely z PC skrze Serial-USB.
int main() { // set high baud rate pc.baud(BAUDRATE); // send hello message via Serial-USB pc.printf("Starting FRDM-KL25Z...\r\n"); // reset camera on power up camera.Reset() ; while (true) { // Look if things are in the Rx-buffer... if(pc.readable()) { int i = 0; // if so, load them into buffer_in while(pc.readable()) { buffer_in[i++] = pc.getc(); } // compare buffer_in with defined commands, execute cmd(); } ledG = LED_OFF; wait_ms(DELAY_MS); ledG = LED_ON; } }
// Parse command from buffer_in and execute function void cmd() { // Read all camera registers - commandline use only (for verification) if(strcmp("reg_status\r\n", buffer_in) == 0) { int i = 0; pc.printf("AD: +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F"); for (i=0; i<OV7670_REGMAX; i++) { int data; data = camera.ReadReg(i); if ((i & 0x0F) == 0) { pc.printf("\r\n%02X: ",i); } pc.printf("%02X ",data); } pc.printf("\r\n"); } // Take a picture else if(strcmp("snapshot\r\n", buffer_in) == 0) { ledR = LED_ON; // Kick things off by capturing an image camera.CaptureNext(); while(camera.CaptureDone() == false); // Start reading in the image data from the camera hardware buffer camera.ReadStart(); ledG = LED_OFF; for(int x = 0; x<resolution; x++) { // Read in the first half of the image if(colorscheme == RAW && resolution != VGA) { camera.ReadOnebyte(RMASK1,ROFFSET1,RMASK2,ROFFSET2); } else if(colorscheme == YUV || colorscheme == RGB) { pc.putc(camera.ReadOnebyte(RMASK1,ROFFSET1,RMASK2,ROFFSET2)); } // Read in the Second half of the image pc.putc(camera.ReadOnebyte(RMASK1,ROFFSET1,RMASK2,ROFFSET2)); // Y only } camera.ReadStop(); ledG = LED_ON; camera.CaptureNext(); while(camera.CaptureDone() == false); pc.printf("Snap_done\r\n"); ledR = LED_OFF; } // Set up commands... else if(strcmp("setup_RAW_VGA\r\n", buffer_in) == 0) { // VGA (640*480) RAW colorscheme = RAW; resolution = VGA; setup(colorscheme,resolution); } else if(strcmp("setup_YUV_QVGA\r\n", buffer_in) == 0) { // QVGA (320*240) YUV 4:2:2 colorscheme = YUV; resolution = QVGA; setup(RAW,resolution); } else { ... // more commands } memset(buffer_in, 0, sizeof(buffer_in)); }
// write to camera void OV7670::WriteReg(int addr,int data) { _i2c.start(); _i2c.write(OV7670_WRITE); wait_us(OV7670_WRITEWAIT); _i2c.write(addr); wait_us(OV7670_WRITEWAIT); _i2c.write(data); _i2c.stop(); } // read from camera int OV7670::ReadReg(int addr) { int data; _i2c.start(); _i2c.write(OV7670_WRITE); wait_us(OV7670_WRITEWAIT); _i2c.write(addr); _i2c.stop(); wait_us(OV7670_WRITEWAIT); _i2c.start(); _i2c.write(OV7670_READ); wait_us(OV7670_WRITEWAIT); data = _i2c.read(OV7670_NOACK); _i2c.stop(); return data; }
int OV7670::ReadOnebyte(int mask1, int offset1, int mask2, int offset2) { int B1; rclk = 1; B1 = (((data & mask1) >> offset1) | ((data & mask2) >> offset2)); rclk = 0; return B1; }
Pro řízení a přenos dat z kamery je využito sériové komunikace skrze USB port. Možností komunikace na straně PC je několik, např. využití běžných terminálových aplikací nebo návrh programu pro sériovou komunikaci a zpracování snímků. V rámci této úlohy bylo využito prostředí MATLAB, které obsahuje integrované nástroje pro sériovou komunikaci, zpracování dat a v neposlední řadě i vývoj aplikací (GUI).
Aplikace je dostupná ke stažení na MATLAB Central. Umožňuje připojení k sériovému portu počítače s pokročilými možnostmi nastavení komunikačního módu. Po připojení aplikace funguje podobně, jako jiné terminály pro sériovou komunikaci. Navíc však obsahuje sadu ovládacích prvků pro řízení kamery - nastavení formátu a zachycení jednotlivých snímků, které jsou následně zobrazeny. Aplikace umožňuje také získané snímky uložit do PC. V další části dokumentace jsou uvedeny příklady sejmutých snímků i video ukazující ovládání programu.
Na následujících snímcích je předvedena kvalita snímků při různých světelných podmínkách a různých formátech snímání. Pro praktické využití je největší překážkou obtížně nastavitelné zaostření, které je vysoce citlivé a lze jej hledat pouze metodou pokud-omyl. V případě snímání na stálou vzdálenost ale prokazuje kamera poměrně vysokou kvalitu snímků, dostatečnou pro širokou nabídku praktických uplatnění.
Následující video dokazuje funkčnost projektu. Je spuštěna aplikace v MATLABu, provedeno připojení k sériovému portu, zachycení a přenesení několika snímků s různým nastavením.
Zadání projektu bylo splněno v celém rozsahu. Ve vývojovém prostředí mbed byl vytvořen firmware pro desku FRDM-KL25Z umožňující komunikace s kamerou OV7670 s FIFO bufferem AL422 skrze sériovou komunikaci přes USB port. V PC byla vytvořena aplikace pro ovládání kamery a příjem snímků.
Dalšími možnostmi rozvoje projektu by byla implementace zbylých formátů, podporovaných kamerou OV7670 a zdokonalení programu v MATLAB. Přes na dnešní dobu nízké maximální rozlišení kamery mají snímky při správném nastavení vysokou kvalitu a kamera by tak byla použitelná například v automatizovaných robotech.
Odkazy ke stažení: * mbed * MATLAB