Arduino-esp32 course – Event driven WiFi and build_flags configuration – Chapter 2

On this new release we will focus on connecting our Espressif board to WiFi and will also the powerful build_flags to inject the defines directly on compilation time. This will make our WiFi configuration easier and leave it in a place where it can be easily configured, again in our platformio.ini project configuration file:

[env:espressif8266] 
build_flags = 
-DWIFI_SSID=\"MyWiFiName\"
-DWIFI_PASS=\"password\" 

; Password with special chars: My pass'word 
-DWIFI_PASS=\"My\ pass\'word\"

-D instructs the compiler to #define the variable WIFI_* and make it available in my program
So actually doing this in main.cpp will accomplish exactly the same:

#define WIFI_SSID "MyWiFiName"
#define WIFI_PASS "password"

But as you can see if we do that we would be hardcoding our credentials in a C++ file which is not the best if we would like to share our program in github so other people can use it. Doing it the build_flags way, we are keeping it in a place tight to our code repository, but that can be configured withouth touching our main code. Nice, doesn’t it?
And of course you can discover more settings about this platformio.ini configuration and define many other things there, like GPIOs that your sensor uses and any other variable that need to be injected in compilation time. Pretty handy to distribute your projects and leave the configuration where it needs to be. So now that we’ve the credentials let’s make our program connect to the WiFi in an event-driven way:

#include "Arduino.h"
#include <WiFi.h>

int lostConnectionCount = 0;

/** Callback for receiving IP address from AP */
void gotIP(system_event_id_t event) {
  Serial.println("Online. Local IP address:");
  Serial.println(WiFi.localIP().toString());
  // We are connected, we could already receive or send something w/WiFi
}

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

void setup() {
  Serial.begin(115200);
  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
  WiFi.begin(WIFI_SSID, WIFI_PASS);
// Event driven WiFi callbacks
// Setup callback function for successful connection
  WiFi.onEvent(gotIP, SYSTEM_EVENT_STA_GOT_IP);

// Setup callback function for lost connection
  WiFi.onEvent(lostCon, SYSTEM_EVENT_STA_DISCONNECTED);
}

void loop() {
}

That was already a step ahead of Chapter 1. This won’t work in Arduino ATMega chip, for this code we already need an Espressif chip that can connect to WiFi. My take on connecting to WiFi are the events that the WiFi library incorporates, since I find it easy to cope with, and with only those two events GOT_IP and STA_DISCONNECTED you should be ready to go.
Now that we are on this point, there is a very handy thing to learn in case we want to make this code work also in ESP8266, since the 8266 version uses a different WiFi library. Plataformio injects some variables to identify what environment we are compiling with. I really don’t know exactly how many they are and you can just read this on their own documentation but I know that this two come very hande for our purpouse:

#ifdef ESP32
   #include <WiFi.h>

#elif ESP8266
   #include <ESP8266WiFi.h>

#endif

So basically if we compile this, editing the ini default_envs in platformio.ini, and compile it on an esp32 then there will be a #define ESP32 set and the first include <WiFi.h> will take place. But if we use an esp8266 then the ESP32 will be not define and the ESP8266 instead. Then the other ESP8266WiFi.h header file will be included.
The #ifdef statements in C are processed in compile time. Is not like a real conditional if in our program, you can imagine this #ifdef as a way to let us shape our program to different environments, or even do different things if a sensor is defined. For example we could have a Firmware that has an optional TEMPERATURE_SENSOR. Well if that is defined, then it should measure the temperature and run an extra code for that, if not then it will simply not include this part letting the program run anyways and do it’s thing but without that part of the code.

Important, the WiFi classes are not the same and ESP8266WiFi class does not have the same event handlers as the ESP32 class so here is the rewritten part if you want to do a version that supports both chips:

#include "Arduino.h"
#include <ESP8266WiFi.h>
int lostConnectionCount = 0;

#ifdef ESP32
/** Callback for receiving IP address from AP */
void gotIP(system_event_id_t event) {
  Serial.println("Online. Local IP address:");
  Serial.println(WiFi.localIP().toString());
  // We are connected, we could already receive or send something w/WiFi
}

/** Callback for connection loss */
void lostCon(system_event_id_t event) {
  ++lostConnectionCount;
  Serial.printf("WiFi lost connection try %d to connect again\n", lostConnectionCount);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  if (lostConnectionCount==4) {
    Serial.println("Cannot connect to the internet. Check your WiFI credentials");
  }
}
#elif ESP8266
  void gotIP() {
    Serial.println("Online. Local IP address:");
    Serial.println(WiFi.localIP().toString());
    // We are connected, we could already receive or send something w/WiFi
  }
#endif

void setup() {
  Serial.begin(115200);
  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
  WiFi.begin(WIFI_SSID, WIFI_PASS);


#ifdef ESP32
// Event driven WiFi callbacks
// Setup callback function for successful connection
  WiFi.onEvent(gotIP, SYSTEM_EVENT_STA_GOT_IP);

// Setup callback function for lost connection
  WiFi.onEvent(lostCon, SYSTEM_EVENT_STA_DISCONNECTED);
#elif ESP8266
  Serial.print("Connecting.");
  while (!WiFi.isConnected()) {
    Serial.print(".");
    delay(200);
  }
  gotIP();
#endif

}

void loop() {
}


So we’ve used this example to make this WiFi part be environment independant and run in both ESP32 or ESP8266 but actually is much more powerful than that and can be used for many other things.

This will be the Serial output when running the program for this chapter

FS2 camera from Blender to production

In this entry, I wanted to document what is the process of making one of this cameras, starting from the 3D – model to the end product where you turn it on and connects to WiFi ready to take pictures.

After removing the support and sanding the round columns the first thing is to connect the front and back case together and see that they fit correctly. Usually, they do but PET is a tricky plastic to print and the end termination is a bit rougher than with PLA so it requires some post-production work. As an advantage, this plastic is stronger than PLA, and will stand a crash much better since it’s more elastic and resistant. I would say the best termination and strength balance would be to print this in ABS but I dislike the smokes and the fact that is also very difficult to print at home.

When this step is ready then it’s the time to heat up the soldier and prepare the ON/off switch and the shutter button. Then there are 8 cables more that go from the Arducam (2 or 5 mega version) to the Wemos D1, that is the responsible of uploading the picture to the cloud. This is a prototype for myself so it looks a bit messy but shows how it is at this stage:

3 pair of cables from the left to the right: Battery, ON/off and shutter button

Then comes the reality shock moment that is to connect the Wemos ESP8266 through USB to the computer and upload the program that will do the magic of receiving the JPEG image from Arducam and upload it to a php API endpoint. Usually, at this point there is something that needs to be corrected, but either nothing works or all is fine and dandy. I open the mobile hotspot and turn on the camera. See if connects, try to take a picture, preview it on the PHP-gallery.  Try to test timelapse mode, see it works, and that’s pretty much it. A new camera is ready to be delivered.

FS2 WiFi camera