2023-01-15 11:20 AM
Hi all,
I am working on a university project to build a small IOT camera. I am using the 32F746GDISCOVERY board with the STM32F746NG MCU along with the ov2460 image sensor from WaveShare, and the B-CAMS-OMV board as an adaptor.
My code is based on an example for the STMF7508 Disco board, however, I have switched out the ov9655 BSP used in the example for the ov2460 BSP provided by STM.
Initially, I am attempting to display a continuous video feed on the LCD screen using the following data path:
Image Sensor → DCMI → DMA2 → Camera Frame buffer → DMA2 → LCD Frame buffer
I am able to communicate with the image sensor through I2C and successfully read the ID. When the image sensor is initialised, I am receiving frame event callbacks, however, no data is being written to the camera frame buffer. The DMA transfer between the camera frame buffer and the LCD frame buffer seems to be working fine.
I am pretty stumped as to why no data is being written to the camera Frame buffer and I have been working solidly on this problem over the last few weeks.
It looks like there is an issue with the DCMI DMA transfer. There could also be a problem in the configuration of the image sensor, however, this seems unlikely as I am receiving frame callbacks.
I was wondering if anyone had any experience with image sensors and STM32 MCUs and might be able to point me in the right direction.
I have attached my code below along with the CubeMX configurations I am using for DCMI and DMA2. The photo below shows a white screen on the LCD where the camera feed should be displayed as the camera frame buffer is memset to 255 upon initialisation.
Camera.c
#include "camera.h"
DMA2D_HandleTypeDef hdma2d_eval;
static TS_StateTypeDef TS_State;
uint32_t i, previous_mode = CONTINOUS_MODE;
uint32_t *ptrLcd;
uint8_t status = CAMERA_OK;
uint8_t *cam_fb;
uint32_t cam_fb_size;
void LCD_init(void) {
BSP_LCD_Init();
BSP_TS_Init(BSP_LCD_GetXSize(), BSP_LCD_GetYSize());
uint32_t *ptrLcd;
/* Init LCD screen buffer */
ptrLcd = (uint32_t*)(LCD_FRAME_BUFFER);
for (int i=0; i<(BSP_LCD_GetXSize()*BSP_LCD_GetYSize()); i++)
{
ptrLcd[i]=0;
}
BSP_LCD_LayerDefaultInit(LTDC_ACTIVE_LAYER, LCD_FRAME_BUFFER);
//BSP_LCD_LayerRgb565Init(LTDC_ACTIVE_LAYER, LCD_FRAME_BUFFER);
/* Set LCD Foreground Layer */
BSP_LCD_SelectLayer(LTDC_ACTIVE_LAYER);
BSP_LCD_SetFont(&LCD_DEFAULT_FONT);
/* Clear the LCD */
BSP_LCD_Clear(LCD_COLOR_BLACK);
BSP_LCD_SetTextColor(LCD_COLOR_BLUE);
BSP_LCD_FillRect(340, 80, 80, 30);
BSP_LCD_FillRect(340, 150, 80, 30);
BSP_LCD_DrawRect(8, 8, 322, 242);
BSP_LCD_DrawRect(9, 9, 321, 241);
BSP_LCD_SetFont(&Font12);
BSP_LCD_SetTextColor(LCD_COLOR_WHITE);
BSP_LCD_SetBackColor(LCD_COLOR_BLUE);
BSP_LCD_DisplayStringAt(345, 90, (uint8_t *)"CONTINUOUS", LEFT_MODE);
BSP_LCD_DisplayStringAt(345, 160, (uint8_t *)" SNAPSHOT", LEFT_MODE);
BSP_LCD_SetFont(&LCD_DEFAULT_FONT);
printf("done screen\n");
}
void I2C_CameraTest(void) {
uint16_t CameraID = 0;
printf("\nHello World\n");
//uint16_t ov5640_ReadID(uint16_t DeviceAddr)
//CameraID = ov5640_ReadID(CAMERA_I2C_ADDRESS);
CameraID = ov2640_ReadID(CAMERA_I2C_ADDRESS);
printf("\n%i\n", CameraID);
}
void cameraTestLoop(void) {
while(1) {
I2C_CameraTest();
HAL_Delay(500);
}
}
void initialiseCapture(void) {
status = BSP_CAMERA_Init(RESOLUTION_R320x240);
if(status != CAMERA_OK)
{
BSP_LCD_SetFont(&Font16);
BSP_LCD_SetTextColor(LCD_COLOR_WHITE);
BSP_LCD_FillRect(10, 10, 320, 240);
BSP_LCD_SetTextColor(LCD_COLOR_RED);
BSP_LCD_SetBackColor(LCD_COLOR_WHITE);
BSP_LCD_DisplayStringAt(20, 100, (uint8_t *)"CAMERA sensor is unpluged", LEFT_MODE);
BSP_LCD_DisplayStringAt(20, 120, (uint8_t *)"Plug the OV2640 sensor ", LEFT_MODE);
BSP_LCD_DisplayStringAt(20, 140, (uint8_t *)"on P1 camera connector ", LEFT_MODE);
BSP_LCD_DisplayStringAt(20, 160, (uint8_t *)"And restart the program ", LEFT_MODE);
}
else
{
// cam_fb_size = 320*240*2; // Resolution * color depth; RGB565=16bit=2byte
//
// cam_fb = (uint8_t *) malloc(cam_fb_size);
memset(CAMERA_FRAME_BUFFER, 255, cam_fb_size);
BSP_CAMERA_Init(RESOLUTION_R320x240);
BSP_CAMERA_ContinuousStart((uint8_t *)CAMERA_FRAME_BUFFER);
}
}
void BSP_CAMERA_LineEventCallback(void)
{
static uint32_t tmp, tmp2, counter;
if(240 > counter)
{
LCD_LL_ConvertLineToARGB8888((uint32_t *)(CAMERA_FRAME_BUFFER + tmp), (uint32_t *)(LCD_FRAME_BUFFER + 0x4B28 + tmp2));
tmp = tmp + 320*sizeof(uint16_t);
tmp2 = tmp2 + (480) * sizeof(uint32_t);
counter++;
}
else
{
tmp = 0;
tmp2 = 0;
counter = 0;
}
}
/**
* @brief Converts a line to an ARGB8888 pixel format.
* @param pSrc Pointer to source buffer
* @param pDst Output color
* @param xSize Buffer width
* @param ColorMode Input color mode
* @retval None
*/
//void BSP_CAMERA_FrameEventCallback(void) {}
void LCD_LL_ConvertLineToARGB8888(void *pSrc, void *pDst)
{
/* Enable DMA2D clock */
//__HAL_RCC_DMA2D_CLK_ENABLE();
/* Configure the DMA2D Mode, Color Mode and output offset */
hdma2d_eval.Init.Mode = DMA2D_M2M_PFC;
hdma2d_eval.Init.ColorMode = DMA2D_OUTPUT_ARGB8888;
//hdma2d_eval.Init.ColorMode = DMA2D_OUTPUT_RGB565;
hdma2d_eval.Init.OutputOffset = 0;
/* Foreground Configuration */
hdma2d_eval.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;
hdma2d_eval.LayerCfg[1].InputAlpha = 0xFF;
hdma2d_eval.LayerCfg[1].InputColorMode = DMA2D_INPUT_RGB565;
hdma2d_eval.LayerCfg[1].InputOffset = 0;
hdma2d_eval.Instance = DMA2D;
/* DMA2D Initialization */
if(HAL_DMA2D_Init(&hdma2d_eval) == HAL_OK)
{
if(HAL_DMA2D_ConfigLayer(&hdma2d_eval, 1) == HAL_OK)
{
if (HAL_DMA2D_Start(&hdma2d_eval, (uint32_t)pSrc, (uint32_t)pDst, 320, 1) == HAL_OK)
{
/* Polling For DMA transfer */
// printf("polling for DMA transfer!");
HAL_DMA2D_PollForTransfer(&hdma2d_eval, 10);
}
}
}
else
{
/* FatFs Initialization Error */
printf("/nFatFs Initialization Error/n");
while(1);
}
}
Camera.h
#ifndef INC_CAMERA_H_
#define INC_CAMERA_H_
#include "stm32f7xx_hal.h"
#include "stm32746g_discovery.h"
#include "stm32746g_discovery_sdram.h"
#include "stm32746g_discovery_camera.h"
#include "stdio.h"
#include "stdlib.h"
#include "LCD.h"
#include "string.h"
//#include "ov5460.h"
//#include "../../Drivers/BSP/Components/ov5640/ov5640.h"
//#include "../Drivers/BSP/Components/ov9665/ov9665.h"
#define CAMERA_FRAME_BUFFER 0xC0260000
//#define CAMERA_FRAME_BUFFER 0x60000000
#define LCD_FRAME_BUFFER 0xC0130000
//#define CAMERA_I2C_ADDRESS (uint16_t)0x60
void I2C_CameraTest(void);
//void cameraTestLoop(void);
void statusTest(void);
void initialiseCapture(void);
//void DCMI_GetCaptureMode(void);
//void runCamera(void);
void BSP_CAMERA_LineEventCallback(void);
void LCD_LL_ConvertLineToARGB8888(void *pSrc, void *pDst);
#endif /* INC_CAMERA_H_ */
Thank you,
Solved! Go to Solution.
2023-01-16 05:23 AM
Hello @SolH and welcome to the Community 🙂,
I checked the OV2640 datasheet camera and I found that the vertical synchronization polarity should be Active High. And you have configured the vertical synchronization polarity at active low.
Could you please change this configuration and let me know if the issue is solved.
For more details, I advise you to refer the AN5020 and precisely Hardware (or external) synchronization section.
Also, I recommend you to take a look at DCMI examples based on STM32CubeMX shared in AN5020 application note.
Thank you.
Kaouthar.
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2023-01-16 05:23 AM
Hello @SolH and welcome to the Community 🙂,
I checked the OV2640 datasheet camera and I found that the vertical synchronization polarity should be Active High. And you have configured the vertical synchronization polarity at active low.
Could you please change this configuration and let me know if the issue is solved.
For more details, I advise you to refer the AN5020 and precisely Hardware (or external) synchronization section.
Also, I recommend you to take a look at DCMI examples based on STM32CubeMX shared in AN5020 application note.
Thank you.
Kaouthar.
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.