1

I am making a project where I want to use a PC/Xbox controller to control my servos with analog sticks. I've been following this tutorial and I've used the code down below to control my servo motor with an analog stick, but encountered a problem of servo jitter, while using RPi.GPIO. I wrote a simple program, which controls the servo with the use of PIGPIO library and it works perfectly. Can anybody help me to transform the code below to use a PIGPIO library instead?

Thank you.

Code I'm using with RPi.GPIO:

import RPi.GPIO as GPIO
import math
import xbox

GPIO_SERVO_PIN  = 20

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)

GPIO.setup(GPIO_SERVO_PIN, GPIO.OUT)


def updateServo(pwm, angle):
    duty = float(angle) / 10.0 + 2.5
    pwm.ChangeDutyCycle(duty)

def angleFromCoords(x,y):
    angle = 0.0
    if x==0.0 and y==0.0:
        angle = 90.0
    elif x>=0.0 and y>=0.0:
        # first quadrant
        angle = math.degrees(math.atan(y/x)) if x!=0.0 else 90.0
    elif x<0.0 and y>=0.0:
        # second quadrant
        angle = math.degrees(math.atan(y/x))
        angle += 180.0
    elif x<0.0 and y<0.0:
        # third quadrant
        angle = math.degrees(math.atan(y/x))
        angle += 180.0
    elif x>=0.0 and y<0.0:
        # third quadrant
        angle = math.degrees(math.atan(y/x)) if x!=0.0 else -90.0
        angle += 360.0
    return angle

if __name__ == '__main__':
    joy = xbox.Joystick()
    pwm = GPIO.PWM(GPIO_SERVO_PIN, 100)
    pwm.start(5)

    while not joy.Back():
        # Servo
        x, y = joy.leftStick()
        angle = angleFromCoords(x,y)
        if angle > 180 and angle < 270:
            angle = 180
        elif angle >= 270:
            angle = 0
        updateServo(pwm, angle)

    joy.close()
    pwm.stop()`

1 Answer 1

0

Try something like the following for a start.

#!/usr/bin/env python

import pigpio
import math
import xbox

GPIO_SERVO_PIN  = 20

MIN_ANG=-180.0 #degrees
MAX_ANG=180.0  #degrees

MIN_PW=1000 # microseconds
MAX_PW=2000 # microseconds

ANG_RANGE=MAX_ANG-MIN_ANG
PW_RANGE=MAX_PW-MIN_PW
PWAR=float(PW_RANGE)/ANG_RANGE

RAD2DEG=180.0/math.pi

def angleToPulseWidth(angle):
   """
   angle is mapped to valid pulse widths for servo
   which are determined by experiment.
   """
   assert MIN_ANG <= angle <= MAX_ANG
   return MIN_PW + ((angle - MIN_ANG) * PWAR)


if __name__ == '__main__':

   import pigpio
   import time

   pi = pigpio.pi()
   if not pi.connected:
      exit()

   joy = xbox.Joystick()

   while not joy.Back():
      x, y = joy.leftStick()
      angle = math.atan2(y, x) * RAD2DEG
      pw = angleToPulseWidth(angle)
      pi.set_servo_pulsewidth(GPIO_SERVO_PIN, pw)
      time.sleep(0.01)

   joy.close()
   pi.stop()
2
  • Thank you for your reply. This seems to work quite good when I tilt the stick to the left and move it up and down. When it comes to the right side, it kinda slows down and doesn't move so much. Is there a way to fix it?
    – m.f
    May 9, 2019 at 12:53
  • @Max.F I can't help there as I don't have a joystick and have little idea of how they operate.
    – joan
    May 9, 2019 at 13:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.