Microcontroller projects

ESP8266 tips and tricks

last updated: 11/03/20

Configure Arduino

Copy the following line:

http://arduino.esp8266.com/stable/package_esp8266com_index.json

to "File > Preferences > Additional Boards Manager URLs:".

Go to "Tools > Board:".." > Boards Manager..." and scroll down. Then click install.

In Linux you have to use udev rules! if you don't want to work as root. See here

Pins

It is important to use the right pins, to avoid conflicts. A really good tutorial can be found here: https://randomnerdtutorials.com/esp8266-pinout-reference-gpios/.

Wifi password

The wifi password must be 8 or more for the Access Point to work (WiFi.softAP(ssid, password) function)! To be shure check the return value :).

Serial

Hardware serial (opened with Serial.begin(9600)) on Wemos D1 mini pro uses UART0 of ESP8266, which is mapped to pins TX (GPIO1) and RX (GPIO3).

Serial1 (opened with Serial1.begin(9600)) uses UART1 which is a transmit-only UART. UART1 TX pin is D4 (GPIO2, LED!!).

If you use serial (UART0) to communicate with hardware, you can't use the Arduino Serial Monitor at the same time to debug your program! The best way to debug is to use Serial1.println() and connect RX of an USB2Serial adapter (FTDI, Profilic, CP210, ch340/341) to D4 and use a terminal program like CuteCom or CleverTerm to listen to D4.

wemos<em>hw</em>serial

Serial (UART0) may be remapped to D8 (TX, GPIO15, 10k Pull-down?) and D7 (RX,GPIO13) by calling Serial.swap(); after Serial.begin();. Calling swap again maps UART0 back to TX and RX.

SPIFFS

The SPI Flash Filing System is designed for SPI flash devices on micro-controller systems with little RAM. It uses statically sized ram buffers (independent of number of files), posix-like API (open, close, read, write, ...) and implements static wear leveling to prolong the life of system flash.

SPIFFS uses a flat structure (no directories). Creating a file with path homie/config.json will create a file called homie/config.json instead of a config.json under directory homie. Write operation might be slow, so it is best used at start up, shut down or when time critical activities are not scheduled.

Here some info on the Wemos boards. Arduino lets you chose the amount of SPIFFS for some boards (newest Arduino and ESP8266 core (2.4!)).

