You probably want to make your robot move around the arena. The most common way of doing this is using electric motors. The motor controller in your kit allows you to control the power delivered to two 12V motors.
From your robot software, you can tell the motor controller to deliver a certain amount of power to the motors. (For those who are interested, the motor controller uses pulse-width modulation to vary the amount of power delivered to the motors.) There is not a linear relationship between power and the speed of the motor. The motor will be subject to a varying load (e.g. your robot may be going up a ramp, or it might be pushing some blocks). There is also variation between different instances of the same motor, and most DC motors run slightly better in one direction.
As delivered power doesn't relate directly to a specific motor speed, it's not really possible to just use timing to get your robot into the position you want.
Since a timing-based approach to motor control doesn't provide repeatable or reliable results, you need to find a different solution. The answer to this problem is "feedback". You will need to write your robot software so that it feeds information from relevant sensors back to your software that determines how to adjust the motor outputs next.
Imagine you had been blind-folded and had to walk across a large room to a chair. Every three steps you are allowed to take your blind-fold off and look around, then put the blind-fold back on before you take any more steps. When you are blind-folded, you have less of an idea about where you are in the room and you hope that your legs carry you in the right direction. Every time you lift up your blind-fold, you are reading your sensors, and when the blind-fold comes back down again you adjust the signals you send to your legs. This is a feedback loop. By periodically examining what needs to be done to reach a given target, and adjusting outputs as necessary, you will eventually reach your target (the chair).
Depending on how you use motors in your robot, there are several different sensors that you could use (and this is a non-exhaustive list):
The connectors on the motor controller are shown in the following diagram:
These are digital I/O pins, and are used to communicate with the AS5030 sensor board.
Each motor output can be configured and used independently of the other one. The SR library provides you with an array of motor channels. You control everything to do with the first motor channel using:
motor[0]Similarly, you control everything to with the second motor channel using:
motor[1]The following documentation talks about using motor[0]. All of these things are also applicable to motor[1].
To control the power delivered to motors directly, rather than use any sensors or control loop on the motor controller, configure the motor controller like this:
motor[0].sensor = motor.NULL motor[0].controller = motor.UNITY motor[0].target = 0
After configuring the channel as above, enable it like so:
motor[0].enable()
Your motor channel is now configured. You can set the output to a certain power using motor[0].target. This takes a number between -100 and 100:
motor[0].target = -50
You can change the power delivered to a motor at any time.
The motor controller incorporates a PID controller that allows you to control the absolute angle of a wheel, or axle that a motor is connected to. The motor controller can sense the rotary position of a rotary shaft using the AS5030 sensor board.
To get the motor controller to use the AS5030 controller, you need to configure it as follows:
motor[0].sensor = motor.AS5030
You have an option of which pins are connected to which. The following code tells the motor controller that the clock pin of the AS5030 is connected to feedback pin 0, and the dio pin is connected to feedback pin 1. The diagram of the motor controller above shows the numbering of the feedback pins.
motor[0].as5030.set_pins( clk = 0, dio = 1 )
The AS5030 is an 8-bit sensor. It is likely that you do not want this many bits, as the least-significant bits are probably too noisy for you to use. You can choose how many bits to lose by calling set_shr. If you are not sure how many to lose, a good number to try first is 2.
motor[0].as5030.set_shr( 2 )
Tell the motor controller to use the PID controller like so:
motor[0].controller = motor.PID
You now need to configure the P, I, and D coefficients used within the PID controller. See "Tuning the PID loop" below to discover what values you should set these to. Set the coefficients like so:
motor[0].PID.set_coeff( kp = -4, ki = -5, kd = -10 )
To get the motor to move to a specific location when using the PID controller, set the target position:
motor[0].target = -3049
The motor will then move until it reaches position -3049 (which is likely to be several rotations away).
You can suspend your code until the motor reaches the position you asked it to using the following code:
motor[0].target = 500 yield motor[0]
Using the PID loop requires slightly more set-up than the open-loop power control option. After connecting up the motor controller and AS5030, you will need to tune the PID controller. To tune the motor controller, you should write a program that commands the motor to switch back-and-forth between two positions, for example:
from sr import *
def main():
motor[0].sensor = motor.AS5030
motor[0].as5030.set_pins( clk = 0, dio = 1 )
motor[0].as5030.set_shr( 2 )
motor[0].controller = motor.PID
motor[0].PID.set_coeff( kp = -5, ki = 0, kd = 0 )
while True:
motor[0].target = 100
yield 1.5
motor[0].target = 0
yield 1.5
Now, you will need to play with the values that the PID coefficients are set to. The following approach is recommended:
To reconfigure a motor controller channel, you should disable it first:
motor[0].disable()