bobhaliwela
Posts: 9
Joined: Tue Sep 03, 2019 10:52 am

[SOLVED] How To Get Smooth PWM Control

Tue Sep 03, 2019 11:54 am

Hi guys, i'm new here in the forum.

So, i have created a self driving rc car project which used Deep Reinforcement Learning algorithm. Long story short, i've tested the algorithm implementation to find the best hyper-parameters before moving onto the real world. I've setup everything and ready to go to the real world, but now i have a problem i can't really solve as i'm not really sure what was the cause of it. The problem i'm having is; the steering can cause a throttle jerk sometimes, even though i didn't move the analog for the throttle. So whenever i'm moving the analog to control the steering rapidly, it will cause a throttle jerk. Here's the link to the video to see the problem in more detail:

https://youtu.be/7_xweHyi9No

The wiring from both ESC and servo are goes straight to the raspberry pi. Then i used Joan's pigpio library. Should i use a servo driver instead for better control? Thanks guys.
Last edited by bobhaliwela on Wed Sep 11, 2019 5:52 pm, edited 1 time in total.

User avatar
joan
Posts: 14473
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: [ASK] How To Get Smooth PWM Control

Tue Sep 03, 2019 1:44 pm

As long as you are using the proper servo calls or PWM they are pretty much the same as using dedicated PWM hardware. We would need to see the code to be sure. Any jerkiness is probably down to the algorithm you are using.

blimpyway
Posts: 192
Joined: Mon Mar 19, 2018 1:18 pm

Re: [ASK] How To Get Smooth PWM Control

Tue Sep 03, 2019 8:49 pm

Or, if you power the steering servo from Pi's 5V (or other "weak" supply) it could mess signal to the throttle pwm controller.

I know servos can interfere with each other - search for servo jitter problems and how they are solved. Perhaps a servos peak starting currents could influence pwm signal of power controller too.

bobhaliwela
Posts: 9
Joined: Tue Sep 03, 2019 10:52 am

Re: [ASK] How To Get Smooth PWM Control

Wed Sep 04, 2019 10:12 am

joan wrote:
Tue Sep 03, 2019 1:44 pm
As long as you are using the proper servo calls or PWM they are pretty much the same as using dedicated PWM hardware. We would need to see the code to be sure. Any jerkiness is probably down to the algorithm you are using.
Here's the code:

Code: Select all

import numpy as np
import pygame
import os
import pigpio
os.system("sudo pigpiod")

from threading import Thread


class ControlTest():
    def __init__(self):
        self.pi = pigpio.pi()

        self.motor_gpio = 4
        self.servo_gpio = 17

        pygame.init()
        pygame.joystick.init()
        self.gamepad = pygame.joystick.Joystick(0)
        self.gamepad.init()

        self.recv_command = True

        self.drive_speed = 1500
        self.turnAngle = 1500

        self.pi.set_mode(self.motor_gpio, pigpio.OUTPUT)
        self.pi.set_mode(self.servo_gpio, pigpio.OUTPUT)

        Thread(target=self.main_loop).start()

    def main_loop(self):


        while self.recv_command:

            # Check button press
            pygame.event.pump()

            steering = self.gamepad.get_axis(0)
            steering = int(steering * 250)

            if steering < 0:
                steering *= -1
                angle_turn = self.turnAngle - steering
                self.pi.set_servo_pulsewidth(self.servo_gpio, angle_turn)
                print("Current turn angle = " + str(angle_turn))
            else:
                angle_turn = self.turnAngle + steering
                self.pi.set_servo_pulsewidth(self.servo_gpio, angle_turn)
                print("Current turn angle = " + str(angle_turn))

            if self.gamepad.get_button(9):
                self.recv_command = False
                self.pi.set_servo_pulsewidth(self.motor_gpio, 1500)
                self.pi.set_servo_pulsewidth(self.servo_gpio, 1500)
                self.close()
                break

    def close(self):
        exit()


if __name__ == '__main__':
    ControlTest()
