Having Trouble Getting Arduino IDE 2.0 Serial Monitor to Print IP of ESP32 Cam

My project is having a fan blow air across bait then when a target inspects the smell a sensor picks up their presence a picture is taken and sent to me via an alert/email. I have had the individual pieces working with separate sketches. When I tried to combine the sketches I ran into problems. My current problem is that I have switched to Arduino IDE 2.0 and the serial monitor is not printing the IP address for me ESP32 Cam. Without the IP Address I cannot see what the camera sees.

Any thoughts would be appreciated. If time permits and you can help with the rest of the code and problems I am encountering please let me know. Thank you. Here is my serial monitor code. (Note: It worked in the previous version of Arduino IDE now that I have begun using 2.0 I am running into problems with new and old.)

// Connect to Wi-Fi if required
  #if defined(SEND_EMAIL) || defined(USE_TIMESTAMP)
    WiFi.mode(WIFI_STA);
    WiFi.setHostname("");
    int connAttempts = 0;

  IPAddress ip;

  WiFi.mode(WIFI_STA);
  WiFi.begin(SSID1, PWD1);
  WiFi.setHostname("");
 

  while (WiFi.status() != WL_CONNECTED);
  {
    delay(500);
    Serial.print(F("."));
    connAttempts++;
  }
{
  ip = WiFi.localIP();
  Serial.println(F("WiFi connected"));
  Serial.println("");
  Serial.println(ip);
  Serial.print("Stream Link: http://");
  Serial.print(ip);
  Serial.println("/mjpeg/1");
  server.on("/mjpeg/1", HTTP_GET, handle_jpg_stream);
  server.on("/jpg", HTTP_GET, handle_jpg);
  server.onNotFound(handleNotFound);
  server.begin();
}

if(WiFi.isConnected()){
      Serial.println("");
      Serial.println("WiFi connected.");
      Serial.println("IP address: ");
      Serial.println(WiFi.localIP());
      Serial.print(" Signal Level: ");
      Serial.println(WiFi.RSSI());
      Serial.println();
    }
else {
      Serial.println(F("Failed to connect to Wi-Fi"));
      sleep();
    }
  #endif

Hi @pmllc. Thanks for your report.

Please try this simple experiment:

  1. Upload the following sketch to your ESP32-Cam board:
    void setup() {
      Serial.begin(9600);
    }
    
    void loop() {
      Serial.println("hello");
      delay(1000);
    }
    
  2. Open Serial Monitor in the Arduino IDE 2.x
  3. Make sure "9600" is selected from the baud rate menu at the top right corner of the Serial Monitor panel.

Do you then see "hello" printed to the Serial Monitor output field once a second?

Doing it now.

I am having trouble with my system and received this message when I tried to upload.

"Connecting......................................

A fatal error occurred: Failed to connect to ESP32: No serial data received.
For troubleshooting steps visit: Troubleshooting - ESP32 - — esptool.py latest documentation
Failed uploading: uploading error: exit status 2"

I get this message sometimes then I reset my esp and the shield I am using. Sometimes it works sometimes it doesn't. Frustrating.

Did you press the button on the ESP32-CAM to start the upload?

The reset worked.

