Elektronik Devreler Projeler Elektronik ve biraz daha fazlası İletişim - Araçlar - Dikkat - Topluluk
Elektronik / Mikrodenetleyici Projeleri/

STM32F4 DCMI & OV9655 Kamera Uygulaması

Sponsorlu Bağlantılar

Merhaba arkadaşlar. Daha önce çinden aldığım OV9655 kamera modülünü çalıştırayım dedim. Yaptığım uygulamada STM32F407′nin DCMI (Digital Camera Interface) modülünü kullandım. Bu uygulamamda DCMI modülü ile kameradan görüntüyü alıp DMA ve FSMC yardımıyla LCD’ye göndereceğiz.

stm32f4-discovery-ov9655-camera-test-final

OV9655 Kamera Modülü

WaveShare’nin aşağıdaki OV9655 kamera modülünü satın almıştım. Link: OV9655 Camera Board Fiyatı 15-20$ arasında değişiyor. Ebay veya Aliexpress gibi sitelerden satın alabilirsiniz.

Modülün üzerinde OV9655 Cmos Sensör bulunmakta. Max. çözünürlüğü 1.3 Megapixel. Bu çözünürlükte SXGA boyutunda yani 1280×1024 boyutlu bir görüntü elde edilebiliyor.

Kameranın desteklediği boyutlar aşağıdaki gibidir.

SXGA = 1280×1024
VGA = 640×480
QVGA = 320×240
QQVGA = 160×120
CIF = 40×30

Kameradan 4 farklı formatta pixel datası alınabilmektedir. Kameranın desteklediği formatları sırasıyla Raw RGB, RGB (GRB 4:2:2, RGB565/555), YUV (4:2:2) ve YCbCr (4:2:2)

Bizim kullandığımız LCD 320×240 çözünürlüğe sahip olduğu için bizde kamerayı QVGA çıkış verecek şekilde kullanıyoruz. Ayrıca Kamerayı RGB565 formatına ayarlamamız gerekiyor.

Kamera ilk enerjilendiğinde SCCB(Serial Camera Control Bus) üzerinden init edilmesi gerekiyor. SCCB bus dediğimiz şey ise Omnivision firmasının kameraları için geliştirdiği bir protokoldür. Fakat I2C protokolüyle çok benzerlik göstermektedir.(Aslında ben bir fark bulamadım. Bildiğin I2C ile haberleşiyor :D) Bu yüzden I2C protokolü kullanılarak kamera ile iletişim kurulabiliyor.

Ben denemelerimde nedense Hardware I2C ile kamerayı çalıştıramadım. Bu yüzden software I2C kütüphanesi kullandım. Açıkçası kamera I2C (yada SCCB) konusunda hata kabul etmiyor. Dikkat etmek lazım. Sırf kameraile iletişim kurabilmek için 1 haftaya yakın uğraştım

OV9655 Kamera modülü’nün üzerinde 2×10 Header bulunmakta. Kameranın bütün bağlantıları buradan yapılmaktadır. Modülün pin bağlantıları aşağıdaki gibidir.

    3.3V

    GND

    SIO_C(SCL)

    SIO_D(SDA)

    VSYNC

    HREF

    PXCLK

    XCLK

    Y9(D7)

    Y8(D6)

    Y7(D5)

    Y6(D4)

    Y5(D3)

    Y4(D2)

    Y3(D1)

    Y2(D0)

    Reset

    Power_Down

    NC

    NC

Kamera modülünün üzerinde Reset ve PowerDown pinleri bulunmakta. Bu pinler defaul olarak modülün üzerindeki jumper’lar ile default konumlarına ayarlanmışlar. Örneğin Kamera modülünün resetlenmesi için Reset pinin Lojik 0′a çekilmesi, Kameranın uyku moduna girmesi içinse PowerDown pininin lojik 1′e çekilmesi gerekiyor. Kameranın normal olarak çalışması için bu işlemlerin tam tersi yapılması gerekir. İşte kameranın bulunduğu PCB’nin üzerinde bu işi jumper’lar ile halletmişler.