Thanks :)
Last edited by bobhaliwela on Wed Sep 04, 2019 8:32 pm, edited 3 times in total.

bobhaliwela
Posts: 9
Joined: Tue Sep 03, 2019 10:52 am

Re: [ASK] How To Get Smooth PWM Control

Wed Sep 04, 2019 10:17 am

blimpyway wrote:
Tue Sep 03, 2019 8:49 pm
Or, if you power the steering servo from Pi's 5V (or other "weak" supply) it could mess signal to the throttle pwm controller.

I know servos can interfere with each other - search for servo jitter problems and how they are solved. Perhaps a servos peak starting currents could influence pwm signal of power controller too.
No i did not. The power for the steering servo is from the nimh battery which used to power the esc. I connect the + (red wire ) from the esc to the servo.

pootle
Posts: 340
Joined: Wed Sep 04, 2013 10:20 am
Location: Staffordshire
Contact: Website

Re: [ASK] How To Get Smooth PWM Control

Fri Sep 06, 2019 7:15 am

I had twitchy servos on a 2 servo project, it turned out that the servos themselves needed decoupling capacitors on the power feed right beside the servos themselves. The voltage spikes caused by servo motors starting and stopping were de-stabilizing the servo's own electronics. Try a moderate electrolytic say 47uF and a fast tantalum in parallel across the 5v line to the servo as close as possible to the servo

bobhaliwela
Posts: 9
Joined: Tue Sep 03, 2019 10:52 am

Re: [ASK] How To Get Smooth PWM Control

Fri Sep 06, 2019 2:23 pm

pootle wrote:
Fri Sep 06, 2019 7:15 am
I had twitchy servos on a 2 servo project, it turned out that the servos themselves needed decoupling capacitors on the power feed right beside the servos themselves. The voltage spikes caused by servo motors starting and stopping were de-stabilizing the servo's own electronics. Try a moderate electrolytic say 47uF and a fast tantalum in parallel across the 5v line to the servo as close as possible to the servo
Thanks for your input. I'm beginning to think that this is what caused the jerky motor that i've been experiencing on my project. In my project, the problem is not exactly a jerky servo, but a jerky motor, happen when the servo move rapidly to different direction. It gives a short throttle burst, just like what you would have seen in the video. Last night, i did a test with the given code below:

Code: Select all

steering = np.random.randint(low=-250, high=250)

if steering < 0:
	steering *= -1
        angle_turn = self.turnAngle - steering
        self.pi.set_servo_pulsewidth(self.servo_gpio, angle_turn)
        print("Current turn angle = " + str(angle_turn))
else:
	angle_turn = self.turnAngle + steering
	self.pi.set_servo_pulsewidth(self.servo_gpio, angle_turn)
	print("Current turn angle = " + str(angle_turn)))
And it still give me that short throttle burst.

User avatar
joan
Posts: 14473
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: [ASK] How To Get Smooth PWM Control

Fri Sep 06, 2019 2:48 pm

Could you give a sample of say fifty of the values you are sending to set_servo_pulsewidth with a timestamp?

Example print statement.

Code: Select all

import time

tstart=time.time()
...
print("{:.2f}={}".format(time.time()-tstart, angle_turn))

blimpyway
Posts: 192
Joined: Mon Mar 19, 2018 1:18 pm

Re: [ASK] How To Get Smooth PWM Control

Fri Sep 06, 2019 7:41 pm

bobhaliwela wrote:
Wed Sep 04, 2019 10:17 am
blimpyway wrote:
Tue Sep 03, 2019 8:49 pm
Or, if you power the steering servo from Pi's 5V (or other "weak" supply) it could mess signal to the throttle pwm controller.

I know servos can interfere with each other - search for servo jitter problems and how they are solved. Perhaps a servos peak starting currents could influence pwm signal of power controller too.
No i did not. The power for the steering servo is from the nimh battery which used to power the esc. I connect the + (red wire ) from the esc to the servo.
Just look (or ask) about similar problems on RC forums/discussion groups. All Remote Controlled stuff is using batteries, nimh, nicads, lipo, it doesn't matter, servo interference is a frequent problem.