"Hash of data verified.
Compressed 8192 bytes to 47...
Writing at 0x0000e000... (100 %)
Wrote 8192 bytes (47 compressed) at 0x0000e000 in 0.1 seconds (effective 487.3 kbit/s)...
Hash of data verified.
Compressed 258320 bytes to 140823...
Writing at 0x00010000... (11 %)
Writing at 0x0001ce0c... (22 %)
Writing at 0x00024d96... (33 %)
Writing at 0x0002a22e... (44 %)
Writing at 0x0002f5a4... (55 %)
Writing at 0x000383ed... (66 %)
Writing at 0x00040db4... (77 %)
Writing at 0x00046491... (88 %)
Writing at 0x0004bb57... (100 %)
Wrote 258320 bytes (140823 compressed) at 0x00010000 in 3.3 seconds (effective 633.1 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin..."

But, no "Hello".

Yes

Sorry, I have to run to work. I look forward to learning from you as soon as I get back. Again, thank you.

You need to press reset again ...................

Ignore the "Hard resetting via RTS pin..." message.

And remove the programing jumper.

On a quick break from work. "Hello" printed.

I re-uploaded my original sketch and hit reset again. The following printed out:

clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1344
load:0x40078000,len:13864
load:0x40080400,len:3608
entry 0x400805f0
C:\Users\stahw\Documents\Arduino\Blynk Live Stream\esp32_camera_mjpeg\esp32_camera_mjpeg.inoSep 30 2022
E (1093) gpio: gpio_install_isr_service(449): GPIO isr service already installed
E (1094) camera: Camera probe failed with error 0x103(ESP_ERR_INVALID_STATE)
Camera init failed with error 0x103 Going to sleep now

Which post you made in this thread has the code to load up a ESP32CAM?

The code is long, so I only put the code in for the IP address, which is the original post. I can post the whole sketch, though.


#include "srcOV2640.h"
#include <WiFi.h>
#include <WebServer.h>
#include <WiFiClient.h>
#include "Arduino.h" // General functionality
#include "esp_camera.h" // Camera
#include <SD.h> // SD Card 
#include "FS.h" // File System
#include "soc/soc.h" // System settings (e.g. brownout)
#include "soc/rtc_cntl_reg.h"
#include "driver/rtc_io.h"
#include <EEPROM.h> // EEPROM flash memory
#include "time.h" // Time functions
// "ESP Mail Client" by Mobizt, tested with v1.6.4
#include "ESP_Mail_Client.h" // e-Mail

// DEFINES
//#define USE_INCREMENTAL_FILE_NUMBERING //Uses EEPROM to store latest file stored
#define USE_TIMESTAMP // Uses Wi-Fi to retrieve current time value
#define SEND_EMAIL // Uses Wi-Fi to email photo attachment
#define TRIGGER_MODE // Photo capture triggered by GPIO pin rising/falling
//#define TIMED_MODE // Photo capture automated according to regular delay



// Select camera model
//#define CAMERA_MODEL_WROVER_KIT
//#define CAMERA_MODEL_ESP_EYE
//#define CAMERA_MODEL_M5STACK_PSRAM
//#define CAMERA_MODEL_M5STACK_WIDE
#define CAMERA_MODEL_AI_THINKER

#include "camera_pins.h"

// Wi-Fi settings
#define SSID1 ""
#define PWD1 ""


OV2640 cam;

WebServer server(80);

const char HEADER[] = "HTTP/1.1 200 OK\r\n" \
                      "Access-Control-Allow-Origin: *\r\n" \
                      "Content-Type: multipart/x-mixed-replace; boundary=123456789000000000000987654321\r\n";
const char BOUNDARY[] = "\r\n--123456789000000000000987654321\r\n";
const char CTNTTYPE[] = "Content-Type: image/jpeg\r\nContent-Length: ";
const int hdrLen = strlen(HEADER);
const int bdrLen = strlen(BOUNDARY);
const int cntLen = strlen(CTNTTYPE);

void handle_jpg_stream(void)
{
  char buf[32];
  int s;

  WiFiClient client = server.client();

  client.write(HEADER, hdrLen);
  client.write(BOUNDARY, bdrLen);

  while (true)
  {
    if (!client.connected()) break;
    cam.run();
    s = cam.getSize();
    client.write(CTNTTYPE, cntLen);
    sprintf( buf, "%d\r\n\r\n", s );
    client.write(buf, strlen(buf));
    client.write((char *)cam.getfb(), s);
    client.write(BOUNDARY, bdrLen);
  }
}

const char JHEADER[] = "HTTP/1.1 200 OK\r\n" \
                       "Content-disposition: inline; filename=capture.jpg\r\n" \
                       "Content-type: image/jpeg\r\n\r\n";
const int jhdLen = strlen(JHEADER);

void handle_jpg(void)
{
  WiFiClient client = server.client();

  cam.run();
  if (!client.connected()) return;

  client.write(JHEADER, jhdLen);
  client.write((char *)cam.getfb(), cam.getSize());
}

void handleNotFound()
{
  String message = "Server is running!\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  server.send(200, "text / plain", message);
}
#define SMTP_HOST "smtp.office365.com"
#define SMTP_PORT 25
#define AUTHOR_EMAIL ""
#define AUTHOR_PASSWORD ""
// CONSTANTS
// GPIO Pin 33 is small red LED near to RESET button on the back of the board
const byte ledPin = GPIO_NUM_33;
// GPIO Pin 4 is bright white front-facing LED 
const byte flashPin = GPIO_NUM_4;
// When using TRIGGER_MODE, this pin will be used to initiate photo capture
const byte triggerPin = GPIO_NUM_13;
// Flash strength (0=Off, 255=Max Brightness)
// Setting a low flash value can provide a useful visual indicator of when a photo is being taken
const byte flashPower = 1;
#ifdef TIMED_MODE
  //const int timeLapseInterval = 30; // seconds between successive shots in TIMELAPSE mode
#endif
const int startupDelayMillis = 3000; // time to wait after initialising  camera before taking photo

// GLOBALS
// Keep track of number of pictures taken for incremental file naming
int pictureNumber = 0;
// Full path of filename of the last photo saved
String path;
#ifdef SEND_EMAIL
  // SMTP session used for eMail sending
  SMTPSession smtp;
  // Function fired on email success/failure
  void smtpCallback(SMTP_Status status);

  // Callback function after eMail sending
void smtpCallback(SMTP_Status status) {
  // Print the current status
  Serial.println(status.info());
  // Show details of successful delivery
  if (status.success())   {
    Serial.println("----------------");
    Serial.printf("Message sent success: %d\n", status.completedCount());
    Serial.printf("Message sent failed: %d\n", status.failedCount());
    Serial.println("----------------\n");
    struct tm dt;
    for (size_t i=0; i<smtp.sendingResult.size(); i++) {
      SMTP_Result result = smtp.sendingResult.getItem(i);
      time_t ts = (time_t)result.timestamp;
      localtime_r(&ts, &dt);
      Serial.printf("Message No: %d\n", i + 1);
      Serial.printf("Status: %s\n", result.completed ? "success" : "failed");
      Serial.printf("Date/Time: %d/%d/%d %d:%d:%d\n", dt.tm_year + 1900, dt.tm_mon + 1, dt.tm_mday, dt.tm_hour, dt.tm_min, dt.tm_sec);
      Serial.printf("Recipient: %s\n", result.recipients);
      Serial.printf("Subject: %s\n", result.subject);
    }
    Serial.println("----------------");
  }
}
#endif

void sleep() {
  // IMPORTANT - we define pin mode for the trigger pin at the end of setup, because most pins on the ESP32-CAM
  // have dual functions, and may have previously been used by the camera or SD card access. So we overwrite them here
  pinMode(triggerPin, INPUT_PULLDOWN);
  // Ensure the flash stays off while we sleep
  rtc_gpio_hold_en(GPIO_NUM_4);
  // Turn off the LED
  digitalWrite(ledPin, HIGH);
  delay(1000);
  #ifdef TRIGGER_MODE
    // Use this to wakeup when trigger pin goes HIGH
    esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, 1);
    // Use this to wakeup when trigger pin goes LOW
    // esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, 0);
  //#elif defined(TIMED_MODE)
    // Or, use this to wakeup after a certain amount of time has elapsed (parameter specified in uS, so multiply secs by 1000000)
    //esp_sleep_enable_timer_wakeup(timeLapseInterval * 1000000);
  #endif
  Serial.println(" Going to sleep now");
  esp_deep_sleep_start();
  Serial.println("This will never be printed");
}

