Individální projekty MPOA

Mikroprocesory s architekturou ARM

Uživatelské nástroje

Nástroje pro tento web


2015:cam-al422

Toto je starší verze dokumentu!


Kamera OV7670 s FIFO AL422

Vytvořil: Martin Kráčala, 17.1.2015

Zadání

  • Připojte modul kamery OV7670 s FIFO bufferem AL422 ke vhodnému Freedom boardu.
  • Vytvořte firmware pro sejmutí snímku z kamery, vyřešte jeho přenos do PC a následné zobrazení.
  • Využijte prostředí KDS nebo mbed.

Úvod

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.

Hardware

Vývojová deska FRDM-KL25Z

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í:

  • Jádro ARM® Cortex™-M0+: 48MHz, 16KB RAM, 128KB FLASH,
  • USB (Host/Device), USB sériový port,
  • rozhraní SPI, I2C, UART,
  • dotykový senzor,
  • MMA8451Q - 3-osý akcelerometr,
  • RGB led,
  • GPIO a další I/O rozhraní.

Obr. 1:  Pin mapa FRDM-KL25Z

Kamera OV7670 s FIFO AL422

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.

Obr. 2:  Fotografie kamery OV7670 s FIFO AL422 Obr. 3:  Fotografie zadní strany kamery OV7670 s FIFO AL422 |Obr. 4:  Layout kamery CF7670C-V3

Výstupem senzoru je 8-bitová datová sběrnice přenášející následující obrazové formáty:

  • YUV/YCbCr 4:2:2
  • RGB565/555/444
  • GRB 4:2:2
  • Raw RGB

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.

Zapojení

 Obr. 5:  Zapojení přípravku

Firmware

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.

Odkaz k programu na mbed.org

Firmware pro KL25Z je k dispozici na stránkách mbed.org KL25Z_OV7670.

Hlavní části main.cpp

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));
}

Některé základní funkce knihovny OV7670

// 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;
}

Ukázky pořízených snímků

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í.

Indoor

 Snímek 1:  "Selfie" formát RAW Bayer to RGB (640x480)  Snímek 2:  "Flora" formát RAW Bayer to RGB (640x480)  Snímek 3:  "Flora" formát RGB 565 (320x240)  Snímek 4:  "Flora" formát YUV 4:2:2 (320x240)

Outdoor

 Snímek 5:  "Proti západu slunce" formát RAW Bayer to RGB (640x480)  Snímek 6:  "Zahrady" formát RAW Bayer to RGB (640x480)  Snímek 7:  "Zahrady" formát RGB 565 (320x240)  Snímek 8:  "Zahrady" formát YUV 4:2:2 (320x240)

Video ukázka

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.

Závěr

2015/cam-al422.1453071613.txt.gz · Poslední úprava: 2016/01/18 00:00 autor: Martin Kráčala