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()`
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()
| improve this answer | |
  • 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? – shdwSix May 9 '19 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 '19 at 13:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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