ESP32-CAM and Blynk -> FTP upload 📸

Hi,

Few people tried to stream their ESP32 camera :camera_flash: to the Blynk App and I’m not sure if someone succeed, however if you want to use stills and show a picture in the App, here’s a solution:

Take a picture -> Upload to your free generic website via FTP (I used 000webhost) -> use the URL generated on the Image Gallery Widget

FTP upload:

  ftp.OpenConnection();

  // Create the new file and send the image
  ftp.InitFile("Type I");
  ftp.ChangeWorkDir("/public_html/zyro/gallery_gen/"); //<- Change this to reflect yout website public directory
  ftp.NewFile("mynewpicture_5465846541.jpg");
  ftp.WriteData( octocat_pic, sizeof(octocat_pic) );
  ftp.CloseFile();

  ftp.CloseConnection();

And the Blynk code as simple as:

Blynk.setProperty(VX, "url", 1, "https://mywebsite/something/mynewpicture_5465846541.jpg")

The full example below, or on GitHub.

/******************************************************************************
ESP32-CAM remote image access via FTP. Take pictures with ESP32 and upload it via FTP making it accessible for the outisde network. 
Leonardo Bispo
July - 2019
https://github.com/ldab/ESP32-CAM-Picture-Sharing
Distributed as-is; no warranty is given.
******************************************************************************/
#include "Arduino.h"

/* Comment this out to disable prints and save space */
//#define BLYNK_DEBUG
//#define BLYNK_PRINT Serial
#define BLYNK_NO_BUILTIN
#define BLYNK_NO_FLOAT

// Enable Debug interface and serial prints over UART1
#define DEGUB_ESP

// Blynk related Libs
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <TimeLib.h>
#include <WidgetRTC.h>

#include "esp_camera.h"
#include "esp_timer.h"
#include "img_converters.h"

#include "esp_http_server.h"
#include "fb_gfx.h"
#include "fd_forward.h"
#include "fr_forward.h"
//#include "soc/soc.h"           //disable brownout problems
//#include "soc/rtc_cntl_reg.h"  //disable brownout problems
#include "dl_lib.h"

// Connection timeout;
#define CON_TIMEOUT   10*1000                     // milliseconds

// Not using Deep Sleep on PCB because TPL5110 timer takes over.
#define TIME_TO_SLEEP (uint64_t)60*60*1000*1000   // microseconds

#ifdef DEGUB_ESP
  #define DBG(x) Serial.println(x)
#else 
  #define DBG(...)
#endif

// FTP Client Lib
#include "ESP32_FTPClient.h"

// Go to the Project Settings (nut icon) and get Auth Token in the Blynk App.
char auth[] = "";

// Your WiFi credentials.
char ssid[] = "";
char pass[] = "";

// FTP Server credentials
char ftp_server[] = "files.000webhost.com";
char ftp_user[]   = "";
char ftp_pass[]   = "";

// Camera buffer, URL and picture name
camera_fb_t *fb = NULL;
String pic_name = "";
String pic_url  = "";

// Variable marked with this attribute will keep its value during a deep sleep / wake cycle.
RTC_DATA_ATTR uint64_t bootCount = 0;

WidgetRTC rtc;
ESP32_FTPClient ftp (ftp_server, ftp_user, ftp_pass);

void deep_sleep(void);
void FTP_upload( void );
bool take_picture(void);

BLYNK_CONNECTED()
{
  // Synchronize time on connection
  rtc.begin();
}

