Cannot attach servo on some GPIOs

Post here first, or if you can't find a relevant section!
Step73
Posts: 27
Joined: Tue Jan 14, 2020 2:55 pm

Cannot attach servo on some GPIOs

Post by Step73 »

I'm using the dev-board Nucleo 144 F429ZI for a specific project where I need to attach 20 servos (or 20 led).
I'm facing two problems:

1. The following GPIO doesn't output the PWM signal:

Code: Select all

PA0    CN10.29
PB10  CN10.32
PA6    CN7.12
PF7    CN9.26
PF8    CN9.24
Reading the https://os.mbed.com/platforms/ST-Nucleo-F429ZI/ I don't see evidence they cannot be used as GPIO (or timer's output for led).
Am I wrong? What should I check further?


2. Because the standard library allows maximum 12 channles per timer and only one timer is defined I had to change it. The first thing I tried is to add a second timer in `ServoTimers.h`:

Code: Select all

typedef enum {
  _timer1,
  _timer2,
  _Nbr_16timers
} timer16_Sequence_t;
But it didn't work. Only the first 12 channels are available.
Next I changed the number of servo per timer in `Servo.h`:

Code: Select all

#define SERVOS_PER_TIMER       20     // the maximum number of servos controlled by one timer
This time all the servo are working (except the GPIO above) but of course the PWM frequency slowed down from 50 Hz to 33 Hz.
Why adding a second timer doesn't work?

By the way, this is my GPIO table:

Code: Select all

|  # | Name | Timer   | Conn.| Pin |
|  1 | PE9  | PWM1/1  | CN10 | 4   |
|  2 | PE11 | PWM1/2  | CN10 | 6   |
|  3 | PE13 | PWM1/3  | CN10 | 10  |
|  4 | PE14 | PWM1/4  | CN10 | 28  |
|  5 | PA0  | PWM2/1  | CN10 | 29  |
|  6 | PB3  | PWM2/2  | CN7  | 15  |
|  7 | PB10 | PWM2/3  | CN10 | 32  |
|  8 | PB11 | PWM2/4  | CN10 | 34  | 
|  9 | PA6  | PWM3/1  | CN7  | 12  |
| 10 | PC7  | PWM3/2  | CN7  | 11  |
| 11 | PC8  | PWM3/3  | CN8  | 2   |
| 12 | PC9  | PWM3/4  | CN8  | 4   |
| 13 | PB6  | PWM4/1  | CN10 | 13  |
| 14 | PD13 | PWM4/2  | CN10 | 19  |
| 15 | PD14 | PWM4/3  | CN7  | 16  |
| 16 | PD15 | PWM4/4  | CN7  | 18  |
| 17 | PE5  | PWM9/1  | CN9  | 18  |
| 18 | PE6  | PWM9/2  | CN9  | 20  |
| 19 | PF7  | PWM11/1 | CN9  | 26  |
| 20 | PF8  | PWM13/1 | CN9  | 24  |
As said I selected those pins because instead of servos I may need to output 20 PWM for leds.
by fpiSTM » Mon Jan 27, 2020 1:25 pm
@Step73
I've merged the fix made by @ABOSTM, here you will find the wiki made by him about the Servo:
https://github.com/stm32duino/wiki/wiki/Servo-library
Go to full post
User avatar
fpiSTM
Posts: 1738
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: Cannot attach servo on some GPIOs

Post by fpiSTM »

When you told some GPIO does not work how did you test it?
ABOSTM
Posts: 60
Joined: Wed Jan 08, 2020 8:40 am
Answers: 7

Re: Cannot attach servo on some GPIOs

Post by ABOSTM »

It is not possible to add new timer for Servo:
It is right that generic Arduino header ServoTimers.h allow to define several timers instructure timer16_Sequence_t.
But stm32duino implementation is designed for only 1 timer for servo.
Step73
Posts: 27
Joined: Tue Jan 14, 2020 2:55 pm

Re: Cannot attach servo on some GPIOs

Post by Step73 »

fpiSTM wrote: Fri Jan 24, 2020 10:21 am When you told some GPIO does not work how did you test it?
With an oscilloscope.
Step73
Posts: 27
Joined: Tue Jan 14, 2020 2:55 pm

Re: Cannot attach servo on some GPIOs

Post by Step73 »

ABOSTM wrote: Fri Jan 24, 2020 10:35 am It is not possible to add new timer for Servo:
It is right that generic Arduino header ServoTimers.h allow to define several timers instructure timer16_Sequence_t.
But stm32duino implementation is designed for only 1 timer for servo.
What a pity! I selected an ARM processor instead of a small AVR to have more resources and then I cannot use two timers...
Anyway, perhaps I may living with a refresh rate of 33 Hz, but still I don't understand why those pins are not functional.
User avatar
fpiSTM
Posts: 1738
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: Cannot attach servo on some GPIOs

Post by fpiSTM »

The Servo library is provided for Arduino compatibility.
By extension the core is to provide as far as possible the same Arduino compatibility for all STM32 series.
You can have a look to the HardwareTimer library or implement your own Servo library.
All is possible... You can even bypass all Arduino layer and fully use the HAL/LL from ST.
Step73 wrote: Fri Jan 24, 2020 12:02 pm With an oscilloscope.
Well, fine... do you think it is a good/complete answer ?

I tried with Fading example and all of those pins works fine.
So don't know what you've made.
Step73
Posts: 27
Joined: Tue Jan 14, 2020 2:55 pm

Re: Cannot attach servo on some GPIOs

Post by Step73 »

