If you own several badges, cards, or tickets and would like to automatically publish the number of unused badges on the web in real-time, there is no off-the-shelf solution. This post describes how to build such an IoT system.

Background Story

In our region, it is possible to use a transferable monthly pass for public transportation. Our village club buys such passes and offers them for free use on a day-by-day base, which hopefully will reduce the use of cars. In return, one is asked for a voluntary donation to keep this project running.

You can go to our local bakery and ask for such a pass. Of course, when you arrive at the bakery and notice that all the tickets are already in use, it is frustrating. And here the story starts. So, why not build a system that senses the number of remaining passes and publishes that on the Internet? There exists no off-the-shelf solution, but as a Maker, it is possible to design and build such a system.


Firstly, you need an organizer or rack where the passes can be stored individually (so that they can be counted). Then, you need sensors that can check their presence. Once the number of passes is known, it should be transmitted to a host computer. Finally, the number needs to be published on a web page.

This should all be done with minimal energy and maximal reliability without compromising the security of the system’s wireless network or the web server that delivers the web page with the information.

The Rack

Building the physical rack is something where 3D design and printing can be helpful. As before, I used Tinkercad to design the rack. This was quite a challenge, taking a few iterations (printing and throwing away prototypes). All in all, the final rack consists of more than 60 objects and holes. What was annoying was that one often accidentally changed something without noticing it. Afterward, I decided to switch to a more powerful CAD tool such as FreeCAD in the near future.

First, I tried to design and print the pockets separately and attach them to the main body. However, there was always a small gap where the pass could slide through. In the end, I decided to print the case upright with integrated pockets. This worked quite well, as one can see in the following (3D animated) sketch.

The final printed result is shown in the next figure. Note that the back of the rack also exists, which is not shown in the photos or the sketch.


Before one can start designing the rack, one must decide on the kind of sensor and how to attach it inside the case. There are several options, such as time-of-flight optical and audio sensors, reflectance measurement sensors, and NFC/RFID sensors. However, I decided early on to use the proximity sensor ADPS9930. It uses IR reflectance measurement to detect objects which are up to 100 mm away. The good thing is that the pockets are made of black plastic, and the angle of the walls leads to relatively low reflectance. The measurement that one gets with no badge in the pocket is between 70 and 150. If a badge is in the pocket, even when made from black paper, the measurements are 400 or higher. So, one can reliably detect whether there is a badge in a pocket.

The sensors can be configured to be in a power-down state most of the time and periodically check for significant changes. When such changes happen, the sensors can raise an interrupt and wake up the MCU.

Wireless Network

Once the sensors have determined the number of badges, one needs to send this information to a web server. The most straightforward solution would be, of course, Wi-Fi. However, in the era of hacked networks, you do not want to ask people to provide access to their network. These days, the alternative to Wi-Fi for IoT applications is LPWAN (low-power wide area network). LTE-M, for instance, is a very affordable LPWAN service offered by mobile data service providers. I got a SIM card for €10 that is valid for 10 years and has a data volume of 500 MB. While this data volume does not sound like much, the expected data transfer rate is probably less than 100 kB/day, which means 500 MB is more than enough. Incidentally, the AVR-IoT Cellular Mini board supports LTE-M. And the MCU on the board, an AVR128DB48, is powerful enough to implement the system. Although with a price of €80, it is not cheap, it leads to working solutions effortlessly, and one is not locked into a proprietary cloud solution. For this reason, this board was chosen as the main component.

Communication Protocol

Once your device is connected to the Internet, it must talk to some host using a communication protocol. MQTT is often the protocol of choice for IoT solutions since it is made for communication with devices that are not always online. This implies that you must run (or rent) an MQTT broker. Since the plan is simply to display only some number in a browser, the more straightforward solution is to transmit this number using a POST request to a web server using, e.g., a CGI script. And this is indeed the chosen solution. Sending is performed using the HTTPS protocol, which guarantees that no man-in-the-middle attack is possible. When the web server receives the measurement, it will store it together with a time stamp so that it is possible to ignore the measurement when it is too old (e.g., more than an hour).

Displaying the Number

Once the number of unused badges and the timestamp have been stored on a web server, say under http://example.org/data/example.txt, it is easily possible to show it on a web page. One easy way is to embed PHP code on the web page, as below.

