Using STM32F103C8T6 PWM pin to drive ws2812b Neopixel Ring in arduino IDE

stevestrong
Posts: 502
Joined: Fri Dec 27, 2019 4:53 pm
Answers: 8
Location: Munich, Germany
Contact:

Re: Using STM32F103C8T6 PWM pin to drive ws2812b Neopixel Ring in arduino IDE

Post by stevestrong »

Exchange SPI1 with SPI2: connect NRF to SPI2 and WS to SPI1.
ozcar
Posts: 143
Joined: Wed Apr 29, 2020 9:07 pm
Answers: 5

Re: Using STM32F103C8T6 PWM pin to drive ws2812b Neopixel Ring in arduino IDE

Post by ozcar »

stevestrong wrote: Mon Jun 15, 2020 6:53 am As I mentioned above, on SP2 you can only get max 18MHz, that is why the pulses are twice as long.
Due to the unusual way SPI is used by the WS2812B library, the maximum speed would be 6MHz (and 12MHz on SPI1), but the LEDs are nowhere near as fast as that, and there is no problem using SPI2 provided the correct divisor is set.

The WS2812B library uses SPI.setClockDivider(), making the assumption that SPI clock is the same as the CPU clock.

SPI.beginTransaction() allows an actual clock / baud rate to be specified, and in determining the divisor to use, it understands the difference between the APB1 and APB2 SPIs (at least for "LeafLabs-style boards"). However, I'm not sure if using that instead would help - it might set a divisor which generates pulses out of spec for the LEDs, which do not actually use SPI (there is no clock line).

I already suggested swapping the usage of SPI1 and SPI2.

Or, my second suggestion was to just change the divisor in the WS2812B library - I tried that and it does work.
ozcar
Posts: 143
Joined: Wed Apr 29, 2020 9:07 pm
Answers: 5

Re: Using STM32F103C8T6 PWM pin to drive ws2812b Neopixel Ring in arduino IDE

Post by ozcar »

Jakub_Szubzda wrote: Mon Jun 15, 2020 10:04 am
ozcar wrote: Sat Jun 13, 2020 7:24 pm What problem did you have with the ST core and the Adafruit library? fpiSTM said it works, but I have not tried it.
I don't really know what's wrong with it, but no matter what i try to do it just doesn seem to light leds.
I tried now using the ST core and the Adafruit library. I think that depending on exactly what LEDs you have, that also might not just work straight out of the box. Compared to the SPI method, I can see definite variation in the timing of the pulses generated by their bit-banging. In particular the timing of the "1" pulses could perhaps cause the opposite problem to what you got with the SPI technique originally - maybe all the bits could be interpreted as "0", resulting in none of the LEDs ever lighting up at all.

Looking at the Adafruit code, for 800kHz LEDs, they are aiming for "1" bit time of 800ns. That might be because the specifications for some of those sort of LEDs say 700ns +/- 150ns, while for others they say 900ns +/- 150ns, and they have chosen the mid-point between those. However, I get times in the range 600 - 700ns. That is obviously OK for the first variant of LED, but out of specification for the second, which needs at least 750ns. I found I had to change the target to around 900ns to ensure that the pulses were at least 750ns. I'm also not sure what effect interrupts would have on their code (for some processors they disable interrupts, but not for STM32 as far as I can see).

I would try to get the WS2812B SPI library to work - it does use more ram per LED, but probably does not matter for the number of LEDs you have.

If changing the SPI divisor did not work for you, check that you don't have two versions of the library available, and that maybe it is not using the one that you expected.

Edit: Scratch what I said about the Adafruit library not disabling interrupts while sending data to the LEDs - it does, I just missed that.
JSTFLK
Posts: 1
Joined: Tue Sep 22, 2020 3:12 am

Re: Using STM32F103C8T6 PWM pin to drive ws2812b Neopixel Ring in arduino IDE

Post by JSTFLK »

Try this for the WS2812B example:

Code: Select all

void setup()
{
  SPI.setModule(2); //SPI2 uses PB15 instead of PA7 for MOSI
  strip.begin();// Sets up the SPI
  strip.show();// Clears the strip, as by default the strip data is set to all LED's off.
  strip.setBrightness(128);  // 0 to 255
  SPI.setClockDivider(SPI_CLOCK_DIV16);	//halve the reported clock speed to fix all-white issue. 
}
This code works for me on a "Super Blue pill".

I haven't tested it, but I think that flipping the clock speed and SPI module number should work to allow access to the NRF24 and WS2812. I plan on going that route since my board has the NRF24 routed directly to SPI1 pins.
Post Reply

Return to “STM32F1 based boards”