The Servo library is provided for Arduino compatibility.
By extension the core is to provide as far as possible the same Arduino compatibility for all STM32 series.
You can have a look to the HardwareTimer library or implement your own Servo library.
That's not the point. I just wonder why limit the library to have only one timer when the MCU has plenty of timers. Is there a technical reason?
In fact, the original Arduino code has defined more than one timer.

Well, fine... do you think it is a good/complete answer ?

I tried with Fading example and all of those pins works fine.
So don't know what you've made.
I'm sorry, don't be rude. I miser-understood your question. I thought you would know how I can say it doesn't work. So my answer was: with an oscilloscope I saw those pins didn't have the PWM signal, but others have.

This is my test code:

Code: Select all

#include <Servo.h>
Servo servo;

void setup() {
  servo.attach(PA0);
  servo.write(90);
}

void loop() { }
To be more clear: the GPIO itself work. If I call `digitalWrite` it changes its state. I doesn't output any PWM if I use the Servo library.
User avatar
fpiSTM
Posts: 1738
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: Cannot attach servo on some GPIOs

Post by fpiSTM »

Step73 wrote: Fri Jan 24, 2020 2:14 pm That's not the point. I just wonder why limit the library to have only one timer when the MCU has plenty of timers. Is there a technical reason?
In fact, the original Arduino code has defined more than one timer.
No, this library was provided like that since a long time. For most of the use case it is enough. We can't answered to all the requests. :? And all requests does not satisfied all users. One wants it works like this, an other like that... It is hard to satisfied all people.
This is a community project do not hesitate to enhance it and share with the community. ;)
Step73 wrote: Fri Jan 24, 2020 2:14 pm I'm sorry, don't be rude. I miser-understood your question. I thought you would know how I can say it doesn't work. So my answer was: with an oscilloscope I saw those pins didn't have the PWM signal, but others have.

This is my test code:

Code: Select all

#include <Servo.h>
Servo servo;

void setup() {
  servo.attach(PA0);
  servo.write(90);
}

void loop() { }
To be more clear: the GPIO itself work. If I call `digitalWrite` it changes its state. I doesn't output any PWM if I use the Servo library.
Well this is more clear like that.
So, the PWM works on thoses pins as analogWrite() do a PWM.
Now, why you didn't see anything using the Servo needs some investigations.
Step73
Posts: 27
Joined: Tue Jan 14, 2020 2:55 pm

Re: Cannot attach servo on some GPIOs

Post by Step73 »

fpiSTM wrote: Fri Jan 24, 2020 2:34 pm No, this library was provided like that since a long time. For most of the use case it is enough. We can't answered to all the requests. :? And all requests does not satisfied all users. One wants it works like this, an other like that... It is hard to satisfied all people.
This is a community project do not hesitate to enhance it and share with the community. ;)
No problem with that! I will be very happy to contribute.
My wonder was about a technical issue: it would end in a waste of time.

I'm going to make a try. If it will work, I'll share the code, of course.
ag123
Posts: 1655
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: Cannot attach servo on some GPIOs

Post by ag123 »

it is possible to declare multiple instances of servo that use different timers?
or perhaps another way is to implement that using HardwareTimer which i'd guess is possible to handle the different timers separately.
imho, i don't think having a single servo instance handle different timers is a good idea / abstraction, it could be better if each servo instance can be associated with a particular timer, the reason partly is that there are many different hardware sets for the different stm32 mcus, some have 5 timers some have 7 timers (or some other sets) and the sets of general and advanced timers are different between the mcus.
it would firstly be difficult to maintain portability (if it is even possible), and it may lead to gotchas and bugs given the more complex setup.

if i understand timers correctly, hardware timers normally have 4 pwm capable channels, they can have different duty cycles but that they need to share a same period for each hardware timer.

another way you could try to enhance the code is to 'bit bang' the pwm. one possible way this can be implemented is to hook a hardware timer interrupt. let it run at an over sampled speeds for the duty cycles that one needs, then one maintain variables for the duty cycles and bit bang the gpio pins (e.g. digitalWrite). this setup works if the pwm speeds is rather low and the duty cycle granularity isn't too fine. as this doesn't depend too much on hardware, you could literally drive servos on any gpio pins. but this can fail badly if higher pwm speeds/frequency or duty cycle granuity/precision are needed, and one would need to go back to the hardware timers

but that said, this is a 'custom' implementation

if i guessed correctly, one possible reason to mess with so many servos is that they form part of a robot e.g. a hexapod
https://en.wikipedia.org/wiki/Hexapod_(robotics)
i'm not sure how timing critical is that, but if it requires high precision and speed pwm to control the servos, one may end up needing to do it the hardware timers way
for servos like sg90
http://www.ee.ic.ac.uk/pcheung/teaching ... asheet.pdf
it may be possible to do it the 'bit bang' way given the rather low granuity 1ms left, 1.5ms mid, 2ms right and 20ms period
but if there are many servos the behaviors may become less predictable as the cpu would have to bit bang pretty much all the servos in that same period

for timing critical stuff, i'd prefer to start with HardwareTimer than any custom 'library', HardwareTimer is a hardware abstraction and would be the 'stm32' way of dealing with these timing specific stuff. non arduino? well, the cost of trying to be 'arduino identical' is you sacrifice the raw power of the stm32 hardware. direcly using non portable stm32 hardware timer specific codes allows you to use the 4 pwm hardware channels, that gives you high precision and you may wel be even be able to pwm it to a particular degree of the servo position. you won't be able to go back to avr after that as avr may not have the same design of 4 pwm hardware channels for each timer
Post Reply

Return to “General discussion”