All our code is freely available on GitHub, do not forget to check our repositories and give us some feedback! ^^
In case you are wondering if this post might be interesting for you, here is what we have achieved and what we will show in it:
- Fully functional piggy bank that is able to differentiate between 1 € and 2 € coins
- Integration of the piggy bank with cloud services like ThingSpeak
- Implementation of a custom server with Flask for real-time visualization of the data read by the sensor and the coin classificaction. See the video above or watch it in Youtube!
- Fast, real-time readings with I2C communication between a 3D Magnetic Sensor 2GO board from Infineon and a NodeMCU development kit, using MicroPython
Coink is an IoT piggy bank.
In the 21st Century piggy banks can be very easily connected to the cloud and become part of the rapidly growing Internet of Things.
Having automatic reports of your savings online is not only very convenient but can also make saving fun for kids! With Coink you can have real-time graphics with your cumulative savings as well as the recent daily savings to track your progress.
Adults may use it as well, not only for fun, but to help them quit smoking, for example, keeping track of the money they save each day. Or in bars and restaurants, to keep track of the tips they get each day.
Of course the magnetic coin detection system can be used elsewhere: in vending machines, arcade game machines... The cloud-connected piggy bank is just an application.
In order to build Coink, we will need:
- A wooden box.
- A magnet attached to the ramp, that generates a static magnetic field.
- A 3D Magnetic Sensor 2GO board from Infineon, that will detect the changes on the magnetic field when a coin passes through the ramp and in between the magnet and the sensor.
- An ESP8266-based board, in particular a NodeMCU development kit that reads the data from the 3D magnetic sensor through I2C and sends it through WiFi to the cloud.
- A simple power circuit consisting of a LiPo battery (single cell) and a 3.3 V step-down DC-DC converter mounted on a breadboard.
- A computer or cloud server to analyze the raw data and identify the different coins.
We use an ESP8266-based board, in particular a NodeMCU development kit.
It is a very cheap, but powerful board.
MicroPython
We use the Python programming language or, more accurately, the MicroPython programming language. Not only it is a beautiful language, but also implements an HTTP stack that will ease the process of communicating with a remote server in any IoT project.
In order to start using MicroPython, we need to load the MicroPython firmware onto the ESP8266 board first.
Flashing the firmware
We need to make sure we have the required permissions to flash the device. Either:
sudo usermod -a -G dialout $USER
Or, to avoid the need to log out of your session:
sudo echo 'ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", MODE="0666"'> /etc/udev/rules.d/99-nodemcu.rules
sudo udevadm control --reload-rules
You might need to adjust theidVendor
andidProduct
depending on what you see withdmesg
when connecting the device.
We use esptool to reflash the device, which is very easy to install with:
pip install --user esptool
Then, reconnect the device and erase its flash memory with:
esptool.py --port /dev/ttyUSB0 erase_flash
Download the latest MicroPython firmware for ESP8266 boards and flash it with:
esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=detect 0 esp8266-20180511-v1.9.4.bin
Testing the REPL
Once the MicroPython firmware is on the device we can access the REPL (Pythonprompt) over serial with a 115000 baudrate:
screen /dev/ttyUSB0 115200
If everything went well we should see a >>>
(if not, try to press “enter”). You may now try to execute a simple print()
call, which will be executed in the board itself:
The 3D Magnetic Sensor 2GO board and the NodeMCU are connected through an I2C bus. The sensor is powered with the ESP8266 board directly, using its 3V3 and GND pins. Wiring them boils down to connect only 4 wires:
Once the sensor is connected to the board we can check the I2C connection by simply:
from machine import I2C
from machine import Pin
i2c = I2C(scl=Pin(5), sda=Pin(4), freq=400000)
devices = i2c.scan()
print(devices)
Which should print a non-empty list.
Build it!Ramp
Coink is actually very easy to build. First we need the ramp to insert the coins. The ramp is a 3D design that can be very easily printed with any FDM 3D printer (or any other more-advance 3D printer if you have access to it).
The 3D design is very simple but, in turn, we need to do some work before using it. First, we need to glue some plastic sheets to cover the inner parts of the ramp. This way we avoid the coin bumping into any disturbances around the sensor board, where the ramp is not continuous:
Then we need to cover the outer part of the ramp by gluing another plastic sheet. We will glue our magnet (in orange) there, just in front of the sensor board. Any magnet will do, we just need to make sure it is not too powerful, or the coins will get stuck in the ramp!
Box
The piggy bank can be made with a small wooden box. Wood is easy to work with, which is important as we will need to create a hole for the ramp in the box:
Once we have the hole, we can very easily glue the ramp to the box with some epoxy to make sure it does not move.
Even if obvious, we should make sure the magnet and the magnetic sensor board both fit inside the box before glueing the ramp!
Once the ramp is fixed, we only need to stick the rest of the components to the lid:
Note that we added a simple power circuit consisting of:
- A LiPo battery (single cell).
- A 3.3 V step-down DC-DC converter mounted on the breadboard.
The output of the converter directly powers the board at 3.3 V.
Analyzing the DataVisualization
If we visualize the sensor readings during one second, when a coin is passing by, we note that there is little time (around 50 milliseconds) to get useful data:
Each of the axis has a different iddle-state reading, so we can normalize the readings by first dividing by the average iddle-state reading and then subtracting 1 to have an iddle-state reading of 0 in all axis and also to have data curves that represent relative variations of the magnetic field instead of absolute.
After doing this normalization we can visualize our region of interest for both 1 € and 2 € coins:
Differences
Having a look at the previous curves we might notice some differences between the 1 € and 2 € curves. Among them we might notice a small difference in the time span. Although that makes sense (the 2 € coin has a bigger diameter than the 1 € coin) and we would expect it to alter the magnetic field for a longer period, this is assuming the speed is the same for both coins. That, of course, is not very reliable, as we could simply insert coins with higher speed when pushing them down the ramp. Therefore, we will ignore differences in the x-axis(time) and focus on the y-axis (magnetic field relative variations).
In order to be able to compare curves and try to differentiate among different coins, we did some simple feature engineering to try to extract some curve features that are relevant and easy to compare/match against known profiles:
min_[axis]
Represents the absolute minimum value, for the given axis.
d0_[axis]
Represents the maximum positive increase since the last rolling minimum from the idle state and until the absolute minimum is reached, for the given axis.
l0_[axis]
Represents the low value where d0_[axis]
started, for the given axis.
Although the differences for those engineered features might seem obvious for the curves shown above, we want to make sure that the differences are significant on average for all the data we gathered.
To visualize these differences we can use box plots for all min
, l0
and d0
features, for all axis as well:
We can see there are many significant differences between the two coins. Although we could use only the most significant among them it is better to simply use all features. Matching against the average plus some expected deviation we can not only differentiate between 1 € and 2 € coins, but also detect unexpected (potentially fake coins) readings.
Uploading the Coink Code to the NodeMCUBefore running our cloud server, we definitely want to actually upload theCoink MicroPython code to the NodeMCU board.
This is actually very simple, but we do need to have some dependenciesinstalled: screen
and ampy
. Once we have those, we can simply connectour board to our computer with an USB cable and:
./flash.sh
This Bash script will upload all the necessary code to our board.
Coink Server IntegrationRunning the Coink server is necessary to appropriately process the data andclassify the coins in “the cloud”, whether it is your own computer or an actualcloud service.
The server is implemented with Flask and requires some other Python packages to run. Fortunately, Pipenv helps us to create the required virtual environment with all dependencies installed:
pipenv sync
If we want to have all the development dependencies installed, use instead:
pipenv sync --dev
Our prototype is designed to work within a local area network, where we have the NodeMCU and our computer connected to the same WiFi network (probably our home network). In order to be able to do so, we need to copy the contents of the config.template.json
to a new config.json
file, that would look like this:
{ "thingspeak_key": "0123456789ABCDEF",
"wifi": {
"ssid": "MyWifi",
"password": "secure123"
},
"server": {
"host": "0.0.0.0",
"port": "5000"
}
}
We need to modify the "wifi"
fields with our network name and password.
Note that there is another section to configure the "server"
. There, we need to put our computer IP address and a port, where our server will be listening on.
The access port should be just a free port, try it for example with5000
Then we can run the server with Pipenv:
pipenv run python server.py
If everything went well, you should be able to access the configured server with your web browser. To do so, visit http://your-defined-host:your-defined-port/
(i.e.:http://192.168.43.110:5000/
), you should see the Coink server page:
Now go ahead and insert one coin into your Coink! ^^
Connecting with ThingSpeakIntegrating Coink with an external cloud service like ThingSpeak is very straight forward thanks to their public RESTful API. We just need to write a couple of lines of code to process and visualize the data appropriately.
The following code snippet plots the daily savings in the last couple of days:
[data, time] = thingSpeakRead(516536, 'Fields', [1], 'NumDays', 7);
data = timetable(time, data)
data = retime(data, 'daily', 'sum')
bar(data.time, data.Variables, 'FaceColor', [1 .5 0])
The following code snippet plots the total accumulated savings:
[data, time] = thingSpeakRead(516536, 'Fields', [1], 'NumDays', 365);
curve = cumsum(data);area(time, curve, 'FaceColor', [1 .5 0]);
title(strcat('Total savings: ', num2str(sum(data), '%.2f'), ' €'));
ylabel('€');
Note that the code above assumes that the ThingSpeak channel was created to ingest a single field, which corresponds to the coin that was detected on insertion. The code then sums by day or calculates the total cumulated sum.
Comments