SKU_DFR0975_FireBeetle_2_Board_ESP32_S3_Advanced_Tutorial-DFRobot

1. Introduction

This is an advanced tutorial for FireBeetle ESP32-S3.
Click here to find more details about FireBeetle ESP32-S3.
Click here to view the basic tutorial for FireBeetle ESP32-S3.
Click here to look for information about Arduino programming.

2. Drive a Display on ESP32-S3

The DFRbot dedicated GDI display interface is for connecting a screen using a 18pin-FPC wire.

Displays that support GDI:

The pin list for using GDI display interface is shown below:

FPC PINS Beetle ESP32 S3 Pins Description
VCC 3V3 3.3V
LCD_BL 21/D13 Backlight
GND GND GND
SCLK 17/SCK SPI clock
MOSI 15/MOSI Host output, slave input
MISO 16/MISO Host input, slave output
LCD_DC 3/D2 Data/command
LCD_RST 38/D3 Reset
LCD_CS 18/D6 TFT Chip Select
SD_CS 9/D7 SD card chip select
FCS 7/D6 Font library chip select
TCS 12/D12 Touch chip select
SCL 2/SCL I2C clock
SDA 1/SDA I2C data
INT 13/D11 INT
BUSY 4/D10 Tearproof pins
X1 NC custom pin 1
X2 NC custom pin 2

When using FPC to connect the screen, please configure the corresponding pin numbers according to the GDL demo. Normally, only three pins need to be configured on different main controllers.

Sample Code

The example is for driving 1.8”128x160 IPS TFT LCD on ESP32-S3. Please download DFRobot_GDL library before use.

#include "DFRobot_GDL.h"

#define TFT_DC  3
#define TFT_CS  18
#define TFT_RST 38

DFRobot_ST7735_128x160_HW_SPI screen(/*dc=*/TFT_DC,/*cs=*/TFT_CS,/*rst=*/TFT_RST);
/* M0 mainboard DMA transfer */
//DFRobot_ST7735_128x160_DMA_SPI screen(/*dc=*/TFT_DC,/*cs=*/TFT_CS,/*rst=*/TFT_RST);


void setup() {
  Serial.begin(115200);
  screen.begin();
}

void loop(){
    testLine();
    testFastLines(COLOR_RGB565_PURPLE,COLOR_RGB565_YELLOW);       
    testRects(COLOR_RGB565_BLACK,COLOR_RGB565_WHITE);
    testRoundRects();
    testCircles(24,COLOR_RGB565_BLUE);
    testTriangles(COLOR_RGB565_YELLOW);
    testPrint();
}


void testLine(){
  uint16_t color = 0x00FF;
  screen.fillScreen(COLOR_RGB565_BLACK);
  for (int16_t x=0; x < screen.width(); x+=6) {
    screen.drawLine(/*x0=*/screen.width()/*Screen width*//2, /*y0=*/screen.height()/*Screen height*//2, /*x1=*/x, /*y1=*/0, /*c=*/color+=0x0700);
  }
  for (int16_t y=0; y < screen.height(); y+=6) {
    screen.drawLine(screen.width()/2, screen.height()/2, screen.width(), y, color+=0x0700);
  }

  for (int16_t x = screen.width(); x >= 0; x-=6) {
    screen.drawLine(screen.width()/2, screen.height()/2, x,screen.height(), color+=0x0700);
  }

  for (int16_t y = screen.height(); y >= 0; y-=6) {
    screen.drawLine(screen.width()/2, screen.height()/2, 0, y, color+=0x0700);
  }
}

void testFastLines(uint16_t color1, uint16_t color2) {
  for (int16_t y=0; y < screen.height(); y+=4) {
    screen.drawFastHLine(/*x=*/0, /*y=*/y, /*w=*/screen.width(),/*c=*/color2);
    delay(10);
  }

  for(int16_t x=0; x < screen.width(); x+=3) {
    screen.drawFastVLine(/*x=*/x, /*y=*/0, /*h=*/screen.height(), /*c=*/color1);
    delay(10);
  }
}

void testRects(uint16_t color1, uint16_t color2) { 
    screen.fillScreen(COLOR_RGB565_BLACK);
    int16_t x=screen.width()-12;
    for (; x > 100; x-=screen.width()/40) {
      screen.drawRect(/*x=*/screen.width()/2 -x/2, /*y=*/screen.height()/2 -x/2 , /*w=*/x, /*h=*/x, /*color=*/color2+=0x0F00);
      delay(100);
    }

    screen.fillRect(/*x=*/screen.width()/2 -x/2, /*y=*/screen.height()/2 -x/2 , /*w=*/x, /*h=*/x, /*color=*/color2);
    delay(100);
    for(; x > 6; x-=screen.width()/40){
      screen.drawRect(screen.width()/2 -x/2, screen.height()/2 -x/2 , x, x, color1);
      delay(100);
    }
}

void testRoundRects() {
  screen.fillScreen(COLOR_RGB565_BLACK);
  int color = 0xF00F;
  int i;
  int x = 0;
  int y = 0;
  int w = screen.width()-3;
  int h = screen.height()-3;
  for(i = 0 ; i <= 10; i+=2) {
    screen.drawRoundRect(/*x0=*/x, /*y0=*/y, /*w=*/w, /*h=*/h, /*radius=*/20, /*color=*/color);
    x+=5;
    y+=5;
    w-=10;
    h-=10;
    color+=0x0100;
    delay(50);
  }
  for(i = 0 ; i <= 10; i+=2) {
    screen.fillRoundRect(/*x0=*/x, /*y0=*/y, /*w=*/w, /*h=*/h, /*radius=*/10, /*color=*/color);
    x+=5;
    y+=5;
    w-=10;
    h-=10;
    color+=0x0500;
    delay(50);
  }
}

void testCircles(uint8_t radius, uint16_t color) {
  screen.fillScreen(COLOR_RGB565_BLACK);
  for (int16_t x=radius; x <=screen.width()-radius; x+=radius*2) {
    for (int16_t y=radius; y <=screen.height()-radius; y+=radius*2) {
      screen.drawCircle(/*x0=*/x, /*y0=*/y, /*r=*/radius, /*color=*/color);
        if(x == y ||x == -y ||x == y + 2*radius)
          screen.fillCircle(/*x0=*/x, /*y0=*/y, /*r=*/radius, /*color=*/color);
       color += 800;
       delay(100);
    }
  }
}