The fact most RC pwm stuff (servos, esc-s) is made to work between 4.5-6V signal levels while your PI-s gpio pwm is a 3.3V signal, it only increases the likelihood of interference

bobhaliwela
Posts: 9
Joined: Tue Sep 03, 2019 10:52 am

Re: [ASK] How To Get Smooth PWM Control

Mon Sep 09, 2019 6:34 am

joan wrote:
Fri Sep 06, 2019 2:48 pm
Could you give a sample of say fifty of the values you are sending to set_servo_pulsewidth with a timestamp?

Example print statement.

Code: Select all

import time

tstart=time.time()
...
print("{:.2f}={}".format(time.time()-tstart, angle_turn))
Here you go, Joan. These are the values i am sending, when i move the PS4 analog button rapidly to the left/right. It gives a short quick throttle burst for fraction of seconds, even though i did not write any code to send pulses to the motor. Thanks for the help!

Code: Select all

7.91=1654
7.91=1654
7.91=1654
7.91=1654
7.91=1654
7.91=1654
7.91=1654
7.91=1654
7.91=1654
7.91=1621
7.91=1621
7.91=1621
7.91=1621
7.91=1621
7.91=1621
7.91=1621
7.91=1621
7.91=1621
7.91=1621
7.91=1621
7.92=1621
7.92=1621
7.92=1621
7.92=1592
7.92=1592
7.92=1592
7.92=1592
7.92=1592
7.92=1592
7.92=1592
7.92=1592
7.92=1592
7.92=1592
7.92=1592
7.92=1592
7.92=1592
7.92=1567
7.92=1567
7.92=1567
7.92=1567
7.92=1567
7.92=1567
7.92=1567
7.92=1567
7.92=1567
7.92=1567
7.92=1567
7.92=1567
7.92=1567
7.92=1567
7.92=1546
7.92=1546
7.92=1546
7.92=1546
7.93=1546
7.93=1546
7.93=1546
7.93=1546
7.93=1546
7.93=1546
7.93=1546
7.93=1546
7.93=1546
7.93=1528
7.93=1528
7.93=1528
7.93=1528
7.93=1528
7.93=1528
7.93=1528
7.93=1528
7.93=1528
7.93=1528
7.93=1528
7.93=1528
7.93=1525
7.93=1525
7.93=1525
7.93=1525
7.94=1525
7.94=1525
7.94=1525
7.94=1525
7.94=1525
7.94=1525
7.94=1525
7.94=1525
7.94=1525
7.94=1525
7.94=1525
7.94=1525
7.94=1525
7.94=1525
7.94=1525
7.94=1525
7.94=1525
7.94=1525
7.94=1525
7.94=1525
7.94=1525
7.94=1525
7.94=1525
7.94=1525
7.94=1525
7.94=1525
7.94=1528
7.94=1528
7.94=1528
7.94=1528
7.95=1528
7.95=1528
7.95=1528
7.95=1528
7.95=1528
7.95=1528
7.95=1528
7.95=1528
7.95=1528
7.95=1528
7.95=1546
7.95=1546
7.95=1546
7.95=1546
7.95=1546
7.95=1546
7.95=1546
7.95=1546
7.95=1546
7.95=1546
7.95=1546
7.95=1546
7.95=1546
7.95=1569
7.95=1569
7.95=1569
7.95=1569
7.95=1569
7.95=1569
7.95=1569
7.95=1569
7.95=1569
7.95=1569
7.95=1569
7.96=1569
7.96=1569
7.96=1569
7.96=1592
7.96=1592
7.96=1592
7.96=1592
7.96=1592
7.96=1592
7.96=1592
7.96=1592
7.96=1592
7.96=1592
7.96=1592
7.96=1592
7.96=1592
7.96=1628
7.96=1628
7.96=1628
7.96=1628
7.96=1628
7.96=1628
7.96=1628
7.96=1628
7.96=1628
7.96=1628
7.96=1628
7.96=1628
7.96=1667
7.96=1667
7.96=1667
7.97=1667
7.97=1667
7.97=1667
7.97=1667
7.97=1667
7.97=1667
7.97=1667
7.97=1667
7.97=1703
7.97=1703
7.97=1703
7.97=1703
7.97=1703
7.97=1703
7.97=1747
7.97=1747
7.97=1747
7.97=1747
7.97=1747
7.97=1747
7.97=1747
7.97=1747
7.98=1747
7.98=1747
7.98=1747
7.98=1749
7.98=1749
7.98=1749
7.98=1749
7.98=1749
7.98=1749
7.98=1749
7.98=1749
7.98=1749
7.98=1749
7.98=1749
7.98=1749
7.98=1749
7.98=1749
7.98=1749
7.98=1749
7.98=1749
7.98=1749
7.98=1749
7.98=1749
7.98=1749
7.98=1749
7.98=1749
7.98=1749
7.98=1749
7.98=1749
7.98=1749
7.98=1749
7.98=1749
7.99=1749
7.99=1749
7.99=1749
7.99=1749
7.99=1749
7.99=1749
7.99=1749
7.99=1749
7.99=1749
7.99=1749
7.99=1749
7.99=1749
7.99=1749
7.99=1749
7.99=1749
7.99=1749
7.99=1749
7.99=1749
7.99=1749
7.99=1749
7.99=1749
7.99=1749
7.99=1749
7.99=1749
7.99=1749
7.99=1749
7.99=1749
7.99=1749
7.99=1749
7.99=1749
8.00=1749
8.00=1749
8.00=1749
8.00=1749
8.00=1749
8.00=1749
8.00=1749
8.00=1749
8.00=1749
8.00=1749
8.00=1749
8.00=1749
8.00=1749
8.00=1749
8.00=1749
8.00=1749
8.00=1749
8.00=1749
8.00=1749
8.01=1749
8.01=1749
8.01=1749
8.01=1749
8.01=1749
8.01=1749
8.01=1749
8.01=1749
8.01=1749
8.01=1749
8.01=1749
8.01=1749
8.01=1749
8.01=1749
8.01=1749
8.01=1749
8.01=1749
8.01=1749
8.01=1749
8.01=1749
8.01=1749
8.01=1749
8.01=1749
8.01=1749
8.01=1749
8.01=1749
8.01=1749
8.01=1749
8.01=1749
8.01=1749
8.01=1749
8.02=1749
8.02=1749
8.02=1749
8.02=1749
8.02=1749
8.02=1749
8.02=1749
8.02=1749
8.02=1749
8.02=1749
8.02=1749
8.02=1749
8.02=1749
8.02=1749
8.02=1749
8.02=1749
8.02=1749
8.02=1749
8.02=1749
8.02=1749
8.02=1749
8.02=1749
8.02=1749
8.02=1749
8.02=1749
8.02=1749
8.02=1749
8.02=1749
8.02=1749
8.02=1749
8.02=1749
8.03=1749
8.03=1749
8.03=1749
8.03=1749
8.03=1749
8.03=1749
8.03=1749
8.03=1749
8.03=1749
8.03=1749
8.03=1749
8.03=1749
8.03=1749
8.03=1749
8.03=1749
8.03=1749
8.03=1749
8.03=1749
8.03=1749
8.03=1749
8.03=1749
8.03=1749
8.03=1749
8.04=1749
8.04=1749
8.04=1749
8.04=1749
8.04=1749
8.04=1749
8.04=1749
8.04=1749
8.04=1749
8.04=1749
8.04=1749
8.04=1749
8.04=1749
8.04=1749
8.04=1749
8.04=1749
8.04=1749
8.04=1749
8.04=1749
8.04=1749
8.04=1749
8.04=1749
8.04=1749
8.04=1749
8.04=1749
8.04=1749
8.04=1749
8.04=1749
8.04=1749
8.04=1749
8.04=1749
8.04=1749
8.05=1749
8.05=1749
8.05=1749
8.05=1749
8.05=1749
8.05=1749
8.05=1749
8.05=1749
8.05=1749
8.05=1749
8.05=1749
8.05=1749
8.05=1749
8.05=1749
8.05=1749
8.05=1749
8.05=1749
8.05=1749
8.05=1749
8.05=1749
8.05=1749
8.05=1749
8.05=1749
8.05=1749
8.05=1749
8.05=1749
8.05=1749
8.05=1749
8.05=1749
8.05=1749
8.05=1749
8.06=1749
8.06=1749
8.06=1749
8.06=1749
8.06=1749
8.06=1749
8.06=1749
8.06=1749
8.06=1749
8.06=1749
8.06=1749
8.06=1749
8.06=1749
8.06=1749
8.06=1749
8.06=1749
8.06=1749
8.06=1749
8.06=1749
8.06=1749
8.07=1749
8.07=1749
8.07=1749
8.07=1749
8.07=1749
8.07=1749
8.07=1749
8.07=1749
8.07=1749
8.07=1749
8.07=1749
8.07=1749
8.07=1749
8.07=1749
8.07=1749
8.07=1749
8.07=1749
8.07=1749
8.07=1749
8.07=1749
8.07=1749
8.07=1749
8.07=1731
8.07=1731
8.07=1731
8.07=1731
8.07=1731
8.07=1731
8.07=1731
8.07=1731
8.07=1731
8.07=1731
8.08=1731
8.08=1731
8.08=1731
8.08=1688
8.08=1688
8.08=1688
8.08=1688
8.08=1688
8.08=1688
8.08=1688
8.08=1688
8.08=1688
8.08=1688
8.08=1688
8.08=1688
8.08=1688
8.08=1641
8.08=1641
8.08=1641
8.08=1641
8.08=1641
8.08=1641
8.08=1641
8.08=1641
8.08=1641
8.08=1641
8.08=1641
8.08=1641
8.08=1641
8.08=1641
8.08=1587
8.08=1587
8.08=1587
8.09=1587
8.09=1587
8.09=1587
8.09=1587
8.09=1587
8.09=1587
8.09=1587
8.09=1587
8.09=1528
8.09=1528
8.09=1528
8.09=1528
8.09=1528
8.09=1528
8.09=1528
Last edited by bobhaliwela on Mon Sep 09, 2019 6:48 am, edited 4 times in total.

