pieperml
Posts: 4
Joined: Sat May 11, 2019 7:26 pm

Using PWM with Sabertooth motor controller

Sat May 11, 2019 8:42 pm

I am new to the forum and to using the RPi. My son had tinkered with small robots for years and now I'm hooked on it. Here is what I'm doing:
I intend to build a robot which will take my trash bin to the curb and back. I have several sensors in play. It will use three ultrasonic sensors on the front and sides to avoid collisions. It will also have a GPS module to navigate from start to curb and back. There are some other details, but not important at this point. I have several existing parts I intend to use for this project. I have a RPi 0w. I also have two good size motors and a Sabertooth 2x25 motor controller. I'm working on this in steps. I already have bread-boarded and tested the ultrasonic sensors. Now I'm working on the motion. I've used the code below to test the use of PWM to drive the motors through the Sabertooth.
(https://www.dimensionengineering.com/da ... th2x25.pdf) The code starts the motors at full forward and steps down to a stop, and then back up to full reverse. At least that is what it is supposed to do. When it gets to a duty cycle of 50% it is supposed to be at full stop, but it isn't. It jerks forward and reverse.
What am I missing in the use of PWM?
I've already considered switching to serial, but will need those pins for the GPS. Besides, I'd really like to understand how to make this work.
Thank you in advance for responses.

Code: Select all

#!/usr/bin/env python
import RPi.GPIO as GPIO
import time

GPIO.cleanup()

LedPin = 12
LedPin2 = 35

GPIO.setmode(GPIO.BOARD)       # Numbers pins by physical location
GPIO.setup(LedPin, GPIO.OUT)   # Set pin mode as output
GPIO.output(LedPin, GPIO.LOW)  # Set pin to low(0V)
GPIO.setup(LedPin2, GPIO.OUT)   # Set pin mode as output
GPIO.output(LedPin2, GPIO.LOW)  # Set pin to low(0V)

p = GPIO.PWM(LedPin, 1000)     # set Frequece to 1KHz
p2 = GPIO.PWM(LedPin2, 1000)     # set Frequece to 1KHz
p.start(50)                     # Start PWM output, Duty Cycle = 50
p2.start(50)

try:
        print('start')
        while True:
                for dc in range(100, -1, -10): # Decrease duty cycle: 100~0
                        p.ChangeDutyCycle(dc)     # Change duty cycle
                        p2.ChangeDutyCycle(dc)
                        print('Duty Cycle = ', dc)
                        time.sleep(5)
        p.stop()
        GPIO.output(LedPin, GPIO.HIGH)    # turn off all leds
             
except KeyboardInterrupt:
        p.stop()
        GPIO.output(LedPin, GPIO.HIGH)    # turn off all leds
        p2.stop()
        GPIO.output(LedPin2, GPIO.HIGH)    # turn off all leds
        GPIO.cleanup()

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

Re: Using PWM with Sabertooth motor controller

Sat May 11, 2019 9:55 pm

Perhaps software timed PWM is not stable enough for your needs.

There are a number of modules which can provide hardware timed PWM, perhaps try one of those.

pieperml
Posts: 4
Joined: Sat May 11, 2019 7:26 pm

Re: Using PWM with Sabertooth motor controller

Sun May 12, 2019 12:15 am

Thank you, Joan. Being new to this, I thought I had read that the 12 and 35 pins of the rpi 0 were hardware timed. Can you please point me toward better research on this, or perhaps share some of your expertise on possible solutions?

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

Re: Using PWM with Sabertooth motor controller

Sun May 12, 2019 8:20 am

It is probably simplest to see if my pigpio works.

sudo pigpiod # start the daemon

pigs pfs 18 1000 # set 18/19 to 1kHz PWM
pigs pfs 19 1000

pigs p 18 128 # set 18 to 50% dutycycle (valid range 0 - 255)
pigs p 19 64 # set 19 to 25%

If that works also have a look at servoblaster, RPIO.GPIO etc.

By the way GPIO 18/19 can also be used for fully hardware PWM.

pieperml
Posts: 4
Joined: Sat May 11, 2019 7:26 pm

Re: Using PWM with Sabertooth motor controller

Sun May 12, 2019 7:52 pm

It did not work. I may be doing something wrong. In the previous tests the change in duty cycle did change the speed. However, using pigs did not change the speed.
While looking through your libraries and some posts, I saw the use of hardware_pwm. I am about to attempt the following:

Code: Select all

# #!/usr/bin/env python
import pigpio
import time

GPIO.setmode(GPIO.BCM)       # Numbers pins by GPIO location
GPIO = pigpio.pi()
# Set the GPIO-Mode to ALT5 for HW-PWM
motor1 = 18
motor2 = 19
GPIO.set_mode(motor1, pigpio.ALT5)
GPIO.set_mode(motor2, pigpio.ALT5)
# Start the signal generation
# 10,000kHz, 50% Duty Cycle – this should be stopped
GPIO.hardware_PWM(motor1, 10000, 500000)
GPIO.hardware_PWM(motor2, 10000, 500000)

try:
        print('start')
        while True:
                for stepvalue in range(100, -1, -25): # Decrease duty cycle: 100~0
                       dc = stepvalue*10000
                       set_PWM_dutycycle(motor1, dc)     # Change duty cycle
                       set_PWM_dutycycle(motor2, dc)     # Change duty cycle
                       print('Duty Cycle = ', dc, ‘  at ‘,stepvalue, ‘%’)
                       time.sleep(5)
        GPIO.stop()
except KeyboardInterrupt:
   GPIO.hardware_PWM(motor1, 10000, 500000)
   GPIO.hardware_PWM(motor2, 10000, 500000)
        GPIO.stop()

Thoughts?
I admit that I don't understand the set mode value of ALT5 - is that explained somewhere? Also, I don't know whether it makes a difference of being on separate channels - each pin will control one of the two wheel motors.
Thank you for being helpful and patient!

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

Re: Using PWM with Sabertooth motor controller

Sun May 12, 2019 8:14 pm

If the pigs command didn't work it's doubtful that any of the other pigpio commands would work either.

pigpio always uses Broadcom GPIO numbering. GPIO18 is pin 12, GPIO19 is pin 35.

https://pinout.xyz/

pigpio does have a hardware PWM command for those GPIO which have hardware capabilities (12/13/18/19 on 40 pin expansion header Pis).

pigs hp http://abyz.me.uk/rpi/pigpio/pigs.html#HP

Python hardware_PWM http://abyz.me.uk/rpi/pigpio/python.html#hardware_PWM

You don't have to change modes, pigpio sets the GPIO to the needed mode for any functions you use.

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

Re: Using PWM with Sabertooth motor controller

Sun May 12, 2019 8:27 pm

Are you talking to a servo or a LED? The commands I gave earlier assumed you were driving a LED at 1kHz as per the code you posted.

Servos are usually driven at 50Hz and are unlikely to respond to a 1kHz signal.

pieperml
Posts: 4
Joined: Sat May 11, 2019 7:26 pm

Re: Using PWM with Sabertooth motor controller

Sun May 12, 2019 8:39 pm

I am trying to control DC motors. I do understand the pi pin numbering. I just tried the pigs hp command and it works.
pigs hp 18 100 800000 # 80% dutycycle
Thank you for the hint on the 50Hz. That may explain the confusing results. At 50% I do get the motors to nearly stop, but when trying to get both to stop at the same time they continue to spin.
pigs hp 18 100 500000 # 50% dutycycle
pigs hp 19 100 500000 # 50% dutycycle

User avatar
omegaman477
Posts: 148
Joined: Tue Feb 28, 2017 1:13 pm
Location: Sydney, Australia

Re: Using PWM with Sabertooth motor controller

Mon May 13, 2019 10:33 pm

Its really hard to debug software PWM's without being able to inspect the output waveform with an Oscilloscope.

Reading up on the Sabertooth 25x2, it can be driven several ways. Its not clear from your post what mode are you using. Are you using the PWM to generate an analogue signal, and the Sabertooth is in Analogue Input Mode, OR is the Sabertooth in Hobby servo RC mode, and you are trying to generate a RadioControl Servo pulse train?

Taking a punt I assume option 1. So in this configuration, converting a PWM to a proportional voltage, requires a filter (R/C network). The value therein are very specific to the base frequency of the PWM train. My bet is the R/C time constant is too fast and PWM pulses are getting through the R/C filter and driving the Sabertooth silly.

So, the Sabertooth needs a clean, ripple free, analogue control voltage. I would isolate the fault thus. Drive the Sabertooth input with a simple potentiometer, say 1k, as a voltage divider and using a multimeter ensure that the Sabertooth behaves properly. Then use the multimeter to determine the voltage swing of the PWM R/C output, with no Sabertooth connected. Using the DMM on the AC setting will show up any ripple. I would expect to see less than say 100mv ripple. But again you really need an oscilloscope to debug this.

Going in blind, I would increase the capacitor and resistor in the filter and see what the result is.

I trust you used the example R/C filter in the Sabertooth datasheet and are running the pulse clock well over 1Khz. The higher the clock, the smoother the signal will be with the appropriate R&C values.
..the only thing worse than a stupid question is a question not asked.

Return to “Automation, sensing and robotics”