Distorted Image when saving to SD Card

Hi, good day folks. I have a problem regarding my on going project. I have an Arduino Mega2560, CC3000 Wifi Shield, an Arducam Mini wiht OV2640,a sensor. Now, heres what I’m trying to do. First, when a sensor detects something it would trigger the capturing of the image then it will do two possible options:

  1. Save to SD Card then send the image to a remote Server(PC) via the Wireless Network and save it to a MySQL database
    or
  2. It will directly save the image to the database of the Server.

Which one is more efficient to use?

and

While trying option number one, I have successfully captured and saved the image to the SD card attached to the Wifi Shield but I’m getting a distorted image like the one attached below.

#include <Adafruit_CC3000.h>
#include <ccspi.h>
#include <SPI.h>
#include <string.h>
#include "utility/debug.h"
#include "RTClib.h"
#include <SD.h>
#include <Wire.h>
#include <Thread.h>
#include <ArduCAM.h>
#include "memorysaver.h"

#define ADAFRUIT_CC3000_IRQ   3 
#define ADAFRUIT_CC3000_VBAT  5
#define ADAFRUIT_CC3000_CS    10
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,
                                         SPI_CLOCK_DIVIDER);

#define WLAN_SSID       ""          
#define WLAN_PASS       ""
#define WLAN_SECURITY   WLAN_SEC_WPA2

#define IDLE_TIMEOUT_MS  3000
#define WEBSITE      "192.168.10.100"
#define WEBPAGE      ""


#define SD_CS 4
#define BMPIMAGEOFFSET 66
#define SPI_CS 53
const int pirPin = 48;
uint32_t ip = 3232238180;
const char 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(OV2640,SPI_CS);
RTC_DS1307 rtc;

void setup() {
  uint8_t temp;
  uint8_t vid,pid;
  #if defined (__AVR__)
    Wire.begin(); 
  #endif
  #if defined(__arm__)
    Wire1.begin(); 
  #endif
  Serial.begin(115200);
  Serial.println("Program Start!\n");
  
  //Initialization of SD Card
  Serial.println(F("Initializing SD Card!"));
  if (!SD.begin(SD_CS)) {
    Serial.println(F("Initialization failed!\n"));
    while(1);
  }
  Serial.println(F("Initialization done!\n"));
  //Initializing RTC
  Serial.println(F("Initializating RTC!"));
  if (!rtc.begin()){
    Serial.println(F("Failed to Initialize RTC!\n"));
  }
  //rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  Serial.println(F("Initialization of RTC sucessful!\n"));
 
  pinMode(SPI_CS, OUTPUT);
  /*
  pinMode(ADAFRUIT_CC3000_CS, OUTPUT);
  digitalWrite(SPI_CS, HIGH);
  digitalWrite(ADAFRUIT_CC3000_CS, LOW); 
  */
  SPI.begin();
  //ARDUCAM
  Serial.println("ArduCAM Start!");
  // set the SPI_CS as an output:
  pinMode(SPI_CS, OUTPUT);
  //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("SPI interface Error!\n");
    while(1);
  }
  
  myCAM.write_reg(ARDUCHIP_MODE, 0x00);

  //Check if the camera module type is OV2640
  myCAM.rdSensorReg8_8(OV2640_CHIPID_HIGH, &vid);
  myCAM.rdSensorReg8_8(OV2640_CHIPID_LOW, &pid);
  if((vid != 0x26) || (pid != 0x42))
    Serial.println("Can't find OV2640 module!\n");
  else
    Serial.println("OV2640 detected\n");

  //Change to BMP capture mode and initialize the OV2640 module  
  myCAM.set_format(BMP);
  myCAM.InitCAM();
  
}