void testTriangles(uint16_t color){
  screen.fillScreen(COLOR_RGB565_BLACK);

  for (int16_t i=0; i <=screen.width(); i+=24)
    screen.drawTriangle(/*x0=*/i,/*y0=*/0,/*x1=*/0,/*y1=*/screen.height()-i,/*x2=*/screen.width()-i,/*y2=*/screen.height(), /*color=*/color);

  for (int16_t i=0; i <screen.width(); i+=24)
    screen.drawTriangle(screen.width(),i*4/3,0,screen.height()-i*4/3,i,0, color);

  for (int16_t i=0; i <screen.width(); i+=24)
    screen.drawTriangle(screen.width(),i*4/3,i,0,screen.width()-i,screen.height(), color);

  color = COLOR_RGB565_RED;
  for (int16_t i=0; i <=screen.width(); i+=24)
    screen.fillTriangle(/*x0=*/i,/*y0=*/0,/*x1=*/0,/*y1=*/screen.height()-i,/*x2=*/screen.width()-i,/*y2=*/screen.height(), /*color=*/color+=100);

  for (int16_t i=0; i <screen.width(); i+=24)
    screen.fillTriangle(screen.width(),i*4/3,0,screen.height()-i*4/3,i,0, color+=100);

  for (int16_t i=0; i <screen.width(); i+=24)
    screen.fillTriangle(screen.width(),i*4/3,i,0,screen.width()-i,screen.height(), color+=100);
}

void testPrint() {
  int16_t color = 0x00FF;
  screen.setTextWrap(false);
  screen.fillScreen(COLOR_RGB565_BLACK);
  screen.setCursor(0, 50);
  screen.setTextColor(color+=0x3000);
  screen.setTextSize(0);
  screen.println("Hello World!");
  screen.setTextColor(color+=0x3000);
  screen.setTextSize(1);
  screen.println("Hello World!");
  screen.setTextColor(color+=0x3000);
  screen.setTextSize(2);
  screen.println("Hello World!");
  screen.setTextColor(color+=0x3000);
  screen.setTextSize(3);
  screen.println("Hello World!");
  screen.setTextColor(color+=0x3000)
  screen.setTextSize(4);
  screen.println("Hello!"); 
  screen.setTextSize(5);
  screen.print("Hello!");
  delay(2000);
  screen.setCursor(0, 0);
  screen.fillScreen(COLOR_RGB565_BLACK);
  screen.setTextSize(2);
  screen.setTextColor(color+=0x3000);
  screen.print("a = ");
  screen.setTextColor(color+=0x3000);
  int a = 1234;
  screen.println(a, 1);
  screen.setTextColor(color+=0x3000);
  screen.print(8675309, HEX);
  screen.println("this is HEX!");
  screen.println("");
  screen.setTextColor(color+=0x0F00);
  screen.println("running for: ");
  screen.setTextColor(color+=0x0F00);
  screen.print(millis());
  screen.setTextColor(color+=0x0F00);
  screen.println("/1000 seconds.");
  char text[] = "Hi DFRobot!";
  screen.setTextColor(color+=0x0F00);
  screen.setTextWrap(true);
  screen.setTextSize(3);
  screen.println(text);
  //screen.setFonts((const gdl_Font_t *)SIMKAIFont18ptBitmaps);
  screen.println(text);
  delay(2000);
}

3. ESP32-S3 Bluetooth Receive & Transmit

3.1 Data Transmission between ESP32-S3 and Mobile Phone

The demo below shows the data transmission between ESP32-S3 and a mobile phone. Users can modify the data transmit or data receive part to fit their needs.

/*
    Video: https://www.youtube.com/watch?v=oCMOYS71NIU
    Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleNotify.cpp
    Ported to Arduino ESP32 by Evandro Copercini

   Create a BLE server that, once we receive a connection, will send periodic notifications.
   The service advertises itself as: 6E400001-B5A3-F393-E0A9-E50E24DCCA9E
   Has a characteristic of: 6E400002-B5A3-F393-E0A9-E50E24DCCA9E - used for receiving data with "WRITE" 
   Has a characteristic of: 6E400003-B5A3-F393-E0A9-E50E24DCCA9E - used to send data with  "NOTIFY"

   The design of creating the BLE server is:
   1. Create a BLE Server
   2. Create a BLE Service
   3. Create a BLE Characteristic on the Service
   4. Create a BLE Descriptor on the characteristic
   5. Start the service.
   6. Start advertising.

*/

/* This example domenstrates the Bluetooth data transparent transmission function. Burn the code, open serial monitor, turn on the BLE debugger on the phone, then,
 * 1. you can see the data sent by ESP32-S3--see APP usage image 
 * 2. send data to ESP32-S3 by the input box of BLE debugger--see APP usage image 
 * This example originates from BLE_uart sample 
 */

#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

BLEServer *pServer = NULL;
BLECharacteristic * pTxCharacteristic;
bool deviceConnected = false;
uint8_t txValue = 0;

// See the following for generating UUIDs:
// https://www.uuidgenerator.net/

#define SERVICE_UUID           "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"


//Bluetooth connect/disconnect. Auto triggered when connection/disconnection event occurs. 
class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {   //Execute this function when Bluetooth is connected. 
      Serial.println("Bluetooth connected");
      deviceConnected = true;
    };

    void onDisconnect(BLEServer* pServer) {  //Execute this function when Bluetooth is disconnected
      Serial.println("Bluetooth disconnected");
      deviceConnected = false;
      delay(500); // give the bluetooth stack the chance to get things ready
      pServer->startAdvertising(); // restart advertising

    }
};

/****************Data Receiving*************/
/****************************************/
//Process received Bluetooth data. Auto triggered when data received. 
class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string rxValue = pCharacteristic->getValue();//Receive data, and assign it to rxValue

      //if(rxValue == "ON"){Serial.println("Turn light on");}   //Determine whether the received character is "ON"

      if (rxValue.length() > 0) {
        Serial.println("*********");
        Serial.print("Received Value: ");
        for (int i = 0; i < rxValue.length(); i++){
          Serial.print(rxValue[i]);
        }
        Serial.println();
        Serial.println("*********");
      }
    }
};
/***************************************/
/****************************************/


void setup() {
  Serial.begin(115200);
  BLEBegin();  //Init Bluetooth

}

void loop() {
/****************Data Transmitting*************/
/****************************************/
  if (deviceConnected) {  //Transmit data when the Bluetooth is connected. 
    pTxCharacteristic->setValue("Hello");  //Send char string 
    pTxCharacteristic->notify();
    delay(10); // bluetooth stack will go into congestion, if too many packets are sent

    pTxCharacteristic->setValue("DFRobot");  //Send char string
    pTxCharacteristic->notify();
    delay(10); // bluetooth stack will go into congestion, if too many packets are sent
  }
/****************************************/
/****************************************/
}