<!DOCTYPE html>
        function read_card_num($url) {
                $headers = @get_headers($url);
		if($headers && strpos( $headers[0], '200')) { // web page exists
		  $data = explode("\n",file_get_contents($url)); // 1st line data, 2nd timestamp
		} else { 
		  return "no info"; // if webpage does not exist

		if (time()-$data[1] > 3600+300 ) { // data is too old
		  return "no info";
		} else {
                  return $data[0];
      <b>Available cards: <?php echo read_card_num("https://example.org/data/example.txt") ?></b>

If you want to render the text on a WordPress website, you can define a shortcode that uses the above PHP function. Shortcodes can, e.g., be defined using the CodeSnippet plugin.


How could bad boys make life miserable? They might try to use the CGI script to upload arbitrary files, or they might try to upload fake data. The script will write data only in one specific file, and one needs a password that is checked before writing any data. So, it appears to be extremely unlikely that somebody could abuse the CGI script, provided the password is kept secret. Note that the only place where the password is stored in plain text is in the Arduino sketch. On the web server, only a cryptographic hash is stored, which is used to verify the transmitted password. Finally, the transmission of the password is protected by using the HTTPS protocol, as mentioned above.

User Interface

The rack’s user interface is elementary. You put a card into a pocket or remove a card from a pocket. In principle, it is possible to shove more than one card into a pocket. However, I have no idea how to prohibit or detect that. One simply should not do that!

There is an LED to give a basic idea of the device’s state. If the LED is on, it signals that the device is working. When a card is added or removed, this is detected after 3 seconds, and then the LED blinks slowly for a few seconds to signal that it transmits the data. In case anything goes wrong, the LED will blink permanently. One might then try to power cycle the system. If this does not help, maintenance is called for.

In the following video, you can see the system at work. First, there are no badges in the pockets, which is shown on the web page. Then two badges are added, which is recognized by the rack, signaled by the blinking LED. After a reload of the web page, this new number is displayed.

Arduino Sketch

Although the Arduino sketch itself contains 400 lines of code, it is not very complicated. Most of it concerns detecting abnormal conditions and reporting them. The main gist of the sketch is given in the pseudocode below.

void setup() {
  init_blink_irq_routine(); // blinks as long as the system is awake

void loop() {
  int numberOfCards;

  numberOfCards = gather_sensor_readings();
  sleep_until_wakeup(); // if a sensor value changes or after one hour, the system wakes up

One interesting detail is how the I2C sensors are handled. Since the board has two I2C buses running with different voltage levels, and since these are in use for communicating with other peripherals, I employed an additional software I2C library, namely FlexWire. This library can replace the Wire library altogether. However, I did not want to mess with the existing libraries. So, I put a copy of the FlexWire library in the src sub-folder that did not contain the magic Wire.h file. In addition, I also copied the APDS9930 library to this sub-folder and modified it to work with FlexWire instead of Wire. Using the software I2C multiplexer trick, I can now communicate with all three sensors without using an additional hardware multiplexer.

Hardware Configuration

The hardware configuration is almost canonical based on the above. The Fritzing sketch below shows how the three sensors and the system LED are connected to the main board, which has a Feather footprint. I used an M328 feather in the Fritzing sketch. However, of course, the real thing is the AVR-IoT Cellular Mini board.

As you can see in the picture in the beginning, I did not use flying leads as suggested in the Fritzing sketch. Instead, I used Dupont cables to connect the sensors and the LED to the main board, which is a prototyping board called FeatherWing Doubler. I soldered the pins for the Dupont connectors on this board, but the space was very limited, so the actual soldering looks hideous. I will definitely design a printed circuit board for this purpose.

Summary & Outlook

Publishing the number of unused badges, cards, tickets, or passes on a web page does not sound terribly complicated. Unfortunately, there are no off-the-shelf solutions for it. However, with 3D printing, the AVR-IoT Cellular Mini board, APDS9930 proximity sensors, and a bit of Arduino programming, one can come up with a robust and secure solution. Although it does not sound overly complex, I still had to spend a few working days with 3D design, making myself familiar with the board, and come up with the necessary set of scripts and sketches. The information about the final system can be found in the project’s GitHub repository.

While I would consider the project as sort of finished, there are a few things that could be done. One thing is to write all log messages to the onboard EEPROM, which has a capacity of 250 kB. My first attempts to utilize the EEPROM were not successful so far.

Another valuable addition on the software side would be to log all sensor readings in a database on the web server. This could later be used to generate statistics about the passes’ usage. Then there is the business of designing a PCB, which would also open up the possibility of supporting more pockets. Finally, the 3D design could be extended to allow for more pockets. This would probably mean printing two cases that can be connected.

Views: 53