bobhaliwela
Posts: 9
Joined: Tue Sep 03, 2019 10:52 am

Re: [ASK] How To Get Smooth PWM Control

Mon Sep 09, 2019 6:43 am

blimpyway wrote:
Fri Sep 06, 2019 7:41 pm
Just look (or ask) about similar problems on RC forums/discussion groups. All Remote Controlled stuff is using batteries, nimh, nicads, lipo, it doesn't matter, servo interference is a frequent problem.

The fact most RC pwm stuff (servos, esc-s) is made to work between 4.5-6V signal levels while your PI-s gpio pwm is a 3.3V signal, it only increases the likelihood of interference
I know the battery isn't the problem. I'm just just trying to clarify that i did not power the steering servo from Pi's gpios. I powered it up straight from the battery by connecting the red wire (+) from the esc to the steering servo.

User avatar
joan
Posts: 14473
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: [ASK] How To Get Smooth PWM Control

Mon Sep 09, 2019 7:33 am

That's quite a movement in 0.2 seconds. I would expect it to be seen as jitter.
Screenshot from 2019-09-09 08-31-23.png
Screenshot from 2019-09-09 08-31-23.png (32.99 KiB) Viewed 509 times

pootle
Posts: 340
Joined: Wed Sep 04, 2013 10:20 am
Location: Staffordshire
Contact: Website