Wemos D1 mini lite v1.0.0 1M bytes (0-512kB SPIFFS)
Wemos D1 mini v3.0 4MB FLASH (1MB or 3MB SPIFFs
Wemos D1 mini pro v1.1.0 16MB FLASH (15MB SPIFFS)
Wemos LOLIN32 Pro v1.0.0 4MB FLASH & 4MB PSRAM
Wemos LOLIN32 lite v1.0.0 4MB FLASH
Wemos LOLIN32 v1.0.0 4MB FLASH

Flash layout

Programming a new sketch will not modify the file system contents. This allows to use file system to store sketch data, configuration files, or content for Web server.

The following diagram illustrates flash layout used in Arduino environment:

|--------------|-------|---------------|--|--|--|--|--|
^              ^       ^               ^     ^
Sketch    OTA update   File system   EEPROM  WiFi config (SDK)

Test size of FLASH

The following example sketch CheckFlashConfig.ino can be found in your core examples (File-Examples-ESP8266-CheckFlashConfig). You see the size in your serial monitor.

Arduino ESP8266 filesystem uploader

Download the plugin from here and unzip the file. Create a folder ESP8266FS in the Arduino tools directory and in this folder a new folder tool. Copy the esp8266fs.jar file into the tool folder (Arduino\tools\ESP8266FS\tool\esp8266fs.jar). If there is only a .java file you have to compile it first sudo ./make.sh. After a restart you find a menu item ESP8266_Sketch_Data_Upload in the Arduino Tools menu.

Go to sketch directory Sketch > Show Sketch Folder and create a directory named data. Load all your files you want to be in SPIFFS to that folder. After this make sure you have selected your board, port, and closed the serial monitor.

Select Tools > ESP8266 Sketch Data Upload. This starts uploading the files into ESP8266 flash file system (be patient; its done when the IDE status bar displays SPIFFS Image Uploaded).

Test SPIFFS

Here is a code snippet lend from Steve Quinn to read a SPIFFS file (first load up your file (e.g. /homie/config.json) to SPIFFS as described below):

#include <string.h>
#include "FS.h"

bool    spiffsActive = false;
#define TESTFILE "/homie/config.json"

void setup() {
  Serial.begin(115200);
  delay(1000);
  if (SPIFFS.begin()) {    // Start filing subsystem
      Serial.println("SPIFFS Active");
      spiffsActive = true;
  } else {
      Serial.println("Unable to activate SPIFFS");
  }
  delay(1000);
}

void loop() {
  if (spiffsActive) {
    if (SPIFFS.exists(TESTFILE)) {
      File f = SPIFFS.open(TESTFILE, "r");
      if (!f) {
        Serial.print("Unable to open ");
        Serial.print(TESTFILE);
      } else {
        String s;
        Serial.print("Contents of file ");
        Serial.println(TESTFILE);
        while (f.position()<f.size()) {
          s=f.readStringUntil('\n');
          s.trim();
          Serial.println(s);
        }
        f.close();
      }
      Serial.println();
    } else {
      Serial.print("Unable to find ");
      Serial.println(TESTFILE);
    }
  }
  while (true){
    yield();
  }
}

More infos here http://www.instructables.com/id/Using-ESP8266-SPIFFS/ and here http://esp8266.github.io/Arduino/versions/2.3.0/doc/filesystem.html

Backup and restore ESP8266 flash

Wee need the python esp tools for this. You find them in /packages/esp8266/hardware/esp8266/2.5.2/tools/esptool/. With the following command we read the flash:

    sudo python ./esptool.py -p /dev/ttyUSB0 -b 460800 read_flash 0 0x400000 flash_contents.img

The parameter are the port (-p), the bitrate (-b), the beginning and ending address and the name of the file. esptool

Uploading to the ESP8266 is done with:

sudo python ./esptool.py -p /dev/ttyUSB0 -b 460800 write_flash -fm qio 0x00000 flash_contents.img

After this we need to reset the chip. We specified the flash-mode qio (-fm qio). If this doesn't work, try the dout method instead (-fm dout).

Delete flash

After uploading a sketch using WiFi your SSID and Wifi password are stored in cleartext in the flash. So it's a good idea to erase the flash if you want to give the board to other persons.

sudo python ./esptool.py -p COM5 erase_flash

External Antenna on Wemos D1 mini pro

To connect an external antenna you have to unsolder the 0Ω resistance near the ceramic antenna and resolder it direction the miniature RF connector (U.FL).

Link to video:

Sending NTP time over Serial1

As stated above, Serial1 uses UART1 which is a transmit-only UART. UART1 TX pin is D4 (GPIO2, LED!!) on Wemos D1 mini pro.

We will use this pin to send NTP time once a day (e.g. 4 AM). Another microcontroller may use this time to synchronise his RTC (sketch for Teensy see here (scroll down)).

Here is the ESP8266 sketch:

    /*
      ESP8266: Sending NTP over Serial1
      weigu.lu
    */

    #include <ESP8266WiFi.h>
    #include <time.h>

    #define SSID            "xxx"
    #define SSIDPWD         "xxx"
    #define TZ              1       // (utc+) TZ in hours
    #define DST_MN          60      // use 60mn for summer time
    #define TZ_SEC          ((TZ)*3600)
    #define DST_SEC         ((DST_MN)*60)

    time_t now;
    struct tm * timeinfo;
    int z=1;

    void setup() {
      Serial1.begin(115200);
      WiFi.mode(WIFI_STA);
      WiFi.begin(SSID, SSIDPWD);
      while (WiFi.status() != WL_CONNECTED) {
        delay(100);
      }
      configTime(TZ_SEC, DST_SEC, "pool.ntp.org");
      delay(120000); // wait 2 minutes
      now = time(nullptr);
    }

    void loop() {
      now = time(nullptr);
      timeinfo = localtime(&now);
      if ((timeinfo->tm_hour==4) && (timeinfo->tm_min==0)) { // at 4 AM
        configTime(TZ_SEC, DST_SEC, "pool.ntp.org");
        delay(120000); //wait 2 minutes
        now = time(nullptr);
        timeinfo = localtime(&now);
        if (timeinfo->tm_hour<10) Serial1.print('0');
        Serial1.print(timeinfo->tm_hour);
        if (timeinfo->tm_min<10) Serial1.print('0');
        Serial1.print(timeinfo->tm_min);
        if (timeinfo->tm_sec<10) Serial1.print('0');
        Serial1.println(timeinfo->tm_sec);
      }
      delay(1000);
    }

Using Interrupt Service Routines

We need to use the linker attribute ICACHE_RAM_ATTR for our Interrupt Service Routines. With this attribute we say that the function should be stored in RAM instead in Flash. As the entire flash is used for the program and storage, reading and writing to the flash can be done only over 1 thread. Accessing the flash simultaneously over 2 different threads will crash the ESP and trigger a watchdog reset.

    ICACHE_RAM_ATTR void ISR() {
      flag = true;
    }

Downloads