void setup()
{
   // Light up the discrete red LED on the back of the board to show the device is active
  pinMode(ledPin, OUTPUT);
  // It's an active low pin, so we write a LOW value to turn it on
  digitalWrite(ledPin, LOW);

  // CAUTION - We'll disable the brownout detection
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);

  // Start serial connection for debugging purposes

  Serial.begin(115200);
  //while (!Serial);            //wait for serial connection.
 Serial.println(__FILE__ __DATE__);

  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;

  // Frame parameters
  //  config.frame_size = FRAMESIZE_UXGA;
  if(psramFound()){
  config.frame_size = FRAMESIZE_QVGA;
  config.jpeg_quality = 12;
  config.fb_count = 2;
} 
else {
    config.frame_size = FRAMESIZE_SVGA;
    config.jpeg_quality = 12;
    config.fb_count = 1;
}
#if defined(CAMERA_MODEL_ESP_EYE)
  pinMode(13, INPUT_PULLUP);
  pinMode(14, INPUT_PULLUP);
#endif

  cam.init(config);
// Disable any hold on pin 4 that was placed before ESP32 went to sleep
  rtc_gpio_hold_dis(GPIO_NUM_4);
  // Use PWM channel 7 to control the white on-board LED (flash) connected to GPIO 4
  ledcSetup(7, 5000, 8);
  ledcAttachPin(4, 7);
  // Turn the LED on at specified power
  ledcWrite(7, flashPower);

  // Initialise the camera
  // Short pause helps to ensure the I2C interface has initialised properly before attempting to detect the camera
  delay(250);
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Camera init failed with error 0x%x", err);
    sleep();
  }

  // Image settings
  sensor_t * s = esp_camera_sensor_get();
  // Gain
  s->set_gain_ctrl(s, 1);      // Auto-Gain Control 0 = disable , 1 = enable
  s->set_agc_gain(s, 0);       // Manual Gain 0 to 30
  s->set_gainceiling(s, (gainceiling_t)0);  // 0 to 6
  // Exposure
  s->set_exposure_ctrl(s, 1);  // Auto-Exposure Control 0 = disable , 1 = enable
  s->set_aec_value(s, 300);    // Manual Exposure 0 to 1200
  // Exposure Correction
  s->set_aec2(s, 0);           // Automatic Exposure Correction 0 = disable , 1 = enable
  s->set_ae_level(s, 0);       // Manual Exposure Correction -2 to 2
  // White Balance
  s->set_awb_gain(s, 1);       // Auto White Balance 0 = disable , 1 = enable
  s->set_wb_mode(s, 0);        // White Balance Mode 0 to 4 - if awb_gain enabled (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
  s->set_whitebal(s, 1);       // White Balance 0 = disable , 1 = enable
  s->set_bpc(s, 0);            // Black Pixel Correction 0 = disable , 1 = enable
  s->set_wpc(s, 1);            // White Pixel Correction 0 = disable , 1 = enable
  s->set_brightness(s, 0);     // Brightness -2 to 2
  s->set_contrast(s, 0);       // Contrast -2 to 2
  s->set_saturation(s, 0);     // Saturation -2 to 2
  s->set_special_effect(s, 0); // (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, 4 - Green Tint, 5 - Blue Tint, 6 - Sepia)
  // Additional settings
  s->set_lenc(s, 1);           // Lens correction 0 = disable , 1 = enable
  s->set_hmirror(s, 0);        // Horizontal flip image 0 = disable , 1 = enable
  s->set_vflip(s, 0);          // Vertical flip image 0 = disable , 1 = enable
  s->set_colorbar(s, 0);       // Colour Testbar 0 = disable , 1 = enable
  s->set_raw_gma(s, 1);        // 0 = disable , 1 = enable
  s->set_dcw(s, 1);            // 0 = disable , 1 = enable
  
  // We want to take the picture as soon as possible after the sensor has been triggered, so we'll do that first, before
  // setting up the SD card, Wifi etc.
  // Initialise a framebuffer 
  camera_fb_t *fb = NULL;
  // But... we still need to give the camera a few seconds to adjust the auto-exposure before taking the picture
  // Otherwise you get a green-tinged image as per https://github.com/espressif/esp32-camera/issues/55
  // Two seconds should be enough
  delay(startupDelayMillis);
  // Take picture
  fb = esp_camera_fb_get();
  // Check it was captured ok  
  if(!fb) {
    Serial.println("Camera capture failed");
    sleep();
  }

  // Turn flash off after taking picture
  ledcWrite(7, 0);

  // Build up the string of the filename we'll use to save the file
  path = "/pic";

  // Following section creates filename based on increment value saved in EEPROM
  #ifdef USE_INCREMENTAL_FILE_NUMBERING
    // We only need 2 bytes of EEPROM to hold a single int value, but according to
    // https://arduino-esp8266.readthedocs.io/en/latest/libraries.html#eeprom
    // Minimum reserved size is 4 bytes, so we'll use that
    EEPROM.begin(4);
    // Read the value from the EEPROM cache
    EEPROM.get(0, pictureNumber);
    pictureNumber += 1;
    // Path where new picture will be saved in SD Card
    path += String(pictureNumber) + "_";
    // Update the EEPROM cache
    EEPROM.put(0, pictureNumber);
    // And then actually write the modified cache values back to EEPROM
    EEPROM.commit();
  #endif

  // Connect to Wi-Fi if required
  #if defined(SEND_EMAIL) || defined(USE_TIMESTAMP)
    WiFi.mode(WIFI_STA);
    WiFi.setHostname("");
    int connAttempts = 0;

  IPAddress ip;

  WiFi.mode(WIFI_STA);
  WiFi.begin(SSID1, PWD1);
  WiFi.setHostname("");
 

  while (WiFi.status() != WL_CONNECTED);
  {
    delay(500);
    Serial.print(F("."));
    connAttempts++;
  }
{
  ip = WiFi.localIP();
  Serial.println(F("WiFi connected"));
  Serial.println("");
  Serial.println(ip);
  Serial.print("Stream Link: http://");
  Serial.print(ip);
  Serial.println("/mjpeg/1");
  server.on("/mjpeg/1", HTTP_GET, handle_jpg_stream);
  server.on("/jpg", HTTP_GET, handle_jpg);
  server.onNotFound(handleNotFound);
  server.begin();
}