Aşağıdaki resimde daha net anlaşılacaktır.

kamera-modul-board

Resimde gördüğünüz JP1, JP2, JP3 ve JP4 bu işe yarıyor. Eğer JP1 yerine JP2, JP3 Yerinede JP4 aktif olsaydı kamera modülündeki PowerDown ve Reset pini dışarıya kullanıcıya aktarılmış olur. Ben ilk başlarda kamerayı çalıştırmak için bu pinleri STM32F407′ye bağlayıp kameranın resetlenme işlemlerini kontrol etmiştim. Şuanda bu pinlerle oynamaya gerek yok.

Ayrıca PCB üzerinde SDA ve SCL hattı Pull-Up yapılmış durumda. Normalde hattın pull up yapılması gerekir. Ama modül üzerinde pull-up yapıldığı için bu işleme gerek kalmıyor.

Şimdi birazda yazılıma bakalım.

STM32F407 üzerinde Bu tip kameralar için DCMI modülü bulunmakta. STM32F407 içerisine gömülmüş olan bu modülün özellikleri kısaca şöyledir.

    8, 10, 12 ve 14 bit’e kadar paralel iletişim desteği

    Gömülü Senkronizasyon sistemi

    Sürekli ve Anlık kare alım seçenekleri

    Kırpma özelliği

    Çeşitli Veri formatları

        8/10/12/14 Bit Progresif Video

        YCbCr 4:2:2

        RGB 565

        JPEG

Normalde Kameradan data okumak hız gerektiren bir işlemdir. DCMI donanımının en büyük artısı herşeyi kendi kendine halletmesi. Bu uygulamamızda olduğu gibi DCMI, DMA ve FSMC kullanılarak neredeyse sıfır işlem gücü ile kameradan görüntü alınıp LCD de görüntülenebiliyor. (STM32 lerin en sevdiğim özelliği budur:) )

Unutmadan önemli bir noktaya daha değinmek istiyorum. Bu tip kameralar çalışmak için dışarıdan harici saat kaynağına ihtiyaç duyarlar. Bazı kamera modüllerinin üzerinde çalışması için gerekli saat kaynağı PCB üzerine eklenen bir kristal ile sağlanıyor. Bizim modülde öyle birşey eklememişler ve bu işi kullanıcıya bırakmışlar. Yani kameranın çalışması için XCLK Pininden biz clock uygulayacağız. Uygulayacağımız frekans kameranın FPS değerini değiştirdiği için böyle olması daha iyidir.

OV9655′in datasheetinden XCLK için min 10Mhz, Max 48Mhz yazıyor. İdeal frekans 24Mhz diyor. Bu yüzden bende 24Mhz clock uyguladım.

24Mhz Clock sağlamak için STM32F407 nin MCO(MicroController Clock Output) Donanımını kullandım. STM32F4 içerisinde bundan 2 adet var(MCO1, MCO2)

MCO1 donanımını HSI, LSI, HSE, ve PLLClock kaynaklarını kullanabilir. Bu noktaların hiçbirinden 24Mhz elde etmek mümkün olmuyor. MCO2 ise HSE, PLL, SysClk ve PLLI2S kaynaklarını kullanabiliyor.

MCO1 işimizi görmediği için MCO2 yi kullanacağız. Saat kaynağınıda PLLI2S olarak seçip PLLI2S ‘den istediğimiz frekansı sağlayacağız

Şimdi bizim PLLI2S çarpanından 48Mhz sinyal almamız gerekiyor. Bu sayede MCO bölücüleri ile oynayarak 48Mhz’ sinyali değiştirebiliriz.

Açıkçası STM32F4′ün Clock ayarlarından biraz bahsetmek istiyorum. Biraz kafa karıştırıcı olabiliyor.