void BLEBegin(){
  // Create the BLE Device
  BLEDevice::init(/*BLE Name*/"UART Service");

  // Create the BLE Server
  pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  // Create the BLE Service
  BLEService *pService = pServer->createService(SERVICE_UUID);

  // Create a BLE Characteristic
  pTxCharacteristic = pService->createCharacteristic(
                    CHARACTERISTIC_UUID_TX,
                    BLECharacteristic::PROPERTY_NOTIFY
                  );

  pTxCharacteristic->addDescriptor(new BLE2902());

  BLECharacteristic * pRxCharacteristic = pService->createCharacteristic(
                      CHARACTERISTIC_UUID_RX,
                      BLECharacteristic::PROPERTY_WRITE
                    );

  pRxCharacteristic->setCallbacks(new MyCallbacks());

  // Start the service
  pService->start();

  // Start advertising
  pServer->getAdvertising()->start();
  Serial.println("Waiting a client connection to notify...");
}

3.2 Bluetooth Communication between two ESP32-S3 Boards

The demo below shows the Bluetooth communication between two ESP32-S3 boards. Users can modify the data transmit or data receive part to fit their needs.

Program for client:

/**
 * A BLE client example that is rich in capabilities.
 * There is a lot new capabilities implemented.
 * author unknown
 * updated by chegewara
 */

#include "BLEDevice.h"
//#include "BLEScan.h"

// The remote service we wish to connect to.
static BLEUUID serviceUUID("4fafc201-1fb5-459e-8fcc-c5c9c331914b");
// The characteristic of the remote service we are interested in.
static BLEUUID    charTXUUID("beb5483e-36e1-4688-b7f5-ea07361b26a8");

static BLEUUID    charRXUUID("beb5483f-36e1-4688-b7f5-ea07361b26a8");

static boolean doConnect = false;
static boolean connected = false;
static boolean doScan = false;
static BLERemoteCharacteristic* pTXRemoteCharacteristic;
static BLERemoteCharacteristic* pRXRemoteCharacteristic;
static BLEAdvertisedDevice* myDevice;


/****************Data Receiving*************/
/****************************************/
//Bluetooth receiving data handle. Auto triggered when data received. 
static void notifyCallback(BLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify) {  //Pass in uint8_t* pData for storing data 
    String BLEData = "";
    for(int i = 0; i < length; i++)  //
      BLEData += (char)pData[i];
    Serial.println("*********");
    Serial.print("Received Value: ");
    Serial.println(BLEData);
    Serial.println("*********");

    //if(BLEData == "ON"){Serial.println("Turn light on");}  //Determine whether the received character is "ON"

    //Serial.print("Notify callback for characteristic ");
    //Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str());
    //Serial.print(" of data length ");
    //Serial.println(length);
}
/****************************************/
/****************************************/

//Bluetooth connect/disconnect. Auto triggered when connection/disconnection event occurs.
class MyClientCallback : public BLEClientCallbacks {
  void onConnect(BLEClient* pclient) {
  }

  void onDisconnect(BLEClient* pclient) {
    connected = false;
    Serial.println("onDisconnect");
  }
};


/**
 * Scan for BLE servers and find the first one that advertises the service we are looking for.
 */
 //Bluetooth scanning handle event. Auto-triggered when scanning is enabled. 
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
 /**
   * Called for each advertising BLE server.
   */
  void onResult(BLEAdvertisedDevice advertisedDevice) {
    //Serial.print("BLE Advertised Device found: ");
    //Serial.println(advertisedDevice.toString().c_str());

    // We have found a device, let us now see if it contains the service we are looking for.
    if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID)) {
      BLEDevice::getScan()->stop();
      myDevice = new BLEAdvertisedDevice(advertisedDevice);
      doConnect = true;
      doScan = true;

    } // Found our server
  } // onResult
}; // MyAdvertisedDeviceCallbacks



void setup() {
  Serial.begin(115200);
  Serial.println("Starting Arduino BLE Client application...");
  bleBegin();

}

void loop() {
  // If the flag "doConnect" is true then we have scanned for and found the desired
  // BLE Server with which we wish to connect.  Now we connect to it.  Once we are 
  // connected we set the connected flag to be true.
  if (doConnect == true) {
    if (connectToServer()) {
      Serial.println("We are now connected to the BLE Server.");
    } else {
      Serial.println("We have failed to connect to the server; there is nothing more we will do.");
    }
    doConnect = false;
  }
/****************Data Transmit*************/
/****************************************/
  if (connected) {  //Transmit data when Bluetooth server is connected
    pTXRemoteCharacteristic->writeValue("I am client");
    pTXRemoteCharacteristic->writeValue("Hello client");
  }
  if(!connected){  //Re-scan when no Bluetooth server is connected 
    BLEDevice::getScan()->start(5,false);  // this is just example to start scan after disconnect, most likely there is better way to do it in Arduino
  }
/****************************************/
/****************************************/
  delay(1000); 
}


void bleBegin()
{
  BLEDevice::init("");

  // Retrieve a Scanner and set the callback we want to use to be informed when we
  // have detected a new device.  Specify that we want active scanning and start the
  // scan to run for 5 seconds.
  BLEScan* pBLEScan = BLEDevice::getScan();
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());//scanning function 
  pBLEScan->setInterval(1349);//Set scanning interval 
  pBLEScan->setWindow(449);//Active scanning time 
  pBLEScan->setActiveScan(true);
  pBLEScan->start(5, false);//Scanning time. Unit: s
  }


//Bluetooth connection handling 
bool connectToServer() {
    Serial.print("Forming a connection to ");
    Serial.println(myDevice->getAddress().toString().c_str());

    BLEClient*  pClient  = BLEDevice::createClient();
    Serial.println(" - Created client");

    pClient->setClientCallbacks(new MyClientCallback());

    // Connect to the remove BLE Server.
    pClient->connect(myDevice);  // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private)
    Serial.println(" - Connected to server");
    pClient->setMTU(517); //set client to request maximum MTU from server (default is 23 otherwise)

    // Obtain a reference to the service we are after in the remote BLE server.
    BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
    if (pRemoteService == nullptr) {
      Serial.print("Failed to find our service UUID: ");
      Serial.println(serviceUUID.toString().c_str());
      pClient->disconnect();
      return false;
    }
    Serial.println(" - Found our service");


    // Obtain a reference to the characteristic in the service of the remote BLE server.
    pTXRemoteCharacteristic = pRemoteService->getCharacteristic(charTXUUID);
    if (pTXRemoteCharacteristic == nullptr) {
      Serial.print("Failed to find our characteristic UUID: ");
      Serial.println(charTXUUID.toString().c_str());
      pClient->disconnect();
      return false;
    }
    pRXRemoteCharacteristic = pRemoteService->getCharacteristic(charRXUUID);
    if (pRXRemoteCharacteristic == nullptr) {
      Serial.print("Failed to find our characteristic UUID: ");
      Serial.println(charRXUUID.toString().c_str());
      pClient->disconnect();
      return false;
    }
    Serial.println(" - Found our characteristic");

    if(pRXRemoteCharacteristic->canNotify())
      pRXRemoteCharacteristic->registerForNotify(notifyCallback);

    connected = true;
    return true;
}

