How To Read BMP data "Arducam Mini Module Camera Shield with OV2640 2 MP"

1.Which seller did you purchase the product(s) from?
Amazon
2.The Model number of the product(s) you have purchased?
Arducam Mini Module Camera Shield with OV2640 2 Megapixels
3.Which Platform are you using the product(s) on?
STM32F746G
4.Which instruction are you following?
https://github.com/ArduCAM/STM32
5.Has your product ever worked properly?
Never Worked
6.What problems are you experiencing?
I am just compiled the code in my STM32F746G platform and I can read and write to the I2C and SPI registers. Now I want to do a single Capture BMP transfer to buffer memory, but I don’t get the BMP data. Basically I have one simple question following the code in https://github.com/ArduCAM/STM32.

In the “main.c” after the case 0x30 that sets up the Arducmap ov2640 in BMP mode. if you look at the code all the way below where a single capture is selected. The function calls out:

StartBMPcapturer();

The definition of this is in “spi.c” the function definition StartBMPcapturer() everthing seems normal except where the VH (Video High) and VL (Video Low) values are read from the SPI register by the function:

VH = SPI2_ReadWriteByte(0x00);
VL = SPI2_ReadWriteByte(0x00);

The definition of the SPI2_ReadWriteByte(0x00) is in “spi.c” file and exactly which SPI register address is the Video address being read from? It can’t be 0x00,because this is defined as “Test Register” in the “2MP SPI Camera Hardware Application Note”.

Here is the “StartBMPcapturer()” code in “spi.c” below.

 

void StartBMPcapture(void)
{
flush_fifo();
clear_fifo_flag();
start_capture();
while(!get_bit(ARDUCHIP_TRIG , CAP_DONE_MASK)){;}
//printf(“ACK CMD capture done\r\n”);
length= read_fifo_length();
// printf(“ACK CMD the length is %d\r\n”,length);
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, 0xff);
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, 0xaa);
for(int temp = 0; temp < BMPIMAGEOFFSET; temp++)
{
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, pgm_read_byte(&bmp_header[temp]));

}
CS_LOW();
set_fifo_burst();
char VH, VL;
int i = 0, j = 0;
for (i = 0; i &lt; 240; i++)
{
    for (j = 0; j &lt; 320; j++)
    {
        VH = SPI2_ReadWriteByte(0x00);          
        VL = SPI2_ReadWriteByte(0x00);      
        while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
        USART_SendData(USART1, VL);
        delay_us(15);
        while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
        USART_SendData(USART1, VH);
        delay_us(15);
    }
}
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, 0xbb);
delay_us(12);
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, 0xcc);
CS_HIGH();

}

 

Thanks!
7.What attempts at troubleshooting have you already made?

8.How would you like us to help you?
Could you explain which SPI register I need to read the Video 16 bit RGB values from?

Hello,

In fact, 0x30 or 0x31 are just commands sent by the serial port to STM32. What you need to pay attention to is the specific operation corresponding to the command.
For example, the 0x31 command is to initialize the camera to BMP mode, the following lines of code are the key:
set_format(BMP);
ArduCAM_Init(sensor_model);
#if !defined(OV2640)
clear_bit(ARDUCHIP_TIM,VSYNC_MASK);
#endif
wrSensorReg16_8(0x3818,0x81);
wrSensorReg16_8(0x3621,0xa7);
printf(“ACK CMD SetToBMP \r\n”);
For reading bmp data, the register and read mode have been set in set_fifo_burst();, and then only need to read. When reading data, we only need to pay attention to the data received by MISO, so MOSI sending 0x00 or other values each time it is read has no effect on the read data.

Hi jyh,

Thank you for your response. I ended up putting the 0x31 code in case 0x3 ; I wanted to read 240 x 320 bitmap picture so I just used the case 3 to set the JPEG size to 352 x 288 which is the closest to 240 x 320. I don’t use the USART to transmit the data, I just want the picture in the buffer to display on the LCD screen. So all USART code is deleted. Secondly I use the HAL functions to read SPI and I2C registers. i.e. I used :

HAL_SPI_TransmitReceive (&hspi2, spiData1,spiData1, Length, 1); to burst read from SPI FIFO at 0x3C.

I created this function to burst read the image FIFO at 0x3C. By the way I am getting an image length of 153,608 bytes. I modified the SPI read burst function by this function:

byte * SPI2_ReadWriteByte_burst(uint8_t TxData, uint32_t Length); you can see the definition below. Now, I do see the data in the buffer looks like is coming from the camera sensor. I am still tying the buffer to the LCD display.

One other question I have is: If I don’t set the JPEG size, will I still see 240 x 320 bitmap image?

See sections of my code below.

:

case 3:
if(sensor_model== OV2640)
{
OV2640_set_JPEG_size(OV2640_352x288);
//printf(“ACK CMD switch to OV2640_352x288\r\n”);
}

set_format(BMP);
ArduCAM_Init(sensor_model);
#if !defined(OV2640)
clear_bit(ARDUCHIP_TIM,VSYNC_MASK);
#endif
wrSensorReg16_8(0x3818,0x81);
wrSensorReg16_8(0x3621,0xa7);
break;

 

if(Camera_WorkMode == 3)
{
if(start_shoot == 3)
{
start_shoot = 0;
Camera_WorkMode = 0;
StartBMPcapture();

Camera_WorkMode = 3;
NewCMD =0;
USART1_RecieveData = 3;
start_shoot = 3;
}
}

