pySerial killing arduino program

Hi everyone,

Introduction & Purpose
I've recently bought the ESP32-CAM as well as the ESP32-CAM-MB (ESP32-CAM Introduction). My aim is to create an Arduino program that takes a still every 5 seconds and then writes its pixel values via Serial port. On the other hand, I want to have a python program that reads the serial port in order to gather this data, so that I could then display the image by using PIL library.

Current approach
I now have the following:

  • Arduino program that takes the still and writes its pixel values to the Serial Port:
#include <esp_camera.h>

#define CAMERA_MODEL_AI_THINKER

#include "camera_pins.h"


#define FRAME_SIZE FRAMESIZE_240X240
#define WIDTH 240
#define HEIGHT 240

#define FLASH_PIN 4


uint8_t img_array_1D [HEIGHT][WIDTH];

bool setup_camera(framesize_t);
bool capture_image();
void display_img();
void set_flash(int);

void setup(){
  Serial.begin(115200);
  setup_camera(FRAME_SIZE);
  // //Serial.println(setup_camera(FRAME_SIZE) ? "Camera initialized OK!" : "Error initing camera!");
  pinMode(FLASH_PIN, OUTPUT);
}

void loop(){
  //Serial.println("Take new image");
  if(!capture_image()){
    //Serial.println("Failed capturing image");
    delay(2000);

    return;
  }
  delay(5000); // Take still every 10 secs
}

bool setup_camera(framesize_t frameSize){
  camera_config_t config;

  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0;
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  config.pin_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_GRAYSCALE;
  config.frame_size = frameSize;
  config.jpeg_quality = 12;
  config.fb_count = 1;

  bool ok = esp_camera_init(&config) == ESP_OK;

  sensor_t *sensor = esp_camera_sensor_get();
  sensor->set_framesize(sensor, frameSize);

  return ok;
}

bool capture_image() {
  
  camera_fb_t * frame = NULL;
  frame = esp_camera_fb_get();
  print_image_shape(frame);

  frame_to_array(frame);

  // display_img();

  esp_camera_fb_return(frame);

  if (!frame){
    //Serial.println("Something went wrong with the camera");
    return false;

  }

  return true;
 }


void print_image_shape(camera_fb_t * frame){

  // print shape of image and total length (=heigth*width)
  //Serial.print("Width: ");
  //Serial.print(frame->width);
  //Serial.print("\tHeigth: ");
  //Serial.print(frame->height);
  //Serial.print("\tLength: ");
  //Serial.println(frame->len);
 }


void frame_to_array(camera_fb_t * frame){

  int len = frame->len;
  char imgBuffer[frame->len];
  int counter = 0;

  // uint16_t img_array_1D [HEIGHT][WIDTH] = { 0 };

  int h_counter = 0;
  int w_counter = 0;

  // write values from buffer into 2D Array
  for (int h=0; h < HEIGHT; h++){
    ////Serial.println(h);
    for (int w=0; w < WIDTH; w++){
      ////Serial.println(w);
      int position = h*(len/HEIGHT)+w;

      // Serial.println(frame->buf[position]);
      img_array_1D[h][w] = frame->buf[position];
      // display_img();
      Serial.print(img_array_1D[h][w]);
      ////Serial.print(",");
      //delay(2);
    }
  }
  Serial.println("Finished image processing");
  set_flash(5);


  ////Serial.println("Current frame:");

  //Serial.println("=====================");

 }

void display_img(){
  for(int h = 0; h < HEIGHT; h++){
    for(int w = 0; w < WIDTH; w++){
      //Serial.print(img_array_1D[h][w] + ",");
    }
  }
}

void set_flash(int msecs){
  digitalWrite(FLASH_PIN, HIGH);
  delay(msecs);
  digitalWrite(FLASH_PIN, LOW);
  delay(msecs);
}
  • Python program that opens the Serial port and reads its data:
import time
import serial

def display_img(img_data):
    print("Displaying data...")
    for i in range(len(img_data)):
        print(img_data[i])

def read_serial_data(arduino_serial):
    if not arduino_serial.is_open:
        arduino_serial.open()

    if arduino_serial.is_open:
        arduino_serial.inWaiting()
        img_data = arduino_serial.readline().decode("utf-8").replace("\r\n", "").split(",")
        display_img(img_data)
        return img_data

def main():
    print("Initing main program...")
    arduino_serial = serial.Serial('COM4', 115200)
    time.sleep(5)
    while True:
        img_data = read_serial_data(arduino_serial)

if __name__ == '__main__':
    main()

Expected behaviour
Everytime a still is taken, its pixel values are printed to the serial port and the python code reads them and displays them on the terminal.

Actual behaviour
I know that the arduino program works fine as I make the led "flash" every time it ends printing the data to the Serial port, however, as soon as I run the python code, and the statement

arduino_serial = serial.Serial('COM4', 115200)

is executed, the Arduino program seems to be killed, as the led is no longer flashing, so I guess it is neither printing anything to the Serial port. The again, if I stop the python code, the led begins to flash again, that's why I concluded (maybe naïvely) that the python code is killing the Arduino one.

Has any of you experienced anything similar? I am quite confused, because I've done this serial communication before with other boards and programs and it's always worked fine.

Thanks for reading
Any help is of great aid!

Check this tutorial on serial comms using python: Demo of PC-Arduino comms using Python

Can FTP server be run on the target?

If you don't use this array for anything other than printing one byte at a time, it does take up some memory.

      img_array_1D[h][w] = frame->buf[position];
      // display_img();
      Serial.print(img_array_1D[h][w]);

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