Help Getting BlynkEdgent To Work

Can you help me get this code to work? Thank you. I have not included all of the files because there is a space limit here. I am open adding more if necessary.

I am using an ESP32 camera with a microwave sensor and a fan. I am trying to upload my Arduino sketch using a FTDI232 via USB. I paid someone off of Fiverr to write the code because I was not able to do it myself and could not find anyone locally. My smartphone is iOS XR. I am trying to use BlynkEdgent so that when I take my device to a new location I do not have upload a sketch. Here is the error message I received when I tried to upload the sketch.

Arduino: 1.8.15 (Windows 10), Board: "AI Thinker ESP32-CAM, 240MHz (WiFi/BT), QIO, 80MHz"

Sketch uses 2921798 bytes (92%) of program storage space. Maximum is 3145728 bytes.

Global variables use 61044 bytes (18%) of dynamic memory, leaving 266636 bytes for local variables. Maximum is 327680 bytes.

esptool.py v3.0-dev

Serial port COM3

Connecting........_____....._____....._____.

Chip is ESP32-D0WDQ6 (revision 1)

Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None

Crystal is 40MHz

MAC: 94:b9:7e:c3:78:34

Uploading stub...

Running stub...

Stub running...

Changing baud rate to 460800

Changed.

Configuring flash size...

Auto-detected Flash size: 4MB

Compressed 8192 bytes to 47...

Writing at 0x0000e000... (100 %)

Wrote 8192 bytes (47 compressed) at 0x0000e000 in 0.0 seconds (effective 4681.2 kbit/s)...

A fatal error occurred: Invalid head of packet (0x78)

A fatal error occurred: Invalid head of packet (0x78)

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

Combined_v1

#define BLYNK_TEMPLATE_ID ""
#define BLYNK_DEVICE_NAME ""
#define BLYNK_AUTH_TOKEN ""

#include "src/OV2640.h"
#include <WiFi.h>
#include <WebServer.h>
#include <WiFiClient.h>
#include "esp_camera.h"

//blynk
//#include <BlynkSimpleEsp32.h>

#define BLYNK_FIRMWARE_TYPE "none"
#define BLYNK_FIRMWARE_VERSION        "0.1.4"
#define BLYNK_PRINT Serial
#define APP_DEBUG
#include "BlynkEdgent.h"

//camera
#define CAMERA_MODEL_AI_THINKER
#include "camera_pins.h"
OV2640 cam;
//picture notification
String my_Local_IP;
void startCameraServer();

//wifi
#define SSID1 ""
#define PWD1 ""

//microwave sensor
#define RADAR 15

//fan
#define fanPin 4
unsigned long previousMillis = 0;
const long interval = 10000; // 30 minutes --> 30min * 60sec/min * 1000ms/sec = 1800000ms

//blynk -> for line notification
char auth[] = "";

//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 notifyMotion() {
  Serial.println("Sent notification");
  Blynk.notify("Motion Detected open to view picture and stream!");
}

void capture(){
  uint32_t number = random(40000000);
  Blynk.notify("Here is the image that was captured..");
  Serial.println("image captured");
  Serial.println("http://"+my_Local_IP+"/capture?_cb="+ (String)number);
  Blynk.setProperty(V1, "urls", "http://"+my_Local_IP+"/capture?_cb="+(String)number);
  delay(1000);
}

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);
}

void setup()
{
  pinMode(fanPin, OUTPUT);
  Serial.begin(115200);
  delay(100);
  //while (!Serial);            //wait for serial connection.
  
  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;
  config.frame_size = FRAMESIZE_QVGA;
  config.jpeg_quality = 12;
  config.fb_count = 2;


  cam.init(config);
  
  BlynkEdgent.begin();
  
  IPAddress ip;
  WiFi.mode(WIFI_STA);
  WiFi.begin(SSID1, PWD1);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(F("."));
  }
  
  ip = WiFi.localIP();
  my_Local_IP = ip.toString();
  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();

  //camera server
  startCameraServer();

  Serial.print("Camera Ready! Use 'http://");
  Serial.print(ip);
  Serial.println("' to connect");
  Blynk.begin(auth, SSID1, PWD1);
  
}

void switchFan() {
  digitalWrite(fanPin, HIGH);
  delay(2000);
  digitalWrite(fanPin, LOW);
}

