Skip to content

Project shows how to control a strip of WS2812B addressable LEDs using an STM32G030 microcontroller. This implementation leverages PWM wave in DMA mode to achieve precise timing required by the WS2812B protocol. Project aims to show proper usage of my library "WS2812B LED Strip Driver".

Notifications You must be signed in to change notification settings

FRSH-0109/STM32_WS2812B_Example

Repository files navigation

STM32_WS2812B_Example

Projects uses my WS2812B LEDs driver library for controlling whole tape/strip of addressable LEDs. Certain protocol is achieved by controlling PWM via DMA mode. List of values prepared for every single diode is transfered as PWM signal of exact period time. It is expected that user knows how to configure new project and etc. in STM32CubeIDE.

Used:

  • STM32G030C8 microcontroller
  • WS2812B addressable LEDs tape
  • STM32CubeIDE (dedicated IDE for ST microcontrollers)

WS2812B driver libs are written in C and are separated from STM32 HAL or other hardware dependent parts of project. Library consists of:

  • ws2812b_driver.c
  • ws2812b_driver.h

They can be found here: https://github.com/FRSH-0109/WS2812B_LED_Strip_Driver.git

How to use?


Get familiar with README file in the driver repository

It describes what should be changed in the driver header file.
Driver .c and .h files have to be copied/imported to your project Src( .c) and Inc( .h) folders.
https://github.com/FRSH-0109/WS2812B_LED_Strip_Driver.git


Configure hardware

Set MCU clock and timers clock frequnecy
In my project the frequency of mcu is set to 64MHz, as well as clock source for Timers(APB timer clocks)
Screenshot from 2022-02-17 23-13-41

Created function have to send proper PWM values, it is recommended to use DMA mode(memory to peripheral).

Screenshot from 2022-02-17 23-12-50

Selecting Timer, choosing clock source and channel mode(PWM generation).
Channel number is strongly connected with signal output pin.

Set proper PWM parameters
Prescalers is simply the divisor(divisor = value + 1, so written 0 sets prescaller to 1) between Timer APB clocks frequency and used in our Timer1 frequency. 64MHz / 1 = 64MHz on Timer1 clock.
Counter Period is the value on which our counter will reload(start counting again from 0). It is set to 79(0-79 gives 80 counter steps). So our one timer cycle would count to 80 times on 64MHz freq, 64Mhz / 80 = 800000Hz = 800kHz = (1/800Khz)s = 0,00125ms = 1,25us(exactly what we would like to achieve with our specific diodes type).

Screenshot from 2022-02-18 13-31-48

Make sure that your Timer channel polarity is set to high, every signal have to start by high volatge level.
Screenshot from 2022-02-18 13-37-12

Enable DMA mode for Timer
DMA have to be configured into memory to peripheral mode(array of values into PWM signal process).
Timer data width: Half Word(16bit), beacuse we are using 16bit Timer1
Memory data width: Byte(8bit), becuase array containing pwm data is uint8_t type variable
Incerement adderess: memory only
Screenshot from 2022-02-17 23-14-29

Screenshot from 2022-02-18 14-50-10


Prepare custom send function

To make whole driver library more hardware independent, send function have to be created by user.
Only thing to do is to get the PWM data array and pass it to the DMA PWM pulse creating function.
In case using the STM32 HAL, it will look like this:
Screenshot from 2022-02-18 17-11-45 ws2812bGetBytesArray(ledStrip); - translates RGB data stored in ledStrip structure into pwm data, also stored in structure. This process is separeted into function, to let user make one translation after changing colors of many diodes.
HAL_TIM_PWM_Start_DMA(&htim1, TIM_CHANNEL_1, (uint32_t *)ledStrip->pwmData, ledStrip->bytesToSend); - STM32 HAL function, which sends PWM via DMA. It needs few arguments like:

  • (uint32_t *)ledStrip->pwmData - pointer to begining of PWM data array
  • ledStrip->bytesToSend - how many bytes have to be send

ledStrip->dataSentFlag; - this boolean variable prevents from sending data before previous one haven't been finished

Timer pulse finished interrupt
It is necessary to handle function which controls when data array has been send completely. I used HAL interrupt routine which is marked as __weak in default HAL files. After the last byte of data has been represented as PWM signal, interrupt changes dataSentFlag, so next send function can be executed successfully. Also the Timer PWM DMA sending routine is stopped, because normally it would work continiously.
Screenshot from 2022-02-18 17-08-25


Usage example

Setting red color on every two diodes. Delay can be removed
Screenshot from 2022-02-18 17-42-16

Creating wave effect on led tape(changable width). Every call of wave function generates next frame of it.
Screenshot from 2022-02-18 14-57-19

About

Project shows how to control a strip of WS2812B addressable LEDs using an STM32G030 microcontroller. This implementation leverages PWM wave in DMA mode to achieve precise timing required by the WS2812B protocol. Project aims to show proper usage of my library "WS2812B LED Strip Driver".

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published