STM32F1xx micro-controller C firmware template
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
King Kévin f7bf415eca README: add project documentation 2 years ago
lib sx172x: add library to communicate with semtech SX127x LoRa module 2 years ago
libopencm3@cb0661f81d update libopencm3 2 years ago
.gitignore cherry-pick from busvoodoo branch, part 2 4 years ago
.gitmodules remove STM32duino-bootloader 6 years ago
Doxyfile doc: fix documentation 2 years ago
LICENSE.txt add GPLv3 license file 4 years ago README: add project documentation 2 years ago
Rakefile Rakefile: use black pill devboard for this project 2 years ago
application.c application: commit YouGotParcel application 2 years ago
application.ld ld: update ld script to updated libopencm3 2 years ago
bootloader.c replace header license with SPDX statement 2 years ago
bootloader.ld ld: update ld script to updated libopencm3 2 years ago
global.c replace header license with SPDX statement 2 years ago
global.h global: disable DEBUG 2 years ago

YouGotParcel is a pair of devices that remotely tells if a parcel has been put in the post box.



one of the device goes into the post box. using switches it can detect when the door of lid have been opened. it then transmits the activity to the other device over radio.

the second device receives the activity messages, and shows the status of the post box using LEDs.

if the lid is opened, the green LED will light up, indicating a package is present in the post box. if the door is opened, the red LED will light up, indicating the post box have been emptied. if no indication has been received (> 1h), both LEDs will switch off.


to transmit the status, the LoRa radio protocol is used. Semtech SX1728 modules for the 433 MHz band (420 - 450 MHz) are used, but any SX172x module for any band (allowed by the local regulation) can be used. it does not use LoRaWAN (which requires an infrastructure and the right band support), but just LoRa directly between the two modules. each part has one of the LoRa modules. one will be used to transmit (the one in the post box), while the other while be used to receive (at the remote location). the modules are the same, and can be used to transmit and receive.

LoRa is used because, as the name says, it can transmit data over a long range. this is at the price of baud rate, but since we only need to transmit if lid or door has been opened (e.g. 1 bit), this is sufficient. the module is configured for most resilient transmission:

  • lowest bandwidth: 62.5 kHz (minimum when using a XTAL clock source)
  • largest spreading factor: 12
  • largest coding rate: 4/8
  • explicit header: providing length
  • CRC checksum: providing forward error correction
  • use power amplifier: providing a 20 dBm signal output
  • no output power reduction: to use the maximum 20 dBm signal output
  • maximum gain amplifier: 1
  • least active frequency: 447.681 MHz (found by scanning the frequency range using the 'scan' action in the receiver menu and using selecting the frequency with the lowest RSSI). using these parameters it take almost 2 seconds to transmit 1 byte of payload.

my flat is only ~ 30 m direct line from the post box. LoRa claims to be able to transmit up to 5-15 km. but the transmitter with be in a post box made of 0.5 mm metal (e.g. almost a faraday cage), and there are several concrete walls in between. in the end, the transmission is reliable enough and 19/20 packets are received.

the post box unit will transmit as soon as the lid or door are opened. it will also transmit the last data every 15 minutes. this will allow the receiver to be restarted and get the status even without activity. this also allows to recover from lost packet transmissions.

the receiver device requires a permanent power source (e.g. a USB power port) since it continuously listens to incoming data. is also allow to have the LED constantly on. the transmitted device is battery operated because no power source is available in the post box. to save power, the transmitter (MCU and radio) are put in sleep mode unless data is transmitted. a LiPo battery (with embedded protection) is directly connected to the USB input. the 3.6-4.2 V is sufficient to provide the 3.3 V (using an LDO) required by MCU and radio. during transmission, the transmitter uses 62 mA, lasting 2 seconds. during sleep, the transmitter uses 0.3 mA. thus, the device uses (2 * 62 + 0.3 * (15 * 60 - 2)) / (15 * 60) = 0.44 mA on average. using a 100 mAh battery, this should last for (1000 / 0.44) / 24 = 94 days. since I go at least once a week to the post box, and can swap the battery, this is plenty sufficient.


the current implementation uses a black pill development board, based on a STM32F103C8T6. this board includes an 32.768 kHz oscillator, used for the RTC in the MCU to periodically wake up.


connect the peripherals the following way (STM32F10X signal; STM32F10X pin; peripheral pin; peripheral signal; comment).

common to both devices:

  • SPI2_NSS; PB12; SX1728 module; NSS;
  • SPI2_SCK; PB13; SX1728 module; SLCK;
  • SPI2_MISO; PB14; SX1728 module; MISO;
  • SPI2_MOSI; PB15; SX1728 module; MOSI;
  • GPIO; PB6; SX1728 module; DIO0; used as SX1728 IRQ output
  • GPIO; PB7; SX1728 module; REST;
  • GND; GND; SX1728 module; GND;
  • 3V3; 3V3; SX1728 module; VCC;

on the transmitter device:

  • GPIO; PB8; board; GND; use a jumper. this is used to differentiate the transmitter from the receiver
  • GPIO; PB10; lid button; common; place button on post box lid to detect when it has been opened
  • GPIO; PB1; lid button; normally open; don't use the normally closed pin since the lid might not be able to close again is the parcel does not fit in the box
  • GPIO; PA7; door button; common; place button so it gets pressed when the door is closed
  • GPIO; PB0; door button; normally open; can also be placed on the normally closed pin since the door will be opened and closed when emptying it.

on the receiver side:

  • GPIO; PB10; green LED; anode; used to provide 3.3V
  • GPIO; PB1; green LED; cathode; with inline 1 kO resistor. used to indicate when the lid of the post box has been opened (e.g. a letter/parcel has arrived)
  • GPIO; PA7; red LED; anode; used to provide 3.3V
  • GPIO; PB0; red LED; cathode; with inline 1 kO resistor. used to indicate when the door of the post box has been opened (e.g. the box has been emptied)

all pins are configured using defines in the corresponding source code.



The source code uses the libopencm3 library. The projects is already a git submodules. It will be initialized when compiling the firmware. Alternatively you can run once: git submodule init and git submodule update.


To compile the firmware run rake.


To generate doxygen documentation run rake doc.


There are two firmware images: bootloader and application. The bootloader image allows to flash the application over USB using the DFU protocol. The bootloader is started first and immediately jumps to the application if it is valid and the DFU mode is not forced (i.e. by pressing the user button on the board or requesting a DFU detach in the application). The application image is the main application and is implemented in application.c. It is up to the application to advertise USB DFU support (i.e. as does the provided USB CDC ACM example).

The bootlaoder image will be flashed using SWD (Serial Wire Debug). For that you need an SWD adapter. The Makefile uses a ST-Link V2 along OpenOCD software. To flash the booltoader using SWD run rake flash_booloader.

Once the bootloader is flashed it is possible to flash the application over USB using the DFU protocol by running rake flash. To force the bootloader to start the DFU mode press the user button or short a pin, depending on the board. It is also possible to flash the application image using SWD by running rake flash_application.

Once the transmitter firmware has been flash over DFU, it is recommended to flash it over SWD using rake flash_application. This is because the transmitter does not provide present itself as USB device, so to save energy. Also, since the transmitter goes to sleep after a couple of second, it is recommended to flash it just after reset. Alternatively, short BOOT1 to 3.3V and reset the device. This will force the USB DFU bootloader, and also to flash using DFU.

The firmware is the same for transmitter and receiver.


SWD also allows to debug the code running on the micro-controller using GDB. To start the debugging session run rake debug.


The firmware offers serial communication over USART1 (transmitter and receiver) and USB (only receiver) (using the CDC ACM device class).