void loop()
{
  unsigned long currentMillis = millis();
  BlynkEdgent.run();
  //Blynk.run();
  //server.handleClient(); 
  if (currentMillis - previousMillis >= interval) {
    // save the last time you turned on the fan
    previousMillis = currentMillis;
    Serial.println("Switching fan on");
    switchFan();
    notifyMotion();
  }
  if (digitalRead(RADAR) == LOW) {
    //notifyMotion();
    //capture();
  }
}

Sketch tab named BlynkEdgent.h


extern "C" {
  void app_loop();
  void eraseMcuConfig();
  void restartMCU();
}

#include "Settings.h"
#include <BlynkSimpleEsp32_SSL.h>

#ifndef BLYNK_NEW_LIBRARY
#error "Old version of Blynk library is in use. Please replace it with the new one."
#endif

#if !defined(BLYNK_TEMPLATE_ID) || !defined(BLYNK_DEVICE_NAME)
#error "Please specify your BLYNK_TEMPLATE_ID and BLYNK_DEVICE_NAME"
#endif

#include "BlynkState.h"
#include "ConfigStore.h"
#include "ResetButton.h"
#include "ConfigMode.h"
#include "Indicator.h"
#include "OTA.h"
#include "Console.h"

inline
void BlynkState::set(State m) {
  if (state != m && m < MODE_MAX_VALUE) {
    DEBUG_PRINT(String(StateStr[state]) + " => " + StateStr[m]);
    state = m;

    // You can put your state handling here,
    // i.e. implement custom indication
  }
}

void printDeviceBanner()
{
  Blynk.printBanner();
  DEBUG_PRINT("--------------------------");
  DEBUG_PRINT(String("Product:  ") + BLYNK_DEVICE_NAME);
  DEBUG_PRINT(String("Firmware: ") + BLYNK_FIRMWARE_VERSION " (build " __DATE__ " " __TIME__ ")");
  if (configStore.getFlag(CONFIG_FLAG_VALID)) {
    DEBUG_PRINT(String("Token:    ...") + (configStore.cloudToken+28));
  }
  DEBUG_PRINT(String("Device:   ") + BLYNK_INFO_DEVICE + " @ " + ESP.getCpuFreqMHz() + "MHz");
  DEBUG_PRINT(String("MAC:      ") + WiFi.macAddress());
  DEBUG_PRINT(String("Flash:    ") + ESP.getFlashChipSize() / 1024 + "K");
  DEBUG_PRINT(String("ESP sdk:  ") + ESP.getSdkVersion());
  DEBUG_PRINT(String("Chip rev: ") + ESP.getChipRevision());
  DEBUG_PRINT(String("Free mem: ") + ESP.getFreeHeap());
  DEBUG_PRINT("--------------------------");
}

void runBlynkWithChecks() {
  Blynk.run();
  if (BlynkState::get() == MODE_RUNNING) {
    if (!Blynk.connected()) {
      if (WiFi.status() == WL_CONNECTED) {
        BlynkState::set(MODE_CONNECTING_CLOUD);
      } else {
        BlynkState::set(MODE_CONNECTING_NET);
      }
    }
  }
}

class Edgent {

public:
  void begin()
  {
    WiFi.persistent(false);
    WiFi.enableSTA(true); // Needed to get MAC

    indicator_init();
    button_init();
    config_init();
    console_init();

    printDeviceBanner();

    if (configStore.getFlag(CONFIG_FLAG_VALID)) {
      BlynkState::set(MODE_CONNECTING_NET);
    } else if (config_load_blnkopt()) {
      DEBUG_PRINT("Firmware is preprovisioned");
      BlynkState::set(MODE_CONNECTING_NET);
    } else {
      BlynkState::set(MODE_WAIT_CONFIG);
    }
  }

  void run() {
    app_loop();
    switch (BlynkState::get()) {
    case MODE_WAIT_CONFIG:       
    case MODE_CONFIGURING:       enterConfigMode();    break;
    case MODE_CONNECTING_NET:    enterConnectNet();    break;
    case MODE_CONNECTING_CLOUD:  enterConnectCloud();  break;
    case MODE_RUNNING:           runBlynkWithChecks(); break;
    case MODE_OTA_UPGRADE:       enterOTA();           break;
    case MODE_SWITCH_TO_STA:     enterSwitchToSTA();   break;
    case MODE_RESET_CONFIG:      enterResetConfig();   break;
    default:                     enterError();         break;
    }
  }

};

