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.
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.
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.
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.
Kamera ile ilgili diyeceklerim bu kadar. İyi çalışmalar.
Şifre-Pass: 320volt.com
Yayım tarihi: 2014/07/28 Etiketler: arm projeleri, ov9655, stm32, stm32f4 dcmi
Çok kapsamlı ve güzel bir çalışma olmuş teşekkürler…
merhaba bununla video kaydı yapabilirmiyiz ve
çektiğimiz videoyu nasıl depolarız.
ç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?