Help speeding up serial communication between an Arduino Uno and a TTL camera

Hello!

I'm using an Arduino UNO and a TTL JPEG camera from Linksprite to take and send pictures to a nodeMCU, and from there send them to my backend.

I was able to do that by following this guide, but my problem is that it takes almost 2 minutes to get the picture from the camera to my arduino and I would like to make this process faster.

Right now I take the photo, which is around 50 kB, and read 32 bytes at a time until it reaches the end of the photo.

According to the camera manual I can change the baud rate of the camera (currently at 38400) and the length of the requested data reading (currently at 32), but I don't know how I could use this knowing that the serial buffer of the Arduino has a maximum size of 64 bytes.

Here's my code; I would appreciate any recommendations.

#include <SoftwareSerial.h> 

// Serial Communication with nodeMCU---------------------------------------------------
const byte rxPin = 10;
const byte txPin = 11;
SoftwareSerial arduinoSerial (rxPin, txPin);

void sendIncominPhotoAlert(int size){
  char finalBuffer[100] = ""; 
  sprintf(finalBuffer, "<INDOOR,1,23/10/2023,14:23:23,1,%d>", size);

  Serial.println(finalBuffer);
  arduinoSerial.print(finalBuffer);
  delay(1000);
}

void sendPhotoFragment(byte* byteArray){
  byte buffer[34];

  buffer[0]=0x3C;
  for(int i=1; i<34; i++){
    buffer[i]=byteArray[i-1];
  }  
  buffer[33]=0x3E;

  arduinoSerial.write(buffer, 34);
}

// TTL Camera --------------------------------------------------------------
// VCC = GREEN / GND = BLUE / TXD = RED /RXD = BLACK

const byte CameraRxPin = 2;
const byte CameraTxPin = 3;
SoftwareSerial cameraSerial (CameraRxPin, CameraTxPin);

byte incomingByte;
int startAdress=0x0000;    
boolean endFlag=0;

uint8_t MSB;
uint8_t LSB; 
uint16_t photoSize = 0;
int sizeCount = 0;

void flushBuffer(){
  while(cameraSerial.available() > 0) {
    incomingByte=cameraSerial.read();
    Serial.print(incomingByte, HEX);
    Serial.print(" ");
  }
  Serial.println("");
}

void useCamera(){
  // Reset camera
  resetCamera();
  delay(3000);
  Serial.println("Reset response: "); 
  flushBuffer();

  // Change photo size
  changePhotoSize();
  delay(3000);
  Serial.println("Change photo size response: "); 
  flushBuffer();

  // Reset camera
  resetCamera();
  delay(3000);
  Serial.println("Reset response: "); 
  flushBuffer();

  // Take picture
  takePicture();  
  Serial.println("Take picture response: "); 
  flushBuffer();

  // Get photo size
  getPhotoSize();
  Serial.println("Get photo size response: "); 
  while(cameraSerial.available() > 0) {
    sizeCount++;
    incomingByte=cameraSerial.read();
    Serial.print(incomingByte, HEX);
    Serial.print(" ");

    if(sizeCount == 8) MSB = incomingByte;
    if(sizeCount == 9) LSB = incomingByte;
  }
  Serial.println("");

  photoSize = MSB;
  photoSize <<= 8; 
  photoSize = photoSize | LSB; 

  Serial.print("Photo size in DEC: ");
  Serial.println(photoSize);  

  // Send first message to nodeMCU 
  //sendIncominPhotoAlert(photoSize);

  // Read photo
  Serial.println("Start pic"); 
  delay(100);

  byte b[32];
  int j=0,
      k=0,
      count=0;
      
  while(!endFlag) {  
    j=0;
    k=0;
    count=0;

    cameraSerial.listen();
    readPicture();
    delay(75);

    while(cameraSerial.available() > 0) {
      incomingByte=cameraSerial.read();
      k++;

      //Save data (Dont read fist 5 bytes)
      if((k>5) && (j<32) && (!endFlag)) {
        b[j]=incomingByte;
        //Final read
        if((b[j-1]==0xFF) && (b[j]==0xD9))
          endFlag=1;                           
        
        j++;
        count++;
      }
    }

    // Print data   
    for(j=0; j<count ;j++) {   
      if(b[j]<0x10)
        Serial.print("0");
      Serial.print(b[j], HEX);
    }
    Serial.print(" ");    
 
    //sendPhotoFragment(b);                              
  }  
  delay(3000);

  stopTakingPictures();
  
  Serial.println("");
  Serial.println("end of pic");
}