if(WiFi.isConnected()){
      Serial.println("");
      Serial.println("WiFi connected.");
      Serial.println("IP address: ");
      Serial.println(WiFi.localIP());
      Serial.print(" Signal Level: ");
      Serial.println(WiFi.RSSI());
      Serial.println();
    }
else {
      Serial.println(F("Failed to connect to Wi-Fi"));
      sleep();
    }
  #endif

  #ifdef USE_TIMESTAMP
    // Following section creates filename based on timestamp
    const long gmtOffset_sec = 0;
    const int daylightOffset_sec = 0;
    // Synchronise time from specified NTP server - e.g. "pool.ntp.org", "time.windows.com", "time.nist.gov"
    // From https://github.com/espressif/arduino-esp32/blob/master/libraries/ESP32/examples/Time/SimpleTime/SimpleTime.ino
    configTime(gmtOffset_sec, daylightOffset_sec, "pool.ntp.org");
    struct tm timeinfo;
    if(!getLocalTime(&timeinfo)){
      Serial.println("Failed to obtain time");
      sleep();
    }
    else {
      Serial.print("Current time is ");
      Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
      char timeStringBuff[50]; //50 chars should be enough
      strftime(timeStringBuff, sizeof(timeStringBuff), "%Y%m%d_%H%M%S", &timeinfo);
      path += (String)timeStringBuff;
    }
  #endif

  // Add the file extension
  path += ".jpg";
  
  // Next, we need to start the SD card
  Serial.println("Starting SD Card");
  if(!MailClient.sdBegin(14, 2, 15, 13)) {
    Serial.println("SD Card Mount Failed");
    sleep();
  }

  // Access the file system on the SD card
  fs::FS &fs = SD;
  // Attempt to save the image to the specified path
  File file = fs.open(path.c_str(), FILE_WRITE);
  if(!file){
    Serial.printf("Failed to save to path: %s\n", path.c_str());
    sleep();
  }
  else {
    file.write(fb->buf, fb->len); // payload (image), payload length
    Serial.printf("Saved file to path: %s\n", path.c_str());
  }
  file.close();

  // Now that we've written the file to SD card, we can release the framebuffer memory of the camera
  esp_camera_fb_return(fb);
  // And breathe for a moment...
  delay(1000);

  #ifdef SEND_EMAIL
    // Get verbose output of emailing process
    smtp.debug(1); 
    // Assign the callback function called after sending
    smtp.callback(smtpCallback);
    // Define the session config data which used to store the TCP session configuration
    ESP_Mail_Session session;
    session.server.host_name = SMTP_HOST;
    session.server.port = SMTP_PORT;
    session.login.email = AUTHOR_EMAIL;
    session.login.password = AUTHOR_PASSWORD;
    session.login.user_domain = "mydomain.net";

    // Define the SMTP_Message class variable to hold the config of the eMail itself
    SMTP_Message message;
    //message.enable.chunking = true; // Enable chunked data transfer for large messages if server supported
    message.sender.name = "ESP32-CAM";
    message.sender.email = AUTHOR_EMAIL;
    message.subject = "Motion Detected - ESP32-CAM";
    message.addRecipient("", "");
    //message.addRecipient("", "");
    //message.addCc("email3");
    //message.addBcc("email4");
    // Set the message content
    message.text.content = "Motion has been detected, and you are receiving a Pest Memo.  Please take a look inside of it.";
    message.text.transfer_encoding = Content_Transfer_Encoding::enc_base64;

    // Now define the attachment properties
    SMTP_Attachment att;
    att.descr.filename = "photo.jpg";
    att.descr.mime = "application/octet-stream"; //binary data
    att.file.path = path.c_str();
    att.file.storage_type = esp_mail_file_storage_type_sd;
    att.descr.transfer_encoding = Content_Transfer_Encoding::enc_base64;
    // Add attachment to the message
    message.addAttachment(att);

    // Connect to server with the session config
    Serial.println("Connecting to SMTP");
    if(!smtp.connect(&session)) {
      Serial.println("Couldn't connect");
      sleep();
    }
    // Start sending Email and close the session
    Serial.println("Sending Mail");
    if(!MailClient.sendMail(&smtp, &message)) {
      Serial.println("Error sending Email, " + smtp.errorReason());
      sleep();
    }
  #endif

  // Now that email is sent, we can turn the Wi-Fi off
  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);

  // And go to bed until the next time we are triggered to take a photo
  sleep();
} 

