ArduCAM / Arduino

This is ArduCAM library for Arduino boards
MIT License
479 stars 351 forks source link

I am trying to collect RGB565 pixel data from the OV5642, but there is no clear wayto do it. #510

Closed TylerW-Robotics closed 3 years ago

TylerW-Robotics commented 3 years ago

I am only trying to try a photo and then collect the RGB565 data from it. I've been through the examples in this Github and I can only get a broken photo of a test photo, and I am not even try to load the test pattern. Here is my code. (I'm using an ESP8266) //----------------------------------------------------------

include

include

include

include

include "memorysaver.h"

define CS_Cam D0

define BMPIMAGEOFFSET 66

const unsigned int bmp_header[BMPIMAGEOFFSET] PROGMEM = { 0x42, 0x4D, 0x36, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x58, 0x02, 0x00, 0xC4, 0x0E, 0x00, 0x00, 0xC4, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00 };

ArduCAM myCAM(OV5642, CS_Cam);

bool is_header = false;

//Important Arrays uint8 VH[320]; uint8 VL[320]; char buf[4]; // Used for converting int into char array // //Functions void take_photo(); void arduCam_setup(); void print_values(); void collect_values(); uint8_t read_fifo_burst(ArduCAM myCAM); //--

void setup() {

Wire.begin();

Serial.begin(115200); pinMode(CS_Cam, OUTPUT);

Serial.println("Here"); delay(100);

arduCam_setup();

take_photo();

Serial.print("\nDone\n"); }

void loop() {

}

void arduCam_setup(){ uint8_t vid, pid; uint8_t temp;

Serial.println(F("ArduCAM Start!"));

SPI.begin();

myCAM.write_reg(0x07, 0x80); // RESET the CPLD delay(100); myCAM.write_reg(0x07, 0x00); delay(100); //--

while(1){ //Check if the ArduCAM SPI bus is OK myCAM.write_reg(ARDUCHIP_TEST1, 0x55); temp = myCAM.read_reg(ARDUCHIP_TEST1); if (temp != 0x55) { Serial.println(F("SPI interface Error!")); delay(1000); continue;
} else{ Serial.println(F("SPI interface OK"));break; }
}

while(1){ //Check if the camera module type is OV5642 myCAM.rdSensorReg16_8(OV5642_CHIPID_HIGH, &vid); myCAM.rdSensorReg16_8(OV5642_CHIPID_LOW, &pid); if ((vid != 0x56) || (pid != 0x42)){ Serial.println(F("Can't find OV5642 module!")); delay(1000);continue; } else{ Serial.println(F("OV5642 detected."));break;
} }

//Change to JPEG capture mode and initialize the OV5642 module myCAM.set_format(JPEG); myCAM.InitCAM();

myCAM.write_reg(ARDUCHIP_TIM, VSYNC_LEVEL_MASK); //VSYNC is active HIGH myCAM.OV5642_set_JPEG_size(OV5642_320x240); myCAM.clear_fifo_flag();

delay(500); }

