PWM pin in STM32F103C8 blue pill

Working libraries, libraries being ported and related hardware
Post Reply
Samrat
Posts: 3
Joined: Sat Jul 29, 2023 6:47 am

PWM pin in STM32F103C8 blue pill

Post by Samrat »

I am new to STM32 and I am using STM32F103C8 blue pill for one of my projects. I tried making every PWM pin to some value using the analogWrite function, but only 3-4 of the total pins showed the exact voltage. What can be the reason for this? Actually, for the project I am controlling 6 motors using PWM. When I changes some pins there was a combination of 6 pins only for which all 6 were showing exact voltage. But why not for any 6 PWM pins?
by ozcar » Mon Jul 31, 2023 2:57 am
Samrat wrote: Sun Jul 30, 2023 8:52 am This is the basic code:-
...

I checked the PWM pins according to the following pin diagram:-
https://how2electronics.com/wp-content/ ... etails.jpg
Your link also does not work for me, so I'm not sure what you were working from.

From what you said before, I got the impression that you were using the "official" STM core which was mentioned by ag123. Maybe that is wrong, but I copied your code and tried it using the STM core. Without checking every pin, I did get many pins that did not behave the way you were hoping.

I then tried with only these pins instead:

Code: Select all

analogWrite(PA0, 100);  // starting with PA0, which you had omitted
analogWrite(PA1, 100); 
analogWrite(PA2, 100); 
analogWrite(PA3, 100); 

analogWrite(PA6, 100); 
analogWrite(PA7, 100); 
analogWrite(PB0, 100); 
analogWrite(PB1, 100);
 
(Note, for the STM core at least, it is not necessary to to use pinMode(), for OUTPUT as the analogWrite() will do that if required, which makes it a bit easier to try different combinations of pins.)

When I run that I get exactly the same looking output on all 8 of the pins. My DSO shows a very close to 1000Hz rectangular waveform, with duty cycle 39.2%. My DMM measures all of these pins as having 1.31VDC on them (without any added filtering). That DMM figure is pretty close to the 1.28V that you saw on some of your pins.

I then added one more pin:

Code: Select all

analogWrite(PA0, 100);  // starting with PA0, which you had omitted
analogWrite(PA1, 100); 
analogWrite(PA2, 100); 
analogWrite(PA3, 100); 

analogWrite(PA6, 100); 
analogWrite(PA7, 100); 
analogWrite(PB0, 100); 
analogWrite(PB1, 100); 

analogWrite(PB10, 200); // note different PWM value of 200 instead of 100
However, when I run that and check PB10, there is no PWM, it is just low, and the DMM reads close to zero on that pin. Not only that, if I check the other 8 pins, PA2 now has PWM with duty cycle 78.6% and the DMM reads 2.60v on that pin (all the other pins exactly as before).

This has to be due to the fact that those two pins, PB10 and PA2, are trying to use the same timer channel TIM2/3. The full set of pins you tried to use must have several more conflicts like that.

