Create a $5 autonomous tracker with ESP8266 and Sigfox

There are multiple ways to track something or someone. Cellphone are using different method to be able to give you a precise location in most of the situation. The more global one is GPS, it works anywhere on earth but do not really work indoor. It is also costly (about 8$ or more) and power consuming. Outdoor your usually have a precision of 15 meters. The less precise one is triangulation : a message received by different antennas will be located by the network in an area covered by all these antennas. This solution works anywhere the network is covering and do not need specific power other than for communicating. The precision is usually from 500m to 10km.

The last usual method we use is the one we are going to implement in this post : the WiFi positioning. The tracker is listening for the WiFi access point around and ask one of the existing database knowing most of the WiFi location to get a position. This is working thanks to the crowding effort all of us are doing with our smartphone of capturing WiFi around us and associated locations. The WiFi solution is working where WiFi is, so usually in the cities ; around buildings. It works well indoor, better than outdoor where WiFi is less active. The precision is about 30-50 meters. The power consumption is lower than GPS.

Sigfox is a LPWA (Low Power Wide Area) network covering about 45 countries (as today) dedicated to low power autonomous devices aka IoT. Asset tracking is one of the best use-case.

The use of Sigfox with a WiFi tracker is allowing to create a low-cost tracker device, autonomous on battery from month to years, getting benefit in 45 countries of a WiFi + network localization.

This post will explain how to get started in this technology by using two standard, easy to use and low cost components allowing to get your prototype for about $5 of hardware.

What we are going to do ?

We want to make a Tracker able to give us a position on regular basis using two possible ways : WiFi or network. Sigfox Network is allowing us to communicate every 10 minutes.

Basically the tracker will sleep for 10 minutes, wake-up, scan the WiFi network around for about 4s and report information about two of them : the one with the best signal. The backend server will get a position from these information.

When no WiFi are around the Sigfox network will report the location itself.

ESP8266 – the WiFi as easy as an Arduino

ESP8266 is a well known MCU offering a WiFi connectivity for less than 2$ on shops like aliexpress. This component has a large success and Arduino has been port on it. The community is large and the internet crowd based support is really large.

This component can run in normal mode where the power consumption is large about 15mA/h when WiFi is down. This is too large for autonomous (IoT) devices. For this reason the following program will take benefits of the Deep Sleep Mode offering by the chip. In this mode the device can sleep and go down to 10uA/h. As we have seen we need to be up and running about 10 seconds every 15 minutes. Considering WiFi reception consumption about 50mAh the average consumption will be about 0.5mAh.

This is about 200 days running on 2xAA cells. Just reduce the frequency of the transmission to jump from months to years.

This mode is really interesting but it create some complexity in the code as when the device wake up from deep sleep it is rebooting, during the deep sleep period the memory is lost and as a consequence only a little peace of memory can be move and store into the RTC (Real Time Clock) memory area.

Also during this boot sequence the Serial port will all be spammed by boot message. This is another complexity to manage for communicating with Wisol module and also a mess to log debugging information.

Wisol – low cost Sigfox module

Wisol module is one of the solution to send messages over Sigfox network. This module is really accessible around $2 and easy to use. It also have an efficient sleep mode only requiring 1uAh.

The communication between ESP8266 and Wisol module is using a TTL serial communication. The best would have been to connect this module to on of the 2 serial line existing on ESP8266. Unfortunately these Serial line are used by ESP8266 boot-loader on startup and a lot of noise is sent over. For this reason I’ve preferred using a SoftwareSerial UART for making the communication.

General schema

The schematic is simple : on the ESP8266 we need to connect Reset and GPIO16 to manage the deep-sleep / wake up process. GPIO 12 & 13 are used for serial communication with Wisol module.

I added a control function on GPIO14 to leave the deep-sleep mode and replace it by a loop function to get a better debugging access and be able to reflash the device on demand. You can just leave it unconnected for a normal run.

Access and Understand the source code

The source code is accessible on github following this link :

This is a multi file Arduino sketch. Containing different libraries I’ll not go in detail in this post. I only want to focus on the main steps of this project.