STM32F4 içerisinde iki adet PLL ve birçok bölücü bulunmaktadır. Bu PLL lerden birtanesi işlemcinin sistem frekansını sağlıyor. Buna Main PLL diyorlar. Diğeri ise STM32F407 Discovery üzerinde bulunan Mikrofon ve Audio çipleri için sabit örnekleme frekansını oluşturmak amacıyla kullanılıyor. Bunada PLLI2S adını vermişler. Biz ise I2S için kullanılan PLL’yi OV9655 kameramızın sistem saatini sağlamak için kullanıyoruz.

İşlemci içerisinde bulunan PLL’lerin girişine 1-2 Mhz arası clock uygulanması gerekiyor. Discovery üzerinde STM32F407′ye 8Mhz kristal bağlı. İşlemcinin Saat kaynağını HSE olarak ayarlayınca sistem 8Mhz kristal üzerinden beslenir. PLL lere max 2Mhz girebiliyorduk. Bu yüzden bu sinyali PLL_M Bölücüsüyle bölmek gerekiyor. Biz PLL_M bölücüsünü 8 yaparak HSE frekansının 8 bölünmesini sağladık. Dolayısıyla PLL’lere 1Mhz clock uygulamış olduk. Artık PLL’ler çalışabilir. :)

İşlemcimizi biz 168Mhz de çalıştırıyoruz. Fakat PLL ile direk bu sinyali elde edemiyoruz çünkü PLL çarpan değeri 192 ile 432Mhz arası bir değer alıyor. 1Mhz giriş frekansından 168Mhz elde etmenin tek bir yolu var. Biz 1Mhz sinyali 336Mhz’e çıkartıp 2′ye bölersek 168Mhz elde etmiş oluruz. Bu yüzden PLL çarpan değerini yani PLL_N değerini 336 yapıyoruz. PLL artık 1Mhz clock sinyalini 336Mhz çıkardı. Şimdi Bu sinyali 2′ye bölerek yain PLL_P değerini 2 yaparak 168Mhz SysClk frekansını elde ederiz. İşlemcideki Bütün donanımlar(USB hariç) bu SysClk üzerinden beslenir. Ayrıca USB donanımının çalışması için gerekli olan 48Mhz sinyali PLL_Q bölücüsünü 7 yaparak sağlıyoruz. 336Mhz 7′ye bölünüp 48Mhz olarak USB birimine aktarılır.

Main PLL ayarları bu şekilde.

@Picproje’den Bülent Ünalmış hocamız bu konuyu çok güzel bir şekilde anlatmış. Kendisine Teşekkürler.

PLLI2S ayarları ise buna benzer. PLL çarpanı 192 ile 432 arası bir değer alıyordu. Bize ise PLL çıkışında 48Mhz lazım. Eğer PLL çarpanını (PLLI2S_N) 240, PLL bölücüsünüde (PLLI2S_R) 5 yaparsak 240/5 den 48Mhz elde edebiliriz.

Ben bu değerleri ayarlamak için ST’nin STM32F4xx Clock Configuration Tool programını kullanıyorum. Bayağı işe yaradığını söyleyebirim.

Yukarıdaki ayarların Clock Configuration Tool programında yapılmış hali resimdeki gibidir.

stm32f40xx-system-clock-configration-tool

Bundan sonra 24Mhz sinyali elde etmek için MCO Bölücüsünü 2 yapmamız yeterlidir. Bu sayede 48Mhz 2 ye bölünüp dışarıya aktarılır.

Clock Ayarları bundan ibaret.

Kamerayı çalıştırmak için Kamera ile Discovery arasında aşağıdaki bağlantıları yapmanız gerekiyor. Bu bağlantıları DCMI-OV9655 Bağlantılarıdır.

D0 = PC6

D1 = PC7

D2 = PE0

D3 = PE1

D4 = PE4

D5 = PB6

D6 = PE5

D7 = PE6

HSYNC = PA4

VSYNC = PB7

XCLK = PC9

PXCLK = PA6

SIO_C= PB8

SIO_D= PB9

Eğer Reset ve PowerDown pinlerinide kullanırsanız bu pinleride işlemciyle kontrol etmeniz gerekir.