void loop() {
  char str[8];
  unsigned long previous_time = 0;
  static int k = 0;
  uint8_t temp;
  myCAM.write_reg(ARDUCHIP_MODE, 0x01);      //Switch to CAM

  while(1)
  {
    
    if(SENSOR-DETECTION)
    {
         k = k + 1;
         itoa(k, str, 10); 
         strcat(str,".bmp");        //Generate file name
         myCAM.write_reg(ARDUCHIP_MODE, 0x00);      //Switch to MCU, freeze the screen 
         GrabImage(str);
    }
  }
}
void GrabImage(char* str)
{
  File outFile;
  char VH,VL;
  uint8_t temp;
  byte buf[256];
  static int k = 0;
  int i,j = 0;
  
  outFile = SD.open(str,O_WRITE | O_CREAT | O_TRUNC);
  if (! outFile) 
  {
    Serial.println("Open File Error");
    return;
  }
    
  //Switch to FIFO Mode
  myCAM.write_reg(ARDUCHIP_TIM, MODE_MASK);
  //Flush the FIFO 
  myCAM.flush_fifo(); 
  //Clear the capture done flag 
  myCAM.clear_fifo_flag();      
  //Start capture
  myCAM.start_capture();
  Serial.println("Start Capture"); 

  //Polling the capture done flag
  while(!(myCAM.read_reg(ARDUCHIP_TRIG) & CAP_DONE_MASK));
  Serial.println("Capture Done!");
  
  k = 0;
  //Write the BMP header
  for( i = 0; i < BMPIMAGEOFFSET; i++)
  {
    char ch = pgm_read_byte(&bmp_header[i]);
    buf[k++] = ch;
  }
  outFile.write(buf,k);

  k = 0;
  //Read 320x240x2 byte from FIFO
  //Save as RGB565 bmp format
  for(i = 0; i < 240; i++)
    for(j = 0; j < 320; j++)
  {
      VH = myCAM.read_fifo();
      VL = myCAM.read_fifo();
      buf[k++] = VL;
      buf[k++] = VH;
      //Write image data to bufer if not full
      if(k >= 256)
      {
        //Write 256 bytes image data to file from buffer
        outFile.write(buf,256);
        k = 0;
      }
  }
  //Close the file  
  outFile.close(); 
  //Clear the capture done flag 
  myCAM.clear_fifo_flag();
  Serial.println("Done!");
  return;
}

Which one is more efficient to use?

Define what “more efficient” means to you. Neither approach will be fast or efficient.

Storing a link to a file in a database makes sense. Storing a file in the database does not.

but I’m getting a distorted image like the one attached below.

There is nothing attached.

  while(1)
  {

In a function that is already called in an endless loop. What a clueless thing to do.

    if(SENSOR-DETECTION)

Where is that defined?

  for( i = 0; i < BMPIMAGEOFFSET; i++)
  {
    char ch = pgm_read_byte(&bmp_header[i]);
    buf[k++] = ch;
  }
  outFile.write(buf,k);

Store the header in PROGMEM so that you can copy it to SRAM. The point of saving the data in PROGMEM escapes me.

Define what “more efficient” means to you. Neither approach will be fast or efficient.

Storing a link to a file in a database makes sense. Storing a file in the database does not.

I mean time efficient when constructing the code. And I cannot find something here in the forum that uses Wifi Shield as a device to send the image to the database. A quick link would be good.

There is nothing attached.

I got some error while trying to attach the image.

    if(SENSOR-DETECTION)

Where is that defined?

i just placed SENSOR-DETECTION, but it must be a condition for a sensor

  for( i = 0; i < BMPIMAGEOFFSET; i++)
  {
    char ch = pgm_read_byte(&bmp_header[i]);
    buf[k++] = ch;
  }
  outFile.write(buf,k);

Store the header in PROGMEM so that you can copy it to SRAM. The point of saving the data in PROGMEM escapes me.

Im quite new to Arduino and such terms makes are hard for me to read.

PS: I just copied the code from the Arducam example and made some modifications on it

1.png

What is the attached png file? As far as I could see the Arducam does not return png files?

Mark

holmes4:
What is the attached png file? As far as I could see the Arducam does not return png files?

Mark

That's the saved file in the SD Card. just converted it to .png format becuase of some error uploading it here on the forums. it is on a .bmp format when saved

Make sure your BMP header is correct.

In your favorite image manipulation program, save a 320x240 image as an rgb565 BMP file.
See how much bigger than 153600 bytes the file is. The first (size - 153600) bytes is the header.

I tried this and got 2 variants (with and without color space information), neither is the same as yours.

With color space information, 138 bytes:

00000000  42 4d 8a 58 02 00 00 00  00 00 8a 00 00 00 7c 00  |BM.X..........|.|
00000010  00 00 40 01 00 00 f0 00  00 00 01 00 10 00 03 00  |..@.............|
00000020  00 00 00 58 02 00 13 0b  00 00 13 0b 00 00 00 00  |...X............|
00000030  00 00 00 00 00 00 00 f8  00 00 e0 07 00 00 1f 00  |................|
00000040  00 00 00 00 00 00 42 47  52 73 00 00 00 00 00 00  |......BGRs......|
00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000060  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000070  00 00 00 00 00 00 00 00  00 00 02 00 00 00 00 00  |................|
00000080  00 00 00 00 00 00 00 00  00 00                    |..........|

and without color space information, 70 bytes:

00000000  42 4d 46 58 02 00 00 00  00 00 46 00 00 00 38 00  |BMFX......F...8.|
00000010  00 00 40 01 00 00 f0 00  00 00 01 00 10 00 03 00  |..@.............|
00000020  00 00 00 58 02 00 13 0b  00 00 13 0b 00 00 00 00  |...X............|
00000030  00 00 00 00 00 00 00 f8  00 00 e0 07 00 00 1f 00  |................|
00000040  00 00 00 00 00 00                                 |......|