void StartBMPcapture(void)
{
byte *p;
uint16_t pntr = 0;
flush_fifo();
clear_fifo_flag();
start_capture();
while(!get_bit(ARDUCHIP_TRIG , CAP_DONE_MASK)){;}
length= read_fifo_length();
CS_LOW();

p = set_fifo_burst_ptr(length);
pntr = 0;
CS_HIGH();
char VH, VL;
int i = 0, j = 0;
for (i = 0; i < 240; i++)
{
for (j = 0; j < 320; j++)
{
VH = *(p + pntr++); //SPI2_ReadWriteByte(0x3c); changed this
VL = *(p + pntr++);// SPI2_ReadWriteByte(0x3c); I change this

mem_buff[i][j] = VL | (VH << 8);
length–;

length–;

if (length < 10)
CS_HIGH();

}
}

CS_HIGH();
}

:

:

byte * set_fifo_burst_ptr(uint32_t length)
{
static byte * ptr;
ptr = SPI2_ReadWriteByte_burst(BURST_FIFO_READ, length);
return ptr;
}

:

byte * SPI2_ReadWriteByte_burst(uint8_t TxData, uint32_t Length)
{
//uint8_t value;
static uint8_t spiData1[153608];

HAL_GPIO_WritePin(GPIOI, GPIO_PIN_3,GPIO_PIN_RESET);
spiData1[0]= TxData; //spiData[0][0] ;0x40;
HAL_SPI_TransmitReceive (&hspi2, spiData1,spiData1, Length, 1);

HAL_GPIO_WritePin(GPIOI, GPIO_PIN_3,GPIO_PIN_SET);

return spiData1;
}

Thanks,

Aynilian

Hi jyh,

Thank you for your response. Some corrections to my previous post: I ended up putting the code in CASE 0x31 code in CASE 0x2 ; I wanted to read a 240 x 320 bitmap picture, so I just used the CASE 2 to set the JPEG size to 240 x 320. I don’t use the USART to transmit the data, I just want the picture in the buffer to display on the LCD screen. So all USART code is deleted. Secondly I use the HAL functions to read SPI and I2C registers. i.e. I used :

HAL_SPI_TransmitReceive (&hspi2, spiData1,spiData1, Length, 1); to burst read from SPI FIFO at 0x3C.

I created this function to burst read the image FIFO at 0x3C. By the way, I am getting an image length of 153,608 bytes. I modified the SPI read burst function using the following function:

byte * SPI2_ReadWriteByte_burst(uint8_t TxData, uint32_t Length); you can see the definition below. After doing the burst SPI read, I do see the data in the buffer looks like is coming from the camera sensor. Now I am going to tie the buffer to the LCD display in the STM32F742G Discovery board using Embedded Wizard.

One other question is: I want a raw RGB bitmap picture. If I don’t set the JPEG size as in CASE 2, will I still see 240 x 320 bitmap image?

See snippets of my code below.

:

case 2:
if(sensor_model== OV2640)
{
OV2640_set_JPEG_size(OV2640_320x240);
set_format(BMP);
ArduCAM_Init(sensor_model);
#if !defined(OV2640)
clear_bit(ARDUCHIP_TIM,VSYNC_MASK);
#endif
wrSensorReg16_8(0x3818,0x81);
wrSensorReg16_8(0x3621,0xa7);
}

break;

:

 

if(Camera_WorkMode == 3)
{
if(start_shoot == 3)
{
start_shoot = 0;
Camera_WorkMode = 0;
StartBMPcapture();

Camera_WorkMode = 3;
NewCMD =0;
USART1_RecieveData = 3;
start_shoot = 3;
}
}

:

void StartBMPcapture(void)
{
byte *p;
uint16_t pntr = 0;
flush_fifo();
clear_fifo_flag();
start_capture();
while(!get_bit(ARDUCHIP_TRIG , CAP_DONE_MASK)){;}
length= read_fifo_length();
CS_LOW();

p = set_fifo_burst_ptr(length);
pntr = 0;
CS_HIGH();
char VH, VL;
int i = 0, j = 0;
for (i = 0; i < 240; i++)
{
for (j = 0; j < 320; j++)
{
VH = *(p + pntr++); //SPI2_ReadWriteByte(0x3c); changed this
VL = *(p + pntr++);// SPI2_ReadWriteByte(0x3c); I change this

mem_buff[i][j] = VL | (VH << 8);
length–;

length–;

if (length < 10)
CS_HIGH();

}
}

CS_HIGH();
}

:

 

byte * set_fifo_burst_ptr(uint32_t length)
{
static byte * ptr;
ptr = SPI2_ReadWriteByte_burst(BURST_FIFO_READ, length);
return ptr;
}

:

byte * SPI2_ReadWriteByte_burst(uint8_t TxData, uint32_t Length)
{
//uint8_t value;
static uint8_t spiData1[153608];

HAL_GPIO_WritePin(GPIOI, GPIO_PIN_3,GPIO_PIN_RESET);
spiData1[0]= TxData; //spiData[0][0] ;0x40;
HAL_SPI_TransmitReceive (&hspi2, spiData1,spiData1, Length, 1);

HAL_GPIO_WritePin(GPIOI, GPIO_PIN_3,GPIO_PIN_SET);

return spiData1;
}

Thanks,

Aynilian

Hi,

Because I am busy with other things, I did not read your code in detail, but you want to display the image taken by the camera on the LCD, you can refer to the example in this link:https://github.com/ArduCAM/Arduino/tree/master/ArduCAM/examples/Shield_V2