STM32 + RGB LEDs Firmware Tutorial (TIM + DMA) - Phil's Lab

  Рет қаралды 13,219

Phil’s Lab

Phil’s Lab

Күн бұрын

How to control addressable RGB LEDs (SK6805, WS2812) using PWM timers with DMA in C using STM32 MCUs. PCBs by PCBWay www.pcbway.com
[SUPPORT]
Hardware design courses: phils-lab-shop.fedevel.education
Course content: www.phils-lab.net/courses
Patreon: / phils94
Free trial of Altium Designer: www.altium.com/yt/philslab
Altium 365: www.altium.com/altium-365
[GIT]
www.github.com/pms67
[SOCIAL]
/ philslabyt
[LINKS]
SK6805 Datasheet: cdn-shop.adafruit.com/product...
[TIMESTAMPS]
00:00 Introduction
01:08 PCBWay
01:42 Hardware & Schematic Overview
06:06 Datasheet
07:25 Data Structure & Timing
13:34 CubeIDE Set-Up
15:16 Timer Set-Up
18:26 DMA Set-Up
20:15 Driver Header Code
27:04 Driver Source Code
30:10 main.c
31:57 Scope Measurement & Demo
34:47 Outro

Пікірлер: 67
@daflamingfox
@daflamingfox 26 күн бұрын
Hey Phil, great video as usual, however, something I noticed with your driver is that I believe that the bit order is wrong. it should be g7..g0, r7..r0, b7..b0, in MSB order. I have a feeling you didn't notice any issues since you were using 255 to test, so all the values for each bit were high anyway, but using any other value gives the incorrect brightness. I used the following and it is working for me with WS2812B leds: uint16_t bufIndex = 0; for (uint8_t led = 0; led < NUM_LEDS; led++) { // for each LED for (uint8_t bits = 0; bits < BITS_PER_LED; bits++, bufIndex++) { // loop through all 24 bits uint8_t byte = (bits / 8) * 8; uint8_t bit = 7 - (bits % 8); uint8_t bitIndex = byte + bit; if ((LED_DATA[led].data >> bitIndex) & 0x01) // If bit set DMA_BUF[bufIndex] = T1H; // set pulse high else DMA_BUF[bufIndex] = T0H; // set pulse low } }
@PhilsLab
@PhilsLab 26 күн бұрын
Thank you! You are completely right - sorry about that!
@daflamingfox
@daflamingfox 26 күн бұрын
@@PhilsLab no worries, it happens! I thought I was losing my mind at first. Appreciate everything you do!
@triplebig
@triplebig Ай бұрын
I'll never understand why Altium sponsors a hobby channel but doesn't offer a hobby license -_-
@tgirard123
@tgirard123 Ай бұрын
It's really sad. I guess they really think that all these hobbyists are going to love their tools so much that they'll pay. Good luck with that. I'll just stay with KiCad thank you...
@ashwin372
@ashwin372 28 күн бұрын
Even fusion 360 is free for hobbyist.
@tarasaurus24
@tarasaurus24 14 күн бұрын
It’s actually insane desperately need a hobby license.
@AlejandroMironov
@AlejandroMironov 25 күн бұрын
Absolutely fantastic video. I’m not new to C but I get lost pretty heavily when I see functions passing pointers as arguments or by reference. It would help a lot if you could make someday a video on why you use them or how is the thought process in the context of microcontrollers. Fantastic work Phil!
@bencemarta5222
@bencemarta5222 Ай бұрын
I love these kind of elegant solutions. At work, I always take the time to write libraries that take advantage of the hardware on this level. One thing I don't really like though is the fact that each bit needs a byte of buffer space to be sent out. This may limit the capabilities of lower end microcontrollers with less memory (And I love the G0 series from ST). I have recently given some thought about using the SPI peripheral with DMA and a timer with some minimal external hardware so that I can control a lot of these LEDs basically without any CPU and memory overhead. It didn't get far but I figured that by using 2 timer channels to generate low and high pulses selecting the right one using MOSI and resetting the timer using the SPI clock, it can be achieved by purely using the SPI peripheral in DMA mode. It would of course be a trade-off but in projects where memory is a constraint, it could be useful. I will certainly do it during summer.
@PhilsLab
@PhilsLab Ай бұрын
That's very true regarding the space needed for the DMA buffer. Interesting idea you have there with SPI + the two timer channels - looking forward to hearing about the results!
@javaguru7141
@javaguru7141 Ай бұрын
Wow, that sounds awesome. I would love to see a reference implementation!
@werelwolf
@werelwolf Ай бұрын
These videos are SO good, thank you for producing them!
@PhilsLab
@PhilsLab Ай бұрын
Thank you, I'm glad to hear that!
@sundinmikael
@sundinmikael Ай бұрын
If you want you can optimize the color DMA update byt using a lookup table of 16x32bits values (LED 4bits). Then you only need 6 writes for RGB values. This works due to you using 1byte for the PWM.
@sigmaxi7822
@sigmaxi7822 Ай бұрын
The STM32U5 seems to handle the DMA/TIM transfer quite differently than other STM32s. I once implemented a WS2812B driver with 4 channels of 128+ LEDs each on an STM32F30, using the same principle. The key to making it work there was to 1) trigger DMA transfers via the TIM CC event (not at the end of the period) and 2) enable AutoReload preload, such that the new value is written to the register before the end of the PWM period. Otherwise it would output each bit value twice because the AR value was not updated fast enough. In this video for the STM32U5, it seems that DMA (or the HAL?) appropriately times the transfer such that there is a new AR value ready for each PWM period, without having to enable AR preload.
@PhilsLab
@PhilsLab Ай бұрын
Interesting to hear that that's the case for that MCU, thanks!
@GaborGubicza
@GaborGubicza Ай бұрын
Thanks Phil, I'm just working on my first Addressable LED project: 50+ LEDs per row.
@PhilsLab
@PhilsLab Ай бұрын
Very cool, good luck with your project!
@tgirard123
@tgirard123 Ай бұрын
These videos are so darn good! I don't mind having to go through them multiple times. There is so much to learn. Just subscribed And became a patreon.
@PhilsLab
@PhilsLab Ай бұрын
Thank you very much for your support, I really appreciate it!
@ksbs2036
@ksbs2036 Ай бұрын
Really nice presentation. Thanks
@PhilsLab
@PhilsLab Ай бұрын
Thank you!
@kiprof4350
@kiprof4350 27 күн бұрын
Thank you so much Phil! nice Video!
@PhilsLab
@PhilsLab 27 күн бұрын
Thanks for watching!
@perceptron9834
@perceptron9834 Ай бұрын
very interesting and informative video, thank you :)
@PhilsLab
@PhilsLab 27 күн бұрын
Thank you!
@fritzbender5916
@fritzbender5916 Ай бұрын
Awesome video and really interested in the FC
@PhilsLab
@PhilsLab 27 күн бұрын
Thank you, Fritz - more to come on that!
@ankurnaidu
@ankurnaidu Ай бұрын
great video there Phil! May i ask from where did you learn Embedded Coding and Firmware coding since your codes are immaculate.
@PhilsLab
@PhilsLab Ай бұрын
Thank you, Ankur! Mainly by working on various projects (personal and for work). It's predominantly self-taught via online resources, books, example code, etc..
@SmashCatRandom
@SmashCatRandom Ай бұрын
I used the WS28xx LEDs in a previous project, and just used DMA=>SPI peripheral; expanding out the bits in a frame-buffer in RAM so that a high bit = 110, and a low bit = 100 in the stream from the MOSI port (CLK not used). Those LEDs don't really need precise timing, so it was reliable and pretty simple to implement really - although a little bit wasteful of RAM, as it obviously needed 9 bytes for each 24bit colour value. 😁
@szymon4602
@szymon4602 Ай бұрын
By additionally using a down count timer in capture mode and directing the MOSI and MISO data to a port (preferably a port that has only the least significant two bits, PORTF - in many MCUs), and using one more DMA channel from overflow, this can be done completely in hardware, using only as many bits (RAM) as SPI needs for such sending.
@smaroukis
@smaroukis Ай бұрын
Perfect timing! I was just wondering how to use DMA to update PWM/brightness levels for a custom seven segment video display wall I'm building. Good concise demo. I'm guessing this is how libraries like SmartLED (nee SmartMatrix) work under the hood?
@PhilsLab
@PhilsLab Ай бұрын
Thank you, hope it's useful! From what I've seen, many openly available libraries have a very similar foundation to this. There are however a number of improvements that could be made (memory requirements, speed, ..).
@chadkrause6574
@chadkrause6574 Ай бұрын
Love your videos! How do you figure this stuff out in the first place? Keep up the good work!
@PhilsLab
@PhilsLab Ай бұрын
Thank you! Mainly via the datasheet, past experience/knowing the peripherals, looking at open-source implementations, etc..
@AngryMosfet
@AngryMosfet Ай бұрын
Hey Phil, your symbols are looking clean! Could you go over your current libraries in Altium? How you structure them, how you put text in the center of the symbol aka caps, res, ic, and any other useful tips you believe are worth mentioning. Thank you!
@d1zz3l
@d1zz3l Ай бұрын
Best guide how to control adressed leds
@PhilsLab
@PhilsLab Ай бұрын
Thank you!
@ruilianglin
@ruilianglin Ай бұрын
Great video as usual! I tried your implementation and found a quirk When running at a slower clock speed (64MHz) where the driver didn't work properly. After sending the PWM data frame once, *_SK6805_DMA_COMPLETE_FLAG_* would get stuck at 0 forever. Turned out, when the clock speed is low, *_HAL_TIM_PWM_Start_DMA_* would finish transfering PWM data to the timer so quickly that *_SK6805_Callback()_* is called BEFORE the code enters *_if (halStatus == HAL_OK)_* in order to clear *_SK6805_DMA_COMPLETE_FLAG_*. Basically, *_HAL_TIM_PWM_Start_DMA_* is called, then *_SK6805_DMA_COMPLETE_FLAG_* is set to 1 by *_SK6805_Callback()_***, but immediatly after ***_SK6805_DMA_COMPLETE_FLAG_* is set to 0 when we finally run *_if (halStatus == HAL_OK)_*. My quick and dirty solution is to ditch *_if (halStatus == HAL_OK)_* and clear *_SK6805_DMA_COMPLETE_FLAG_* before *_HAL_TIM_PWM_Start_DMA_*. There's for sure a more elegant solution.
@PhilsLab
@PhilsLab Ай бұрын
That's very interesting - thanks for sharing! Oddly enough, I haven't come across that myself (even on a G0 MCU running at 64MHz). Another (not particularly elegant) approach would be to check the complete flag in the while(1) loop in main.
@cakeforcat
@cakeforcat Ай бұрын
Nicely put together! What's your opinion on hijacking the SPI peripheral for this purpose? (sorry if this is mentioned in the video, can't watch it right now)
@PhilsLab
@PhilsLab Ай бұрын
Thank you! Haven't actually tried with SPI yet, but my first thought is that would by default enable more pins than needed on the MCU. Question is how to repurposes the unused SPI lines (CLK) if needed. The timer approach is quite straightforwardy (also peripheral/pinning-wise), so I don't really see a reason to not use it - unless free timers aren't available.
@Kageni32
@Kageni32 13 күн бұрын
Love your videos, the next step in my project happened to be designing a ws2812 driver for those exact led chips for a stm32u0 lol. You didn't need to use logic voltage translator? I have run into problems int the past when I didn't use on. Although with that project, I was using a bq24075 as my battery charger which outputs constant 5V no matter the battery charge, so that may be the difference.
@robby091000
@robby091000 Ай бұрын
I was literally looking into how to do this for a set of leds last week and finally figure out how to configurate the DMA with the timer after not being able to find a good guide that use the GPDMA!!! Now im looking into options that allow me to do a similar function with simpler microcontrollers without DMA to Peripheral interfaces that dont rely on CPU nop instructions to delays pulses
@PhilsLab
@PhilsLab Ай бұрын
Yeah I haven't found a good guide on setting up GPDMA either :(
@casualnoises2808
@casualnoises2808 Ай бұрын
This is a very elegant solution!!! Thanks for the detailed explanation Phil!!!
@PhilsLab
@PhilsLab Ай бұрын
Thank you!
@JoelCranmer
@JoelCranmer Ай бұрын
Great video! Just curious why you chose C34/35 to be 220nF as opposed to the value shown in section 16 of the datasheet of 104 (which corresponds to 100nF).
@PhilsLab
@PhilsLab Ай бұрын
Thanks! That's for BoM consolidation. I needed a specific 220n cap for a pin of the magnetometer, but the actual decoupling value for the rest of these parts is not a precise, required quantity.
@ianlee6416
@ianlee6416 Ай бұрын
I prefer the sk9822 led using the spi peripheral or simply bit-bang it. Just takes one more pin.
@alaeddinekh3716
@alaeddinekh3716 Ай бұрын
very nice video as usual. a little question, how can i detect if there are some abnormalities concerning the functionality of the rgb led (e.g. LED Strip ) Danke.
@PhilsLab
@PhilsLab Ай бұрын
Thank you! Not that I'm aware of with a single-wire implementation.
@emielv7677
@emielv7677 Ай бұрын
The protocol is very simple but getting the timing right without sacrificing a lot of processing time is quite difficult in my experience 😅
@mwafakaljabi9611
@mwafakaljabi9611 Ай бұрын
Thank you for the great Video as always. Is it professionally ok to always use HAL libraries instead of writing our own bare metal code?
@PhilsLab
@PhilsLab Ай бұрын
Thank you! Sure, I've seen HALs used in development for many products.
@hippie-io7225
@hippie-io7225 Ай бұрын
Thanks. I really enjoyed how you abstracted your code from low-level (hardware) to high-level (firmware). I have not used a STM IDE since 2010. Any opinions on this current IDE and a beginners (for the IDE) learning curve?
@PhilsLab
@PhilsLab Ай бұрын
Thank you! Despite some occasional bugs, CubeIDE is my favourite (Eclipse-based) IDE. The whole pin-out, peripheral, clock, etc.. config makes set-up far more straightforward than many other system, in my eyes. Plus there's a large community behind all of this.
@hippie-io7225
@hippie-io7225 Ай бұрын
@@PhilsLab Thanks!
@rallymax2
@rallymax2 Ай бұрын
Nice job, especially going through the schematic, which a lot of people struggle with.
@PhilsLab
@PhilsLab Ай бұрын
Thank you!
@tamaseduard5145
@tamaseduard5145 Ай бұрын
👍🙏❤️
@christiankoch4627
@christiankoch4627 Ай бұрын
Due to the nested for loop the set function is really slow.. Not suitable for fast led driving
@PhilsLab
@PhilsLab Ай бұрын
Can be yes, but for my needs in this case this is sufficient and for a tutorial this is a simple demo to get the basics across.
@blanchehermine
@blanchehermine Ай бұрын
HAL is hideous.
@bengkiatng3828
@bengkiatng3828 20 күн бұрын
Are the bits order reversed in your code. Bit-7 of the color code is to be sent first, and not bit 0. kzbin.info/www/bejne/g6LFe4egZaiqbNE. This code works for me //Fill DMA buf with LED data int bufIndex = 0; for (int i=0; i=0; b--) { // reverse if ( (RGBLED_DATA[i].data>>b)&0x01) RGBLED_DMA_BUF[bufIndex] = RGBLED_HI_PULSE; else RGBLED_DMA_BUF[bufIndex] = RGBLED_LO_PULSE; bufIndex++; } } struct needs to be redefined typedef union { //RGBLED data order is GGGGGGGGRRRRRRRRBBBBBBBB struct { uint8_t b; uint8_t r; uint8_t g; } colour; uint32_t data; } RGBLED_DATA_TYPE;
@bengkiatng3828
@bengkiatng3828 20 күн бұрын
ignore this. I just noticed somebody has asked similar question
STM32H7 ADC + DMA + Timer Firmware Tutorial - Phil's Lab #138
35:22
Can you beat this impossible game?
00:13
LOL
Рет қаралды 64 МЛН
Which one is the best? #katebrush #shorts
00:12
Kate Brush
Рет қаралды 11 МЛН
Arduino To ESP32: How to Get Started!
9:26
Robonyx
Рет қаралды 207 М.
SPI Hardware & PCB Design - Phil's Lab #134
33:22
Phil’s Lab
Рет қаралды 23 М.
PCB Stack-Up and Build-Up - Phil's Lab #56
20:15
Phil’s Lab
Рет қаралды 48 М.
RC Low-Pass Filter Deep-Dive - Phil's Lab #118
45:40
Phil’s Lab
Рет қаралды 37 М.
Extracting Firmware from Embedded Devices (SPI NOR Flash) ⚡
18:41
Flashback Team
Рет қаралды 535 М.
DIY 256-Core RISC-V super computer
10:29
bitluni
Рет қаралды 217 М.
USB-C Power Delivery Hardware Design - Phil's Lab #104
29:52
Phil’s Lab
Рет қаралды 91 М.
Will the battery emit smoke if it rotates rapidly?
0:11
Meaningful Cartoons 183
Рет қаралды 6 МЛН
Карточка Зарядка 📱 ( @ArshSoni )
0:23
EpicShortsRussia
Рет қаралды 705 М.
сюрприз
1:00
Capex0
Рет қаралды 434 М.