The white Raspberry Pi shield has three connectors. The 3-pin connector near the GND and +5V marking is for powering the Raspberry Pi, whereas, the other two are for controlling the motor and the servo. Note, the motor and the servo are powered separately from the pi in order to prevent them interfere with the camera which is sensitive to noise in the power line.
Brow and black cables connect to the blue line, GND. Red cable to red line, +5V. And white and yellow signal cables face the resistor side.
Important: Do not power the board from the USB port and the battery at the same time. Always use only one source of power.
Motor and servo are controlled by modulating the pulse width of a periodic signal. The protocol for both, servo and motor, follows a convention of a 20 millisecond pulse period with a duty cycle ranging from 1 millisecond for off, motor brake and 0 servo angle, to 2 millisecond for max speed motor and max angle for servo. More info on servo protocol can be found here.
To generate this signals we need the pwm Linux module to be enable on the Raspberry Pi. For that, check if /boot/config.txt file contains the following line that enables 2 channel pwm with the output of the first channel sent to pin 12 and second channel to pin 13:
dtoverlay=pwm-2chan,pin=12,func=4,pin2=13,func2=4
If the line is missing, add it and reboot. If the servo and the motor are connected as in the above image, then channel PWM(0) will control the motor speed and PWM(1) will control the servo angle. Swapping the the cable order will swap the channels.
To control the servo and the motor from python we will use the pwmpy module from here https://github.com/scottellis/pwmpy. Download the pwm.py file into pi either using git or paste the file content using a text editor. As this code needs access to Raspberry Pi hardware run the python interpreter with sudo.
workon raceon
sudo python3
Next, we will test the motor by configuring a PWM pulse on channel 0. First we import the PWM class from the pwm module, and in the next two lines we initialize the channel 0. After initializing, we can set the period and the duty cycle, both values are in nanoseconds, to 20 ms for period and 1 ms for duty cycle. Next we enable the output of channel zero. This would not spin the motor as the 1 ms duty cycle corresponds to motor break, however, this is needed to initialize the motor controller to accept speed commands. Note, the motor controller has a protection mechanism that requires the first motor command to be brake (1 ms duty cycle). Now we can spin the motor by setting the duty cycle to 1.3 ms. The last to commands set the duty cycle to 1 ms for motor break and then disable the output. Attention, setting enable to false would not stop the motor from spinning, it disables the Raspberry Pi PWM output only. To properly stop the motor set duty cycle to 1 ms.
>>> from pwm import PWM
>>> pwm0 = PWM(0)
>>> pwm0.export()
>>> pwm0.period = 20000000
>>> pwm0.duty_cycle = 1000000
>>> pwm0.enable = True
>>> pwm0.duty_cycle = 1300000
>>> pwm0.duty_cycle = 1000000
>>> pwm0.enable = False
The code for servo is similar except that servo can accept immediately position commands. The following code set the servo angle to middle (1.5 ms) then to far left/right (depends on how the servo was mounted) followed by a far right/left. To correctly calibrate the servo, first detach the servo arm to disconnect the servo from the steering mechanism, set servo position to middle (1.5 ms) and now attach the arm such that front wheels point forward. Check both extremes to make sure that the wheel can turn the same amount left and right. Repeat servo alignment if needed or screw the servo arm in place if satisfied by the turning angles.
>>> from pwm import PWM
>>> pwm1 = PWM(1)
>>> pwm1.export()
>>> pwm1.period = 20000000
>>> pwm1.duty_cycle = 1500000
>>> pwm1.enable = True
>>> pwm1.duty_cycle = 2000000
>>> pwm1.duty_cycle = 1000000
>>> pwm1.enable = False
To adjust the steering angle and the car speed base on its position on the racing track you can use a PID controller. A python implementation you can get from https://github.com/ivmech/ivPID.