Position sensing + motor drive ⇒ a servo
1. Review
These are tasks you have done before using your Maker Pi board. This task combines past experience.
1.1. Measuring a voltage with the ADC
In Lab 17 Analog Inputs to the Microcontroller you learned about the analog-to-digital converter (ADC).
You used several ADC channels again in Lab 18 Interfacing to a Joystick.
That hardware on the MCU converts a voltage at a (specifically capable) pin into an integer of a certain bit width — 16 bits in this case.
1
2
3
4
5
6
import analogio
pot = analogio.AnalogIn(board.GP26)
# read the voltage and convert to 0.0 to 1.0 range for convenience.
position = pot.value / 65535
1.2. Controlling a DC motor’s speed
Way back in MCU motors and PWM you used the Maker Pi board to drive a DC motor with the help of an H-bridge chip on the board. You changed the speed by turning the motor voltage high and low very quickly with a certain duty cycle percentage called pulse-width modulation (PWM).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import board
import digitalio as dio
import pwmio
from adafruit_motor import motor
# DC motor setup
M1A = pwmio.PWMOut(board.GP8, frequency=1_000)
M1B = pwmio.PWMOut(board.GP9, frequency=1_000)
dcmotor = motor.DCMotor(M1A, M1B)
# set .throttle to the range -1.0 to +1.0
# .throttle = 0 means *brake mode*
# .throttle = None means *coast mode*
dcmotor.throttle = 0.75
2. Software-defined servo
Create a program that takes in a number in degrees (0 to 180) and causes your servo’s output shaft to move to that angle and stay there if pushed away from that position.
2.1. Tips
It is best (way best, by a huge margin) to approach this task one step at a time.
-
Use the MCU to read the position of the shaft by wiring the ends of the potentiometer to +3.3 V and GND. The middle pin’s voltage is: Vx = (% rotation) * (3.3-0) V
Figure out where the mechanical mid-rotation point is and mark its position as 90°. Then turn the shaft to 0° and 180° and write down the values as measured by the MCU’s analog-to-digital converter attached to the potentiometer’s middle pin. (these numbers will not be 0 and 65535 since the potentiometer’s range is more than 180°)
Pay attention to the direction the shaft moves compared to the ADC numbers!
-
Drive the motor inside the servo unit.
Figure out how to drive the motor at various speeds and directions.
Pay attention to the sign you give to dcmotor.throttle = NUMBER
and the physical direction.
This is how you get the shaft to go to the position you desire.
Remember that driving the motor sets its speed and not the position directly!
You will need to stop the motor when the output shaft reaches the commanded angle.
It will be very helpful to include in this while True:
loop some way to change the commanded position.
Perhaps by using the two buttons on the board to increment or decrement the postion’s value.
You have seen examples of reading user input while doing other things.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# ...
# ... setup code for pin inputs, outputs, motor drivers, etc.
# ...
while True:
#
# Handle user input on the buttons
#
if button0.value == 0:
command = command - 1
if button1.value == 0:
command = command + 1
# some code to ensure 'command' stays between 0 and 180
# if command > ....: and so on
#
# Get the position of the shaft via the potentiometer's voltage.
#
...your code here...
#
# Compute which direction to move
# and how much to move
#
...this is your job...
#
# Command the DC motor to go in that direction
# (the speed is also up to you)
#
...remember, one step at a time...
... which means: test one small thing at once!