Edgent BlynkEdgent;
BlynkTimer edgentTimer;

void app_loop() {
    edgentTimer.run();
    edgentConsole.run();
}

BlynkState.h


enum State {
  MODE_WAIT_CONFIG,
  MODE_CONFIGURING,
  MODE_CONNECTING_NET,
  MODE_CONNECTING_CLOUD,
  MODE_RUNNING,
  MODE_OTA_UPGRADE,
  MODE_SWITCH_TO_STA,
  MODE_RESET_CONFIG,
  MODE_ERROR,

  MODE_MAX_VALUE
};

#if defined(APP_DEBUG)
const char* StateStr[MODE_MAX_VALUE+1] = {
  "WAIT_CONFIG",
  "CONFIGURING",
  "CONNECTING_NET",
  "CONNECTING_CLOUD",
  "RUNNING",
  "OTA_UPGRADE",
  "SWITCH_TO_STA",
  "RESET_CONFIG",
  "ERROR",

  "INIT"
};
#endif

namespace BlynkState
{
  volatile State state = MODE_MAX_VALUE;

  State get()        { return state; }
  bool  is (State m) { return (state == m); }
  void  set(State m);
};

@drehawk
When you Compile code have any error?

If no error you have to erase your esp32 then try
Best Regards
Maaz

I believe I compiled it with no errors. I am compiling it again just to be sure.

How exactly is your FTDI connected to your board, and what position is the logic level voltage jumper on the FTDI ?

Pete.

After I compiled it again, I re-tried uploading it, and it uploaded. That part is over. The LED is flashing, and the serial monitor showed that it was connecting to the blynk.cloud. Even though the LED is flashing it is not showing that my device is online. It even allowed me to ship a firmware update over Blynk.Air and says it finished.

I want to actually test the device out by seeing what the camera is seeing. Then I want to be able to take the device with me to a new location to see if the WiFi provisions is going to work by asking me for the new WiFi credentials.

Where are you looking to see this information?
Have you refreshed the view by either refreshing the web browser or pulling downwards in the app?

The LED should stop flashing and transition to a slow pulsing once you’ve completed the provisioning process.

Are you specifying an auth token? If so then you shouldn’t be when using Edgent with dynamic provisioning.

This isn’t part of the standard ESP32 Edgent sketch. Why is it here?

You don’t have any board type defined (unless an entry has been created in Settings.h for CAMERA_MODEL_AI_THINKER) so we need to see your Settings.h file. We also need to know which GPIO pins are being used by other parts of your sketch.

The BlynkState.h appears to be missing 8 lines at the end.

The only changes that should be made to the basic ESP32 Edgent sketch are in the Edgent_ESP32.ino file and Settings.h file. If changes have bene made to the other standard Edgent files then I’d suggest that you replace them with the original files from the latest library examples.

Pete.

The "Blynk_Firmware_Type does not seem to be getting used. I will remove it.

Settings.h file


/*
 * Board configuration (see examples below).
 */

#if defined(USE_WROVER_BOARD)

  #define BOARD_BUTTON_PIN            15
  #define BOARD_BUTTON_ACTIVE_LOW     true

  #define BOARD_LED_PIN_R             0
  #define BOARD_LED_PIN_G             2
  #define BOARD_LED_PIN_B             4
  #define BOARD_LED_INVERSE           false
  #define BOARD_LED_BRIGHTNESS        128

#elif defined(USE_TTGO_T7)

  // This board does not have a built-in button
  // Connect a button to gpio0 <> GND
  #define BOARD_BUTTON_PIN            0
  #define BOARD_BUTTON_ACTIVE_LOW     true

  #define BOARD_LED_PIN               19
  #define BOARD_LED_INVERSE           false
  #define BOARD_LED_BRIGHTNESS        64

#else

  #warning "Custom board configuration is used"

  #define BOARD_BUTTON_PIN            0                     // Pin where user button is attached
  #define BOARD_BUTTON_ACTIVE_LOW     true                  // true if button is "active-low"

  #define BOARD_LED_PIN               4                     // Set LED pin - if you have a single-color LED attached
  //#define BOARD_LED_PIN_R           15                    // Set R,G,B pins - if your LED is PWM RGB
  //#define BOARD_LED_PIN_G           12
  //#define BOARD_LED_PIN_B           13
  //#define BOARD_LED_PIN_WS2812      4                     // Set if your LED is WS2812 RGB
  #define BOARD_LED_INVERSE           false                 // true if LED is common anode, false if common cathode
  #define BOARD_LED_BRIGHTNESS        64                    // 0..255 brightness control