void take_photo(){

//myCAM.flush_fifo(); myCAM.clear_fifo_flag(); //Start capture myCAM.start_capture(); delay(100);

if (myCAM.get_bit(ARDUCHIP_TRIG, CAP_DONE_MASK)){ Serial.println(F("ACK CMD CAM Capture Done. END")); delay(50); read_fifo_burst(myCAM); //Clear the capture done flag myCAM.clear_fifo_flag(); } collect_values();

myCAM.clear_fifo_flag();

}

void print_values(){ uint16 num; for (int count = 0; count < 320; count++){

//VH_[count]; = R4, R3, R2, R1, R0, G5, G4, G3
//VL_[count]; = G2, G1, G0, B4, B3, B2, B1, B0 
num = (VH_[count] << 8) | (VL_[count] & 0xff);
Serial.print(num);
if (count == 319) {
  Serial.println();
}
else {
  Serial.print(",");
}

} delay(50); }

uint8_t read_fifo_burst(ArduCAM myCAM){ uint8_t temp = 0, temp_last = 0; uint32_t length = 0; length = myCAM.read_fifo_length(); Serial.println(length, DEC); if (length >= MAX_FIFO_SIZE){ //512 kb Serial.println(F("ACK CMD Over size. END")); return 0; } if (length == 0 ){ //0 kb Serial.println(F("ACK CMD Size is 0. END")); return 0; } myCAM.CS_LOW(); myCAM.set_fifo_burst();//Set fifo burst mode temp = SPI.transfer(0x00); length --; while ( length-- ){ temp_last = temp; temp = SPI.transfer(0x00); if (is_header == true){ Serial.write(temp); } else if ((temp == 0xD8) & (temp_last == 0xFF)){ is_header = true; Serial.println(F("ACK IMG END")); Serial.write(temp_last); Serial.write(temp); } if ( (temp == 0xD9) && (temp_last == 0xFF) ) //If find the end ,break while, break; delayMicroseconds(15); } myCAM.CS_HIGH(); is_header = false; return 1; }

void collect_values() { uint8_t VH,VL;

for (int i = 0; i < 240; i++){ for (int j = 0; j < 320; j++){ VH = myCAM.read_fifo(); VL = myCAM.read_fifo();

  VH_[j] = VH;
  VL_[j] = VL;

}
print_values();

} } //--------------------------------------------------------------

I've been at this for 2 weeks and I need help. I can't, for some reason, use my SD card reader so I need to use the serial monitor to put it into a CSV file and then I use a python file I made to create a PNG of it. I'll also post the photo for reference. Please help me. I feel like this is a simple request, but I can't seem to figure it out.

result

TylerW-Robotics commented 3 years ago

Now I am farther from the answer then I was before. I am just trying to take a snapshot from the OV5642 camera and now the data I get comes out like this result

I just want o take a snapshot and put it into a CSV. I'll looked at playback ino codes in your Github and I'm not finding good results. Our team don't want to invest more time and money into a different product. My new code is below.

#include <Arduino.h>
#include <Wire.h>
#include <ArduCAM.h>
#include <SPI.h>
#include "memorysaver.h"

#define CS_Cam D0     

#define BMPIMAGEOFFSET 66
const unsigned int bmp_header[BMPIMAGEOFFSET] PROGMEM =
{
  0x42, 0x4D, 0x36, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x28, 0x00,
  0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x03, 0x00,
  0x00, 0x00, 0x00, 0x58, 0x02, 0x00, 0xC4, 0x0E, 0x00, 0x00, 0xC4, 0x0E, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x00, 0x1F, 0x00,
  0x00, 0x00
};

ArduCAM myCAM(OV5642, CS_Cam);

bool is_header = false;

//Important Arrays
uint8 VH_[320];
uint8 VL_[320];
char buf[4]; // Used for converting int into char array 
//
//Functions
void take_photo();
void arduCam_setup();
void print_values();
void collect_values();
uint8_t read_fifo_burst(ArduCAM myCAM);
//--

void setup() {

  Wire.begin();

  Serial.begin(115200);
  pinMode(CS_Cam, OUTPUT);
  digitalWrite(CS_Cam, 0);
  Serial.println("Here");
  delay(100);

  arduCam_setup();

  take_photo();

  Serial.print("\nDone\n");
}

void loop() {

}

void arduCam_setup(){
  uint8_t vid, pid;
  uint8_t temp;

  Serial.println(F("ArduCAM Start!"));

  SPI.begin();

  myCAM.write_reg(0x07, 0x80);  // RESET the CPLD
  delay(100);
  myCAM.write_reg(0x07, 0x00);
  delay(100);                   //--

  while(1){
    //Check if the ArduCAM SPI bus is OK
    myCAM.write_reg(ARDUCHIP_TEST1, 0x55);
    temp = myCAM.read_reg(ARDUCHIP_TEST1);
    if (temp != 0x55)
    {
      Serial.println(F("SPI interface Error!"));
      delay(1000); continue;    
    } else{
      Serial.println(F("SPI interface OK"));break;
    }     
  }

  while(1){
    //Check if the camera module type is OV5642
    myCAM.rdSensorReg16_8(OV5642_CHIPID_HIGH, &vid);
    myCAM.rdSensorReg16_8(OV5642_CHIPID_LOW, &pid);
    if ((vid != 0x56) || (pid != 0x42)){
      Serial.println(F("Can't find OV5642 module!"));
      delay(1000);continue; 
    } else{
      Serial.println(F("OV5642 detected."));break;    
    }
  } 

  //Change to JPEG capture mode and initialize the OV5642 module
  myCAM.set_format(MCU2LCD_MODE);
  myCAM.InitCAM();

  myCAM.write_reg(ARDUCHIP_TIM, VSYNC_LEVEL_MASK);   //VSYNC is active HIGH
  myCAM.OV5642_set_JPEG_size(OV5642_320x240);
  myCAM.clear_fifo_flag();

  delay(500);
}

void take_photo(){  

  myCAM.set_mode(MCU2LCD_MODE);     //Switch to MCU, freeze the screen

  myCAM.flush_fifo();

  myCAM.start_capture();

  //Polling the capture done flag
  while (!myCAM.get_bit(ARDUCHIP_TRIG, CAP_DONE_MASK));

  delay(100);

/*  if (myCAM.get_bit(ARDUCHIP_TRIG, CAP_DONE_MASK)){
    Serial.println(F("ACK CMD CAM Capture Done. END"));
    delay(50);
    read_fifo_burst(myCAM);
    //Clear the capture done flag
    myCAM.clear_fifo_flag();
  }*/
  //myCAM.CS_LOW();
  //myCAM.set_fifo_burst();

  delay(100);
  myCAM.read_fifo();
  collect_values();

  myCAM.clear_fifo_flag();

}

void print_values(){
  uint16 num;
  for (int count = 0; count < 320; count++){

    //VH_[count]; = R4, R3, R2, R1, R0, G5, G4, G3
    //VL_[count]; = G2, G1, G0, B4, B3, B2, B1, B0 
    num = (VH_[count] << 8) | (VL_[count] & 0xff);
    Serial.print(num);
    if (count == 319) {
      Serial.println();
    }
    else {
      Serial.print(",");
    }
  }
    delay(10);
}

//uint8_t read_fifo_burst(ArduCAM myCAM){
//  uint8_t temp = 0, temp_last = 0;
//  uint32_t length = 0;
//  length = myCAM.read_fifo_length();
//  Serial.println(length, DEC);
//  if (length >= MAX_FIFO_SIZE){ //512 kb
//    Serial.println(F("ACK CMD Over size. END"));
//    return 0;
//  }
//  if (length == 0 ){ //0 kb
//    Serial.println(F("ACK CMD Size is 0. END"));
//    return 0;
//  }
//  myCAM.CS_LOW();
//  myCAM.set_fifo_burst();//Set fifo burst mode
//  temp =  SPI.transfer(0x00);
//  length --;
//  while ( length-- ){
//    temp_last = temp;
//    temp =  SPI.transfer(0x00);
//    if (is_header == true){
//      Serial.write(temp);
//    }
//    else if ((temp == 0xD8) & (temp_last == 0xFF)){
//      is_header = true;
//      Serial.println(F("ACK IMG END"));
//      Serial.write(temp_last);
//      Serial.write(temp);
//    }
//    if ( (temp == 0xD9) && (temp_last == 0xFF) ) //If find the end ,break while,
//    break;
//    delayMicroseconds(15);
//  }
//  myCAM.CS_HIGH();
//  is_header = false;
//  return 1;
//}

void collect_values() {
  uint8_t VH,VL;

  for (int i = 0; i < 240; i++){
    for (int j = 0; j < 320; j++){
      VH = myCAM.read_fifo();
      delayMicroseconds(12);
      VL = myCAM.read_fifo();
      delayMicroseconds(12);
      VH_[j] = VH;
      VL_[j] = VL;

    }
    print_values();
  }
}
BillyBee123 commented 3 years ago

If you're trying to extract RGB from image pixels, it's much easier to work with bitmap rather than jpeg. I did this a couple of years ago with a 2MP ArduCAM and NodeMCU ESP8266.

The complication with jpeg is that the images stored in the buffer are compressed, and vary in size. This makes jpeg images faster to transfer, and smaller for storage. However, if you want to know the RGB of pixel[87,119], for example, you'll need additional code to first uncompress that pixel location.

It looks like your code to collect and print values is exceeding the size of the jpeg image stored in the buffer, resulting in bad images. After the image capture, add one line as follows:

while (!myCAM.get_bit(ARDUCHIP_TRIG, CAP_DONE_MASK));

size_t len = myCAM.read_fifo_length(); //read camera FIFO length

Your loops to collect and print values should then iterate to 'len', and not 320x240.

TylerW-Robotics commented 3 years ago

I am sorry if I seem un-experienced in my coding, but my intent is to create a bitmap. Am I using the wrong commands in the code for asking for a bitmap?

BillyBee123 commented 3 years ago

It looks like your code was intended to be used with an LCD display, which might be adding to your problems. There's a relevant discussion, with links to OV5642 only demonstration code, in the ArduCAM forum:
https://www.arducam.com/forums/topic/bmp-mode-problems/

In your setup function, set the image format to bitmap with the following:

myCAM.set_format(BMP);

myCAM.InitCAM();

and delete myCAM.OV5642_set_JPEG_size(OV5642_320x240). The bitmap resolution is set in the bitmap header byte array at the beginning of your code.

In your print_values() function, you need to first print the contents of the header, followed by the pixel values. You can find this in the demonstration code links at the bottom of that forum discussion.

TylerW-Robotics commented 3 years ago

I followed your istructions and even used the test code that was mentioned in the referenced forms and I think we have some progress. The image I received from both my new code and from "ArduCAM_Mini_5MP_Plus_Video_Streaming.ino" are nearly the exact some, the problem is that they both show a black screen with little gray pixels. I did check and the screen cap is on and the jpeg mode on the host app is working perfectly. This is great progress, but I don't know why the code provided for ArduCam isn't working in bitmap mode. image

TylerW-Robotics commented 3 years ago

Same result from the Host App V2 I'll post new code below, but I am really starting to feel the my camera has a problem if the ArduCam code isn't working. Code for Arduino:

`#include

include

include

include

include "memorysaver.h"

define CS_Cam 7

define BMPIMAGEOFFSET 66

const unsigned int bmp_header[BMPIMAGEOFFSET] PROGMEM = { 0x42, 0x4D, 0x36, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x58, 0x02, 0x00, 0xC4, 0x0E, 0x00, 0x00, 0xC4, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00 };

ArduCAM myCAM(OV5642, CS_Cam);

bool is_header = false;

//Important Arrays uint8t VH[320]; uint8t VL[320]; // //Functions void take_photo(); void arduCam_setup(); void print_values();

//--

void setup() {

Wire.begin();

Serial.begin(115200); pinMode(CS_Cam, OUTPUT); digitalWrite(CS_Cam, 0); Serial.println("Here"); delay(100);

arduCam_setup();

take_photo();

Serial.print("\nDone\n"); }

void loop() {

}

void arduCam_setup(){ uint8_t vid, pid; uint8_t temp;

Serial.println(F("ArduCAM Start!"));

SPI.begin();

myCAM.write_reg(0x07, 0x80); // RESET the CPLD delay(100); myCAM.write_reg(0x07, 0x00); delay(100); //--

while(1){ //Check if the ArduCAM SPI bus is OK myCAM.write_reg(ARDUCHIP_TEST1, 0x55); temp = myCAM.read_reg(ARDUCHIP_TEST1); if (temp != 0x55) { Serial.println(F("SPI interface Error!")); delay(1000); continue;
} else{ Serial.println(F("SPI interface OK"));break; }
}

while(1){ //Check if the camera module type is OV5642 myCAM.rdSensorReg16_8(OV5642_CHIPID_HIGH, &vid); myCAM.rdSensorReg16_8(OV5642_CHIPID_LOW, &pid); if ((vid != 0x56) || (pid != 0x42)){ Serial.println(F("Can't find OV5642 module!")); delay(1000);continue; } else{ Serial.println(F("OV5642 detected."));break;
} }

//Change to JPEG capture mode and initialize the OV5642 module myCAM.set_format(BMP);

myCAM.InitCAM();

myCAM.clear_bit(ARDUCHIP_TIM, VSYNC_LEVEL_MASK); myCAM.wrSensorReg16_8(0x3818, 0x81); myCAM.wrSensorReg16_8(0x3621, 0xA7);

delay(500); }

void take_photo(){

myCAM.flush_fifo(); myCAM.clear_fifo_flag();

myCAM.start_capture();

//Polling the capture done flag while (!myCAM.get_bit(ARDUCHIP_TRIG, CAP_DONE_MASK));

uint32_t length = 0; length = myCAM.read_fifo_length(); if (length >= MAX_FIFO_SIZE ) { Serial.println(F("ACK CMD Over size. END")); myCAM.clear_fifo_flag(); return; } if (length == 0 ) //0 kb { Serial.println(F("ACK CMD Size is 0. END")); myCAM.clear_fifo_flag(); return; } myCAM.CS_LOW(); myCAM.set_fifo_burst();//Set fifo burst mode

delay(100); for (int temp = 0; temp < BMPIMAGEOFFSET; temp++) { Serial.write(pgm_read_byte(&bmp_header[temp])); } Serial.println(); uint8_t VH,VL;

myCAM.read_fifo();

for (int i = 0; i < 240; i++){ for (int j = 0; j < 320; j++){ VH = myCAM.read_fifo(); VL = myCAM.readfifo(); VH[j] = VH; VL_[j] = VL;

}
print_values();

} myCAM.CS_HIGH(); myCAM.clear_fifo_flag();

}

void print_values(){ uint16_t num; for (int count = 0; count < 320; count++){

//VH_[count]; = R4, R3, R2, R1, R0, G5, G4, G3
//VL_[count]; = G2, G1, G0, B4, B3, B2, B1, B0 
num = (VH_[count] << 8) | (VL_[count] & 0xff);
Serial.print(num);
if (count == 319) {
  Serial.println();
}
else {
  Serial.print(", ");
}

} delay(10); } `

Python Photo Code: https://stackoverflow.com/questions/52027382/how-do-i-convert-a-csv-file-16bit-high-color-to-image-in-python

BillyBee123 commented 3 years ago

You need to change the baud rate in the Host App to 115200 to match what you're using for serial

Serial.begin(115200);

Does it work now?

TylerW-Robotics commented 3 years ago

It doesn't seem to make a difference. I'm sorry. I'm not sure why the BMP mode is having problems

BillyBee123 commented 3 years ago

I'd focus on getting the example ArduCAM_Mini_5MP_Plus_Video_Streaming.ino working first, and then modify it for your own code.

Now I remember there are some subtle modifications to be made for ESP8266. In that demo code above, uncomment SPI.transfer(0x00) on line 355. Then add a couple of yields in the loops below as follows:

VH = SPI.transfer(0x00);; yield(); VL = SPI.transfer(0x00);; yield();