void loop()
{
  server.handleClient();
}

OV2640.h

#ifndef OV2640_H_
#define OV2640_H_

#include <Arduino.h>
#include <pgmspace.h>
#include <stdio.h>
#include "esp_log.h"
#include "esp_attr.h"
#include "esp_camera.h"

extern camera_config_t esp32cam_config, esp32cam_aithinker_config, esp32cam_ttgo_t_config;

class OV2640
{
public:
    OV2640(){
        fb = NULL;
    };
    ~OV2640(){
    };
    esp_err_t init(camera_config_t config);
    void run(void);
    size_t getSize(void);
    uint8_t *getfb(void);
    int getWidth(void);
    int getHeight(void);
    framesize_t getFrameSize(void);
    pixformat_t getPixelFormat(void);

    void setFrameSize(framesize_t size);
    void setPixelFormat(pixformat_t format);

private:
    void runIfNeeded(); // grab a frame if we don't already have one

    // camera_framesize_t _frame_size;
    // camera_pixelformat_t _pixel_format;
    camera_config_t _cam_config;

    camera_fb_t *fb;
};

#endif //OV2640_H_

camera_pins.h

#if defined(CAMERA_MODEL_WROVER_KIT)
#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

#elif defined(CAMERA_MODEL_ESP_EYE)
#define PWDN_GPIO_NUM    -1
#define RESET_GPIO_NUM   -1
#define XCLK_GPIO_NUM    4
#define SIOD_GPIO_NUM    18
#define SIOC_GPIO_NUM    23