#endif


/*
 * Advanced options
 */

#define BUTTON_HOLD_TIME_INDICATION   3000
#define BUTTON_HOLD_TIME_ACTION       10000

#define BOARD_PWM_MAX                 1023

#define BOARD_LEDC_CHANNEL_1     1
#define BOARD_LEDC_CHANNEL_2     2
#define BOARD_LEDC_CHANNEL_3     3
#define BOARD_LEDC_TIMER_BITS    10
#define BOARD_LEDC_BASE_FREQ     12000

#define CONFIG_AP_URL                 "blynk.setup"
#define CONFIG_DEFAULT_SERVER         "blynk.cloud"
#define CONFIG_DEFAULT_PORT           443

#define WIFI_NET_CONNECT_TIMEOUT      30000
#define WIFI_CLOUD_CONNECT_TIMEOUT    30000
#define WIFI_AP_IP                    IPAddress(192, 168, 4, 1)
#define WIFI_AP_Subnet                IPAddress(255, 255, 255, 0)
//#define WIFI_CAPTIVE_PORTAL_ENABLE

//#define USE_TICKER
//#define USE_TIMER_ONE
//#define USE_TIMER_THREE
//#define USE_TIMER_FIVE
#define USE_PTHREAD

#define BLYNK_NO_DEFAULT_BANNER

#if defined(APP_DEBUG)
  #define DEBUG_PRINT(...) BLYNK_LOG1(__VA_ARGS__)
#else
  #define DEBUG_PRINT(...)
#endif

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

Thank you.

You’ve answered some of my questions, but not others, so it’s impossible to help much.
However, my comments on the information you have supplied are…

You are using these settings from the camera_pins.h file, because you have #define CAMERA_MODEL_AI_THINKER in your .ino file…

You are also using these custom settings from the Settings.h file, because you don’t have a #define USE_WROVER_BOARD or #define USE_TTGO_T7 entry in your ,ino file…

As you can hopefully see, GPIO0 is being used for two different purposes, once by the Edgent software (to put the board into provisioning mode, or clear the provisioned values when pressed for 10 seconds) and once by your camera code. This won’t work.

Pete.

Thank you. I have shared this with my programmer.

I removed #define BLYNK_FIRMWARE_TYPE “none”. I had specified the auth token. I just didn’t include it here. I compared multiple BlynkState.h sketches using Edgent and could not find any missing lines. Can you share the lines that you find are missing and what version of Edgent that is from? I changed #define XCLK_GPIO_NUM to 14.

I didn’t answer the FTDI questions because I solved that. But, the voltage jumper was on 5 volts.

However, I am connecting VCC from the FTDI to 5v on the ESP32 CAM and connecting the ground from the FTDI to the ground right under the 5v pinout on the ESP32 Cam.

“The LED should stop flashing and transition to a slow pulsing once you’ve completed the provisioning process.”

It is still flashing every 500 ms. My Blynk.Console is saying that I have been able to update my firmware twice via Blynk.Air but I still cannot get the device to say it is online in Blynk and I am not able to see what the camera sees even after I corrected the double use of GPIO0.

Why?
If you want to use Edgent then the auth token will be provided as part opf the provisioning process.

My mistake, I missed the namespace BlynkState section when I was doing the comparison.
However, I’d still suggest replacing all of the standard Edgent .h files with those from the latest library.

The ESP32 uses 3.3v logic levels.

You really need to be able to see the serial monitor output to understand what is happening during the provisioning process.
Personally, I’d suggest that you load the Edgent example sketch as it stands and run through the provisioning process, with the serial monitor attached, so that you understand this process.

Pete.

My programmer included //blynk → for line notification
char auth = “” so I put my Blynk generated auth token in #define BLYNK_AUTH_TOKEN “”
from my template. Should char auth = “” be removed, too?

Check this out
https://docs.blynk.io/en/getting-started/activating-devices/blynk-edgent-wifi-provisioning