Testing the new ESP32-S2

I got one ESP32-S2 Saola board and I will be making some tests on this repository:


ESP32-S2 integrates a rich set of peripherals, with 43 programmable GPIOs which can be flexibly configured to provide USB OTG, LCD interface, camera interface, SPI, I2S, UART, ADC, DAC and other common functionality. ESP32-S2 provides the optimal HMI solution for touchscreen and touchpad-based devices.
The arduino-espressif32 is getting it’s finals touches of grace before being available and I will just do a small repository and try to test as much as I can and also make some benchmark comparisons.

In the first tests the impression is that most of the arduino framework is already working with a few exceptions. Not all the features are supported yet but they will be soon.
Sadly the deepsleep is still not optimized correctly in this first revisions of the Saola board and on 3.4 v I measured 0.79 mA/hour. On a good ESP32 board like tinyPICO it’s 0.08 mA/hour (10 times less) now that’s something you can plug to a battery and make it wake up every hour to do something.
Please note this is not a fair comparison at this point. It’s only a test with same firmware, same conditions and bypassing power regulator to see how much it consumes directly powering the board with the 3.3V pin.
On the other hand, making processor intensive tests like receiving UDP packets or receiving and decompressing at the same time, it showed similar speed with much less consumption than the ESP32.

But other than this small annoyance in this first board revision it’s a really promising product and very powerful System on a Chip. The feature list is impressive:

  • Xtensa® single-core 32-bit LX7 microcontroller
  • 43 programmable GPIOs.
  • Standard peripherals including SPI, I2C, I2S, UART, ADC/DAC and PWM.
  • LCD (8-bit parallel RGB/8080/6800) interface and also support for 16/24-bit parallel.
  • Camera interface supports 8 or 16-bit DVP image sensor, with clock frequency of up to 40 MHz.

Please follow the repository and add issues or just leave a comment here if you want me to test any of the features and I will publish the results. Note that the only condition is that the results should be shared with the community on the internet. It’s all open-source, so we will keep the same spirit and share the results with everyone else.
Another example of ESP32-S2 in action, controlling 144 RGB Neopixels using Makuna library https://twitter.com/martinfasani/status/1267015931689144320

What GPIOs not to use in ESP32-S2

GPIODescription / default configuration
26PSRAM pin
46Pull-down – INPUT only
43 *default UART0 pin on S2
44 *default UART0 pin on S2
NOTE: GPIO26 it applies primarily to WROVER as those come with PSRAM.
* not sure if you should not use 43,44 but if you will use UART0 output in your project is the best you don’t use them

Important documentation
ESP32-S2 Technical reference manual (page 39-40 for the not-use GPIOs)

Arduino-esp32 course – Espressif is on the www WebServer vs HttpClient – Chapter 4

As a preamble I wanted to make clear that is not my intention to teach C or C++ here, since they are very good online resources for that, and more to make my point in some easy ways to get the most of espressif/arduino-esp32 Framework.

In chapter 2 it was explained how to connect the ESP32 to WiFi so I thought it would be great to make an additional chapter that makes use of the connection in both directions:

  1. WebServer class – the ESP32 will listen on a port and reply or react to your query
    Additionally, we will use the ESPmDNS class to enable multicast DNS
  2. HttpClient class – it will send a GET or POST request to an endpoint

For the HttpClient I will make a special endpoint that it will be available in a subdomain of fasani.de and it will just answer with the time (HH:MM). Please note that after chapter 3 I will only focus on ESP32 since it was already explained how you can write code that works in both Espressif chips ESP8266 or ESP32 using Platformio environments and #ifdef conditionals.

1. WebServer example: ESP32 listens on port 80

The first example will be very simple and to the point. We will just take as a base what we wrote in chapter 2 to connect to WiFi and we will extend it using WebServer class. Once the ESP32 is online and we got the IP Address in the Serial output we will hit the route: http://ESP_IP_ADDRESS/switch