#define Y9_GPIO_NUM      36
#define Y8_GPIO_NUM      37
#define Y7_GPIO_NUM      38
#define Y6_GPIO_NUM      39
#define Y5_GPIO_NUM      35
#define Y4_GPIO_NUM      14
#define Y3_GPIO_NUM      13
#define Y2_GPIO_NUM      34
#define VSYNC_GPIO_NUM   5
#define HREF_GPIO_NUM    27
#define PCLK_GPIO_NUM    25

#elif defined(CAMERA_MODEL_M5STACK_PSRAM)
#define PWDN_GPIO_NUM     -1
#define RESET_GPIO_NUM    15
#define XCLK_GPIO_NUM     27
#define SIOD_GPIO_NUM     25
#define SIOC_GPIO_NUM     23

#define Y9_GPIO_NUM       19
#define Y8_GPIO_NUM       36
#define Y7_GPIO_NUM       18
#define Y6_GPIO_NUM       39
#define Y5_GPIO_NUM        5
#define Y4_GPIO_NUM       34
#define Y3_GPIO_NUM       35
#define Y2_GPIO_NUM       32
#define VSYNC_GPIO_NUM    22
#define HREF_GPIO_NUM     26
#define PCLK_GPIO_NUM     21

#elif defined(CAMERA_MODEL_M5STACK_WIDE)
#define PWDN_GPIO_NUM     -1
#define RESET_GPIO_NUM    15
#define XCLK_GPIO_NUM     27
#define SIOD_GPIO_NUM     22
#define SIOC_GPIO_NUM     23

