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!