Re: [ASK] How To Get Smooth PWM Control

Mon Sep 09, 2019 8:19 am

As I read the code, you aren't changing the throttle setting at all in the test, yet the drive motor speeds up and slows down. Is this true?

Also I note you are going round the control loop at a hell of a rate - 2,500 times per second. I'm wondering if this is causing a problem somewhere downstream.

I suspect it would be better to limit the rate at which you call set_servo_pulsewidth - after all the servo controller only sends 50 pulses per second, so changing the value 50 times during every pulse isn't actually going to help.

So this is a fairly random idea, but......

Try limiting the update rate - either by slowing down the loop (not sure how practical this is inside pygame tho) or by the loop only updating the internal value and calling set_servo_pulsewith only 20 ms after the last call.

It might be interesting to log the result of self.pi.get_servo_pulsewidth(self.motor_gpio) in the print statement- we know what to expect.........

(unexpected result => scientist gets excited, engineeer get worried)

As a general principle you should clamp the value of angle_turn to avoid damaging the servo / stalling the motor. If you want the absolute max range of movement you can test each servo to find the values which hits the end stops and back of a smidgen.

Running control loops at a fixed frequency is also important if you later want to do smart things like smooth the rate of steering changes or start using PID correction for any reason.

bobhaliwela
Posts: 9
Joined: Tue Sep 03, 2019 10:52 am

