This project is designed using KiCad. If you wish to examine the design yourself the project is available for download below. There’s also an IOC file for use with STM32CubeMX available in the example projects. The datasheets for each IC are linked at the end of this page. The current PCB version is DERULER-04.


Ground (Vss)All voltages in the circuit are referenced from this point and by definition its voltage is 0V
Supply voltage (VDD)The supply voltage generated for providing power to the circuitry. We call it VDD for historical reasons which references the MOSFET drain connection. Similarly Vss for ground is based on naming for the MOSFET source connection.
Low SignalThe voltage of the signal or pin is near ground
High SignalThe voltage of the signal or pin is near VDD
Active LowThe signal is inverted and activates a function when it’s low
Pull-down resistorA resistor connected between the signal and ground to keep it low when not connected or driven by anything else
Pull-up resistorA resistor connected between the signal and supply (VDD) to keep it high when not connected or driven by anything else
GPIOGeneral purpose Input/Output
Falling edgeSignal change from high to low
Rising edgeSignal change from low to high


The STM32L051K6T6 is a 32-bit Cortex M0+ microcontroller capable of 32 MHz operating frequency with 8 kilobytes of RAM and 32 kilobytes of flash storage. It comes in a 32-pin LQFP package and can operate with a supply voltage between 1.8 to 3.6 V. In this circuit we’ve chosen a supply voltage of 3.3V which is a common value that’s compatible with many other devices. It is also the supply voltage provided by our programmer. The part number after the microcontroller type “STM32L051”, meaning the “K6T6” segment, details the pin count, flash size, package type and temperature rating. In this case “K” means 32 pins, “6” means 32 kilobytes flash storage, “T” means LQFP package and “6” means –40 to 85 °C operating temperature. For more details on decoding the part number see page 125 in the microcontroller datasheet.

Power pin decoupling

Each supply pin should have one small capacitor placed near it for high-frequency noise decoupling. A value of 0.1uF is common due to low cost and sufficient capacity. VDDA is the supply for the analog portion of the microcontroller, such as the analog-to-digital converter. As we don’t require low noise for analog applications in our circuit we will treat it as any other supply pin. Otherwise it may benefit from additional filtering.


The N in front of RST (short for Reset) indicates the signal is active low. This means when this pin is grounded (near 0V) it will activate the reset signal inside the microcontroller and keep it in that state until the signal is changed to high state (near VDD). There’s an internal pull-up resistor to VDD inside the microcontroller which keeps this signal inactive when not connected to anything. We’ve added a 0.1 uF capacitor (C4) to the pin to prevent it from glitching (unintended activation). You can test this effect first by not adding this capacitor and touching the pin with your finger while the microcontroller is running your code.


Specific to STM32 microcontrollers is the BOOT0 pin which lets you specify the boot mode of the microcontroller. If the signal is low it will run the code uploaded by the user. If the signal is high it will run a built-in bootloader programmed from the factory. The pin state is sampled when the microcontroller first powers on and is later ignored. The bootloader is useful for updating the firmware of the microcontroller without specific programming tools. In this project we do have a programmer tool and this function is not necessary. We’ve added an external pull-down resistor (R1) of 100kohm to make sure the microcontroller starts in the correct mode and runs the user code.


In order to evaluate where we want to connect our signals to pins of the microcontroller we have to know which peripheral (internal hardware function) can be used on which pin. ST provides a great graphical tool called STM32CubeMX which helps you configure the pins to perform the function you want and generate the initialization code. By clicking each pin you can see which functions are available.

Debug pins

ARM microcontrollers support the SWD (serial-wire debug) protocol which we use to connect the ST-Link v2 programmer. This lets us upload code to the device and also debug it in real-time. It’s possible to pause and check what the microcontroller is doing each cycle and see what values are of the variables, registers or memory which is very useful for development. On our microcontroller this interface is available on the PA13 (SWC, serial-wire clock) and PA14 (SWD, serial-wire data) and we connect these pins to our programming header J1 together with NRST, VDD and GND.


RGB LED circuit

The RGB LED we’ve chosen in our circuit consists of three separate red, green and blue LEDs combined in one package. Pins 1-3 are the cathodes (negative pin) of each LED which we connect to ground. We then connect each of separate LED anodes (positive pin) to our microcontroller. This lets us turn on or off each color LED by adjusting the pin state in our code.

Both the LEDs and the microcontroller pins have limits on how much current can safely flow through them. The amount of current will determine how bright our LED will be. After checking the datasheets for both parts we find the chosen to limit the current of each LED to 20mA limit the max current for each LED to 20 mA by adding current limiting resistors. You can calculate the resistance value using the below equation. In the datasheet the forward voltage listed is a range from min to max. We’re using the average value of those two values for our calculation.

