Three years ago (June 2021) the GoPiGo3 team was in a pickle. New GoPiGo3 motors arrived with 16 encoder ticks per revolution where the previous motors only had 6 encoder ticks per revolution.
The solution - a “Pickle File” containing the serial numbers of all the GoPiGo3 kits that included the new motors - AND modify every GoPiGo3 function that used ENCODER_TICKS including the graphical tool to tune Wheel Diameter, along with modifying the install code. It was a big pickle but the “team” (@cleoqc) managed to implement the solution with impressive quality on the first release.
Eighteen months later (Dec 2022) I noticed the GoPiGo3 C++ API was not paying attention to that “Pickle File” and so put my hand in the pickle barrel for the GoPiGo C++ API. I created a C++ “drive GoPiGo3 from key presses” to test my changes.
Now March 2024, I decided to mate a Raspberry Pi5 to my GoPiGo3 robot Dave. The RPi 5 made a big change from the former versions in the handling of the GPIO pins, which totally breaks the Python API due to a dependance on the unmaintained pigpiod interface daemon and the deprecated for Pi5 RPI.GPIO package. Rather than try to solve the Python API for the RPi 5, I guessed that the C++ API might just work on the Pi5.
Indeed, once I ported the Python gopigo3_power service to the new GPIO interface for the Pi5, the GoPiGo3 C++ interface appeared to be fully working for sensors, servos, and motors.
I started to enhance the “drive with keys” program and suddenly found that my test program was driving Dave very slowly. My original test program had masked a couple more places in the GoPiGo3 C++ API affected by the pickle that need attention.
I am very rusty in C++ and will have to review the Python API to find where ENCODER_TICKS need to be applied, then relearn enough C++ to make the changes. Eventually, I will submit a new pull request that gets the GoPiGo3 C++ API out of this pickle.
Example: set_motor_dps()
- In Python:
def set_motor_dps(self, port, dps):
"""
Set the motor target speed in degrees per second
Keyword arguments:
port -- The motor port(s). MOTOR_LEFT and/or MOTOR_RIGHT.
dps -- The target speed in degrees per second
"""
dps = int(dps * self.MOTOR_TICKS_PER_DEGREE) <<---- OH MY, DPS is no longer DPS
outArray = [self.SPI_Address, self.SPI_MESSAGE_TYPE.SET_MOTOR_DPS, int(port),\
((dps >> 8) & 0xFF), (dps & 0xFF)]
self.spi_transfer_array(outArray)
NOTE that the “dps” sent in the SET_MOTOR_DPS message to the red board is actually DPS times MOTOR_TICKS_PER_DEGREE - Lesson: don’t read the words, read the code.
- The C++ API (sends DPS without conversion for Ticks):
int GoPiGo3::set_motor_dps(uint8_t port, int16_t dps){
spi_array_out[0] = Address;
spi_array_out[1] = GPGSPI_MESSAGE_SET_MOTOR_DPS;
spi_array_out[2] = port;
spi_array_out[3] = ((dps >> 8) & 0xFF); <<-- here the real DPS is sent in the message
spi_array_out[4] = (dps & 0xFF);
return spi_transfer_array(5, spi_array_out, spi_array_in);
}
That’s on the commanding side “set_motor_dps”; all the get_ functions that deal with encoders have to be made aware of the pickle.
p.s. My original test program used NO_LIMIT_SPEED which is 1000 DPS. The GoPiGo3 won’t do 1000 DPS but passing 1000 on a “6-Tick Motor” still gets 500 DPS and on a “16-Tick Motor” gets 186 DPS which is a good test speed. When I tried commanding Dave for 150 DPS in C++, he only goes forward at 28 DPS which is slower than an Alaskan glacier.