Program for Server:

/*
    Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleServer.cpp
    Ported to Arduino ESP32 by Evandro Copercini
    updates by chegewara
*/

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLE2902.h>

// See the following for generating UUIDs:
// https://www.uuidgenerator.net/

#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID_RX "beb5483e-36e1-4688-b7f5-ea07361b26a8"
#define CHARACTERISTIC_UUID_TX "beb5483f-36e1-4688-b7f5-ea07361b26a8"
uint8_t txValue = 0;
bool deviceConnected = false;
BLECharacteristic *pTxCharacteristic;


//Bluetooth connect/disconnect. Auto triggered when connection/disconnection event occurs.
class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {   //Execute this function when Bluetooth is connected. 
      Serial.println("Bluetooth connected");
      deviceConnected = true;
    };

    void onDisconnect(BLEServer* pServer) {  //Execute this function when Bluetooth is disconnected
        Serial.println("Bluetooth disconnected");
        deviceConnected = false;
        delay(500); // give the bluetooth stack the chance to get things ready
        BLEDevice::startAdvertising(); // restart advertising
    }
};
/****************Data Receiving*************/
/****************************************/
//Bluetooth receiving data handle. Auto triggered when data received.
class MyCallbacks: public BLECharacteristicCallbacks {
    void onWrite(BLECharacteristic *pCharacteristic) {
      std::string rxValue = pCharacteristic->getValue();  //Receive data, and assign it to rxValue

      //if(rxValue == "ON"){Serial.println("Turn light on");}   //Determine whether the received character is "ON"

      if (rxValue.length() > 0) {
        Serial.println("*********");
        Serial.print("Received Value: ");
        for (int i = 0; i < rxValue.length(); i++)
              Serial.print(rxValue[i]);    //Print the received data out

        Serial.println();
        Serial.println("*********");
      }
    }
};
/****************************************/
/****************************************/

void setup() {
  Serial.begin(115200);
  Serial.println("Starting BLE work!");
  bleBegin();
}

/****************Data Transmitting*************/
/****************************************/
void loop() {
  if(deviceConnected){  //Transmit data when the Bluetooth is connected. 
    pTxCharacteristic->setValue("I am server");
    pTxCharacteristic->notify();

    pTxCharacteristic->setValue("Hello Sever");
    pTxCharacteristic->notify();
  }
  /****************************************/
  /****************************************/
  delay(1000);
}


void bleBegin()
{
  BLEDevice::init(/*BLE name*/"Long name works now");
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());
  BLEService *pService = pServer->createService(SERVICE_UUID);
  BLECharacteristic *pRxCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID_RX,
                                         BLECharacteristic::PROPERTY_WRITE 
                                       );
  pRxCharacteristic->setCallbacks(new MyCallbacks()); 

 pTxCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID_TX,
                                         BLECharacteristic::PROPERTY_NOTIFY
                                       );
 pTxCharacteristic->addDescriptor(new BLE2902());

  pService->start();
  // BLEAdvertising *pAdvertising = pServer->getAdvertising();  // this still is working for backward compatibility
  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_UUID);
  pAdvertising->setScanResponse(true);
  pAdvertising->setMinPreferred(0x06);  // functions that help with iPhone connections issue
  pAdvertising->setMinPreferred(0x12);
  BLEDevice::startAdvertising();

  }

4. Control LED via WiFi

The ESP32-S3 is equipped with WiFi function. The example below creates a WiFi server using ESP32-S3, and then connects a client to this server to control the LED's ON/OFF.

Steps:

  1. Connect WiFi to “ESP32 S3”, WiFi password: 12345678
  2. Access the website: http://192.168.4.1/ON to turn on the LED. Enter http://192.168.4.1/OFF to turn off the LED.
  3. Click here to control the brightness of LED.

Sample Code

/*
**Steps:**
1. Connect WiFit to “ESP32 S3”, WiFi password: 12345678
2. Access the website: http://192.168.4.1/ON to turn on the LED. Enter http://192.168.4.1/OFF to turn off the LED.
3. Click **here** to control the brightness of LED.
*/

#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiAP.h>

#define myLED 21 //Set pin 21 to the LED pin 
// Set WIFI name and password 
const char *ssid = "ESP32 S3";//WIFI name 
const char *password = "12345678";//password

WiFiServer server(80);//Port 80 is the default web server port 


void setup() {
  pinMode(myLED, OUTPUT);

  Serial.begin(115200);
  Serial.println();
  Serial.println("Configuring access point...");

  //Delete password if you want an open network.
  WiFi.softAP(ssid, password);
  IPAddress myIP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(myIP);
  server.begin();

  Serial.println("Server started");
}

void loop() {
  WiFiClient client = server.available();   // Detect waiting for connection...

  if (client) {                             // Connection detecting 
    Serial.println("New Client.");
    String currentLine = "";                // Create a String variable to store data 
    while (client.connected()) {            // loop when keep connecting
      if (client.available()) {             // Detect is there is data on the connection
        char c = client.read();             // Read the received data 
        //Serial.write(c);                    // Print on serial monitor 
        if (c == '\n') {                    // If an newline character  is read

          //Use newline character to indicate the end
          if (currentLine.length() == 0) {
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println();
             //Connect character with here 
            client.print("Click <a href=\"/ON\">here</a> to turn ON the LED.<br>");
            client.print("Click <a href=\"/OFF\">here</a> to turn OFF the LED.<br>");

            // empty line in a HTTP response
            client.println();
            // Break out of a loop 
            break;
          } else {    // Clear cached data in variable if there is one newline character 
            currentLine = "";
          }
        } else if (c != '\r') {  // If characters except Carriage Return is obtained
          currentLine += c;      // Add the obtained character to end of the variable
        }

        // Check if /ON or /OFF is obtained 
        if (currentLine.endsWith("/ON")) {
          digitalWrite(myLED, HIGH);               //Turn on LED when /ON is obtained 
        }
        if (currentLine.endsWith("/OFF")) {
          digitalWrite(myLED, LOW);                //Turn on LED when /OFF is obtained 
        }
      }
    }
    // disconnect
    client.stop();
    Serial.println("Client Disconnected.");
  }
}

Result

