Summer Project Part 6: A matching bookend
Since the last post, I've completed the project - at least in it's initial form. The IoT device I've been building is finished - along with the backend that receives the data and trains an AI on it. I've learnt a great deal whilst working on it. Unfortunately, I've been very short on time, so I haven't been able to blog about it as frequently as I'd have liked to.
Before we continue, it's perhaps best to show a diagram here of how the completed system works:
(Above: A diagram showing the typical workflow when using the completed system. Taken from my dissertation.).
Operation is divided up into 3 sections:
- Data collection: Using the Internet of Things (IoT) device to collect data.
- Processing the collected data: The data file on the microSD card of the device is folded into the main database (more on this later), and AIs are trained
- Viewing the final map in your browser.
Because the application is somewhat distributed in nature, it's not exactly obvious how the data flows across the application. Let's use another diagram to show how this works:
(Above: A diagram showing the data flow throughout the application. Taken from my dissertation.)
This diagram looks complicated, but it really isn't as complex as it looks.
- First, the IoT device takes a reading. This includes the GPS location (latitude and longitude) and a random id (unsigned 32-bit integer)
- This reading is both stored on a local SD card, and transmitted via LoRa
- The copy transmitted via LoRa travels through The Things Network and is picked up by the TTN listener, which stores the reading in an SQLite database
- Once data collection has been completed, the data on the microSD card is folded into the SQLite database generated by the TTN listener by the data processor. This ensures we have data points for places that the signal isn't, as well as where it is.
- 1 AI is then trained per gateway. These AIs are trains on the signal strength data for their gateway, but also the data for where the signal is not.
- The trained AIs are serialised to disk with an index file, where the web interface picks them up.
Training the AIs was a bit of a pain. Getting the inputs and outputs right along with the AIs topology to a point where the output is meaningful was quite challenging - especially considering the limited amount of data I managed to collect. I'd like to tweak and improve on it further, if I have time.
I ended up getting quite a bit of noise in the final dataset that I trained the AIs with - simply because of the way I designed the IoT device - and because of the time constraints, I didn't have the time to go back and fix it. The device currently logs the data point to disk and transmits it via LoRa afterwards. When the battery was low, I noticed that it had a tendency to reset when transmitting via LoRa, leading to a reset-loop and lots of bogus readings on the microSD card. And because I don't store the timestamp, I can't even tell them apart!
I also had a bit of a problem with configuration files - specifically that they kept multiplying. At the end of the project, I now have no fewer than 3-4 different configuration files - all in different formats! I'd love to consolidate them into 1 single configuration file, to make configuration much easier for the end user.
- 1 for the pin definitions and features to enable / disable in C++
#definestatements for the IoT device - Another 1 in C++ for the private TTN LMiC settings
- 1 in TOML for the server
- 1 in Javascript for the web interface
Ideally, I want everything to be defined in the TOML configuration file, since I developed a system by which I have a default configuration file, and a custom one in which the user can override any of the default settings.
With all this said, the output isn't bad:

(Above: A screenshot of the web interface, with the background map removed for privacy)
The AIs do appear to have learnt a round circle of coverage around the gateways, which is somewhat frustrating - since the aim was to take obstructions into account too. I suspect that I need more data - and to figure out a way of training the AI of places that other gateways pick up a signal, but the current gateway does not (currently the gateway is only trained on positive readings and negative ones where no gateway picks up the signal).
If anyone is interested in the code behind the project, I have now open-sourced it, and it is available here:
The repository includes source code, user and hardware manuals, and a circuit diagram.
I may blog about this in the future, but it's likely to be a while. I'm starting a PhD this academic year, which is sure to be fun! Expect some posts about that in the near future.
Found this interesting? Comment below!