#define Y9_GPIO_NUM       19
#define Y8_GPIO_NUM       36
#define Y7_GPIO_NUM       18
#define Y6_GPIO_NUM       39
#define Y5_GPIO_NUM        5
#define Y4_GPIO_NUM       34
#define Y3_GPIO_NUM       35
#define Y2_GPIO_NUM       32
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     26
#define PCLK_GPIO_NUM     21

#elif defined(CAMERA_MODEL_AI_THINKER)
#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

#else
#error "Camera model not selected"
#endif

srcOV2640.h

#include "OV2640.h"

#define TAG "OV2640"

// definitions appropriate for the ESP32-CAM devboard (and most clones)
camera_config_t esp32cam_config{

    .pin_pwdn = -1, // FIXME: on the TTGO T-Journal I think this is GPIO 0
    .pin_reset = 15,

    .pin_xclk = 27,

    .pin_sscb_sda = 25,
    .pin_sscb_scl = 23,

    .pin_d7 = 19,
    .pin_d6 = 36,
    .pin_d5 = 18,
    .pin_d4 = 39,
    .pin_d3 = 5,
    .pin_d2 = 34,
    .pin_d1 = 35,
    .pin_d0 = 17,
    .pin_vsync = 22,
    .pin_href = 26,
    .pin_pclk = 21,
    .xclk_freq_hz = 20000000,
    .ledc_timer = LEDC_TIMER_0,
    .ledc_channel = LEDC_CHANNEL_0,
    .pixel_format = PIXFORMAT_JPEG,
    // .frame_size = FRAMESIZE_UXGA, // needs 234K of framebuffer space
    // .frame_size = FRAMESIZE_SXGA, // needs 160K for framebuffer
    // .frame_size = FRAMESIZE_XGA, // needs 96K or even smaller FRAMESIZE_SVGA - can work if using only 1 fb
    .frame_size = FRAMESIZE_SVGA,
    .jpeg_quality = 12, //0-63 lower numbers are higher quality
    .fb_count = 2       // if more than one i2s runs in continous mode.  Use only with jpeg
};

camera_config_t esp32cam_aithinker_config{

    .pin_pwdn = 32,
    .pin_reset = -1,

    .pin_xclk = 0,

    .pin_sscb_sda = 26,
    .pin_sscb_scl = 27,

    // Note: LED GPIO is apparently 4 not sure where that goes
    // per https://github.com/donny681/ESP32_CAMERA_QR/blob/e4ef44549876457cd841f33a0892c82a71f35358/main/led.c
    .pin_d7 = 35,
    .pin_d6 = 34,
    .pin_d5 = 39,
    .pin_d4 = 36,
    .pin_d3 = 21,
    .pin_d2 = 19,
    .pin_d1 = 18,
    .pin_d0 = 5,
    .pin_vsync = 25,
    .pin_href = 23,
    .pin_pclk = 22,
    .xclk_freq_hz = 20000000,
    .ledc_timer = LEDC_TIMER_1,
    .ledc_channel = LEDC_CHANNEL_1,
    .pixel_format = PIXFORMAT_JPEG,
    // .frame_size = FRAMESIZE_UXGA, // needs 234K of framebuffer space
    // .frame_size = FRAMESIZE_SXGA, // needs 160K for framebuffer
    // .frame_size = FRAMESIZE_XGA, // needs 96K or even smaller FRAMESIZE_SVGA - can work if using only 1 fb
    .frame_size = FRAMESIZE_SVGA,
    .jpeg_quality = 12, //0-63 lower numbers are higher quality
    .fb_count = 2       // if more than one i2s runs in continous mode.  Use only with jpeg
};

camera_config_t esp32cam_ttgo_t_config{

    .pin_pwdn = 26,
    .pin_reset = -1,

    .pin_xclk = 32,

    .pin_sscb_sda = 13,
    .pin_sscb_scl = 12,

    .pin_d7 = 39,
    .pin_d6 = 36,
    .pin_d5 = 23,
    .pin_d4 = 18,
    .pin_d3 = 15,
    .pin_d2 = 4,
    .pin_d1 = 14,
    .pin_d0 = 5,
    .pin_vsync = 27,
    .pin_href = 25,
    .pin_pclk = 19,
    .xclk_freq_hz = 20000000,
    .ledc_timer = LEDC_TIMER_0,
    .ledc_channel = LEDC_CHANNEL_0,
    .pixel_format = PIXFORMAT_JPEG,
    .frame_size = FRAMESIZE_SVGA,
    .jpeg_quality = 12, //0-63 lower numbers are higher quality
    .fb_count = 2       // if more than one i2s runs in continous mode.  Use only with jpeg
};