Use the mobile phone to connect to this wifi, access 192.168.4.1 through the browser. As shown in the figure below, the IP address is 192.168.4.1, and the service is enabled.

Access the IP address on a broswer and the fllowing will appear.

Member function

5. ESP-NOW Data Transfer

SP-NOW is a protocol developed by Espressif, which enables multiple devices to communicate with one another without using Wi-Fi. It can be widely used in smart light, remote controlling, sensor, etc.

5.1 Get Controller MAC Address

Burn the code, open the serial port and you can see the device MAC address.

#include "WiFi.h"

void setup(){
  Serial.begin(115200);
  WiFi.mode(WIFI_MODE_STA);
}

void loop(){
  Serial.println(WiFi.macAddress());
  delay(1000);
}

5.2 Receive & Transmit Data

Fill in the MAC address and burn the code, then data can be transmitted and received between two devices.

#include <esp_now.h>
#include <WiFi.h>

//MAC
uint8_t MAC1[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

typedef struct struct_message {
  char a[16];
  int b;
  float c;
  bool d;
} struct_message;

struct_message sendData;
struct_message recvData;

esp_now_peer_info_t peerInfo;

//SCallback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  if(status == ESP_NOW_SEND_SUCCESS){
    Serial.println("Send_Success");
  }else{
    Serial.println("Send_Fail");
  }
}

//Callback when data is received
void OnDataRecv(const uint8_t * mac, const uint8_t *Data, int len) {
  memcpy(&recvData, Data, sizeof(recvData));
  Serial.print("Bytes received: ");
  Serial.println(len);
  Serial.println(recvData.a);
  Serial.println(recvData.b);
  Serial.println(recvData.c);
  Serial.println(recvData.d);
  Serial.println("---------");
}

void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);

  //Init ESP-NOW
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing");
    return;
  }

  //Register callback on data sent 
  esp_now_register_send_cb(OnDataSent);

  peerInfo.channel = 0;  
  peerInfo.encrypt = false;
  //Register MAC1 Device 
  memcpy(peerInfo.peer_addr, MAC1, 6);
  if (esp_now_add_peer(&peerInfo) != ESP_OK){
    Serial.println("Failed to add peer");
    return;
  }

  //Register callback on data received
  esp_now_register_recv_cb(OnDataRecv);
}

void loop() {
  strcpy(sendData.a, "DFRobot");
  sendData.b = 10;
  sendData.c = 9.9;
  sendData.d = true;

  esp_err_t result = esp_now_send(MAC1, (uint8_t *)&sendData, sizeof(sendData));

  if (result == ESP_OK) {
    Serial.println("Send success");
  }
  else {
    Serial.println("Send Fail");
  }
  delay(2000);
}

Send Data to Multiple Devices

Fill in the MAC address and burn the code, data can be sent to multiple devices.

#include <esp_now.h>
#include <WiFi.h>

//MAC
uint8_t MAC1[] = {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA};
uint8_t MAC2[] = {0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB};

typedef struct struct_message {
  uint8_t ID;
  int data;
} struct_message;

struct_message sendData;
struct_message recvData;

esp_now_peer_info_t peerInfo;

// Callback when data is sent  
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  if(status == ESP_NOW_SEND_SUCCESS){
    Serial.println("Send Success");
  }else{
    Serial.println("Send Fail");
  }
}

// Callback when data is received
void OnDataRecv(const uint8_t * mac, const uint8_t *Data, int len) {
  memcpy(&recvData, Data, sizeof(recvData));
  Serial.print("Bytes received: ");
  Serial.println(len);
  Serial.println(recvData.ID);
  Serial.println(recvData.data);
  Serial.println("---------");
}

void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);

  //Init ESP-NOW
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing");
    return;
  }

  //Register callback on data sent 
  esp_now_register_send_cb(OnDataSent);

  peerInfo.channel = 0;  
  peerInfo.encrypt = false;
  //Register MAC1 Device 
  memcpy(peerInfo.peer_addr, MAC1, 6);
  if (esp_now_add_peer(&peerInfo) != ESP_OK){
    Serial.println("Failed to add peer");
    return;
  }
  //Register MAC2 Device
  memcpy(peerInfo.peer_addr, MAC2, 6);
  if (esp_now_add_peer(&peerInfo) != ESP_OK){
    Serial.println("Failed to add peer");
    return;
  }

  //Register callback on data received
  esp_now_register_recv_cb(OnDataRecv);
}

void loop() {
  sendData.ID = 0;
  sendData.data = 10;

  //Send message to all registered devices
  esp_err_t result = esp_now_send(0, (uint8_t *)&sendData, sizeof(sendData));
  if (result == ESP_OK) {
    Serial.println("Send success");
  }
  else {
    Serial.println("Send Fail");
  }
  //Send message to specified MAC device 
  //esp_err_t result = esp_now_send(MAC1, (uint8_t *)&sendData, sizeof(sendData));
  //if (result == ESP_OK) {
  //  Serial.println("Send success");
  //}
  //else {
  //  Serial.println("Send Fail");
  //}
  delay(2000);
}

6. Applications

6.1 Display temperature & humidity on OLED

Get temperature & humidity information and display them on OLED.

Requirements

Connection Diagram

Sample Code


#include <Arduino.h>
#include <U8g2lib.h> //Import font library 
//#include <SPI.h>
#include <Wire.h>

#include <DFRobot_SHT3x.h>