I note that some Bluepill pinout diagrams (say like the one here: https://www.electronicshub.org/wp-conte ... Layout.gif) don't show PB10 as PWM capable. Maybe that was/is totally true for other STM32 cores, but from my test, it is more subtle on the STM core.

Perhaps you have some other conflict besides timer channels. The odd result for PB4 hints to me that maybe JTAG is enabled.
Go to full post
GonzoG
Posts: 403
Joined: Wed Jan 15, 2020 11:30 am
Answers: 27
Location: Prudnik, Poland

Re: PWM pin in STM32F103C8 blue pill

Post by GonzoG »

PWM does not control voltage. You cannot use PWM to lower voltage, it only controls time how long power is turned on and off.
Voltage reading will depend on your meter, PWM frequency, board hardware and MCU.
ag123
Posts: 1655
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: PWM pin in STM32F103C8 blue pill

Post by ag123 »

for PWM DAC you would need to put a RC setup as like

Code: Select all

 gpio + --- R (maybe 1k?) --- + ---.> out
                              |
                              C (maybe 1 uF?)
                              |
                              GND
^ note those values are nonsense
https://en.wikipedia.org/wiki/Low-pass_filter
and maybe a bit more here
https://blog.mbedded.ninja/electronics/ ... c-filters/

or get a real DAC some of the stm32 in the 'higher' series have it
i think like stm32f405 or f407 have it
and more recently STM32G431 'small and fast and good (lots of pheriperials) cortex M4 chip
viewtopic.php?t=2075
ozcar
Posts: 143
Joined: Wed Apr 29, 2020 9:07 pm
Answers: 5

Re: PWM pin in STM32F103C8 blue pill

Post by ozcar »

All the meters I have give a sort-of reasonable reading for DC volts on a PWM pin without any filtering. Some meters may be able to measure the frequency, and even duty cycle too. But in any event, there must be some explanation why different pins show different results.

In STM32DUINO, analogWrite() can do very different things depending on what the pin is capable of:

If a "real" DAC is available on the pin it will use that (but as ag123 says, F103 has no DAC).

If no DAC, then it checks for PWM and uses that if available on the pin.

If no DAC nor PWM available, then it just does DigitalWrite LOW or HIGH depending on the AnalogWrite value.

So, what pins "work" for you, and what pins do not?

For the pins that do not work, what voltage do you see? Assuming you did not use analogWriteResolution(), what voltage do you see if you do analogWrite(pin,0) or analogWrite(pin,255) ?

Have you selected the correct board? Another thread here mentions trouble with PWM on Bluepill pins PB6 to PB9, due to selecting the wrong board - viewtopic.php?p=12026 .
Samrat
Posts: 3
Joined: Sat Jul 29, 2023 6:47 am

Re: PWM pin in STM32F103C8 blue pill

Post by Samrat »

This is the basic code:-
#include <Arduino.h>

void setup()
{
pinMode(PA1, OUTPUT);
pinMode(PA2, OUTPUT);
pinMode(PA3, OUTPUT);
pinMode(PA6, OUTPUT);
pinMode(PA7, OUTPUT);
pinMode(PB0, OUTPUT);
pinMode(PB1, OUTPUT);
pinMode(PB10, OUTPUT);
pinMode(PB11, OUTPUT);
pinMode(PB5, OUTPUT);
pinMode(PB4, OUTPUT);
pinMode(PB3, OUTPUT);
pinMode(PA15, OUTPUT);
pinMode(PA11, OUTPUT);
pinMode(PA10, OUTPUT);
pinMode(PA9, OUTPUT);
pinMode(PA8, OUTPUT);
pinMode(PB15, OUTPUT);
pinMode(PB14, OUTPUT);
pinMode(PB13, OUTPUT);
}

void loop()
{
delay(100);
analogWrite(PA1, 100); // 0.02V
analogWrite(PA2, 100); // 1.28V
analogWrite(PA3, 100); // 1.28V
analogWrite(PA6, 100); // 0.02V
analogWrite(PA7, 100); // 0.02V
analogWrite(PB0, 100); // 0.02V
analogWrite(PB1, 100); // 0.02V
analogWrite(PB10, 100); // 0.02V
analogWrite(PB11, 100); // 0.02V
analogWrite(PB5, 100); // 1.28V
analogWrite(PB4, 100); // 3.24V
analogWrite(PB3, 100); // 0.02V
analogWrite(PA15, 100); // 1.27V
analogWrite(PA11, 100); // 1.27V
analogWrite(PA10, 100); // 0.02V
analogWrite(PA9, 100); // 0.02V
analogWrite(PA8, 100); // 0.02V
analogWrite(PB15, 100); // 0.02V
analogWrite(PB14, 100); // 0.02V
analogWrite(PB13, 100); // 0.02V
}

Here I have also mentioned the voltage of each of these pins. As you can see only 5 pins are showing correct output (1.28V). I tried to change the board also, but I still got the same output.

I checked the PWM pins according to the following pin diagram:-
https://how2electronics.com/wp-content/ ... etails.jpg
ag123
Posts: 1655
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: PWM pin in STM32F103C8 blue pill

Post by ag123 »

well that image link is not accessible it says something to the extent that direct linking is not allowed.
And actually there are a couple of issues.

if you are using that core mentioned in
https://how2electronics.com/getting-sta ... ng-of-led/
i.e.
http://dan.drown.org/stm32duino/package ... index.json
this core is deemed a 'fork' of libmaple core
the 'original' "Roger's" libmaple core is here
https://github.com/rogerclarkmelbourne/Arduino_STM32
for this particular core analogWrite() is not defined if I'm correct about it.

while the "official" STM core is here
https://github.com/stm32duino/Arduino_Core_STM32
and the wiki is here
https://github.com/stm32duino/Arduino_Core_STM32/wiki

"official" STM core has analogWrite() as is documented here:
https://github.com/stm32duino/Arduino_C ... API#analog
in which case constructs like:

Code: Select all

  analogWrite(A1, 127); // Start PWM on A1, at 1000 Hz with 50% duty cycle
that value there is mainly the *duty cycle* i.e. 127 out of 255 about 50%.
there are some notes as mentioned in the wiki.
  • True analog output when using on pins with DAC capabilities anf if HAL_DAC_MODULE_ENABLED is defined
  • PWM on pins with timer (TIM) capabilities.
  • GPIO toggling HIGH/LOW depending on requested value: HIGH if > 127 else LOW
in this case except for a *real* DAC with the "official" STM core
https://github.com/stm32duino/Arduino_Core_STM32
none of the rest is actually a voltage.
The duty cycle *do not* automatically translates to a voltage
some random stuff I stumbled into during web search:
https://www.allaboutcircuits.com/techni ... nto-a-dac/
https://www.allaboutcircuits.com/techni ... g-voltage/
https://www.ti.com/lit/an/spraa88a/spra ... 0716092684

you would likely find more if you do a web search for "PWM DAC"
ag123
Posts: 1655
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: PWM pin in STM32F103C8 blue pill

Post by ag123 »

on a side note, for stm32(duino) I'd prefer to use the
Hardware Timer
https://github.com/stm32duino/Arduino_C ... er-library
this is based on the hardware on your MCU e.g. for stm32f103c8
RM0008 on the hardware timer chapters would be relevant reading
https://www.st.com/resource/en/referenc ... ronics.pdf
as is the datasheet to find which are the relevant pins
https://www.st.com/en/microcontrollers- ... 103c8.html
and not least is the api itself
https://github.com/stm32duino/Arduino_C ... er-library
and some examples
https://github.com/stm32duino/STM32Exam ... dwareTimer
timebase call back
PWM using hardware timer - full config

Hardware timer are far more precise in determining the definitions of the duty cycle and period in terms of the number of clock cycles that the hardware timer supports.

But that this requires identifying the exact hardware timer pins, check the specs sheet and configure them accordingly.

i'd guess the codes would mostly look like such

Code: Select all

TIM_TypeDef *Instance = TIM2; // use timer 2
HardwareTimer Timer2 = new HardwareTimer(Instance);

void setup()
{
  Timer2.pause();  
  // configure PWM pins - note this must match Timer h/w pins as given in the spec sheet
  // configure PWM Timer 2 channel 1 on pin PA0
  Timer2.setMode(1, TIMER_OUTPUT_COMPARE_PWM1, PA0);
  // configure PWM Timer 2 channel 2 on pin PA1
  Timer2.setMode(2, TIMER_OUTPUT_COMPARE_PWM1, PA1);
  // configure PWM Timer 2 channel 3 on pin PA2
  Timer2.setMode(3, TIMER_OUTPUT_COMPARE_PWM1, PA2);
  // configure PWM Timer 2 channel 4 on pin PA3
  Timer2.setMode(4, TIMER_OUTPUT_COMPARE_PWM1, PA3);

  // set the period, setOverflow is setting the period
  Timer2.setOverflow(100000, MICROSEC_FORMAT); // 100000 microseconds = 100 milliseconds
  
  // timer 2 channel 1 i.e. PA0 50% duty cycle
  Timer2.setCaptureCompare(1, 50, PERCENT_COMPARE_FORMAT); 
  
  // timer 2 channel 2 i.e. PA1 25% duty cycle
  Timer2.setCaptureCompare(2, 25, PERCENT_COMPARE_FORMAT); 

  // timer 2 channel 3 i.e. PA2 75% duty cycle
  Timer2.setCaptureCompare(3, 75, PERCENT_COMPARE_FORMAT); 

  // timer 2 channel 4 i.e. PA3 67% duty cycle
  Timer2.setCaptureCompare(4, 67, PERCENT_COMPARE_FORMAT); 

  // note that all the above timer channels share the same period configured in setOverflow()

  Timer2.refresh();
  Timer2.resume();
}

void loop() {
	delay(1000); // this is practically no op, you can blink a led if you want
}
But nevertheless, hardware timer only provides control of period and duty cycle, this does not directly translate to voltages, and to translate that to voltages, one would need to study the RC filter on the timer generated PWM waves, that determines how that actual output signal looks like at the output of the RC filter.

hardware timers are standalone hardware and it keep generating the signal train once configured, there is no 'analogWrite()'. Then in loop() your codes can do other things, e.g. blink a led etc.
ozcar
Posts: 143
Joined: Wed Apr 29, 2020 9:07 pm
Answers: 5

Re: PWM pin in STM32F103C8 blue pill

Post by ozcar »

Samrat wrote: Sun Jul 30, 2023 8:52 am This is the basic code:-
...

I checked the PWM pins according to the following pin diagram:-
https://how2electronics.com/wp-content/ ... etails.jpg
Your link also does not work for me, so I'm not sure what you were working from.

From what you said before, I got the impression that you were using the "official" STM core which was mentioned by ag123. Maybe that is wrong, but I copied your code and tried it using the STM core. Without checking every pin, I did get many pins that did not behave the way you were hoping.

I then tried with only these pins instead:

Code: Select all

analogWrite(PA0, 100);  // starting with PA0, which you had omitted
analogWrite(PA1, 100); 
analogWrite(PA2, 100); 
analogWrite(PA3, 100); 

analogWrite(PA6, 100); 
analogWrite(PA7, 100); 
analogWrite(PB0, 100); 
analogWrite(PB1, 100);
 
(Note, for the STM core at least, it is not necessary to to use pinMode(), for OUTPUT as the analogWrite() will do that if required, which makes it a bit easier to try different combinations of pins.)

When I run that I get exactly the same looking output on all 8 of the pins. My DSO shows a very close to 1000Hz rectangular waveform, with duty cycle 39.2%. My DMM measures all of these pins as having 1.31VDC on them (without any added filtering). That DMM figure is pretty close to the 1.28V that you saw on some of your pins.

I then added one more pin:

Code: Select all

analogWrite(PA0, 100);  // starting with PA0, which you had omitted
analogWrite(PA1, 100); 
analogWrite(PA2, 100); 
analogWrite(PA3, 100); 

analogWrite(PA6, 100); 
analogWrite(PA7, 100); 
analogWrite(PB0, 100); 
analogWrite(PB1, 100); 

analogWrite(PB10, 200); // note different PWM value of 200 instead of 100
However, when I run that and check PB10, there is no PWM, it is just low, and the DMM reads close to zero on that pin. Not only that, if I check the other 8 pins, PA2 now has PWM with duty cycle 78.6% and the DMM reads 2.60v on that pin (all the other pins exactly as before).

This has to be due to the fact that those two pins, PB10 and PA2, are trying to use the same timer channel TIM2/3. The full set of pins you tried to use must have several more conflicts like that.

I note that some Bluepill pinout diagrams (say like the one here: https://www.electronicshub.org/wp-conte ... Layout.gif) don't show PB10 as PWM capable. Maybe that was/is totally true for other STM32 cores, but from my test, it is more subtle on the STM core.

Perhaps you have some other conflict besides timer channels. The odd result for PB4 hints to me that maybe JTAG is enabled.
Samrat
Posts: 3
Joined: Sat Jul 29, 2023 6:47 am

Re: PWM pin in STM32F103C8 blue pill

Post by Samrat »

Thanks a lot @ozcar , I understood your point. Thanks @ag123 , for giving the idea of HardwareTimer. I will try with that also.
Post Reply

Return to “Libraries & Hardware”