void setup()
{
#ifdef DEGUB_ESP
  Serial.begin(115200);
  Serial.setDebugOutput(true);
#endif

  //WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector

  camera_config_t config;
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer   = LEDC_TIMER_0;
  config.pin_d0       = 5;
  config.pin_d1       = 18;
  config.pin_d2       = 19;
  config.pin_d3       = 21;
  config.pin_d4       = 36;
  config.pin_d5       = 39;
  config.pin_d6       = 34;
  config.pin_d7       = 35;
  config.pin_xclk     = 0;
  config.pin_pclk     = 22;
  config.pin_vsync    = 25;
  config.pin_href     = 23;
  config.pin_sscb_sda = 26;
  config.pin_sscb_scl = 27;
  config.pin_pwdn     = 32;
  config.pin_reset    = -1;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_JPEG;

  //init with high specs to pre-allocate larger buffers
  config.frame_size = FRAMESIZE_XGA; // set picture size, FRAMESIZE_XGA = 1024x768
  config.jpeg_quality = 10;          // quality of JPEG output. 0-63 lower means higher quality
  config.fb_count = 2;

  // camera init
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK)
  {
    Serial.print("Camera init failed with error 0x%x");
    DBG(err);
    return;
  }

  // Change extra settings if required
  //sensor_t * s = esp_camera_sensor_get();
  //s->set_vflip(s, 0);       //flip it back
  //s->set_brightness(s, 1);  //up the blightness just a bit
  //s->set_saturation(s, -2); //lower the saturation
  
  // Enable timer wakeup for ESP32 sleep
  esp_sleep_enable_timer_wakeup( TIME_TO_SLEEP );

  WiFi.begin( ssid, pass );
  DBG("\nConnecting to WiFi");

  while ( WiFi.status() != WL_CONNECTED && millis() < CON_TIMEOUT )
  {
    delay(500);
    Serial.print(".");
  }

  if( !WiFi.isConnected() )
  {
    DBG("Failed to connect to WiFi, going to sleep");
    deep_sleep();
  }

  DBG("");
  DBG("WiFi connected");
  DBG( WiFi.localIP() );

  Blynk.config( auth );

}

void loop()
{

  Blynk.run();

  if(Blynk.connected() && timeStatus() == 2)
  {
      // Take picture
    if( take_picture() )
    {
      FTP_upload();

      deep_sleep();
    }

    else
    {
      DBG("Capture failed, sleeping");
      deep_sleep();
    }
  }

  if( millis() > CON_TIMEOUT)
  {
    DBG("Timeout");

    deep_sleep();
  }

}

void deep_sleep()
{
  DBG("Going to sleep after: " + String( millis() ) + "ms");
  Serial.flush();

  esp_deep_sleep_start();
}

bool take_picture()
{
  DBG("Taking picture now");

  fb = esp_camera_fb_get();  
  if(!fb)
  {
    DBG("Camera capture failed");
    return false;
  }
  
  // Rename the picture with the time string
  pic_name += String( now() ) + ".jpg";
  DBG("Camera capture success, saved as:");
  DBG( pic_name );

  return true;
}

void FTP_upload()
{
  DBG("Uploading via FTP");
  ftp.OpenConnection();
  
  //Create a file and write the image data to it;
  ftp.InitFile("Type I");
  ftp.ChangeWorkDir("/public_html/zyro/gallery_gen/"); // change it to reflect your directory
  const char *f_name = pic_name.c_str();
  ftp.NewFile( f_name );
  ftp.WriteData(fb->buf, fb->len);
  ftp.CloseFile();

  // Change URL on Blynk App
  pic_url += pic_name;
  DBG("Change App URL to: ");
  DBG( pic_url );
  Blynk.setProperty(V0, "url", 1, pic_url);

  // Breath, withouth delay URL failed to update.
  delay(100);

}

Peace.

6 Likes

You can use rstp to see video streaming

and read with Blynk video streaming widget using :

rtsp://yourdevipaddr:8554/mjpeg/1

1 Like

Good to know, but I’m afraid I will need some port-forwarding for that, right?

to access from outside ? yes port 8554
else no matter

Thought so, and this is/was my motivation for the example given, no port forwarding.

2 Likes

Creative use of Image Gallery! :clap::clap::clap:

3 Likes

Hi Pavel
it had been a long time since we had seen you
:joy::joy:
Alexis

Big Brother is always there… watching :joy:

3 Likes

In that case you should stop watching and get on with Blynk 2.0 Beta :grinning:

Pete.

4 Likes

Holiday party is on :joy::joy:

Here a similar project.
Please watch my new video.
Voice controlled motion detection camera using ESP32CAM and PIR motion sensor. & Blynk

Hi,

Can you update this code with Blynk 2.0?

Best.

hello sir, I want to ask how to connect from esp 32 cam to blynk, is it possible? and how? :grin:

Yes, it is possible.
How you do that depends on your local network setup, so there is no simple step-by-step guide - it will be different for each user.

If you don’t have a static public IP address then you will need to use a DDNS service, and you’ll need to use a DDNS update client running on a device on your network. This might be your router, if it supports that, or an MCU running DDNS client software.
Your ESP32 CAM will need a static local IP address, and you’ll then need to do port forwarding in your router to forward inbound traffic on the port you are using to the ESP32 CAM device’s local IP address.

Once you’ve done this, and have a publicly resolvable URL for your video stream, using the DDNS URL you’ve created, you will be able to use that URL in the Blynk video streaming widget.

Pete.