And in this route, using WebServer event handlers, we are going to toggle a GPIO high and low. Pretty simple, but powerful since if instead of a LED, we could use a relay that turns a 220v light or any other device On/Off via WiFi, so you can control it from any other terminal connected to the same WiFi Network. Using your imagination, you may build multiple endpoints that perform different things using predefined routes and modifying this example.

#include "Arduino.h"
#include <WiFi.h>
#include <ESPmDNS.h>  // multicast DNS
#include <WebServer.h>
#define LED_GPIO 25   // Update to a internal LED or just connect one with a resistance in that GPIO
int lostConnectionCount = 0;
char apName[] = "fasani";
bool switchState = false;
WebServer server(80); // port where we start the server

// Callback see defineServerRouting
void onServerSwitch(){
   switchState = !switchState;
   digitalWrite(LED_GPIO, switchState);
   String switchStatus = "OFF";
   if (switchState) {
     switchStatus = "ON";
   server.send(200, "text/html", switchStatus);

void onServerNotFound(){
  server.send(200, "text/html", "404 this route is not defined on "We could not read the time.\nPlease check in the browser that the given url: %d is correct anddefineServerRouting()");

// ROUTING Definitions. Add your server routes here
void defineServerRouting() {
  server.on("/switch", HTTP_GET, onServerSwitch);

/** Callback for receiving IP address from AP */
void gotIP(system_event_id_t event) {
  Serial.println("Online. Local IP address:");

  MDNS.addService("http", "tcp", 80);
  Serial.println(String(apName)+".local mDns started");

  Serial.println("Server started");

/** Callback for connection loss */
void lostCon(system_event_id_t event) {
  Serial.printf("WiFi lost connection try %d to connect again\n", lostConnectionCount);
  if (lostConnectionCount==4) {
    Serial.println("Cannot connect to the internet. Check your WiFI credentials");

void setup() {
  Serial.println("setup() started let's connect to WiFI");
  Serial.printf("WiFi name: %s\nWiFi pass: %s\n", WIFI_SSID, WIFI_PASS);
// Start our connection attempt
// Event driven WiFi callbacks
// Setup callback function for successful connection

// Setup callback function for lost connection

void loop() {
  // Run our server engine

Note: Only Linux and Mac support mDNS out of the box. If you use windows you will need to install additional software for that. Now since we use a multicast DNS server if we are using a client that supports it once we upload that code to an ESP32 we could access it from this 2 URLs:

  1. http://ESP_IP_ADDRESS/switch
  2. http://fasani.local/switch

Please note that even that WordPress makes the links above are not clickable and I also used fasani as ApName as shameless self-promotion. Please feel free to change it to your own updating the apName char variable.

This little program will just connect to WiFi, start a mDNS server and a WebServer in port 80, define the route /switch and simply turn a GPIO High and give 3.3v (ON) or Low 0v (OFF) to a GPIO. I just added a function where the routes are defined, since I’m a web developer, and I would like to emulate how other Web frameworks do to keep the routing in a single place. It’s useful, both for the program and for the documentation, to have a single function to place all the actions that your Firmware will support. This example is very simple but it has potential since you can expand it with as many actions you want, and not only turn High or Low a Gpio but also change variables using your server routes, or any other thing you desire.

2. HttpClient: The ESP32 will make a GET request

For this I prepared a very simple endpoint:

http://fs.fasani.de/time.php -> Will return the time in Europe/Berlin as default
http://fs.fasani.de/time.php?tz=America/Los_Angeles will return the time of that timezone

Of course you can use any timezone you want. The source of time.php is just 4 lines and you can put it in any server that supports PHP no matter what version:

$tz = isset($_GET['tz'])?$_GET['tz']:'Europe/Berlin';
echo date("H:i");

So this example will be even easier than number 1. It will simply connect to WiFi and query this URL to print in the Serial output the current time. The applications can be endless, for example, you can return only the hour as an integer, and your program can decide to turn on something depending on the hour.

#include "Arduino.h"
#include <WiFi.h>
#include <HTTPClient.h>
int lostConnectionCount = 0;
HTTPClient http;
String url = "http://fs.fasani.de/time.php?tz=Europe/Berlin";

void gotIP(system_event_id_t event) {
  Serial.println("Online. Local IP address:");
  int httpCode = http.GET();  //Make the request
  Serial.printf("http status:%d\n", httpCode);

  if (httpCode == 200) { 
     String response = http.getString();
     Serial.printf("The time now is: %s\n", response);
  } else {
    Serial.printf("We could not read the time.\nPlease check in the browser that the given url: %s is correct and replies with an HTTP 200 OK status", url);

void lostCon(system_event_id_t event) {
  Serial.printf("WiFi lost connection try %d to connect again\n", lostConnectionCount);
  if (lostConnectionCount==4) {
    Serial.println("Cannot connect to the internet. Check your WiFI credentials");

void setup() {
  Serial.println("setup() started let's connect to WiFI");

void loop() {

I hope this two easy examples will serve you to build more powerful things on top. I will be monitoring the commentaries if you want to achieve things that are not explained here.
In the next chapters we will explore more possibilities, based on my last 2 years journey, but also on your feedback.

Arduino-esp32 Basic course – Getting started – Chapter 1

First of all, this small series of blog posts, assume you have installed and are familiar with Platformio IDE to edit and upload code to your Espressif chips. We ‘ve covered in another post the installation and getting started part with this nice IoT editor. Please refer to this section of Platformio to get the basics right of the editor.
Prerequisites: Just grab any ESP32 or ESP8266 and make sure it works. Check that you can see the Serial monitor so we can debug the code. 

The platformio.ini project configuration file

This is the configuration file where we can define what are the environment targets (chips) where we want to upload and run our program. For example, we can have the same code, to run in ESP8266 or ESP32 using the same source. 

; File: platformio.ini

; This is the default environment but we can also use command line
; or change here to espressif8266 to upload it to this target
default_envs = lolin_d32

platform = https://github.com/platformio/platform-espressif32.git
board = lolin_d32
framework = arduino
monitor_speed = 115200
; set frequency to 80/ 160MHz 160000000L
board_build.f_cpu = 160000000L

platform = espressif8266
board = d1_mini_lite
framework = arduino
monitor_speed = 115200

So this will be our first program, will just include the Arduino framework, start a counter on 0.  As every program on Arduino framework, will have a setup() that is executed only once when the chip is powered, and a loop() method that is precisely on a loop.  It will just print what you see on setup and then a new line every second. 
I also invite you to to be curious enough to use the CTRL+LEFT click over Arduino.h and to explore what it does. It includes the framework. Actually it includes the FreeRTOS that is a real-time OS for microcontrollers and also some other important definitions and includes for the Arduino ESP32 framework itself to work. And this is the way to discover any library or thing you include in your program, just CTRL+LEFT and explore the code, trying to understand what function it has.
So now let’s code our first little program:

// File: src/main.cpp

#include "Arduino.h";

int counter = 0;

void setup() { 
   Serial.println("setup() started");

void loop() { 
   Serial.printf("Counter: %d\n", counter);

Very simple right? Not too many things. Just a variable in the global scope, that get’s incremented in the loop, and is getting printed using printf in a single line. So we created a very short and nice program that actually does nothing except printing some Serial output.
The variable scope is easy to grasp and is also the same for other languages as javascript. A global scope variable that is defined on top, can be incremented from each function. That means that if we would move the:

int counter = 0;

At the beginning of the loop() the loop itself would have no sense, since it will add one and go back to 0 all the time.

In the next chapter, we will learn how to use the environments we defined in platformio.ini, to add different codes keeping the same program to run in esp8266 and esp32. Just follow this blog or keep tuned to @martinfasani twitter account to read the next release.

NOTE: Up to here we could also have compiled and run the very same code in an Arduino board and it will do exactly the same. Since we are not using any of the Espressif extra goodies like WiFi, this could be run also in another boards, keep tuned to see what is coming next that will be using WiFi or Bluetooth.

Simple IoT image logging using BigIot.net

Since beginning of 2019 I’m participating in a project called “Low cost / low power sleep / WiFi Camera” so I purchased a couple of low cost boards, between them the LilyGO ESP 32 Camera.

ESP32 Lilygo 800×600 pix SVGA Camera. If you need a case, made one here

BigIot.net is an interesting IOT API site

Not only an API but a very interesting infrastructure that is also possible to link BIGIOT with WeChat allowing to “chat” with your device and use it for Smart home or just to check what was the last image uploaded.
In my fork of this ESP32 Camera, since the original looks a bit unmaintained without even an issue board, I added some better display information:

https://github.com/martinberlin/ESP32-Camera BIGIOT_UpdateImage.ino

This example shows how to set up an automatic camera that takes pictures every 20 seconds and sends them like an API Post push to BigIot.
So far so good, it works at first glance. The issue is that BigIOT is all in Chinese and there is no english. So if you consider that a problem then you can stop here. I didn’t because I think the Chinese know hell about this and they are leading the IoT world for a good reason.

So I translated it as I could just to register and get this pieces of information:

#define BIGIOT_API_KEY "KEYHASH" ( 智能设备 Devices -> APIKEY)

BigIOT Registration -> 注册


After registering you just have to open the activation Email and you are good to go. Just log in the Admin Panel and try to feel at home. Most important parts are:

智能设备列表 List of your Devices -> Add a “Camera device”

数据接口列表 List of your Inputs -> This is the Interface, so just make an “Upload interface”

And that are the two IDs you need, device ID and interface ID. After that and compiling this, the small camera is going to start pushing pictures to BigIOT and you can just click on the stats on the interface area and start checking the pictures when you are away.

Very good to control for example a 3D printer that you leave at home finishing something. This is the result:

Interface statistics
BigIOT Interface statistics

Here there is a great example on how to Listen to Commands to interact with WeChat

PlatformIO: An alternative to Arduino IDE and a complete ecosystem for IoT

PlatformIO Logo

As an introduction I would like to make clear that I’m not a C++ advanced coder or IoT professional, I do this just because it’s a challenge, and because it’s a lot of fun compared to my 9 hrs/5 days a week web developer doing PHP and Admin panels for clients in Germany. Two months ago I started tinkering with SPI Cameras and the Espressif systems boards and that’s how this open source project was born. So far I was using Arduino since I do not need a super IDE, sometimes I also edit the code with vi or gedit instead of open a monster IDE that will eat your CPU alive. But gladly this is not the case. I was since long looking for a competitive alternative to Arduino when this github issue on the FS2 Camera Project called my interest:

tablatronix commented 8 days ago

I had to manually install this button library as it is not in platformio , is it in arduinos?

And that’s how after a few clicks I discovered Plaftormio.org that according to their home page it’s an open source IoT ecosystem. But what interested me more than this is the subtitle:  “Cross-platform IDE and unified debugger. Remote unit testing and firmware updates

So instead of answering tablatronix issue, I started installing this new IDE, that happened in a breeze.
1. First thing is to install the VS CODE Version. I choosed the Visual Studio code option since it has more features. Microsoft’s Visual Studio Code is the base and PlatformIO is built on the top of this.

2. Go to “Extensions” and install PlatformIO IDE “Development environment for IoT, Arduino, Espressif (ESP8266/ESP32)”

platformio IDE extensions is marked in RED just before PlatformIO logo

3. In my case since I used Arduino IDE before, go to PlatformIO alien face logo and select “Import project from Arduino”. Then select the folder where your Arduino project is and PlatformIO will create a Workspace for you with all the necessary structure.

4. Adjust serial monitor baud rate.  If you are using Espressif chips edit platformio.ini and add the following line at the end:

monitor_baud = 115200

This will make your serial work in the right baud rate for ESP8266 /ESP32 (Serial is the plug icon in the bottom just before the Terminal > icon)

5. FS Data. If you are using SPIFFS that in Arduino is the /data folder inside your sketch you will notice that in PlatformIO this folder needs to be at the root level. So you can simply move it one directory above. To upload SPIFFS data use the following command in the terminal:

pio run --target uploadfs
IMPORTANT: As difference with Arduino if you try to save a file in /1.JPG here you will get it saved on:
/spiffs/1.JPG so create this folder on /data or you will get; VFSFileImpl(): fopen(/spiffs/1.jpg) failed

6. Libraries in PlatformIO live inside a folder on your project called .piolibdeps Thanks god, they are not distributed on 3 different parts, like it happens with Arduino (Some in Arduino/libraries, some in Programs/Arduino/libraries and so on) but are there available for you in just one place :)
To install a new library is very easy, just go to PlatformIO.org/lib and type the name of the library to search. If found copy the resultant line in the Terminal just like point 5 and the IDE will look this up for you and download it using github to the  .piolibdeps folder.

pio lib install "WifiManager"

Sometimes you will need a library in a special branch and there is also an easy way to do this. Just use :

pio lib install <repository#tag> 

// Install development version of WifiManager library
pio lib install https://github.com/tzapu/WiFiManager.git#development

7. If you use Arduino before it’s possible that you used some of it’s constants. So if your sketch compiles, but it does not runs like expected try to add this include line at the beginning

#include <Arduino.h>
Including Arduino.h at the beginning of the sketch

As a footer note I must make clear that it takes some time to get accustomed to the new IDE. But it comes with a great benefit as it shows you much better C++ warnings, it’s prettier to use, and has the advantage that you can Ctrl+Click and navigate between different classes. Something that it was not possible to do with my old IDE. And the most beautiful update is that all libraries are in a single place per Project, like it should be, leaving you a clear idea of how much code and dependencies you are adding into your sketch.

In FS2 project porting it to the ESP8266 Wemos board this happened like a breeze. And it was just the fact of upgrading my code to use OneButton library. adding the include Arduino.h and that is. After uploading SPIFFS data and the new code, the camera was ready to be used. Now it’s not always that easy. trying to compile the same code to an Heltec ESP32 board, I got SPI communication issues with the camera and I’m still fighting with it.

UPDATE: I found what is going on here, and it’s that there are some problems with my sketch that uses I2C and wire library to comunicate with the Camera on the Heltec ESP32 environment. Error message is:
i2cCheckLineState(): Bus Invalid State, TwoWire() Can’t init. I solved it updating the platformio.ini configuration file to use:
board = lolin_d32
So using this board it compiles and works correctly. No idea why it does not using heltec_wifi_lora_32 I will have to research more.

Additional links of interest:

Source filter: src_filter
This option allows to specify which source files should be included/excluded from build process. It could be useful to keep the same core for ESP8266 and ESP32 but including different files to support both. So far I’ve been using 2 different branches something that is hard to maintain for obvious reasons.

Library dependencies: lib_deps declaration in platformio.ini
Like composer for PHP, this IDE offers a way to declarate your libs in the ini file. To check how a professional software for 3D-printing does take a look in Marlin configuration file. This is a very important point to keep in mind since after the lib_deps list is correctly added and tested, people testing your code just need to hit “build” to download them, saving a huge amount of time.

New Project: ESP-IDF Component for epapers

Lately I’ve started to spend time trying Espressif’s own IoT development framework: ESP-IDF. At the moment of updating this post in version 4.0
And I must say that I like it a lot!

CalEPD is an epaper display component

The development + testing is happening in this repository:

If you want to use this as a component in your existing project: github.com/martinberlin/CalEPD