2

I've got an Arducam OV2640 which takes a picture as a JPEG that I'd like to send to another Arduino using a pair of nRF24L01 wireless transceivers to eventually display it on an SSD1351 OLED.

Unfortunately, because the JPEG data is so large, it's being handled in a way I'm unfamiliar with, and I've also never really tried sending any data between Arduinos, let alone a JPEG, but I'm hoping that won't stop me.

The code I've posted below for the camera seems to be reading from a FIFO buffer that I'm assuming is on the camera module itself. Based on how it's saving it to the SD card, I know when I send it to the Arduino I have to send it in chunks and tell it how many chunks, when to start, and when to stop, but I'm having trouble finding good resources on how exactly to do that.

Currently, the code saves it to an SD card. My plan was to send the data to the second Arduino, have it save it to the SD card, and then display the JPEG from the SD card onto the OLED, but if I could skip the SD read/write that'd be preferable.

Camera code:

#include <ArduCAM.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include "memorysaver.h"
    
#define SD_CS 10

const int SPI_CS = 7;
    
ArduCAM myCAM( OV2640, SPI_CS );
    
void setup() {
  uint8_t vid, pid;
  uint8_t temp;
      
  Wire.begin();
  Serial.begin(9600);
  Serial.println(F("ArduCAM Start!"));
      
  // set the CS as an output:
  pinMode(SPI_CS, OUTPUT);
  digitalWrite(SPI_CS, HIGH);
      
  // initialize SPI:
  SPI.begin();
      
  // Reset the CPLD
  myCAM.write_reg(0x07, 0x80);
  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;
    }
  }
      
  //Initialize SD Card
  while (!SD.begin(SD_CS)) {
    Serial.println(F("SD Card Error!"));
    delay(1000);
  }
  Serial.println(F("SD Card detected."));
    
  while(1) {
    //Check if the camera module type is OV2640
    myCAM.wrSensorReg8_8(0xff, 0x01);
    myCAM.rdSensorReg8_8(OV2640_CHIPID_HIGH, &vid);
    myCAM.rdSensorReg8_8(OV2640_CHIPID_LOW, &pid);
    if ((vid != 0x26 ) && (( pid != 0x41 ) || ( pid != 0x42 ))) {
      Serial.println(F("Can't find OV2640 module!"));
      delay(1000);
      continue;
    } else {
      Serial.println(F("OV2640 detected."));
      break;
    } 
  }
  myCAM.set_format(JPEG);
  myCAM.InitCAM();
  myCAM.OV2640_set_JPEG_size(OV2640_320x240);
  delay(1000);
}
    
void loop() {
  myCAMSaveToSDFile();
  delay(5000);
}
    
void myCAMSaveToSDFile() {
  char str[8];
  byte buf[256];
  static int i = 0;
  static int k = 0;
  uint8_t temp = 0, temp_last=0;
  uint32_t length = 0;
  bool is_header = false;
  File outFile;
      
  // Flush the FIFO
  myCAM.flush_fifo();
      
  // Clear the capture done flag
  myCAM.clear_fifo_flag();
      
  // Start capture
  myCAM.start_capture();
  Serial.println(F("start Capture"));
  while(!myCAM.get_bit(ARDUCHIP_TRIG , CAP_DONE_MASK));
  Serial.println(F("Capture Done."));
        
  length = myCAM.read_fifo_length();
  Serial.print(F("The fifo length is :"));
  Serial.println(length, DEC);
  if (length >= MAX_FIFO_SIZE) { // 384K
    Serial.println(F("Over size."));
    return;
  }
  if (length == 0 ) { // 0 kb
    Serial.println(F("Size is 0."));
    return ;
  }

  // Construct a file name
  k = k + 1;
  itoa(k, str, 10);
  strcat(str, ".jpg");

  //Open the new file
  outFile = SD.open(str, O_WRITE | O_CREAT | O_TRUNC);
  if (!outFile) {
    Serial.println(F("File open faild"));
    return;
  }
  myCAM.CS_LOW();
  myCAM.set_fifo_burst();
  while (length--) {
    temp_last = temp;
    temp =  SPI.transfer(0x00);
    //Read JPEG data from FIFO
    if ((temp == 0xD9) && (temp_last == 0xFF)) { // If find the end, break while
      buf[i++] = temp;  // save the last 0XD9     

      // Write the remain bytes in the buffer
      myCAM.CS_HIGH();
      outFile.write(buf, i);    

      // Close the file
      outFile.close();
      Serial.println(F("Image save OK."));
      is_header = false;
      i = 0;
    }  
    if (is_header == true) {
      // Write image data to buffer if not full
      if (i < 256)
        buf[i++] = temp;
      else {
        // Write 256 bytes image data to file
        myCAM.CS_HIGH();
        outFile.write(buf, 256);
        i = 0;
        buf[i++] = temp;
        myCAM.CS_LOW();
        myCAM.set_fifo_burst();
      }          
    } else if ((temp == 0xD8) & (temp_last == 0xFF)) {
      is_header = true;
      buf[i++] = temp_last;
      buf[i++] = temp;   
    } 
  } 
}

Transmitter Code:

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
    
RF24 radio(7, 8); // CE, CSN
    
const byte address[6] = "00001";
    
void setup() {
  radio.begin();
  radio.openWritingPipe(address);
  radio.setPALevel(RF24_PA_MIN);
  radio.stopListening();
}
    
void loop() {
  const char text[] = "Hello World";
  radio.write(&text, sizeof(text));
  delay(1000);
}

Receiver Code:

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
    
RF24 radio(7, 8); // CE, CSN
    
const byte address[6] = "00001";
    
void setup() {
  Serial.begin(9600);
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setPALevel(RF24_PA_MIN);
  radio.startListening();
}
    
void loop() {
  if (radio.available()) {
    char text[32] = "";
    radio.read(&text, sizeof(text));
    Serial.println(text);
  }
}

So I know the JPEG is too big to be saved to a variable, so I can't just Radio.write it out and I have to hijack the loop being done in the SD card saving code.

I'm just so unfamiliar with this part of Arduino, I could really use some advice on how to make it work.

7
  • I think, even if you manage to transfer the data, decoding and displaying a JPEG on an Arduino will be a non-starter.
    – Majenko
    Jan 22 at 23:14
  • @Majenko I can also choose to send it in Bitmap form if that matters, but I don't have a great example of that code.
    – JShoe
    Jan 23 at 0:32
  • I did find arduino.cc/reference/en/libraries/jpegdecoder and arduino.cc/reference/en/libraries/jpegdec that may possibly be able to handle it, I obviously haven't tested it haha.
    – JShoe
    Jan 23 at 0:54
  • the filetype is irrelevant to the question ... the file is simply a collection of bytes ... what those bytes represent makes no difference to the problem of transmitting them
    – jsotola
    Jan 23 at 3:41
  • 1
    There are a couple of discussions out there on similar issues. Answer seems to be to block up the data into 32 byte chuncks (a limitation of the NRF24L01) and stitch them together at the receiver. forum.arduino.cc/index.php?topic=254713.0 forum.arduino.cc/index.php?topic=479587.0
    – RowanP
    Jan 25 at 3:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.