Complete guide to using all of the features of the MotorGo Plink Python API
- Table of Contents
- Getting Started
- Accessing Motor Channels
- Reading Encoder Data
- Controlling Motors
- Reading IMU Data
- Reading Light and Range Sensor Data
- Examples
To start using the MotorGo Python API, first import your MotorGo board from the motorgo module:
from motorgo import PlinkNext, create an instance of the board you imported:
plink = Plink()Optionally, you can configure the communication parameter for the board:
plink = Plink(frequency = 200, timeout = 1.0)Frequency defines the frequency of data transmission to the MotorGo board. Reducing the frequency results in less CPU usage on the MotorGo and Pi. The frequency may not be stable above 200 Hz. Timeout defines the time in seconds to wait for a response from the MotorGo board before attempting to reset communications.
To begin communication, run the following command:
plink.connect()The MotorChannel objects are the primary interface for controlling the motors and reading their corresponding encoder data. The MotorChannel objects are accessible as:
plink.channel1
plink.channel2
plink.channel3
plink.channel4You can save a reference to the MotorChannel objects as local variables for convenience. For example:
left_drive_wheel = plink.channel1
right_drive_wheel = plink.channel2The encoder data can be accessed from the MotorChannel objects in the Plink object. The MotorChannel objects are accessible as:
To read the encoder data, simply access the position and velocity attributes of the MotorChannel object:
left_position = left_drive_wheel.position # Position, in radians
left_velocity = left_drive_wheel.velocity # Velocity, in radians/sec
channel_3_position = plink.channel3.position
channel_3_velocity = plink.channel3.velocity
print(f"Left wheel: {left_position}\t {left_velocity}")
print(f"Channel 3: {channel_3_position}\t {channel_3_velocity}")Note that the forward direction of the position is dependent on the direction that the motor is connected to the MotorGo and the direction the encoder is connected to the motor.
The Plink supports two motor control modes: ControlMode.POWER and ControlMode.VELOCITY.
In power control mode, the motor is controlled by directly setting the power level. The power level is a value between -1.0 and 1.0, where -1.0 is full reverse, 0.0 is stopped, and 1.0 is full forward. To configure a motor channel to power control mode, set the control_mode attribute of the MotorChannel object to ControlMode.POWER.
from motorgo import ControlMode
left_drive_wheel.control_mode = ControlMode.POWERTo set the power level of the motor, set the power attribute of the MotorChannel object to a value between -1.0 and 1.0.
left_drive_wheel.power = 0.5In velocity control mode, the motor is controlled by setting the desired velocity in rad/s. To configure a motor channel to velocity control mode, set the control_mode attribute of the MotorChannel object to ControlMode.VELOCITY.
from motorgo import ControlMode
left_drive_wheel.control_mode = ControlMode.VELOCITYNext, you must configure the velocity PID controller parameters for the motor:
left_drive_wheel.set_velocity_pid_gains(p = 1.0, i = 0.0, d = 0.0, output_ramp = None, lpf = None)The output_ramp can be set to limit the rate of change of the motor power output. The lpf parameter can be set to apply a low-pass filter to the velocity setpoint. You can set any of the parameters to None to use the default values.
Finally, set the desired velocity of the motor by setting the velocity attribute of the MotorChannel object to the desired velocity in rad/s.
left_drive_wheel.velocity = 1.0If the motor seems to be spinning at the top speed regardless of the velocity setpoint, you may need to flip the sign of the PID gains, as the motor may be spinning in the opposite direction of the encoder.
The data from the onboard IMU can be accessed through the IMU object in the Plink object.
imu = plink.imuThe IMU object provides the raw IMU data from the gyroscope, accelerometer, and magnetometer.
gyro = imu.gyro
accel = imu.accel
mag = imu.mag
The data is returned as numpy.ndarray objects, each containing 3 elements corresponding to the x, y, and z axes. The coordinate frame is on the MotorGo board. The gyroscope data is in rad/s, the accelerometer data is in m/s^2, and the magnetometer data is in uT.
In addition to the raw data, the MotorGo Python API filters the IMU data to compute the orientation of the MotorGo relative to the Earth's gravity vector. You can access the orientation of the Plink board as a quaternion:
orientation = imu.orientation # Returns a numpy.ndarray containing [w, x, y, z]You can also read the gravity vector, relative to the MotorGo board, as a numpy.ndarray containing [x, y, z]:
gravity_vector = imu.gravity_vectorSince the QWIIC ports on the MotorGo are connected to the Raspberry Pi I2C bus, you can access the sensors directly from the Raspberry Pi.
Once you have connected the sensor, you can confirm that the Raspberry Pi can detect the sensor by running the following command:
i2cdetect -y 1You should see the address of the sensor in the output. For example, the BH1750 light sensor has an address of 0x23.
You can read the light sensor data in Python with the following code:
import board
import adafruit_bh1750
i2c = board.I2C() # uses board.SCL and board.SDA
# i2c = board.STEMMA_I2C() # For using the built-in STEMMA QT connector on a microcontroller
sensor = adafruit_bh1750.BH1750(i2c)
while True:
print("%.2f Lux" % sensor.lux)
time.sleep(0.2)You can read the range sensor data in Python with the following code:
import board
import adafruit_vl53l4cx
i2c = board.I2C() # uses board.SCL and board.SDA
# i2c = board.STEMMA_I2C() # For using the built-in STEMMA QT connector on a microcontroller
vl53 = adafruit_vl53l4cx.VL53L4CX(i2c)
print("VL53L4CX Simple Test.")
vl53.start_ranging()
while True:
while not vl53.data_ready:
pass
vl53.clear_interrupt()
print("Distance: {} cm".format(vl53.distance))You can find full examples of using the MotorGo Plink Python API in the examples directory of this repository.