RLIM = (VDD – VF ) / IF

If we configure the RGB LED signals (LED_R = red, LED_G = green, LED_B = blue) as standard outputs, we only have a limited number of configurations with each signal being high or low (LED on or off). Instead we want to be able to control the intensity of each signal in order to create a wide range of colors. To do this we can use a PWM (pulse width modulation) signal where we can control the duty cycle of each color. A duty cycle of 10% would mean the LED is turned on 10% of the time. To do this we need a timer peripheral which counts up or down to a configurable value and then starts over. We can also configure how fast the timer increases or decreases the counter value. It’s easiest to use a single timer with one channel for each LED color. This means the timer period will be the same but the duty cycle can be adjusted per color. On our microcontroller the TIM2 timer is available with pin PA0 being mapped to channel 1, PA1 = channel 2 and PA2 = channel 3 which we’ll use for this purpose.

Notes for PCB version DERULER-04

  • There is a mismatch between the pin numbering of the schematic part we used for the RGB LED and the actual part we ended up using in this project. This results in the RGB LED being rotated 180 degrees in our layout.
  • It may be a better choice to calculate the max current used based on the worst case situation. This would mean using the lowest of the Vf values in the datasheet for calculating the current limit resistor value.
  • After reviewing the microcontroller datasheet again we should have limited the maximum pin current to 16mA to stay within safe limits (originally it was planned to use a STM32F0 part which has max specification of 25mA). However we still expect the circuit to be safe as the I/O voltage will be de-rated at these current levels and thus reduce the current. Measurements show about 3.0V output voltage from the GPIO and LED currents 8.7-12.4mA.


Similarly in order to generate an audio signal to the buzzer we need a timer with PWM output. The frequency of the PWM output will determine the tune of the audio and the duty cycle can adjust the characteristics. TIM22 channel 1 can serve this purpose on pin PB4.

Because the buzzer may use up to 100 mA of current it’s not enough to simply attach it to one of the microcontroller GPIO pins. We need an amplification stage which we’ve designed with the help of a NPN-type BJT (negative-positive-negative bipolar-junction transistor). When the buzzer signal is high the transistor will conduct to ground and turn on the buzzer, otherwise it’s off. Based on the transistor datasheet the gain factor (hFE) is about 50 at 100 mA. We can use this value to calculate the base current needed and eventually the current limiting resistor for the base.

IB = IC/hFE = 100 mA/50 = 2 mA

RB = (VIN – VB)/IB = (3.3 V-0.7 V)/2 mA = 1300 ohm

As the magnetic buzzer is an inductive load we also need to put a diode across the buzzer terminals. If the voltage starts increasing on the negative buzzer terminal it will start conducting to VDD and prevent high voltages on this node when turning the Q1 transistor off. Click here for more information on this phenomenon.


To detect when the button has been pressed we can simply configure it as an input and continuously read its state in our code. But unless this is the only task we have to perform, it would be possible to miss a button press when performing other tasks. Not to mention it would waste clock cycles. A better way is to configure an external interrupt to occur whenever the pin state is changed. This is a another peripheral available in the microcontroller which jumps to a certain place in your code when a condition has been detected without us having to continuously monitor it. Almost all pins can be used for this purpose on our microcontroller but we’ve decided to use EXTI3 on PB3 for BUTTON1 and EXTI15 on PA15 for BUTTON2 because those pins were in a suitable for making the physical connection to the push button switches. We also have to configure these pins to use an internal pull-up so their default state is high and when the button is pressed the signal is pulled low. Then we set the external interrupt to detect a falling edge condition (signal going from high to low).

I2C and UART

Not included in the sample project but still routed on the circuit board are connections and a header for using PB6 and PB7 for serial communication. Both I2C (inter integrated circuit) SCL/SDA (serial clock/data) and UART (universal asynchronous receiver transmitter) RX/TX (receive/transmit) are available. It can be used to communicate with external devices, such as sensors (temperature, humidity, light etc) or other microcontrollers (Arduino, Raspberry PI, EVC2 etc). Either interface can function as both master and slave devices.

Voltage regulator and battery

In order to drive the circuit from a 9V battery we need a voltage regulator which can convert the input voltage of 9V down to the 3.3V VDD voltage we want to use to supply our circuit. Here we’ve added an LDO (low-dropout) linear regulator. The TP1 test point is the positive battery input pad and TP3 is the negative pad which means we get 9V supplied to the input of the LDO (LDO_VIN net, pin #3 on U1). The datasheet recommends input & output decoupling capacitors of at least 10µF and ESR < 0.5ohm. The JP1 solder jumper is added so that the voltage regulator can be easily connected and disconnected to the circuit.