Re: [ASK] How To Get Smooth PWM Control

Mon Sep 09, 2019 9:49 am

joan wrote:
Mon Sep 09, 2019 7:33 am
That's quite a movement in 0.2 seconds. I would expect it to be seen as jitter.

Screenshot from 2019-09-09 08-31-23.png
The movement is happening because i am moving the steering servo via PS4 analog button rapidly quick (to the left/right). The servo itself does not jitters, but the motor did. It gives me a quick of burst throttle for a fraction of seconds. This happens even when i don't even write a code to send pulses to the motor. The servo is fine when it's on its idle state, it does not jitter at all.
Last edited by bobhaliwela on Mon Sep 09, 2019 10:08 am, edited 1 time in total.

bobhaliwela
Posts: 9
Joined: Tue Sep 03, 2019 10:52 am

Re: [ASK] How To Get Smooth PWM Control

Mon Sep 09, 2019 10:06 am

pootle wrote:
Mon Sep 09, 2019 8:19 am
As I read the code, you aren't changing the throttle setting at all in the test, yet the drive motor speeds up and slows down. Is this true?
Yes. I did not write any code to send pulses to drive the motor. I only write a code to send pulses to the servo. Yet, the motor gives a quick throttle burst whenever i move the steering servo rapidly quick via PS4 analog button.
pootle wrote:
Mon Sep 09, 2019 8:19 am
Try limiting the update rate - either by slowing down the loop (not sure how practical this is inside pygame tho) or by the loop only updating the internal value and calling set_servo_pulsewith only 20 ms after the last call.
I might try this later tonight. Thanks!
pootle wrote:
Mon Sep 09, 2019 8:19 am
It might be interesting to log the result of self.pi.get_servo_pulsewidth(self.motor_gpio) in the print statement- we know what to expect.........
Ah, how come i didn't think about this? Lol.
pootle wrote:
Mon Sep 09, 2019 8:19 am
As a general principle you should clamp the value of angle_turn to avoid damaging the servo / stalling the motor. If you want the absolute max range of movement you can test each servo to find the values which hits the end stops and back of a smidgen.
Already did that, the line below does exactly this.

Code: Select all

steering = int(steering * 250)
pootle wrote:
Mon Sep 09, 2019 8:19 am
Running control loops at a fixed frequency is also important if you later want to do smart things like smooth the rate of steering changes or start using PID correction for any reason.
I did this in the full implementation of my project, but on the GymEnv server side. Should try your suggestion later tonight. Thanks a lot for your input.

bobhaliwela
Posts: 9
Joined: Tue Sep 03, 2019 10:52 am

Re: [ASK] How To Get Smooth PWM Control

Wed Sep 11, 2019 5:52 pm

Solved the issue by adding PCA9685 guys, no more motor jitters/jerks. Thanks a lot for the help before!

Return to “Automation, sensing and robotics”