void setup() { 
  Serial.begin(9600);
  arduinoSerial.begin(9600);
  cameraSerial.begin(38400); 

  useCamera();
}

void loop() { 
}

// HELPER FUNCTIONS............................................
void resetCamera(){
  cameraSerial.write((byte)0x56);
  cameraSerial.write((byte)0x00);
  cameraSerial.write((byte)0x26);
  cameraSerial.write((byte)0x00);   
}

void changePhotoSize(){
  cameraSerial.write((byte)0x56);
  cameraSerial.write((byte)0x00);
  cameraSerial.write((byte)0x31);
  cameraSerial.write((byte)0x05);   
  cameraSerial.write((byte)0x04);
  cameraSerial.write((byte)0x01);
  cameraSerial.write((byte)0x00);
  cameraSerial.write((byte)0x19);
  cameraSerial.write((byte)0x00); 
}

void takePicture(){
  cameraSerial.write((byte)0x56);
  cameraSerial.write((byte)0x00);
  cameraSerial.write((byte)0x36);
  cameraSerial.write((byte)0x01);
  cameraSerial.write((byte)0x00);
  
  //reset so that another picture can taken
  startAdress=0x0000; 
}

void getPhotoSize(){
  cameraSerial.write((byte)0x56);
  cameraSerial.write((byte)0x00);
  cameraSerial.write((byte)0x34);
  cameraSerial.write((byte)0x01);
  cameraSerial.write((byte)0x00);        
}

//Read data
void readPicture(){
  uint8_t MH=startAdress/0x100;
  uint8_t ML=startAdress%0x100;
      
  cameraSerial.write((byte)0x56);
  cameraSerial.write((byte)0x00);
  cameraSerial.write((byte)0x32);
  cameraSerial.write((byte)0x0C);
  cameraSerial.write((byte)0x00);
  cameraSerial.write((byte)0x0A);

  //init address
  cameraSerial.write((byte)0x00);
  cameraSerial.write((byte)0x00);
  cameraSerial.write((byte)MH);
  cameraSerial.write((byte)ML);

  //data length (32)
  cameraSerial.write((byte)0x00);
  cameraSerial.write((byte)0x00);
  cameraSerial.write((byte)0x00);
  cameraSerial.write((byte)0x20);

  //spacing interval
  cameraSerial.write((byte)0x00);
  cameraSerial.write((byte)0x0A);

  startAdress+=0x20; 
}

void stopTakingPictures(){
  cameraSerial.write((byte)0x56);
  cameraSerial.write((byte)0x00);
  cameraSerial.write((byte)0x36);
  cameraSerial.write((byte)0x01);
  cameraSerial.write((byte)0x03);        
}

It is hard to see how the code will do anything since it will not compile as posted.

So the camera data comes into the Uno in 32 byte chunks stored in an array (b) then is output through the Serial port? Is that right?

Why not output the data at 38400 instead of 9600?

Why do you need the Uno?

Can't you control and read the camera with the NodeMCU? It seems that you can get much faster serial speed with EspSoftwareSerial

Hey! Thank you for answering.

I made some changes to the code before posting but I changed it back and now it will compile.

i tried this but i was the same.

Im using the UNO to read data from some other sensors + the camera, and the nodeMCU as a wifi shield. Since the UNO has the 5V output needed for the camera i connected to the camera to it.

At the moment im not using any other sensors, just the UNO and the Camera like this:

I will start off saying that I am not a NodeMCU expert, but I have used ESP8266 boards quite a bit.

The NodeMCU Vin pin may supply the USB voltage (5V) or a bit less (diode drop) on some board versions. Check it with your DMM (Digital MultiMeter).

It seems to me over complicated to use the Uno just to be a power supply to the camera. I would consider using the Vin pin on NodeMCU ( if possible) or another 5V source to power the camera and control the camera with the NodeMCU, taking advantage of the much faster serial transfer rate.

Since the camera RX has a voltage divider on it that means that the RX and RX pins are 3.3V compatible so should connect directly to the NodeMCU.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.