Hi All,
I am trying to port this AI Vision project from TechieSMS over to XIAOESP32-S3 Sense Board.
Basically I'm trying to capture a photo (no need to save it) and ask a preprogrammed question about it to OpenAI API and then print the output to the serial monitor.
I'm getting weird error message when it connects to WiFi. I've confirmed that it can connect to WiFi with other scripts.
Here's his project on ESP32-CAM board:
Youtube Video
Here's my code:
/*
ESP32-CAM Image Analysis with OpenAI API and Capacitive Touch
This code captures an image using the ESP32-CAM module, processes it,
and sends it to OpenAI's GPT-4o API for analysis. It uses capacitive touch
for triggering instead of a physical button.
Tested with:
- Arduino IDE version 2.3.2
- ESP32 boards package version 3.0.0
- ArduinoJson library version 7.1.0
- Base64 library (default version with ESP32 boards package)
Make sure to install these libraries and configure your environment
as specified above before running the code.
*/
#include <WiFi.h>
#include <HTTPClient.h>
#include <Base64.h>
#include "esp_camera.h"
#include <ArduinoJson.h>
// WiFi credentials
const char* ssid = "mywifi";
const char* password = "mywifipassword";
// OpenAI API key
const String apiKey = "API KEY";
// Question to be Asked about the image
String Question = "Summarize the image";
// Pin definitions for ESP32-CAM AI-Thinker module
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0
#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 21
#define Y4_GPIO_NUM 19
#define Y3_GPIO_NUM 18
#define Y2_GPIO_NUM 5
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
// Capacitive touch pin for ESP32
#define TOUCH_PIN A5 // T0 corresponds to GPIO4
#define BUZZER_PIN 2 // Buzzer connected to GPIO2
// Function to encode image to Base64
String encodeImageToBase64(const uint8_t* imageData, size_t imageSize) {
return base64::encode(imageData, imageSize);
}
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
pinMode(BUZZER_PIN, OUTPUT); // Set Buzzer pin as output
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println("WiFi Connected!");
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_JPEG;
config.frame_size = FRAMESIZE_QVGA;
config.jpeg_quality = 10;
config.fb_count = 1;
if (esp_camera_init(&config) != ESP_OK) {
Serial.println("Camera init failed");
return;
}
Serial.println("Camera Initialized");
}
void captureAndAnalyzeImage() {
Serial.println("Capturing image...");
camera_fb_t* fb = esp_camera_fb_get(); // Get the frame buffer
if (!fb) {
Serial.println("Camera capture failed");
return;
}
Serial.println("Image captured");
String base64Image = encodeImageToBase64(fb->buf, fb->len);
beep();
esp_camera_fb_return(fb); // Return the frame buffer to free memory
if (base64Image.isEmpty()) {
Serial.println("Failed to encode the image!");
return;
}
AnalyzeImage(base64Image);
}
void AnalyzeImage(const String& base64Image) {
Serial.println("Sending image for analysis...");
String result;
String url = "data:image/jpeg;base64," + base64Image;
DynamicJsonDocument doc(4096);
doc["model"] = "gpt-4o";
JsonArray messages = doc.createNestedArray("messages");
JsonObject message = messages.createNestedObject();
message["role"] = "user";
JsonArray content = message.createNestedArray("content");
JsonObject textContent = content.createNestedObject();
textContent["type"] = "text";
textContent["text"] = "Summarize the context of this image?";
JsonObject imageContent = content.createNestedObject();
imageContent["type"] = "image_url";
JsonObject imageUrlObject = imageContent.createNestedObject("image_url");
imageUrlObject["url"] = url;
imageContent["image_url"]["detail"] = "auto";
doc["max_tokens"] = 400;
String jsonPayload;
serializeJson(doc, jsonPayload);
if (sendPostRequest(jsonPayload, result)) {
Serial.print("[ChatGPT] Response: ");
Serial.println(result);
DynamicJsonDocument responseDoc(4096);
deserializeJson(responseDoc, result);
String responseContent = responseDoc["choices"][0]["message"]["content"].as<String>();
Serial.println("[ChatGPT] Parsed response: " + responseContent);
} else {
Serial.print("[ChatGPT] Error: ");
Serial.println(result);
}
}
bool sendPostRequest(const String& payload, String& result) {
HTTPClient http;
http.begin("https://api.openai.com/v1/chat/completions");
http.addHeader("Content-Type", "application/json");
http.addHeader("Authorization", "Bearer " + apiKey);
http.setTimeout(20000);
Serial.print("Payload size: ");
Serial.println(payload.length());
int httpResponseCode = http.POST(payload);
if (httpResponseCode > 0) {
result = http.getString();
Serial.println("HTTP Response Code: " + String(httpResponseCode));
Serial.println("Response Body: " + result);
http.end();
return true;
} else {
result = "HTTP request failed, response code: " + String(httpResponseCode);
Serial.println("Error Code: " + String(httpResponseCode));
Serial.println("Error Message: " + http.errorToString(httpResponseCode));
http.end();
return false;
}
}
void loop() {
// Use capacitive touch instead of button press
int touchValue = touchRead(TOUCH_PIN);
if (touchValue < 30) { // Adjust this threshold as needed for your environment
Serial.println("Touch detected! Capturing image...");
captureAndAnalyzeImage();
delay(1000); // Small delay to debounce touch
}
}
void beep(){
digitalWrite(2,HIGH);
delay(300);
digitalWrite(2,LOW);
}
The error I'm getting is:
Here's the error message:
Connecting to WiFi...Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
20:44:32.042 ->
20:44:32.042 -> Core 1 register dump:
20:44:32.042 -> PC : 0x42050989 PS : 0x00060230 A0 : 0x8204969e A1 : 0x3fcab600
20:44:32.042 -> A2 : 0x3fcb7004 A3 : 0x3fcab6d8 A4 : 0xffff8fff A5 : 0x00000064
20:44:32.042 -> A6 : 0x3c0d6e2c A7 : 0x00000001 A8 : 0x3c0d6e84 A9 : 0x00000000
20:44:32.042 -> A10 : 0x00000016 A11 : 0x00000060 A12 : 0x00000060 A13 : 0x00000064
20:44:32.042 -> A14 : 0x00000000 A15 : 0x00000002 SAR : 0x00000011 EXCCAUSE: 0x0000001c
20:44:32.042 -> EXCVADDR: 0x00000000 LBEG : 0x400570e8 LEND : 0x400570f3 LCOUNT : 0x00000000
20:35:10.733 -> PC : 0x42050989 PS : 0x00060230 A0 : 0x8204969e A1 : 0x3fcab570
20:35:10.733 -> A2 : 0x3fcb7004 A3 : 0x3fcab648 A4 : 0xffff8fff A5 : 0x00000064
20:35:10.733 -> A6 : 0x3c0d6e2c A7 : 0x00000001 A8 : 0x3c0d6e84 A9 : 0x00000000
20:35:10.733 -> A10 : 0x00000016 A11 : 0x00000060 A12 : 0x00000060 A13 : 0x00000064
20:35:10.733 -> A14 : 0x00000000 A15 : 0x00000002 SAR : 0x00000015 EXCCAUSE: 0x0000001c
20:35:10.733 -> EXCVADDR: 0x00000000 LBEG : 0x400570e8 LEND : 0x400570f3 LCOUNT : 0x00000000
20:35:10.733 ->
20:35:10.733 ->
20:35:10.733 -> Backtrace: 0x42050986:0x3fcab570 0x4204969b:0x3fcab5c0 0x42049222:0x3fcab5f0 0x420034a1:0x3fcab640 0x4200efb7:0x3fcab6d0 0x4037df46:0x3fcab6f0
20:35:10.733 ->
20:35:10.733 ->
20:35:10.733 ->