Şuanda STM32F407 nin yazılımda yaptığı işlem DCMI dan görüntüyü alıp DMA ile FSMC’ye taşıyor. Kamera ve LCD 16 bit RGB565 Formatında olduğu için görüntü olduğu gibi LCD de çıkıyor. FSMC kullanıldığı için LCD yi FSMC pinlerine bağlamanız gerekiyor. FSMC LCD bağlantıları aşağıdaki gibidir.

LCD_D0 = PD14

LCD_D1 = PD15

LCD_D2 = PD0

LCD_D3 = PD1

LCD_D4 = PE7

LCD_D5 = PE8

LCD_D6 = PE9

LCD_D7 = PE10

LCD_D8 = PE11

LCD_D9 = PE12

LCD_D10 = PE13

LCD_D11 = PE14

LCD_D12 = PE15

LCD_D13 = PD8

LCD_D14 = PD9

LCD_D15 = PD10

LCD_CS = PD7

LCD_RS = PD11

LCD_RD = PD4

LCD_WR = PD5

Bundan sonraki işlem DMA’yı kullanarak DCMI – FSMC bağlantısını yapmak. Bunun için DMA ayarlarında Donanım adresinin DCMI modülünün Data register adresini, Memory adresini ise FSMC LCD Data adresini vermek gerekiyor.

STM32F407 için bu adresler aşağıdaki gibidir. Bu adresler kütüphane içerisinde tanımlanmıştır.

DCMI_DR_ADDRESS = 0×50050028
FSMC_LCD_ADDRESS = 0×60020000

Ben bu uygulamada SSD1289 çipsetli bir LCD kullandım. Normalde sistemin çalışması şöyledir. Kameraya start vermeden önce LCD ye 320 ye 240 pixel boyutunda bir pencere açarız. Sonra kameraya start veririz ve DCMI DMA ve FSMC görüntü datalarını alıp ekrana taşır. Bizde kameradaki görüntüyü LCD’de görürüz. Fakat bu SSD1289′a beyaz pixel geldiği zaman bazende olsa ekranı karışabiliyor. Yeni bir görüntü geldiğinde ekranın toparlanması için bende DCMI_Frame kesmesini aktif ettim. Dolayısıyla ekran tümüyle doldurulduğunda kesme oluşuyor. Bende gidip kesmede tekrar 320 ye 240 pixel boyutunda pencere açıyorum. Bu durumda Ekran counter’i sıfırlandığı için yeni görüntü geldiğinde ekran toparlanmış oluyor. İşlemci birtek bu işle uğraşıyor. LCD de donma veya beyaz pixel problemleri yoksa kesmeyede gerek yoktur. Zaten kesme olmasa 0 iş gücüyle görüntüyü LCD ye aktarmış oluruz :)

Aşağıda test videosunu görebilirsiniz.

Videodaki 15FPS de görüntü alınmaktadır. Açıkçası 15FPS de bile gayet iyi. 30FPS için XCLK frekansını 48Mhz çıkarmanız gerekir. Ben 30FPS yi de denedim. Kamera gerçekten hızlanıyor. Görüntü dahada akıcılaşıyor. Datasheet’te ideal XCLK frekansı 24Mhz dediği için bende 24Mhz & 15FPS de kullanıyorum. Videodan da anlaşılacağı üzere 15FPS gayet iyi.

Proje Dosyaları: stm32f4-dcmi-ov9655.rar alternatif link2

Kamera ile ilgili diyeceklerim bu kadar. İyi çalışmalar.

http://arectron.com/arm/stm32f4-dcmi-ov9655-kamera-uygulamasi.html

  • Çok kapsamlı ve güzel bir çalışma olmuş teşekkürler…

  • Ertuğrul Kılıç

    merhaba bununla video kaydı yapabilirmiyiz ve
    çektiğimiz videoyu nasıl depolarız.

  • MK

    çok güzel bir çalışma. SCCB için özelleşmiş bir pin var mı yoksa herhangi bir I2C üzerinden haberleşebiliyor muyuz? Birde bahsettiğiniz software ve hardware I2C nedir?