/*
---Display Hardware I2C Interface---
U8G2_R0 No rotation, horizontal, draw from left to right
U8G2_R1 Rotate 90 degrees clockwise, draw from top to  bottom
U8G2_R2 Rotate 180 degrees clockwise, draw from right to left
U8G2_R3 Rotate 270 degrees clockwise, draw from bottom to top
U8G2_MIRROR Display image content normally(v2.6.x and above)   Note: U8G2_MIRROR needs to be used with setFlipMode().
U8x8_PIN_NONE for empty pin, reset pin will not be used.
---Display Hardware SPI Interface---
cs connect as pinout(Selected by users)
dc connect as pinout(Selected by users)
*/
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(/* rotation=*/U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

//Select 0x45 when ADR is connected to VDD; select 0x44 when ADR goes to GND
//Default to 0x45, unnecessary to connect RST(reset pin)
DFRobot_SHT3x sht3x(&Wire,/*address=*/0x45,/*RST=*/4);

//Comment out the codes above when using SPI, and run the codes below
//DFRobot_SHT3x   sht3x;

void setup() {
  Serial.begin(115200);
  u8g2.begin();
  u8g2.setFontPosTop();//When you use drawStr to display strings, the default criteria is to display the lower-left coordinates of the characters. The function can be understood as changing the coordinate position to the upper left corner of the display string as the coordinate standard.
  //Init sensor 
  while (sht3x.begin() != 0) {
        Serial.println("Failed to Initialize the chip, please confirm the wire connection");
        delay(1000);
      }
      Serial.print("Chip serial number");
      Serial.println(sht3x.readSerialNumber());
      if(!sht3x.softReset()){
         Serial.println("Failed to Initialize the chip....");
       }
}

void loop() {
  //Clear display 
  u8g2.clearBuffer();
  //Assign reading to temp and humi for displaying 
  float   temp = sht3x.getTemperatureC();
  float   humi = sht3x.getHumidityRH();  
  //Display temperature 
  u8g2.setFont(u8g2_font_osb18_tf);    // Select font type and size(see official)
  u8g2.drawStr(5,10,"Temp");//Write character to the specified position 
  u8g2.setFont(u8g2_font_t0_18b_tr);
  u8g2.setCursor(75, 15);//Display content from this position
  u8g2.print(temp);
  //Display humidity
  u8g2.setFont(u8g2_font_osb18_tf);    
  u8g2.drawStr(5,40,"Humi");
  u8g2.setFont(u8g2_font_t0_18b_tr);
  u8g2.setCursor(75, 45);
  u8g2.print(humi);
  u8g2.sendBuffer(); 
  delay(1000);
}

Result

Member function

6.2 Obtain Temperature & Humidity

This example introduces how data transmission works over WiFi in local area network. Users can learn how to access the IP address under the LAN to obtain the SHT30 temperature and humidity sensor status in another place.

Requirements

Connection Diagram

  1. Connect to WiFi "ESP32 S3", password: 12345678
  2. Access website http://192.168.4.1/GET to get the temperature & humidity information in local area network.
  3. Refresh the temp & humi webpage to get the latest sensor data.

Sample Code

/*
Connect SHT30 to ESP-S3, get temperature & humidity via LAN
*/

#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiAP.h>
#include <DFRobot_SHT3x.h>
//Select 0x45 when ADR is connected to VDD; select 0x44 when ADR goes to GND
//Default to 0x45, unnecessary to connect RST(reset pin)
DFRobot_SHT3x sht3x(&Wire,/*address=*/0x45,/*RST=*/4);

//Comment out the codes above when using SPI, and run the codes below
//DFRobot_SHT3x   sht3x;

// Set WIFI name and password
const char *ssid = "ESP32 S3";//WIFI Name 
const char *password = "12345678";//Password 

WiFiServer server(80);//Port 80 is the default web server port

//Display the last sensor feedback status 
void setup() {
  //pinMode(myLED, OUTPUT);

  Serial.begin(115200);
  Serial.println();
  Serial.println("Configuring access point...");

  //Delete password if you want an open network 
  WiFi.softAP(ssid, password);
  IPAddress myIP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(myIP);
  server.begin();

  Serial.println("Server started");
  //Init sensor 
  while (sht3x.begin() != 0) {
        Serial.println("Failed to Initialize the chip, please confirm the wire connection");
        delay(1000);
      }
      Serial.print("Chip serial number");
      Serial.println(sht3x.readSerialNumber());
      if(!sht3x.softReset()){
         Serial.println("Failed to Initialize the chip....");
       }
}

void loop() {

WiFiClient client = server.available();   // Detect waiting for connection

  if (client) {                             // Connection detecting 
    Serial.println("New Client."); 
    String currentLine = "";                // Create a String variable to store data 
    while (client.connected()) {            // Loop when keep connecting
      if (client.available()) {             // Detect is there is data on the connection 
        char c = client.read();             // Read the received data
        //Serial.write(c);                    // Print on serial monitor
        if (c == '\n') {                    // If an newline character is read

          //Clear cached content 
          if (currentLine.length() == 0) {
            client.print(" ");
            break;
          } else {    // Clear cached data in variable if there is one newline character 
            currentLine = "";
          }
        } else if (c != '\r') {  // If characters except Carriage Return is obtained
          currentLine += c;      // Add the obtained character to end of the variable
        }

        // Check if /GET is obtained at the end
        if (currentLine.endsWith("/GET")) {
             //Read temperature and humidity 
             float   temp = sht3x.getTemperatureC();
             float   humi = sht3x.getHumidityRH();  
             //Print on webpage 
             client.print("temp (C): "); client.println(temp);
             client.print("humi (%RH): "); client.println(humi);
        }
      }
    }
    // disconnect 
    client.stop();
    Serial.println("Client Disconnected.");
  }
  }

Result

You can access the website through a mobile phone, computer, etc. to obtain the temperature and humidity under the LAN.

Member function

6.3 Get Network Time via WiFi

Get time from network time server and keep time updated using he RTC clock on ESP32.

This demo is from CSDN blogger[Naisu Xu].

#include <WiFi.h>

const char *ssid = "********";    //WIFI Name
const char *password = "********"; //WIFI Password 

const char *ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 8 * 3600;
const int daylightOffset_sec = 0;

void printLocalTime()
{
    struct tm timeinfo;
    if (!getLocalTime(&timeinfo))
    {
        Serial.println("Failed to obtain time");
        return;
    }
    Serial.println(&timeinfo, "%F %T %A"); // Format output 
}

void setup()
{
    Serial.begin(115200);
    Serial.println();

    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED)
    {
        delay(500);
        Serial.print(".");
    }
    Serial.println("WiFi connected!");

    // Get time from network time server and configure it 
    // When succeed, the chip will use RTC clock to keep the time updated 
    configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
    printLocalTime();

    WiFi.disconnect(true);
    WiFi.mode(WIFI_OFF);
    Serial.println("WiFi disconnected!");
}

void loop()
{
    delay(1000);
    printLocalTime();
}

struct tm

struct tm {
int tm_sec; // second, from 0-59;
int tm_min; // minute, from 0-59;
int tm_hour; // hour, from 0-23;
int tm_mday; // day in a month, from 1-31;
int tm_mon; // month, from 0-11;
int tm_year; // year, = real year-1900;
int tm_wday; // Week, from 0-6, 0 for sunday, 1 for monday, and so on; 
int tm_yday; // Date in a year, from 0-365, 0 for January 1, 1 for January 2, and so on; 
int tm_isdst; // Daylight Saving Time identifier, tm_isdst is positive when DST is implemented; tm_isdst is equal to 0 if DST is not implemented; tm_isdst() is negative for unknown situation 
};

struct tm Format Output

