You can use the RPI3 to use the servos. But the servo power will need to separte from the RPI3. The RPI3’s 5V is not enough to use servos long term. For initial testing they will work. But what you will find is the servos will glitch if connected to the RPI3’s header. The RPI3 causes the glitches. So eventually you need to find an alternative way to run the servos. There are two options I had on hand: a Maestro Mirco and PCA9685.
Maestro Micro
The Maestro Micro can be used, but it will require a 3.3V to 5V TTL level convert for the serial communication. The Maestro Micro uses 5V TTL logic. The RPI3 uses 3.3V TTL logic. So for the 2 boards to communicate through serial communication, you will need a TTL level converter. I ended up not using this board, because the RPI3 needs power, the Maestro Micro needs power and the TTL Level Convert needs power. This required too many connections versus the PCA9685. And the PCA9685 has 16 channels and I haved used it before in my DonkeyCar.
I do not plan to persue this board any more. I will stick with the PCA9685 that you can see in my next blog post.
You will need to download the Maestro library. You can find it on my github for now. You will also need to configure the RPI3 to handle using the serial port. The source code gives the instructions in the comments at the top.
importmaestroimporttimeimportsysclassMaestroServoControl:"""
Use the Maestro board to control the servos.
1. Disable console serial
sudo raspi-config select interfacing options -> Serial -> No -> Yes save & exit
2. Install pyserial
python -m pip install pyserial (may be a bit slow)
3. Clone Repo
git clone https://github.com/FRC4564/Maestro
4. Disable bluetooth uart
sudo nano /boot/config.txt
append to bottom: dtoverlay=pi3-disable-bt
save
"""def__init__(self,comm_port='/dev/ttyACM0',min_servo=3000.0,max_servo=9000.0):"""
Initialize the maestro. Set the comm port if you need to set the specific. Set the min
and max servo pulse width if not default.
:param comm_port: Comm port of the maestro.
:param min_servo: Min servo pulse width in quarter seconds.
:param max_servo: Max servo pulse width in quarter seconds.
"""self.comm_port=comm_port# Serial comm portself.maestro=None# Hold the maestro controllerself.min_servo=min_servo# Min pulse width of servo in quarter secondsself.max_servo=max_servo# Max pulse width of servo in quarter secondsself.setup_controller()# Setup maestrodefsetup_controller(self):"""
Setup the maestro controller
:return:
"""self.maestro=maestro.Controller(self.comm_port)self.maestro.setRange(0,self.min_servo,self.max_servo)print("Min Servo: "+str(self.maestro.getMin(0)))print("Max Servo: "+str(self.maestro.getMax(0)))defshutdown(self):"""
Shutdown the object. This will properly shutdown everything.
:return:
"""self.maestro.close()defcenter(self):"""
Center the servo.
:return:
"""self.set_angle(0.0)# CENTER (6000)defset_angle(self,chan,angle):"""
Set the servo to the given angle.
:param chan: Servo channel to move
:param angle: Angle to move the servo
:return:
"""ifangle>180:angle=180ifangle<0:angle=0curr_pos=self.maestro.getPosition(chan)print("Current Servo Position: "+str(chan)+" pw: "+str(curr_pos))pw=self.calc_quater_sec_pulse_width(angle)print("Servo: "+str(chan)+" angle: "+str(angle)+" pw: "+str(pw))self.maestro.setTarget(chan,int(pw))new_pos=self.maestro.getPosition(chan)print("New Servo Position: "+str(chan)+" pw: "+str(new_pos))defcalc_quater_sec_pulse_width(self,angle):"""
Calculate the pulse width in quarter seconds based off the angle given.
:param angle:
:return: Duty cycle for servo based off angle.
"""ifangle<=0.0:returnself.min_servoifangle>=180.0:returnself.max_servoreturn(self.max_servo+self.min_servo)/180.0*angledefset_speed(self,chan,speed):self.maestro.setSpeed(chan,speed)defset_accel(self,chan,speed):self.maestro.setAccel(chan,speed)if__name__=='__main__':#servos = MaestroServoControl(comm_port="/dev/ttyAMA0")#servos.set_speed(0, 10)#servos.set_speed(1, 10)#servos.set_angle(0, 90.0)#servos.set_angle(1, 90.0)#servos.shutdown()importmaestroservo=maestro.Controller()servo.setAccel(0,4)# set servo 0 acceleration to 4servo.setTarget(0,6000)# set servo to move to center positionservo.setSpeed(1,10)# set speed of servo 1x=servo.getPosition(1)# get the current position of servo 1servo.close()