STM32F1xx micro-controller C firmware template
Go to file
King Kévin de6a6637e6 global: add SPI DMA macros 2017-10-09 09:36:23 +02:00
lib lib/flash_internal: re-add used library 2017-10-08 18:59:26 +02:00
libopencm3@ad5ec6af08 add libopencm3 and STM32duino-bootloader submodules dependencies 2016-01-15 15:36:00 +01:00
.gitignore ignore generated documentation 2016-08-14 19:26:46 +02:00
.gitmodules remove STM32duino-bootloader 2016-08-14 19:03:17 +02:00
Doxyfile add changes from spark abacus project 2016-10-23 17:42:27 +02:00
README.md README: port LED clock README 2017-10-08 17:33:37 +02:00
Rakefile Rakefile: change library order for libm to be used correctly 2017-10-08 16:53:36 +02:00
application.c application: better new hour animation 2017-10-08 18:35:57 +02:00
application.ld bootloader is now 8 kB thanks to better dependency handling 2017-10-04 13:55:43 +02:00
bootloader.c bootloader: fix clang warning 2017-10-04 13:55:43 +02:00
bootloader.ld bootloader is now 8 kB thanks to better dependency handling 2017-10-04 13:55:43 +02:00
global.c global: add ms in us sleep utilities 2017-10-04 13:55:43 +02:00
global.h global: add SPI DMA macros 2017-10-09 09:36:23 +02:00

README.md

The LED clock is an add-on for round wall clocks. The purpose is to have LEDs on the circumference of the clock to show the progress of the time using coloured light.

For that you will need:

  • a WS2812B RGB LEDs strip (long enough to go around the clock)
  • a development board with a STM32F103 micro-controller equipped with a 32.768 kHz oscillator for the Real Time Clock (such as the blue pill), or using a external Maxim DS1307 RTC module
  • a coin cell battery to keep the RTC running (optional)
  • a GL5528 photo-resistor to adjust the LED brightness (optional)
  • a DCF77 module to set and update the time automatically (salvaged from a radio controlled digital clock)

project

summary

The time will be shown as arc progress bars, in addition to the original hands of the clock pointing at the current time. The hours passed since the beginning of the midday are shown using blue LEDs. The minutes passed sine the beginning of the hour are shown using green LEDs. Whichever progress is higher will be shown on top of the other. For example if it's 6:45, the first half of the circle will be blue, and an additional quarter will be green. The seconds passed since the beginning of the minute are shown using a running red LED, similar to the seconds hand. The red colour might be added on top of the blue, or green colour, then showing as violet or orange. The (gamma corrected) brightness of the last LED shows how much of the hour, minute, or second has passed.

technology

The brain of this add-on is a STM32 F1 series micro-controller (based on an ARM Cortex-M3 32-bit processor).

To keep track of the time a Real Time Clock (RTC) is used. If the board includes a 32.768 kHz oscillator (such as a blue pill) the micro-controller will use the internal RTC. Otherwise connect an external Maxim DS1307 RTC module to the I2C port and set EXTERNAL_RTC in main.c to true. Also connect the external RTC square wave output in order to have a sub-second time precision.

Connect a DCF77 module (e.g. salvaged from a radio controlled clock) to the micro-controller. This will allow to automatically get precise time (at least in Europe) when booting. Since the RTC is drifting, the time will get updated using DCF77 every hour to keep <0.5 s time precision. Alternatively set the time using serial over the USB port (providing the CDC ACM profile) or USART port and enter "time HH:MM:SS".

Power the board using an external 5 V power supply (e.g. through the USB port). This will power the micro-controller, and the LEDs (a single LED consumes more energy than the micro-controller). To keep the correct time in case the main power supply gets disconnected optionally connect a 3 V coin battery on the VBAT pin for the internal RTC, or in the module for the external RTC.

For the LEDs use a 1 meter LED strip with 60 red-green-blue WS2812B LEDs. Tape the LED strip along the border/edge of the clock. Ideally the wall clock has a diameter of 32 cm for a 1 m LED strip to completely fit. Otherwise change the number of actually used LEDs in the source files. Connect the 5 V power rail of the LED strip to the 5 V pin of the board. Connect the DIN signal line of the LED strip to the MISO pin of the micro-controller on PA6. SPI is used to efficiently shift out the LED colour values to the WS2812B LEDs. A custom clock is provided for this operation using channel 3 of timer 3 on pin PB0. Simply connect this clock to the SPI CLK input on pin PA5.

The brightness of the LEDs is dependant on the ambient luminance. To measure the ambient luminance a GL5528 photo-resistor is used. Connect one leg of the photo-resistor to ADC channel 1 and the other to ground. Connect one leg of a 1 kOhm resistor to ADC channel 1 and the other to a 3.3 V pin. This voltage divider allows to measure the photo-sensor's resistance and determine the luminance. If you don't want to use this feature, connect PA1 to ground for the highest brightness or Vcc for the lowest brightness.

board

The current implementation uses a blue pill.

The underlying template also supports following board:

Which board is used is defined in the Makefile. This is required to map the user LED and button provided on the board

connections

Connect the peripherals the following way (STM32F10X signal; STM32F10X pin; peripheral pin; peripheral signal; comment):

  • USART1_TX; PA9; RX; UART RX; optional, same as over USB ACM
  • USART1_RX; PA10; TX; UART TX; optional, same as over USB ACM
  • I2C1_SDA; PB7; DS1307 SDA; SDA; optional, when using external RTC
  • I2C1_SCL; PB6; DS1307 SCL; SCL; optional, when using external RTC
  • TIM2_CH1_ETR; PA0; DS1307 SQ; square wave output; optional, when using external RTC
  • ADC12_IN1; PA1; GL5528; photo-resistor + 1 kOhm to 3.3 V; without GL5528 photo-resistor connect to ground for highest brightness or Vcc for lowest brightness
  • TIM3_CH3; PB0; PA5; SPI1_SCK; generated clock for WS2812B transmission
  • SPI1_MISO; PA6; WS2812B DIN; DIN; WS2812B LED strip data stream
  • GPIO; PA2; DCF77 PO; #EN; DCF77 enable on low
  • GPIO; PA3; DCF77 TN; DCF77; DCF77 high bit pulses

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

code

dependencies

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.

firmware

To compile the firmware run rake.

documentation

To generate doxygen documentation run rake doc.

flash

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 Black Magic Probe, or a ST-Link V2 (per default) 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.

debug

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

USB

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

You can also reset the board by setting the serial width to 5 bits over USB. To reset the board run rake reset. This only works if provided USB CDC ACM is running correctly and the micro-controller isn't stuck.