I'm trying to use classic bluetooth to stream images from ESP32, already did this with the HC12 using RF and got an FPS of around 1.53 which makes sense considering the maximum 115200 baud rate from the ESP32 to the HC12.
The ESP32 I'm using is a ESP32-WROVER-E with camera (OV2640).
Using classic bluetooth I expected to get a considerably higher FPS, was hoping for at least 3-4 FPS hopefully considerably more (1-3Mbps), however I am getting even less than with RF, an an FPS of around 0.97-1.3 FPS. The arduino code is as follows, I'm leaving in the code for RF since I hope to be able to switch between RF streaming and Bluetooth streaming, in case there is some funky interaction I'm not aware of which may be causing this problem:
#include <HardwareSerial.h>
#include "esp_camera.h"
#include "esp_bt_main.h"
#include "esp_bt_device.h"
#include "BluetoothSerial.h"
BluetoothSerial SerialBT;
// BT Address : A0:B7:65:FE:74:62
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
// HC12 is on 115,200bps Baud Rate, 236,000 over the air baud rate, channel 010 (437.4MHz), maximum power settings (+20dBM, 100mW) and FU3 transmission mode
// Commands for setup are:
// AT+B115200
// AT+C010
// After setting SET to HIGH for 80ms, then LOW and waiting 40ms
#define RXD2 33 //(RX2)
#define TXD2 32 //(TX2)
#define SET 13 // (SET)
HardwareSerial HC12(2); //Hardware serial 2 on the ESP32
// OV2640 camera module pins
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 21
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39
#define Y6_GPIO_NUM 36
#define Y5_GPIO_NUM 19
#define Y4_GPIO_NUM 18
#define Y3_GPIO_NUM 5
#define Y2_GPIO_NUM 4
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
//Bluetooth Flag
int btFlag = 1;
int takeImg = 0;
int first = 0;
long timer;
void takeImage(){
camera_fb_t * fb = NULL;
fb = esp_camera_fb_get();
//Sometimes Bugs
if(first == 0){
esp_camera_fb_return(fb);
fb = NULL;
fb = esp_camera_fb_get();
first++;
}
if (!fb) {
Serial.println("Camera capture failed");
return;
}
if(btFlag==0){ //Check if bluetooth flag is active
//HC12.println(fb->len);
for(int iter = 0; iter < fb->len; iter++){
HC12.write(fb->buf[iter]); // Send byte by byte over HC12 (Radio)
}
} else { // If bluetooth flag is active
for(int iter = 0; iter < fb->len; iter++){
SerialBT.write(fb->buf[iter]); // Send byte by byte over Bluetooth
}
}
Serial.println(fb->len);
esp_camera_fb_return(fb);
fb = NULL;
}
// Function to enter setup for HC12 so that settings can be changed, to be called in setup()
void HC12Setup(){
pinMode(SET, OUTPUT);
digitalWrite(SET, HIGH);
delay(80);
digitalWrite(SET, LOW);
delay(40);
}
void setup()
{
Serial.begin(115200); // Serial port to computer
HC12.begin(115200, SERIAL_8N1, RXD2, TXD2); // Serial port to HC12
// OV2640 camera module
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.frame_size = FRAMESIZE_VGA; //640x480
config.frame_size = FRAMESIZE_HVGA; //480x320
//config.frame_size = FRAMESIZE_SVGA; //800x600
config.pixel_format = PIXFORMAT_JPEG;
config.jpeg_quality = 10;
config.fb_count = 2;
config.grab_mode = CAMERA_GRAB_LATEST;
config.fb_location = CAMERA_FB_IN_PSRAM;
// Init camera
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
}
// Change camera settings for better visibility KEEP COMMENTED OR THE FUCKING IMAGE QUALITY GETS SHOT IN THE HEAD LIKE I WISH I WAS FOR ADDING THESE LINES
sensor_t * s = esp_camera_sensor_get();
/*
s->set_brightness(s, 0); // -2 to 2
s->set_contrast(s, 0); // -2 to 2
s->set_saturation(s, 0); // -2 to 2
s->set_special_effect(s, 0); // 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, 4 - Green Tint, 5 - Blue Tint, 6 - Sepia)
s->set_whitebal(s, 1); // 0 = disable , 1 = enable
s->set_awb_gain(s, 1); // 0 = disable , 1 = enable
s->set_wb_mode(s, 0); // 0 to 4 - if awb_gain enabled (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
s->set_exposure_ctrl(s, 1); // 0 = disable , 1 = enable
s->set_aec2(s, 0); // 0 = disable , 1 = enable
s->set_ae_level(s, 0); // -2 to 2
s->set_aec_value(s, 300); // 0 to 1200
s->set_gain_ctrl(s, 1); // 0 = disable , 1 = enable
s->set_agc_gain(s, 0); // 0 to 30
s->set_gainceiling(s, (gainceiling_t)0); // 0 to 6 (6 from "timelapse" example sjr, OK)
s->set_bpc(s, 0); // 0 = disable , 1 = enable
s->set_wpc(s, 1); // 0 = disable , 1 = enable
s->set_raw_gma(s, 1); // 0 = disable , 1 = enable
s->set_lenc(s, 1); // 0 = disable , 1 = enable
s->set_hmirror(s, 0); // 0 = disable , 1 = enable
s->set_vflip(s, 0); // 0 = disable , 1 = enable
s->set_dcw(s, 1); // 0 = disable , 1 = enable
s->set_colorbar(s, 0); // 0 = disable , 1 = enable
*/
// Start BT
SerialBT.begin("Cubesat");
delay(1000);
}
void loop()
{
delay(50);
takeImage();
// We use the following section only really for debugging and changing HC12 settings
/*
while (HC12.available())
{
// If HC-12 has data
Serial.write(HC12.read()); // Send the data to Serial monitor
}
while (Serial.available())
{
// If we have data from Serial monitor
HC12.write(Serial.read()); // Send that data to HC-12
}
*/
}
In the case of RF, another ESP32 is connected to another HC12 module and feeding the data from the HC12 directly to my computer through UART. The code is extremely simple and should not have any influence on the bluetooth comms.
In the case of bluetooth my computer connects to it through python using the socket library. I could attach the python code as well but I'd like to make sure I didn't make a stupid mistake on the ESP32 side since I'm a newbie in all things arduino related and have a bit more experience in python, although not much.
Any help is appreciated since this problem has been stumping me for a while now.
Thanks!!