To use it, as a prerequisite you need a configured ESP8266 environment. The sketch has been made for a WeMos D1 mini module so the hardware config is related to this platform.

To modify the configuration you can check the config.h file. You will find the hardware config and also the scanning frequency timer, debug & logging configuration.

The main.ino file contains the main routine, basically every time the device is wake up from deep-sleep the setup function is executed and the reset cause is analyzed to detect if we are facing the first run or a deep-sleep wake up.

void loop() {

    // ----
    // For real this loop will be executed only one time after every deep sleep wake up
    uint32_t elapsed = ( debugModeLoop )? 0 : millis(); 
    if ( debugModeLoop || lowPowerService.wakeUp((uint8_t*)&trackrService.state, &trackrService.state.crc32, sizeof(trackrService.state)) ) {

      // This is a standard loop from a device wake up signal or after an internal wait loop
      // We execute all what we have to do on regular basis
      trackrService.execute(SCHEDULER_PERIOD_MS+elapsed);                              // Load the context from RTC memory & execute actions
    } else {

      // This is the first loop after powering ON the device
      // We can call boot method to execute all the first time settings 
      trackrService.boot(elapsed+5000);                                               // What have to be done just one time on startup from a reset
      // wait for potential debug mode switch for 5 seconds
      uint32_t start = millis();
      while ( (millis() - start) < 5000 ) {

    if ( ! debugMode ) {
      // In the normal mod the ESP8266 is going deep sleep
      // going deep sleep...
      lowPowerService.deepSleep( SCHEDULER_PERIOD_MS,(uint8_t*)&trackrService.state, &trackrService.state.crc32, sizeof(trackrService.state) );
    } else {
      // debug mode, no sleep, always run so we can listen for command on the
      // serial line
      uint32_t start = millis();
      while ( (millis() - start) < SCHEDULER_PERIOD_MS ) {
    if ( debugMode ) debugModeLoop = true;

In this function we have two different ways to loop on execution depending if the debug mode is activated (by putting the GPIO14 to ground) or if the deep-sleep mode is running. In this case, in the wake up function the memory context is restored, that way the execute() function do not have to manage the deep-sleep context.

The debug mode can also be switched during the 5 first seconds of the boot by typing a command on the serial line. This command is “!d”. Once in debug mode there is a list of command you can type on the Serial line like “:l” to dump the log file on console ; “!P” to get the Sigfox device initial PAC…

For this pure trackr code, some of these element could be removed but if you want to add different behavior to this trackr to make it smarter, the state backup and the configuration storage, as the logging are all really important things.

This main file is executing the trackr function every 15 minutes:

 * This function is called on every wake-up and manage the other one
 * The context has already been restored in Main
 * Elapsed Time = time in Ms elapsed since Last call
void TrackrClass::execute(uint32_t elapsedTime) {
    uint32_t start = millis();
    uint8_t  mac1[6];
    uint8_t  mac2[6];

    // Reinit hardware - reload config
    configService.init(false);                        // load the configuratin from flash
    _log.init(configService.config.logConfig);        // init logging engine

    // Scan for Wifi
    if ( wifiscanService.getFirstAndSecondBestWiFi(mac1, mac2) == 2 ) {
      char macStr[20];
      dsk_macToString(macStr,mac1);"1. %s\r\n",macStr);
      dsk_macToString(macStr,mac2);"2. %s\r\n",macStr);   

      // Prepare the frame !
      uint8_t msg[12];
      for ( int i = 0 ; i < 6 ; i++ ) {

    // Prepare to sleep
    state.totalMs += elapsedTime + (millis() - start);

WiFi around are scanned, the scanning function is searching up-to 4 different SSID, it filter the Mac address and SSID to maximize the localization capabilities. It removes the multicast and locally defined Mac addresses. It tries to prohibit the SSID name used by smartphone hotspot.

Then it search for the 2 Mac address with best signal and report them on Sigfox network. If we want to add a network positioning when WiFi conditions are not viable we could add a single byte transmission in a else condition.

Integration with Sigfox

Sigfox has a localization service named Atlas, it actually offer a network positioning for each of frame received in sigfox backend. In a really near future this service will be extended to support the WiFi localization.

The source code I’ve been provided is working with Sigfox Atlas service. This way by sending a message containing the two best WiFi Mac address around you will get a position. If the WiFi information match with a location stored in the Here ( database (the backend service Sigfox use) a call back will be performed on your server with the location. The given precision goes from 30 to 100 meters. When the WiFi match no position or when you have no WiFi, the network will return a network based position with a precision from 500m to 10km.

Thanks to this service you do not need to implement any third party service to get a location and the price is included in the Sigfox subscription. So basically on top of the $5 hardware you just need less than $10 per year to get a tracker.

To configure the Atlas-WiFi service, you just need to configure two call back in the Sigfox backend:

The first one is a Data Uplink callback pointing to the service, the second one is a redirection of the GEOLOC callback pointing to the same service. This way the service mix the network information and the WiFi information to create a callback for your own server. The GEOLOC message received on your server side is looking like this:

{"id":"2147XX", "seqnum":254, "time":1527523426, "latitude":45.XX72536, "longitude":3.XX4630017, "accuracy":65, "source":"Wifi"}
{"id":"2147XX", "seqnum":255, "time":1527525367, "latitude":45.XX3529450733224, "longitude":3.XX084631508202, "accuracy":4241, "source":"Network"

The first frame is corresponding to a position obtained from WiFi, the second one from the network. (Some XX have been added fro my own privacy ;))

I’ll detail later the complete configuration : at this time the service is only accessible for beta testing and the final configuration process is not in place.


To conclude

You may find my code a little bit complex for what has to be demonstrated. There are two reason for this :

  • This is an open source, really simplified, version of one of the coming family member of Sigfox trackers. For this reason it includes production ready components like config, RTC/deep-sleep, advanced logging.
  • The second was to share a full project source code running ESP8266, something that can be used for a good starting point for making a product. That’s my first project in this environment (ESP8266) and I did not found a such project sample code. Hope it will save to some of view most of the time I spent starting for basic examples to fully working, scalable, reliable code.




14 thoughts on “Create a $5 autonomous tracker with ESP8266 and Sigfox

  1. Can you follow up with the Sigfox backend configuration details (callbacks and the Atlas service)? I believe this will be of great value for lots of users.
    Great project, by the way.

  2. Excellent! Looking forward to that. Thank you.

    Also, I’ve noticed a interesting behavior: My build is sending data to Sigfox (I can see messages on the backend). Interval is set to 15min.
    But data only gets published every ~4 hours. When it happens, I always get to uplinks in a row (15min apart).
    So it’s 4h without any communication, then two uplinks in sequence (15min apart), then 4h in the dark again. Then the sequence repeats.

    This is pretty consistent, been happening for a couple of weeks, like clockwork. Have you seen this before?

    • Strange behavior, in the console log, do you see the same behavior with WiFi scanning and communications ? Basically the transmission is on every ESP8266 wake up. So if your WakeUp/reset pin is not correctly connected you can have some strange behavior like this one.

      • Actually, if the device is connected to the PC, the log clearly states the device does wake up every 15 minutes (every time it scans wifi then publishes the command to the Sigfox module).
        Also, the LEDs on the Wisol module blink 3 times every 15min, just like they should.
        Here is an excerpt of the times in which the module worked, according to the Sigfox backend (the device was turned on during the whole time). Notice the pattern mentioned on my last message:
        19/08/2018 19:06
        19/08/2018 18:51
        19/08/2018 14:22
        19/08/2018 14:07
        19/08/2018 09:51
        19/08/2018 09:36
        19/08/2018 05:21
        19/08/2018 05:06
        19/08/2018 00:51
        19/08/2018 00:36

      • If you have 15minute wake up in the console log but 4h transmission sometime on sigfox it can be related to the communication between ESP8266 and Wisol. The softserial implementation on ESB8266 has some unexpected behavior.As written in the wisol source code comment (ok that’s hidden a bit ..) ( Requires : SoftwareSerial – /!\ version > 3.4.1 is recommended )

      • Despite using espsoftwareserial 3.4.1, still getting an random uplink every four hours… Follows the same pattern (two uplinks in a row, then ~4h until the next two).
        Anything else I should consider ?

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.