Formatting characters Output
%a Abbreviation for day of the week
%A Full name of the day of the week
%b Abbreviation for month
%B Full name for month
%c Time string for standard date
%C Last two digits of the year
%d Day of the month in decimal
%D Month/day/year
%e Day of the month in decimal in a two-character field
%F Year-month-day
%g The last two digits of the year, using a week-based year
%G Years, use week-based years
%h Abbreviated month name
%H 24 hour clock
%I 12 hour clock
%j Day of the year in decimal
%m Month in decimal
%M Minutes in decimal
%p Equivalent display of local AM or PM
%r Time in 12 hours
%R Display hours and minutes: hh:mm
%S Second in decimal
%t Horizontal tab
%T Display hours, minutes and seconds in hh:mm:ss format
%u Day of the week, Monday is the first day (values from 0 to 6, Monday is 0)
%U Week of the year, with first Sunday as the first day of week one (values from 0 to 53)
%V Week of the year, using a week-based year
%w Day of the week in decimal (values from 0 to 6, 0 for Sunday)
%W Week of the year, with first Monday as the first day of week one(values from 0 to 53)
%x Standard date string
%X Standard time string
%y Year in decimal without century (values from 0 to 99)
%Y Year in decimal with century
%z Time zone name, or return null if no time zone name is available

6.4 Get WiFi Weather Infromation

This example domenstrates how to get weather information and extract data from information obtained in HTTP through Json, and print it out.

  1. Install the Arduino_JSON library. Enter Arduino_JSON in Arduino IDE Tools -> Manage Libraries and install the library

  1. Register an OpenWeather account to get the weather information you want. Go to https://openweathermap.org/appid/, and create an account.
  1. Click My API Keys to enter the interface for obtaining API
  1. Copy the key here (this key is your only key to get weather information from OpenWeather)
  1. You can fill the Key into the following URL and fill in the city name and country to get the city weather information.

http://api.openweathermap.org/data/2.5/weather?q=yourCityName,yourCountryCode&APPID=yourAPIkey

For example, fill in Chengdu in yourCityName, CN for yourCountryCode, fill in yourAPIkey which is the API key obtained earlier, the following is the URL of Chengdu, China with the API added:

http://api.openweathermap.org/data/2.5/weather?q=ChengDu,CN&APPID=4de305d0a52ddaceaecba50a757e9968

Copying your URL into your browser will return a set of information corresponding to your local weather. On the day this tutorial was written, we had the following information about the weather in Chengdu, China.

Sample Code


/*
This example gets weather information
*/

#include <WiFi.h>
#include <HTTPClient.h>
#include <Arduino_JSON.h>

//Modify WIFI name and password
const char* ssid = "******";//WIFI name
const char* password = "******";//WIFI password

//Fill in the API Key you got
String openWeatherMapApiKey = "4de305d0a52ddaceaecba50a757e9968";
//Example:
//String openWeatherMapApiKey = "4de305d0a52ddaceaecba50a757e9968";

// Fill in your city name and country abbreviation
String city = "ChengDu";
String countryCode = "CN";

//Example:
//String city = "ChengDu";
//String countryCode = "CN";

//Set the interval for obtaining information, the following is used for testing, so it is set to 10 seconds
//You should limit the minimum interval of accessing time according to the upper limit of the number of times to access the data within the specified time period of the website you need to obtain the data.
unsigned long lastTime = 0;
//Set to get weather data every 10 minutes
//unsigned long timerDelay = 600000;
//Set to get weather data every 10 seconds
unsigned long timerDelay = 10000;

String jsonBuffer;

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  Serial.println("Connecting");

  //Determine if WIFI is connected
  while(WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to WiFi network with IP Address: ");
  Serial.println(WiFi.localIP());
  Serial.println("Timer set to 10 seconds (timerDelay variable), it will take 10 seconds before publishing the first reading.");
}

void loop() {
  //Send HTTP to get request
  if ((millis() - lastTime) > timerDelay) {
    //Check if WIFI is connected
    if(WiFi.status()== WL_CONNECTED){
      String serverPath = "http://api.openweathermap.org/data/2.5/weather?q=" + city + "," + countryCode + "&APPID=" + openWeatherMapApiKey;

      //Put the combined URL into the httpGETRequest function to get the text through HTTP get request.
      jsonBuffer = httpGETRequest(serverPath.c_str());
      Serial.println(jsonBuffer);

      //Store the parsed Json object value in the Jsonu buffer
      JSONVar myObject = JSON.parse(jsonBuffer);

      //Determine if the parsing was successful
      if (JSON.typeof(myObject) == "undefined") {
        Serial.println("Parsing input failed!");
        return;
      }

      Serial.print("JSON object = ");
      Serial.println(myObject);
      Serial.print("Temperature: ");
      //The obtained temperature is actually Kelvin.
      //Kelvin = Celsius + 273.15
      double c = myObject["main"]["temp"];
      c = c-273.15;
      Serial.println(c);
      Serial.print("Pressure: ");
      //myObject["main"]["pressure"], the front is the content of the quotation marks before {}, and the latter is the data to be read in quotation mark
      Serial.println(myObject["main"]["pressure"]);
      Serial.print("Humidity: ");
      Serial.println(myObject["main"]["humidity"]);
      Serial.print("Wind Speed: ");
      Serial.println(myObject["wind"]["speed"]);
    }
    else {
      Serial.println("WiFi Disconnected");
    }
    lastTime = millis();
  }
}

String httpGETRequest(const char* serverName) {
  WiFiClient client;
  HTTPClient http;

  //Connect URL
  http.begin(client, serverName);

  //Send HTTP site request
  int httpResponseCode = http.GET();

  //This array is used to store the obtained data
  String payload = "{}";

  //Put the obtained data into the array
  if (httpResponseCode>0) {
    Serial.print("HTTP Response code: ");
    Serial.println(httpResponseCode);
    payload = http.getString();
  }
  else {
    Serial.print("Error code: ");
    Serial.println(httpResponseCode);
  }

  //Release resources
  http.end();

  //Return the obtained data for Json processing
  return payload;
}

Result

Member function

7. Smart Config One-click Networking + Auto-Connection

The demo below allows for one-click networking with Espressif ESP-TOUCH.

Click to download Espressif Esptouch

#include <WiFi.h>

void SmartConfig()
{
  WiFi.mode(WIFI_STA);
  Serial.println("\r\nWait for Smartconfig...");
  WiFi.beginSmartConfig();
  while (1)
  {
    Serial.print(".");
    delay(500);                   // wait for a second
    if (WiFi.smartConfigDone())
    {
      Serial.println("SmartConfig Success");
      Serial.printf("SSID:%s\r\n", WiFi.SSID().c_str());
      Serial.printf("PSW:%s\r\n", WiFi.psk().c_str());
      break;
    }
  }
}