void OV2640::run(void)
{
    if (fb)
        //return the frame buffer back to the driver for reuse
        esp_camera_fb_return(fb);

    fb = esp_camera_fb_get();
}

void OV2640::runIfNeeded(void)
{
    if (!fb)
        run();
}

int OV2640::getWidth(void)
{
    runIfNeeded();
    return fb->width;
}

int OV2640::getHeight(void)
{
    runIfNeeded();
    return fb->height;
}

size_t OV2640::getSize(void)
{
    runIfNeeded();
    if (!fb)
        return 0; // FIXME - this shouldn't be possible but apparently the new cam board returns null sometimes?
    return fb->len;
}

uint8_t *OV2640::getfb(void)
{
    runIfNeeded();
    if (!fb)
        return NULL; // FIXME - this shouldn't be possible but apparently the new cam board returns null sometimes?

    return fb->buf;
}

framesize_t OV2640::getFrameSize(void)
{
    return _cam_config.frame_size;
}

void OV2640::setFrameSize(framesize_t size)
{
    _cam_config.frame_size = size;
}

pixformat_t OV2640::getPixelFormat(void)
{
    return _cam_config.pixel_format;
}

void OV2640::setPixelFormat(pixformat_t format)
{
    switch (format)
    {
    case PIXFORMAT_RGB565:
    case PIXFORMAT_YUV422:
    case PIXFORMAT_GRAYSCALE:
    case PIXFORMAT_JPEG:
        _cam_config.pixel_format = format;
        break;
    default:
        _cam_config.pixel_format = PIXFORMAT_GRAYSCALE;
        break;
    }
}

esp_err_t OV2640::init(camera_config_t config)
{
    memset(&_cam_config, 0, sizeof(_cam_config));
    memcpy(&_cam_config, &config, sizeof(config));

    esp_err_t err = esp_camera_init(&_cam_config);
    if (err != ESP_OK)
    {
        printf("Camera probe failed with error 0x%x", err);
        return err;
    }
    // ESP_ERROR_CHECK(gpio_install_isr_service(0));

    return ESP_OK;
}

What I will be trying to add in for my fan is:

int speedPin=5;
int dir1=4;
int dir2=3;
int mSpeed=255;

void setup() {
pinMode (speedPin, OUTPUT);
pinMode (dir1, OUTPUT);
pinMode (dir2, OUTPUT);
Serial.begin (115200);

void loop() {
digitalWrite (dir1, HIGH);
digitalWrite (dir2, LOW);
analogWrite (speedPin, mSpeed);
}

I am hoping that I can have the fan turn on for 3 seconds then sleep for 30 minutes then repeat. I would like to use code like this:

#define TIMED_MODE

const int timelapseinterval = 1800 seconds //seconds between 3 second burst
void sleep() {

pinMode(triggerPin, INPUT_PULLUP);
esp_sleep_enable_enable_ext0_wakeup(GPIO_NUM_14, 0);

#elif defined(TIMED_MODE)

esp_sleep_enable_timer_wakeup(timelapseInterval * 1800000000)

how about adding

while (WiFi.status() != WL_CONNECTED);
  {
    delay(500);
    Serial.print(F("."));
    connAttempts++;
  }
{
Serial.print ( "woot! woot! I connected! " );
Serial.println( WiFi.localIP() );
  ip = WiFi.localIP();
  Serial.println(F("WiFi connected"));
  Serial.println("");
  

adding the above print statements does it print the IP address?

You know serial printing during callbacks is a bad idea? You can do your research on this site to find out why.

You should fix that first. (in a test sketch)

1 Like

Good point.

Any thoughts on how I can fix that? I was researching how to fix it last night and this morning. The ESP32 Cam it showed up in is a brand new board and camera.

Try another camera, or put the camera you have in another ESP32CAM.

Post an image of the ESP32 camera connected to the module.