Introduction: Sigfox GPS Tracker
You may have wondered how GPS trackers work. At the end of this tutorial, you will be able to have a fully functional GPS tracker that sends data to your server. The use cases are endless, from tracking your pets or your shipments to tracking your motorbike, your boat or your drone. Feel free to share what you are tracking, it might give others great ideas!
What will be covered by this tutorial?
We will be using the TD1205P device (it should work also with TD1204 but I haven't tested and it has a different shape) from Telecom Design using Sigfox network.
Note that at the time I wrote the tutorial, the TD1205P was not officially released. We had the chance to test it before its official release.
Thus, we will see how to get started with Telecom Design SDK, how to download the sources, configure your laptop. We will also see how GPS works and how to request a GPS fix, how Sigfox works, how to encode the GPS fix into a Sigfox message (12 bytes) and send it, how to use the Sigfox bidirectional functionality to configure your device, how to set a callback in Sigfox's backend to send the data to your server.
What is Sigfox?
Sigfox is a connectivity solution dedicated to the Internet of Things. The operated network is currently operating in +22 countries, on every continent. Focused on tiny messages (up to 12 bytes) & low energy consumption, it currently powers 7 million devices. Various Sigfox-compatible technical solutions are available, from different silicon vendors.
Subscriptions to the Sigfox service are free for developers ( development kits & evaluation boards). Otherwise, they range between 1€/month & 1€/year depending on the volume commitment.
This project uses a TD1205 device from Telecom Design.
Ready to get started? Let's go!
Any skills required?
In my point of view, if you follow this tutorial, you should be able to reproduce it. However, knowing some basics of C programming will be a real plus. We will see in details what the code does and I commented the code to understand every step. Do not hesitate to leave a comment for the parts you don't understand if I haven't been clear enough.
This tutorial is quite long but will cover every step.
Who am I?
My name is Louis Moreau, I'm an intern at Sigfox. My role is to create prototypes and PoC using Sigfox network. I want these projects to be fun and instructive. I want to show you that it is easy to develop the first steps of your ideas. I will try to make this tutorial as complete as I can. Do not hesitate to ask me for more details if needed.
Contribution
I would like to thank Telecom Design (manufacturer of the device) and especially Jérôme Guerin, his precious time helped me to resolve many issues.
Step 1: Hardware
The easiest way to get the hardware is to buy a Telecom Design EVB:
- Documentation: http://rfmodules.td-next.com/evb/
- Get one: https://silica.avnet.com/wps/portal/silica/manufacturers/td-next/
Make sure to order one with a TD1204 or TD1205P, these two models include a GPS chip. The EVB include:
- a TD1205P (or TD1204)
- an EFM32 Tiny Gecko (around 30$)
- an FTDI cable
One year subscription to the Sigfox network
In order to have a fully functional device, you will also need a battery. You can use a LiPo or a small battery (no more than 3.7V).
Step 2: Get Started With Telecom Design SDK
These next parts are surely the hardest parts. I had many troubles to get started with the TD SDK. Not to mention that it is only for Windows OS... However, as I encountered many of the issues related on the td-next community forum, I will try to be as clear and illustrative as possible.
Get access to the Github repository
The first thing you need to do is to have access to the Github repository. To do so, you can follow the few steps on http://rfmodules.td-next.com/sdk/
I will still explain the steps with some screenshots:
- Go to https://developers.insgroup.fr/dashboards/develope... or https://developers.insgroup.fr/register.html
- Create an account and log in
- Navigate to "My Account" tab
- Navigate to the "Github" subtab
- Fill the form input with your Github username
Now you should have access to the private Github repository. When you have a look at the README.md documentation, here is what it is said.
The first parts are pretty simple, I did not get any trouble. However, when it came to the compiling part I found it way harder. I'll do a dedicated step for the compilation where I will try to add many screenshots.
Download the toolkits
You can get it on: https://s3-eu-west-1.amazonaws.com/assetstdnext/d...
Note that you have to unzip in C:/ (Windows root) otherwise it won't work.
Get the sources
The following steps detail how to download the source code and import all projects into the Eclipse environment.
- Navigate to the
"C:\TD\TD_RF_Module_SDK-v6.0.0\eclipse"
folder and double-click on the"eclipse.exe"
icon - Open the
"File"
menu and select the"Import..."
item. - In the
"Import"
dialog, unfold the"Git"
folder by clicking on the"+"
sign left to it, select the"Projects from Git"
item and click on the"Next >"
button - In the
"Import Projects from Git"
, select the"URI"
icon ad click on the"Next >"
button - Enter The Github repository URL
"https://github.com/Telecom-Design/TD_RF_Module_SDK.git"
in the"URI"
field - Enter your Github username and password in the
"User:"
and"Password:"
fields, respectively and click on the"Next >"
button - Check the
"Master"
branch box and click on the"Next >"
button - Enter
"C:\TD\TD_RF_Module_SDK-v6.0.0\Github\TD_RF_Module_SDK"
in the"Directory:"
field and click on the"Next >"
button - Check the
"Import existing projects"
radio button and click on the"Next >"
button - Click on the
"Finish"
button. The Git import will take place, this may take a while
All the available libraries and examples should now be available in the Project Explorer panel.
Organise the sources
By default, all projects are presented in Eclipse at the same level without particular organisation except that they are sorted alphabetically.
In order to have a more logical organisation, we must import an Eclipse "Working Set" that will provide a grouping of projects by categories.
To do so, launch Eclipse by navigating to the "C:\TD\TD_RF_Module_SDK-v6.0.0\eclipse"
folder and double-click on the "eclipse.exe"
icon (if not already done) and:
- Open the
"File"
menu and select the"Import..."
item. - In the
"Import"
dialog, unfold the"General"
folder by clicking on the"+"
sign left to it, select the"Working Sets"
item and click on the"Next >"
button - Enter
"C:\TD\TD_RF_Module_SDK-v6.0.0\Github\TD_RF_Module_SDK\TD_RF_Module_SDK.wst"
in the"Browse..."
field, check all working sets and click on the"Finish"
button - Click on the small downwards arrow in the top-right corner of the
"Project Explorer"
panel and select the"Select Working Sets..."
item - In the
"Select Working Sets"
dialog, click on the"Select All"
, then on the"OK"
button - Click on the small downwards arrow in the top-right corner of the
"Project Explorer"
panel again and select the"Top Level Elements > Working Sets"
item
All the available libraries and examples should now be better organised in the Project Explorer panel.
Step 3: (Re)set the Device With the Original Firmware
In the unfortunate event where anything works, you may need to reset the device to its original state (yes, I had to do it a few times :p).
Here is the procedure:
- Plug your device and your evaluation board as shown in the picture (don't worry about the wires soldered on the EFM32 right now)
- Get the original firmware:
- For the TD1205P: https://s3-eu-west-1.amazonaws.com/assetstdnext/do...
- For the TD1205: https://s3-eu-west-1.amazonaws.com/assetstdnext/do...
- For the TD1204: https://s3-eu-west-1.amazonaws.com/assetstdnext/do...
Easiest way:
- Download the TDLoader.exe program:
https://developers.insgroup.fr/downloads/TDLoaderV... - Select the original firmware and click on acquire
In my case, this method did not work... I had some different errors such as "could not initialize COM port" or "SRAM error". Don't worry there are other ways :)
Another way:
- Open the program under:
C:\TD\TD_RF_Module_SDK-v6.0.0\energymicro\energyAware Commander\eACommander.exe
- Click on connect
- Go to "Kit" tab and set the parameters as in the screenshots (Out)
- Go to "Flash" tab and select the original firmware
- Click on Flash EFM32
I had an issue where even this step did not work. To solve this problem, I had to do a small trick on the evaluation board as it is said in this document page 5: https://github.com/Telecom-Design/Documentation_TD...
You have to solder the evaluation board as it is described (see the pictures for a visual -> don't judge me about my soldering skills please)
Right now you should have a fully functional TD1205P. Now we will access it using AT commands and send our first Sigfox message. Ready?
Step 4: Send Your First Sigfox Message
Before we try to compile anything, we will do one first test to check if everything works fine.
Note that if you already have uploaded a custom firmware it won't work, but you still can upload again the official firmware to make these tests (see the previous step). The names of these firmware are "like td120X_modem_SOFTXXXX.bin"
We will try to send a simple Sigfox message saying 01CAFE (in hex). We will try to do so using the AT commands:
- Plug the FTDI cable to your laptop
- Check on which COM port the FTDI cable is: Go to "Windows" and search "device manager"
- Open the
C:\TD\TD_RF_Module_SDK-v6.0.0\putty\putty.exe
program - Click on serial radio button
- Go to the serial tab
- Set the parameters as they are in the screenshot (Baud rate: 9600, parity: none and flow control: none)
- Click on "Open"
Now, plug the TD1205P to your EVB.
On the Putty terminal:
Hit AT&V
, you should see the result with some information (as you may see on the screenshot).
Now hit AT$SF=01CAFE
the result should be "OK".
Let's see what your message look like in Sigfox backend.
Step 5: View Your Message in Sigfox Backend
If you don't have an account yet, please contact subscribe@sigfox.com
It has not been automatized yet but hopefully, it should become easier in the near future...
Once you have access to your devices, go to "device" and select your device by clicking on its id.
Then, you will see its information, on the left-hand menu, click on "message". Here you go you should see the message sent by the device.
Now I would suggest that you stop for a coffee, next parts are going to be tricky... But please come back!
Step 6: Import Project
All the sources are available on https://github.com/luisomoreau/sigfox_gps_tracker
Import the "Sigfox GPS Tracker" project
Open the "File"
menu and select the "Import..."
item.
- In the
"Import"
dialogue, unfold the"Git"
folder by clicking on the"+"
sign left to it, select the"Projects from Git"
item and click on the"Next >"
button - In the
"Import Projects from Git"
, select the"URI"
icon ad click on the"Next >"
button - Enter The Github repository URL
"https://github.com/luisomoreau/sigfox_gps_tracker.git"
in the"URI"
field - Enter your Github username and password in the
"User:"
and"Password:"
fields, respectively and click on the"Next >"
button - Check the
"Master"
branch box and click on the"Next >"
button - Enter
"C:\TD\TD_RF_Module_SDK-v6.0.0\workspace"
in the"Directory:"
field and click on the"Next >"
button - Check the
"Import existing projects"
radio button and click on the"Next >"
button - Click on the
"Finish"
button. - You can also create a workspace called
"Tutorial"
and add the project to this workspace.
Step 7: Compile the Sources
Ok right now comes the hard part. I had many troubles while compiling. I will try to overcome most of the issues and how to solve it.
Add the environment variables
With the exception of the binary-only static libraries in the "libtddrivers"
and "libtdrf"
projects, all deliverables are presented in source form only, and must be compiled to obtain an executable firmware. To compile properly you must add the GCC path into your Eclipse environment variables by opening:
Window -> Preferences -> C/C++ -> Build -> Environment -> Add...
Please add the PATH variable with the following value:
"C:\TD\TD_RF_Module_SDK-v6.0.0\gnu\bin;"
and "C:\TD\TD_RF_Module_SDK-v6.0.0\gnu\arm-none-eabi\bin"
At first, I had imported only the first path "C:\TD\TD_RF_Module_SDK-v6.0.0\gnu\bin" as it was suggested in the Telecom-Design' s Github repository but I had some troubles when compiling. Thus I strongly advise to add both paths. (See screenshot for the error logs)
Edit 10th October 2016: It appears that eclipse stores some cached data, try to clean the projects first and you should be able to compile it without adding any environment variables...
Compiling for TD1204 and TD1205
I haven't tested these devices but you should be able to make it work if you follow the official procedure:
- In order to avoid unnecessary rebuilds of the common libraries, it is best to set the right build configuration for all these libraries: unfold the
"Common_Libraries"
working set in the Project Explorer panel on the left side, then select all the projects by clicking on the first one in the list, pressing the"SHIFT"
key, then clicking on the last one in the list - Click on the small downwards arrow right next to the
"Hammer"
icon in the top menu bar and select the right build configuration corresponding to your board:"TD1204 or TD1205"
"GCC Release (EFM32G210F128)"
for a stripped down firmware - Open the file
"sigfox_gps_tracker.c"
- Click again on the small downwards arrow right next to the
"Hammer"
icon in the top menu bar and select the same build configuration as for the libraries above ("TD1205P"
) - Compilation of the
"sigfox_gps_tracker"
project and all the required dependencies will take place, which can be monitored in the"Console"
tab of the bottom panel.
Compiling for TD1205P
The TD1205P was not officially released when I wrote the tutorial, you should be able to compile the project for the TD1205P with this project (configuration is included in this repository). However, if you wish to go back from scratch, few tricks will be needed.
Then if we take this project as an example, here are the steps required to compile it:
- In order to avoid unnecessary rebuilds of the common libraries, it is best to set the right build configuration for all these libraries: unfold the
"Common_Libraries"
working set in the Project Explorer panel on the left side, then select all the projects by clicking on the first one in the list, pressing the"SHIFT"
key, then clicking on the last one in the list. - Click on the small downwards arrow right next to the
"Hammer"
icon in the top menu bar and select the right build configuration corresponding to your board:"TD1205P"
"GCC Release EZR"
for a stripped down firmware. - Unfold the
"Tutorial"
working set in the Project Explorer panel on the left side, then select the"sigfox_gps_tracker"
project - Click right on the project and select
"Properties"
. - Go to
C/C++ build -> Build variable
. Make sure that the TD1205P appear. If not you can create it by clicking on"Manage Configuration" -> "New" ->
add"TD1205P Release"
and copy the "TD1508" configuration. Then go to"Settings"->"Preprocessor"
and replace the revision with"MODULE_REVISION=REVISION_TD1205P"
. Make sure you do it for both preprocessors tab (under assembler and compiler). - Click on OK
- Open the file
"sigfox_gps_tracker.c"
- Click again on the small downwards arrow right next to the
"Hammer"
icon in the top menu bar and select the same build configuration as for the libraries above ("TD1205P"
) - Compilation of the
"sigfox_gps_tracker"
project and all the required dependencies will take place, which can be monitored in the"Console"
tab of the bottom panel.
The same procedure can be used for all the example projects when required.
Other encountered issue
Note that this may occur only with the TD1205P version.
I had an error with the _cs3_interrupt_vector_em (see screenshots) and it took me a pretty long time to solve. I proposed a pull request on Github official repository to solve this. I don't know neither if it will be accepted nor when. Thus, to solve it you can follow the very simple procedure:
Change the name of this file :
C:\TD\TD_RF_Module_SDK-v6.0.0\Github\TD_RF_Module_SDK\lib\Device\EnergyMicro\EFM32LG\Source\G++\startup_efm32lg.s
By:
C:\TD\TD_RF_Module_SDK-v6.0.0\Github\TD_RF_Module_SDK\lib\Device\EnergyMicro\EFM32LG\Source\G++\startup_efm32lg.S
Yes, just change the extension with an upper S... :/
Step 8: Code Explanation
What is the code doing?
Basically, we wanted a GPS tracker that sends the GPS coordinates every hour. However, we were not certain about the battery consumption, thus we wanted to be able to configure the device to send the coordinates every 2, 3, 6, 24 hours if needed (after our tests).
We did not want either to let the GPS switch on for a too long time if no GPS fix was available. Thus we wanted to be able to configure the GPS timeout.
We wanted to know the battery level, the speed and the precision hdop and the number of satellites received) .
We also wanted to be able to encrypt the Sigfox payload if needed.
Payload encoding
Here is how the payload is encoded:
- Byte 0: Lat
- Byte 1: Lat
- Byte 2: Lat
- Byte 3: Lat
- Byte 4: Long
- Byte 5: Long
- Byte 6: Long
- Byte 7: Long
Byte 8:
Voltage between 0 and 3825 with a 15mV stepByte 9:
Hdop on the first 2 bits (0 if <1; 1 if < 2; 2 if <5; 3 if >5)
Number of satellites received on the 2 next bits (0 if <3, 1 if <6; 2 if <8; 3 if >8)- Byte 10:
Acquisition time between 0 and 75s with a 5s step on the 4 first bits
Speed in km/h between 0 and 155km/h with a 5km/h step on the 4 last bits - Byte 11: Empty
Code
Now let's have a deeper look into the code in sigfox_gps_tracker.c, especially at the comments for a better understanding:
/****************************************************************************** * @file * @brief Simple GPS periodic fix application for the TDxxxx RF modules. * @author Telecom Design S.A. * @version 1.1.0 ****************************************************************************** * @section License * <b>(C) Copyright 2014-2015 Telecom Design S.A., <a> http://www.telecomdesign.fr </a>> ****************************************************************************** * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. * * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Telecom Design SA has no * obligation to support this Software. Telecom Design SA is providing the * Software "AS IS", with no express or implied warranties of any kind, * including, but not limited to, any implied warranties of merchantability * or fitness for any particular purpose or warranties against infringement * of any proprietary rights of a third party. * * Telecom Design SA will not be liable for any consequential, incidental, or * special damages, or any other relief, or for any claim by any third party, * arising from your use of this Software. * ******************************************************************************/ #include "config.h" #include <stdint.h> #include <stdbool.h> #include <efm32.h> #include <td_core.h> #include <td_uart.h> #include <td_printf.h> #include <td_stream.h> #include <td_flash.h> #include <td_scheduler.h> #include <td_watchdog.h> #include <td_gpio.h> #include <td_utils.h> #include <td_measure.h> #include <td_sensor.h> #include <sensor_data_geoloc.h> #include <td_accelero.h> #include <td_geoloc.h> #include <td_sigfox.h> #include <td_config.h> /******************************************************************************* ****************************** DEFINES **************************** ******************************************************************************/ /** Flash variable version ID */ #define VARIABLES_VERSION 0 // Interval at which position is reported (in seconds) #define FIX_INTERVAL 1*3600 // Send a Sigfox message every 1 hour /** Boot monitoring, 1 to enable */ #define BOOT_MONITORING 0 /** Keepalive monitoring interval in hours, 0 to disable * If you wish to send a keepalive frame remember to add a scheduler as well in the setup function */ #define KEEPALIVE_INTERVAL 0 #define DEBUG_USE_PRINTF 0 //trace on serial #if DEBUG_USE_PRINTF #define DEBUG_PRINTF(...) tfp_printf(__VA_ARGS__); #else #define DEBUG_PRINTF(...) #endif TD_GEOLOC_Fix_t CurrentGPSPosition; int timeout; uint8_t fixIntervalSchedulerId; //Configure the downlink request every maxCounter sigfox message int downlinkCounter; int downlinkMaxCounter; bool encrypt = false; int gpsSleepMode = TD_GEOLOC_OFF; int precision = TD_GEOLOC_2D_FIX; /******************************************************************************* ****************************** GLOBAL FUNCTIONS **************************** ******************************************************************************/ void encryption(uint8_t * bytes, uint8_t * cryptMessage, int size){ //Here you can insert your own encryption method - This function does nothing int i=0; for(i=0;i<size;i++){ cryptMessage[i] = bytes[i]; } } /***************************************************************************//** * @brief * GPS fix callback * * @param[in] fix * The GPS fix data structure. * * @param[in] timeout * Flag that indicates whether a timeout occurred if set to true. ******************************************************************************/ static void GPSFix(TD_GEOLOC_Fix_t * fix, bool timeout) { int i; uint8_t bytes[12]; uint8_t cryptMessage[12]; uint8_t timeoutMessage[1]; unsigned long latitude, longitude; char latitude_direction, longitude_direction; int hdop, nbSat, acqTime, speed, size; //Message init - Set to zero not to get random unwanted values for(i=0;i<12;i++){ bytes[i] = 0x00; } // if (fix->type >= precision && fix->hard.rtc_calibrated) { uint32_t mv = TD_MEASURE_VoltageTemperatureExtended(false); DEBUG_PRINTF("Voltage: %d\r\n", mv); DEBUG_PRINTF("Lat: %d - %08lX\r\n", fix->position.latitude, fix->position.latitude); DEBUG_PRINTF("Long: %d - %08lX\r\n", fix->position.longitude, fix->position.longitude); DEBUG_PRINTF("Hdop: %d \r\n", fix->quality.hdop); DEBUG_PRINTF("nb sat: %d \r\n", fix->quality.sat); DEBUG_PRINTF("acquisition time: %d \r\n", fix->duration); DEBUG_PRINTF("speed: %d \r\n", fix->speed.speed_kmh); //Stop GPS TD_GEOLOC_StopFix(gpsSleepMode); //Now we add the received data in the bytes array: //Latitude //Hint: divid the return value by 10 will make it understandable by Sigfox backend if (fix->position.latitude < 0) { latitude = (int32_t)(-1)* ((int32_t)fix->position.latitude / 10) ; latitude_direction = 'S'; latitude = latitude| 0x80000000; } else { latitude = fix->position.latitude / 10; latitude_direction = 'N'; } bytes[0] = (latitude >> 24) & 0xFF; bytes[1] = (latitude >> 16) & 0xFF; bytes[2] = (latitude >> 8) & 0xFF; bytes[3] = latitude & 0xFF; //Longitude if (fix->position.longitude < 0) { longitude = (int32_t)(-1)* ((int32_t)fix->position.longitude / 10) ; longitude_direction = 'W'; longitude = longitude| 0x80000000; } else { longitude = fix->position.longitude / 10; longitude_direction = 'E'; } bytes[4] = (longitude >> 24) & 0xFF; bytes[5] = (longitude >> 16) & 0xFF; bytes[6] = (longitude >> 8) & 0xFF; bytes[7] = longitude & 0xFF; //Battery for(i=0; i<255; i++){ if(mv>=i*15 && mv<=(i+1)*15){ bytes[8] = bytes[8] | i; }else if(mv>3825){ bytes[8] = bytes[8] | 0xFF; } } //Hdop /* * On the byte 9, we will encode both quality (hdop) and number of satellites * h h s s (h for hdop and s for the number of satellites) * Byte : _ _ _ _ _ _ _ _ */ hdop = fix->quality.hdop / 100; if(hdop > 5){ //Set the 2 first bits to 3 bytes[9] = 0xC0; } else if(hdop >= 2 && hdop <=5){ //Set the 2 first bits to 2 bytes[9] = 0x80; } else if(hdop >= 1 && hdop <2){ //Set the 2 first bits to 1 bytes[9] = 0x04; } //Satellites number nbSat = fix->quality.sat; if(nbSat >=8){ bytes[9] = bytes[9] | 0x30; }else if(nbSat >=6 && nbSat <= 8){ bytes[9] = bytes[9] | 0x20; }else if(nbSat >=4 && nbSat <= 6){ bytes[9] = bytes[9] | 0x10; } //Acquisition time /* * On the byte 10, we will encode both acquisition (a) time and the speed (s) * a a a a s s s s * Byte : _ _ _ _ _ _ _ _ */ uint8_t mask; acqTime = fix->duration; for(i=0; i<15; i++){ if(acqTime>=i*5 && acqTime<=(i+1)*5){ mask = i << 4 ; bytes[10] = bytes[10] | mask; }else if(acqTime>75){ bytes[10] = bytes[10] | 0xF0; } } //Speed speed = fix->speed.speed_kmh; for(i=0; i<15; i++){ if(speed>=i*5 && speed<=(i+1)*5){ bytes[10] = bytes[10] | i; }else if(speed>75){ bytes[10] = bytes[10] | 0x0F; } } //DEBUG size = sizeof(bytes)/sizeof(bytes[0]); for(i=0;i<size;i++){ DEBUG_PRINTF("bytes[%d]: %x\r\n", i, bytes[i]); } //TD_GEOLOC_PrintfFix(fix); encryption(&bytes, &cryptMessage, size); for(i=0;i<size;i++){ DEBUG_PRINTF("crypt[%d]: %x\r\n", i, cryptMessage[i]); } //Send data /* * If downlinkMaxCounter is reached, send a downlink request with the sigfox message */ //DEBUG_PRINTF("Downlink counter: %d / %d\r\n", downlinkCounter, downlinkMaxCounter); if(downlinkCounter >= downlinkMaxCounter){ TD_SIGFOX_SendV1(MODE_FRAME, false,encrypt?cryptMessage:bytes, size, 2, true, false); downlinkCounter = 0; }else{ TD_SIGFOX_Send(encrypt?cryptMessage:bytes, size, 2); downlinkCounter++; } } else if (timeout) { //If no GPS fix has been found, we still send the voltage uint32_t mv = TD_MEASURE_VoltageTemperatureExtended(false); DEBUG_PRINTF("Voltage: %d\r\n", mv); for(i=0; i<255; i++){ if(mv>=i*15 && mv<=(i+1)*15){ timeoutMessage[0] = timeoutMessage[0] | i; }else if(mv>3825){ timeoutMessage[0] = timeoutMessage[0] | 0xFF; } } //Set the device in its sleep mode TD_GEOLOC_StopFix(gpsSleepMode); DEBUG_PRINTF("Fix Timeout\r\n"); DEBUG_PRINTF("Time: %d \r\n", fix->duration); TD_GEOLOC_PrintfFix(fix); DEBUG_PRINTF("Downlink counter: %d / %d\r\n", downlinkCounter, downlinkMaxCounter); if(downlinkCounter >= downlinkMaxCounter){ TD_SIGFOX_SendV1(MODE_FRAME, false, timeoutMessage, 1, 2, true, false); downlinkCounter = 0; }else{ TD_SIGFOX_Send((uint8_t *) timeoutMessage, 1, 2); downlinkCounter++; } } } /***************************************************************************//** * @brief * Call-back function for SIGFOX downlink. * * @param[in] rx_frame * Pointer to the received frame or null if timeout occurred. * * @param[in] length * Length in bytes of the received frame. * * @return * Returns the buffer length if OK, -1 if an error occurred. ******************************************************************************/ static int DownlinkCallback(uint8_t *rx_frame, uint8_t length) { int i; int fixInterval; DEBUG_PRINTF("Downlink...\r\n"); if (rx_frame == 0) { // Finished receiving //TD_SIGFOX_DOWNLINK_SetUserCallback(0); DEBUG_PRINTF("RX END\r\n"); // Done return 1; } else { if (length == 0) { // Start receiving DEBUG_PRINTF("RX BEGIN\r\n"); // Done return 1; } // Received one good frame tfp_dump("RX=", rx_frame, length); DEBUG_PRINTF("rx_frame: %d - %x - %s\r\n", rx_frame, rx_frame, rx_frame); for(i=0;i<8;i++){ DEBUG_PRINTF("rx_frame[%d]: %x - %d\r\n", i, rx_frame[i], rx_frame[i]); } //Here is the GPS timeout value meaning the maximum time you will try to get a GPS fix timeout = rx_frame[0]; DEBUG_PRINTF("timeout: %d (in seconds)\r\n", timeout); //The fixInterval (in hours) is the time interval to send a message fixInterval = rx_frame[1]; if(fixInterval>3 && fixInterval<48){ DEBUG_PRINTF("fixInterval: %d (in hours)\r\n", fixInterval); TD_SCHEDULER_SetInterval(fixIntervalSchedulerId, fixInterval * 3600,0,0); gpsSleepMode = TD_GEOLOC_OFF; } if(fixInterval>0 && fixInterval<=3){ DEBUG_PRINTF("fixInterval: %d (in hours)\r\n", fixInterval); TD_SCHEDULER_SetInterval(fixIntervalSchedulerId, fixInterval * 3600,0,0); gpsSleepMode = TD_GEOLOC_HW_BCKP; } //you can add restriction for the max number of uplink to occur before requesting a downlink here //When 255, it will always be true //You can easily calculate the interval time for downlinks doing '(fixInterval * downlinkMaxCounter) + 1' if(rx_frame[2]<48){ downlinkMaxCounter = rx_frame[2]; DEBUG_PRINTF("downlinkMaxCounter: %d (in hours)\r\n", downlinkMaxCounter); } // Done return 1; } } /***************************************************************************//** * @brief * Start fixing periodically. * * @param[in] arg * Generic argument set by the user that is passed along to the callback * function. * * @param[in] repeat_count * Updated repeat count, decremented at each timer trigger, unless it is an * infinite timer. ******************************************************************************/ static void StartFixing(uint32_t arg, uint8_t repeat_count) { DEBUG_PRINTF("Start fixing\r\n"); TD_GEOLOC_TryToFix(TD_GEOLOC_NAVIGATION, timeout, GPSFix); } /***************************************************************************//** * @brief * User Setup function. ******************************************************************************/ void TD_USER_Setup(void) { TD_UART_Options_t options = {LEUART_DEVICE, LEUART_LOCATION, 9600, 8, 'N', 1, false}; // Open an I/O stream using LEUART0 TD_UART_Open(&options, TD_STREAM_RDWR); // Use a 64 s automatic watchdog TD_WATCHDOG_Init(64); TD_WATCHDOG_Enable(true, true); TD_SENSOR_Init(SENSOR_TRANSMITTER, 0, 0); // Geoloc and accelerometer initialization TD_GEOLOC_Init(); TD_ACCELERO_Init(); //Fix timeout timeout = 60; //Init downlink counter downlinkCounter = 0; //Once every x uplink downlinkMaxCounter = 23; //One downlink every day #if BOOT_MONITORING // Will only send a boot monitor frame on NEXT reboot TD_SENSOR_MonitorBoot(true, 0); #endif #if KEEPALIVE_INTERVAL > 0 // Send a keep-alive frame immediately, then at given interval TD_SENSOR_MonitorKeepAlive(true, KEEPALIVE_INTERVAL); #endif // Start fixing right now StartFixing(0, 0); // Start the fix infinite timer fixIntervalSchedulerId = TD_SCHEDULER_Append(FIX_INTERVAL, 0, 0, TD_SCHEDULER_INFINITE, StartFixing, 0); TD_SIGFOX_DOWNLINK_SetUserCallback(DownlinkCallback); } /***************************************************************************//** * @brief * User loop function. ******************************************************************************/ void TD_USER_Loop(void) { // Process Sensor events TD_SENSOR_Process(); // Process geoloc events TD_GEOLOC_Process(); // Process downlink events TD_SIGFOX_DOWNLINK_Process(); }
Step 9: Flash Project to the Device
Debug
You can debug the project using Putty (same method as in the reset the device step) and enable DEBUG variables in the project (Set the variable to 1 - ligne 78).
Software
If it does not work, please try to reset your device.
Unlike some dedicated embedded Interactive Development Environments (IDEs), Eclipse does not come with fixed Flash/Debug commands or menu buttons: they need to be added explicitly on a project by project basis.
Fortunately, these Flash/Debug "Launchers"
can be imported or duplicated to other projects easily:
- Open the
"File"
menu and select the"Import..."
item. - In the
"Import"
dialogue, unfold the"Run/Debug"
folder by clicking on the"+"
sign left to it, select the"Launch Configurations"
item and click on the"Next >"
button - Enter
"C:/TD/TD_RF_Module_SDK-v6.0.0/Github/TD_RF_Module_SDK/Eclipse Launchers"
in the"Browse..."
field, check the box in front of the"Eclipse Launchers"
item and click on the"Finish"
button - All the default Flash/Debug
"Launchers"
will be added to the top menu"Bug"
and"Green Circle with With Right Arrow and Briefcase"
icons - If required, you can edit these
"Launchers"
by choosing the "Debug Configurations..."or
"External Tools Configurations..." entries in the menu obtained by the small downwards arrow right next to the corresponding"Bug"
or"Green Circle with With Right Arrow and Briefcase"
icon - In the dialogue windows that opens, you can edit a given configuration directly and click on the
"Apply"
and"Close"
buttons, or you can duplicate it by right-clicking on it and selecting the"Duplicate"
entry in the contextual menu that pops up
Then, to flash a firmware to the TD12xx/TD15xx board:
- Select the desired project in the Project Explorer panel on the left side
- Right-click on the project and select the
"Build Configurations > Set Active >"
and the desired build configuration as explained above - Optionally click on the
"Hammer"
icon in the top menu bar to build the project - Click on the small downwards arrow right next to the
"Green Circle with With Right Arrow and Briefcase"
icon and select"Flash Selected Project"
in the contextual menu.
Hardware
Depending on how you want to supply power to the device, use the switch on the EVB (see screenshot of the documentation):
- The upper position will supply power from the FTDI cable
- The lower position will supply power from the EFM32 board
- No jumper will use the power from the device (Battery, Lipo, etc...)
Be careful not to put the jumper when the device is powered by an external source otherwise, it may damage your device!!
Step 10: View the Geolocalisation
Now that our device can send data, let see how to see the geolocalisation on Sigfox Backend:
- Go to "Device Type"
- Click on your device type
- You should arrive on the information tab. Click on "edit" upper right corner
- Change the display type to "Geolocalisation" "Default (root)"
- Save
- Go to "Device"
- Select your device
- Scroll down on the information tab until you see "See the device track on map"
- Click on it, you will see your device last positions on a map
- You can also go to message and see the latitude and longitude
Step 11: Bravo
Let your imagination guide you.
Now you can connect and track your dog, your bike, your car or whatever you want.
You just need to solder a small battery (be careful not to overstep 3.7V) and let your device live its life!
Do not hesitate to share what you made. I'll be glad to answer your question. Feel free to contact me!
We haven't discussed the part where you send a callback to your own server. I wrote a small part on this on my first tutorial "Sigfox Talking Plant" (step 7). Go and have a look if you are interested ;)
Thank you for your attention. I know this tutorial is not the easiest I made. Bravo if you've reached the end!!!