bool AutoConfig()
{
    WiFi.begin();
    for (int i = 0; i < 20; i++)
    {
        int wstatus = WiFi.status();
        if (wstatus == WL_CONNECTED)
        {
            Serial.println("WIFI SmartConfig Success");
            Serial.printf("SSID:%s", WiFi.SSID().c_str());
            Serial.printf(", PSW:%s\r\n", WiFi.psk().c_str());
            Serial.print("LocalIP:");
            Serial.print(WiFi.localIP());
            Serial.print(" ,GateIP:");
            Serial.println(WiFi.gatewayIP());
            return true;
        }
        else
        {
            Serial.print("WIFI AutoConfig Waiting......");
            Serial.println(wstatus);
            delay(1000);
        }
    }
    Serial.println("WIFI AutoConfig Faild!" );
    return false;
}

void setup() {
  Serial.begin(115200);
  delay(100);
  if (!AutoConfig())
  {
      SmartConfig();
  }
}

void loop() {

}

8. Using With a Camera

Please download the AXP313A library first before use.

API Functions

  /**
   * @fn enum
   * @brief Select various cameras 
   */
  typedef enum{
    eOV2640,
    e0V7725
  }eCamera_t;

  /**
   * @fn enableCameraPower
   * @brief Enable camera power 
   * @param camera Select camera 
   * @return NONE
   */
  void enableCameraPower(eCamera_t camera);

  /**
   * @fn disablePower
   * @brief Disable camera power 
   * @return NONE
   */
  void disablePower(void);

  /**
   * @fn enum
   * @brief Select showdown level time 
   */
  typedef enum{
    eTime6s,
    eTime10s
  }eShutdownKeyLevelTime_t;

  /**
   * @fn setShutdownKeyLevelTime
   * @brief Set showdown key level time 
   * @param offLevelTime Showdown key level time
   * @return NONE
   */
  void setShutdownKeyLevelTime(eShutdownKeyLevelTime_t offLevelTime);
  1. Select File->Examples->ESP32->Camera->CameraWebServer example in Arduino IDE.
  2. Replace the codes in CameraWebServer with the code below(Note: please fill in WiFi account and password)
#include "esp_camera.h"
#include <WiFi.h>

//
// WARNING!!! PSRAM IC required for UXGA resolution and high JPEG quality
//            Ensure ESP32 Wrover Module or other board with PSRAM is selected
//            Partial images will be transmitted if image exceeds buffer size
//
//            You must select partition scheme from the board menu that has at least 3MB APP space.
//            Face Recognition is DISABLED for ESP32 and ESP32-S2, because it takes up from 15 
//            seconds to process single frame. Face Detection is ENABLED if PSRAM is enabled as well

// ===================
// Select camera model
// ===================
#define PWDN_GPIO_NUM     -1
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM     45
#define SIOD_GPIO_NUM     1
#define SIOC_GPIO_NUM     2

#define Y9_GPIO_NUM       48
#define Y8_GPIO_NUM       46
#define Y7_GPIO_NUM       8
#define Y6_GPIO_NUM       7
#define Y5_GPIO_NUM       4
#define Y4_GPIO_NUM       41
#define Y3_GPIO_NUM       40
#define Y2_GPIO_NUM       39
#define VSYNC_GPIO_NUM    6
#define HREF_GPIO_NUM     42
#define PCLK_GPIO_NUM     5

#include "DFRobot_AXP313A.h"

DFRobot_AXP313A axp;

// ===========================
// Enter your WiFi credentials
// ===========================
const char* ssid = "*****";
const char* password = "******";

void startCameraServer();

void setup() {
  Serial.begin(115200);
  Serial.setDebugOutput(true);
  Serial.println();
  while(axp.begin() != 0){
    Serial.println("init error");
    delay(1000);
  }
  axp.enableCameraPower(axp.eOV2640);//Enable the power for camera
  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_UXGA;
  config.pixel_format = PIXFORMAT_JPEG; // for streaming
  //config.pixel_format = PIXFORMAT_RGB565; // for face detection/recognition
  config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
  config.fb_location = CAMERA_FB_IN_PSRAM;
  config.jpeg_quality = 12;
  config.fb_count = 1;

  // if PSRAM IC present, init with UXGA resolution and higher JPEG quality
  //                      for larger pre-allocated frame buffer.
  if(config.pixel_format == PIXFORMAT_JPEG){
    if(psramFound()){
      config.jpeg_quality = 10;
      config.fb_count = 2;
      config.grab_mode = CAMERA_GRAB_LATEST;
    } else {
      // Limit the frame size when PSRAM is not available
      config.frame_size = FRAMESIZE_SVGA;
      config.fb_location = CAMERA_FB_IN_DRAM;
    }
  } else {
    // Best option for face detection/recognition
    config.frame_size = FRAMESIZE_240X240;
#if CONFIG_IDF_TARGET_ESP32S3
    config.fb_count = 2;
#endif
  }

#if defined(CAMERA_MODEL_ESP_EYE)
  pinMode(13, INPUT_PULLUP);
  pinMode(14, INPUT_PULLUP);
#endif

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

  sensor_t * s = esp_camera_sensor_get();
  // initial sensors are flipped vertically and colors are a bit saturated
  if (s->id.PID == OV3660_PID) {
    s->set_vflip(s, 1); // flip it back
    s->set_brightness(s, 1); // up the brightness just a bit
    s->set_saturation(s, -2); // lower the saturation
  }
  // drop down frame size for higher initial frame rate
  if(config.pixel_format == PIXFORMAT_JPEG){
    s->set_framesize(s, FRAMESIZE_QVGA);
  }

#if defined(CAMERA_MODEL_M5STACK_WIDE) || defined(CAMERA_MODEL_M5STACK_ESP32CAM)
  s->set_vflip(s, 1);
  s->set_hmirror(s, 1);
#endif

#if defined(CAMERA_MODEL_ESP32S3_EYE)
  s->set_vflip(s, 1);
#endif

  WiFi.begin(ssid, password);
  WiFi.setSleep(false);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");

  startCameraServer();

  Serial.print("Camera Ready! Use 'http://");
  Serial.print(WiFi.localIP());
  Serial.println("' to connect");
}

void loop() {
  // Do nothing. Everything is done in another task by the web server
  delay(10000);
}
  1. Fill in WiFi information, burn the code, open serial monitor and then check IP.
  2. Access IP address to enter camera settings interface.

FAQ

1. What will cause burning error?

How to solve

2. Data cannot be printed on serial port

For any questions, advice or cool ideas to share, please visit the DFRobot Forum.

More Documents

DFshopping_car1.png Get FireBeetle 2 Board ESP32 S3 from DFRobot Store or DFRobot Distributor.

Turn to the Top