Making a Rpi Pico Based Smart Vehicle
ProjectsJun 3018 / 18Sep 105h ago1 MONTH LATER

I am drafting a test function to proving the concept of:
- Using a list of two interrupt event counts of this 2WD (later 4 counts for 4WD).
- Using only one callback function for 2WD’s two interrupt pins.
# *** Interrupt Functions ***
# *** Interrupt Event Variables and Service Routines ***
# *** Setup Motor and Vehicle ***
def setupMotorV2(motorDriverDictNum, motorNum):
motorDriverDict = motorDriverDictDict[str(motorDriverDictNum)] # Get driver dict
driverStandBy = Pin(motorDriverDict['STANDBY'], Pin.OUT) # create driverStandBy pin object
motorIn1 = Pin(motorDriverDict[str(motorNum)]['IN1'], Pin.OUT) # Create Motor # motorNum In1 pin object
motorIn2 = Pin(motorDriverDict[str(motorNum)]['IN2'], Pin.OUT) # Create Motor # motorNum In2 pin object
motorPwm = PWM(Pin(motorDriverDict[str(motorNum)]['PWM'])) # Create Motor # motorNum Pwm pin object
motorEncode = Pin(motorDriverDict[str(motorNum)]['ENCODE'], Pin.IN, Pin.PULL_DOWN) # Create Motor # motorNum Encode pin object
motorPwmFreq = motorDriverDict[str(motorNum)]['DEFAULT_PWM_FREQ']
motorDutyCycle = motorDriverDict[str(motorNum)]['DEFAULT_DUTY_CYCLE']
motorEncodeIntCount = 0
motorConfigDict = {'StdBy': driverStandBy, 'In1': motorIn1, 'In2': motorIn2, 'Pwm': motorPwm, 'Encode': motorEncode}
motorConfigDict['StdBy'].high() # enable motor driver normal operation, (low = disable)
motorConfigDict['Pwm'].freq(motorPwmFreq) # setup frequency
motorConfigDict['Pwm'].duty_u16(int(65536 / 100) * motorDutyCycle) # and duty cycle
motorStateDict = {'PwmFreq': motorPwmFreq, 'DutyCycle': motorDutyCycle, 'MotorEncodeIntCount': motorEncodeIntCount}
motorDict = {'MOTOR_CONFIG_DICT': motorConfigDict, 'MOTOR_STATE_DICT': motorStateDict}
stopMotor(motorConfigDict)
return motorDict
def setupVehicleV2(vehicleNum):
print(' setupVehicle(), ...')
motorDriverDictNum = vehicleDictDict[str(vehicleNum)]['MOTOR_DRIVER_DICT_NUM']
frontLeftMotorDict = setupMotorV2(motorDriverDictNum, 1)
frontRightMotorDict = setupMotorV2(motorDriverDictNum, 2)
frontLeftMotorInterruptPin = frontLeftMotorDict['MOTOR_CONFIG_DICT']['Encode']
frontRightMotorInterruptPin = frontRightMotorDict['MOTOR_CONFIG_DICT']['Encode']
motorInterruptPinList = [frontLeftMotorInterruptPin, frontRightMotorInterruptPin]
vehicleDict = {'FRONT_LEFT_MOTOR': frontLeftMotorDict, 'FRONT_RIGHT_MOTOR': frontRightMotorDict, 'INTERRUPT_PIN_LIST': motorInterruptPinList}
return vehicleDict
def testSyncTwoVehicleWheels():
print('testSyncTwoVehicleWheels(), ...')
# *** This function reads one of the interrupt count list ***
def readMotorEncodeIntCount(countNum):
return motorEncodeIntCount[countNum]
# *** motorEncodeCallBack ***
# Notes:
# This callback function is a bit too clever to understand. All motor interrupt pins will trigger this callback.
# The callback will find which interrupt pin interrupts, then increment the corresponding element of the int count list.
def motorEncodeIntCallBack(pin):
index = interruptPinList.index(pin)
motorEncodeIntCountList[index] += 1
return
vehicleDict = setupVehicleV2(vehicleNum = 1)
vehicleDict['INTERRUPT_PIN_LIST'][0].irq(motorEncodeIntCallBack, Pin.IRQ_FALLING)
vehicleDict['INTERRUPT_PIN_LIST'][1].irq(motorEncodeIntCallBack, Pin.IRQ_FALLING)
#print(' motorEncodeIntServiceRoutine[2] =', motorEncodeIntCountList[2])
return
# *** Main Tests ***
#testMoveVehicleForwardBackwardTurnLeftTurnRight()
testSyncTwoVehicleWheels()
# End
I was jealous that PiTop4 can use mpu6050 gesture to control a robot. This morning I read how to do it. So I might try later to use my smart phone to control my smart robot, to say, first walk in a straight line.
Raspberry Pi Pico Controls Robot with Smartphone Accelerometer – Ash Hill, 2021sep07Tom’s Hardware – 6 Sep 21

Raspberry Pi Pico Controls Robot with Smartphone Accelerometer
It’s like Kirby Tilt and Tumble but without Kirby and your Game Boy is a phone.
Raspberry Pi: Python Libraries for I2C, SPI, UART – Sebastian Günther, 2021sep06DEV Community

Raspberry Pi: Python Libraries for I2C, SPI, UART
The Raspberry Pi is one of the most popular single board computers for hobbyists. Its 40 Pins support…
I feel jealous that some smart guy has a smart 4WD, while mine is only a stupid looking 2WD, which should damage my reputation. So I am stalling my 2WD project and go build a smart 4WD. Stay tuned. See you later.four_wheel_drive_2021sep07021192×751 229 KB
Scaling up 2WD to 4WD
So there you are, 2WD becomes 4WD!

# Program Name
# spv5013_2021sep0603.py - tlfong01 2021sep06hkt1802
# Reference
# Pi-Top Forum - making-a-rpi-pico-based-smart-vehicle/924
# https://forum.pi-top.com/t/making-a-rpi-pico-based-smart-vehicle/924
#
# Configuration
# Acer Aspire XC-780 Intel CORE i5-6400 2.7GHz, 8GB, Chinese Windows 10 Home (64-bit, 2020nov15),
# Thonny 3.3.3, Python 3.7.9 (32-bit), Tk 8.6.9, USB COM Port #4
#
# Thonny MicroPython Intepreter
# Micropython (Rapsberry Pi Pico)
#
# DC Motor
# TT130 1:48 gear motor
# 9.0V = 350mA = 240uS = 70rpm
# 7.2V = 270mA = 300us = 55rpm
# 6.0V = 250mA = 340us = 49rpm
# 4.5V = 200mA = 400us = 42rpm
# 3.0V = 150mA = 660us = 25rpm
# N20 1:100 6V DC Gear Motor with quadrature encoder signals A, B
# N20 Gear Motor Spec (6V gear 1:100 no load speed = 300 rpm (https://www.pololu.com/search/compare/173)
#
# DC Motor Driver
# TB6612FNG Dual DC Motor Driver
# Brief Description of Program Function
# 1. Move DC motor forward, backware, stop.
# 2. Use PWM to control motor speed
# 3. Use motor encoder to measure speed
# 4. Use encoder signals to help driving a 2WD to move in a straight line
# Digital Oscilloscope ATTEN ADS1102CAL+
# https://toolboom.com/en/digital-oscilloscope-atten-ads1102calplus/
# ATTEN ADS100 User Manual
# https://micromir.ucoz.ru/Oscil/Atten/ADS1000_User_Manual.pdf
import utime
from machine import Pin, PWM
# ========= ========= ========= ========= ========= ========= ========= =========
# ========= ========= ========= ========= ========= ========= ========= =========
# ========= ========= ========= ========= ========= ========= ========= =========
# ========= ========= ========= ========= ========= ========= ========= =========
# *** Motor Level Config and Functions ***
# *** Motor Dicts ***
motorDriverDict02 = {
'TITLE' : 'TB6612FNG Dual DC Motor Driver Dictionary v0.2 tlfong01 2021aug23hkt1009',
'STANDBY' : 5,
'1': {'IN1': 10, 'IN2': 11, 'PWM' : 3, 'ENCODE': 14, \
'DEFAULT_PWM_FREQ': 1000, 'DEFAULT_DUTY_CYCLE': 50, 'DEFAULT_ENCODE_INT_PULSE_PER_REVOLUTION': 980},
'2': {'IN1': 12, 'IN2': 13, 'PWM' : 4, 'ENCODE': 15, \
'DEFAULT_PWM_FREQ': 1000, 'DEFAULT_DUTY_CYCLE': 50, 'DEFAULT_ENCODE_INT_PULSE_PER_REVOLUTION': 980},
'3': {'IN1': 0, 'IN2': 0, 'PWM' : 0, 'ENCODE': 0, \
'DEFAULT_PWM_FREQ': 1000, 'DEFAULT_DUTY_CYCLE': 50, 'DEFAULT_ENCODE_INT_PULSE_PER_REVOLUTION': 980},
'4': {'IN1': 0, 'IN2': 0, 'PWM' : 0, 'ENCODE': 0, \
'DEFAULT_PWM_FREQ': 1000, 'DEFAULT_DUTY_CYCLE': 50, 'DEFAULT_ENCODE_INT_PULSE_PER_REVOLUTION': 980},
}
motorDriverDictDict = {
'1': motorDriverDict02,
'2': motorDriverDict02,
}
# *** Motor Functions ***
def setupMotor(motorDriverDictNum, motorNum):
motorDriverDict = motorDriverDictDict[str(motorDriverDictNum)] # Get driver dict
driverStandBy = Pin(motorDriverDict['STANDBY'], Pin.OUT) # create driverStandBy pin object
motorIn1 = Pin(motorDriverDict[str(motorNum)]['IN1'], Pin.OUT) # Create Motor # motorNum In1 pin object
motorIn2 = Pin(motorDriverDict[str(motorNum)]['IN2'], Pin.OUT) # Create Motor # motorNum In2 pin object
motorPwm = PWM(Pin(motorDriverDict[str(motorNum)]['PWM'])) # Create Motor # motorNum Pwm pin object
motorEncode = Pin(motorDriverDict[str(motorNum)]['ENCODE'], Pin.IN, Pin.PULL_DOWN) # Create Motor # motorNum Encode pin object
motorPwmFreq = motorDriverDict[str(motorNum)]['DEFAULT_PWM_FREQ']
motorDutyCycle = motorDriverDict[str(motorNum)]['DEFAULT_DUTY_CYCLE']
motorEncIntCntRev = motorDriverDict[str(motorNum)]['DEFAULT_ENCODE_INT_PULSE_PER_REVOLUTION']
motorConfigDict = {'StdBy': driverStandBy, 'In1': motorIn1, 'In2': motorIn2, 'Pwm': motorPwm, 'Encode': motorEncode}
motorStateDict = {'PwmFreq': motorPwmFreq, 'DutyCycle': motorDutyCycle, 'EncodeIntCntRev': motorEncIntCntRev}
motorDict = {'MOTOR_CONFIG_DICT': motorConfigDict, 'MOTOR_STATE_DICT': motorStateDict}
motorConfigDict['StdBy'].high() # enable motor driver normal operation, (low = disable)
motorConfigDict['Pwm'].freq(motorStateDict['PwmFreq']) # setup frequency
motorConfigDict['Pwm'].duty_u16(int(65536 / 100) * motorStateDict['DutyCycle']) # and duty cycle
stopMotor(motorConfigDict)
return motorDict
def changeMotorPwmFreqAndDutyCycle(motorDict, pwmFreq, dutyCycle):
motorStateDict = motorDict['MOTOR_STATE_DICT']
motorStateDict['PwmFreq'] = pwmFreq
motorStateDict['DutyCycle'] = dutyCycle
motorConfigDict = motorDict['MOTOR_CONFIG_DICT']
motorConfigDict['Pwm'].freq(motorStateDict['PwmFreq'])
motorConfigDict['Pwm'].duty_u16(int(65536 / 100) * motorStateDict['DutyCycle'])
return
def stopMotor(motorConfigDict):
motorConfigDict['In1'].low()
motorConfigDict['In2'].low()
return
def moveMotorForwardNonStop(motorConfigDict):
motorConfigDict['In1'].low() # move motor
motorConfigDict['In2'].high() # backward
return
def moveMotorForwardSeconds(motorConfigDict, moveSeconds):
moveMotorForwardNonStop(motorConfigDict)
utime.sleep(moveSeconds)
stopMotor(motorConfigDict)
return
def moveMotorForwardHoldTime(motorConfigDict, holdTime):
moveMotorForwardNonStop(motorConfigDict)
utime.sleep(holdTime)
stopMotor(motorConfigDict)
return
def moveMotorBackwardNonStop(motorConfigDict):
motorConfigDict['In1'].high() # move motor
motorConfigDict['In2'].low() # backward
return
def moveMotorBackwardSeconds(motorConfigDict, moveSeconds):
moveMotorBackwardNonStop(motorConfigDict)
utime.sleep(moveSeconds)
stopMotor(motorConfigDict)
return
# ========= ========= ========= ========= ========= ========= ========= =========
# ========= ========= ========= ========= ========= ========= ========= =========
# ========= ========= ========= ========= ========= ========= ========= =========
# ========= ========= ========= ========= ========= ========= ========= =========
# *** Interrupt Related Functions ***
def encodeIntCallBack(pin):
global encodeIntCount
encodeIntCount = encodeIntCount + 1
return
def readEncodeIntCount(motorDriverDictNum, motorNum, pwmFreq, dutyCycle, moveSeconds):
motorDict = setupMotor(motorDriverDictNum, motorNum)
motorStateDict = motorDict['MOTOR_STATE_DICT']
motorConfigDict = motorDict['MOTOR_CONFIG_DICT']
changeMotorPwmFreqAndDutyCycle(motorDict, pwmFreq, dutyCycle)
motorConfigDict['Encode'].irq(encodeIntCallBack, Pin.IRQ_FALLING)
global encodeIntCount
encodeIntCount = 0
moveMotorForwardNonStop(motorConfigDict)
utime.sleep(moveSeconds)
stopMotor(motorConfigDict)
totalEncodeIntCount = encodeIntCount
return totalEncodeIntCount
# *** Move revoloutions and distance ***
def moveMotorEncodeIntCount(motorDriverDictNum, motorNum, encodeIntCount):
motorDict = setupMotor(motorDriverDictNum, motorNum)
motorConfigDict = motorDict['MOTOR_CONFIG_DICT']
#intCountPerSecond = 983
intCountPerSecond = 750
print(' encodeIntCount =', encodeIntCount)
print(' intCountPerSecond =', intCountPerSecond)
moveSeconds = encodeIntCount / intCountPerSecond
print(' moveSeconds =', moveSeconds)
moveMotorForwardNonStop(motorConfigDict)
utime.sleep(moveSeconds)
stopMotor(motorConfigDict)
return
def moveMotorRevolutions(motorDriverDictNum, motorNum, revolutions):
motorDict = setupMotor(motorDriverDictNum, motorNum)
motorConfigDict = motorDict['MOTOR_CONFIG_DICT']
intCountPerRevolution = 983
intCountPerSecond = 750
moveSeconds = (revolutions * intCountPerRevolution) / intCountPerSecond
print(' intCountPerRevolution =', intCountPerRevolution)
print(' intCountPerSecond =', intCountPerSecond)
print(' moveSeconds =', moveSeconds)
moveMotorForwardNonStop(motorConfigDict)
utime.sleep(moveSeconds)
stopMotor(motorConfigDict)
return
# *** Test Functions ***
def testMoveMotorForwardSeconds(motorDriverDictNum, motorNum, moveSeconds):
print('\ntestmoveMotorForwardSeconds()')
motorDict = setupMotor(motorDriverDictNum, motorNum)
motorConfigDict = motorDict['MOTOR_CONFIG_DICT']
moveMotorForwardSeconds(motorConfigDict, moveSeconds)
stopMotor(motorConfigDict)
return
def testMoveMotorBackwardSeconds(motorDriverDictNum, motorNum, moveSeconds):
print('\ntestMoveMotorBackwardSeconds()')
motorDict = setupMotor(motorDriverDictNum, motorNum)
motorConfigDict = motorDict['MOTOR_CONFIG_DICT']
moveMotorBackwardSeconds(motorConfigDict, moveSeconds)
stopMotor(motorConfigDict)
return
def testChangeMotorPwmFreqAndDutyCycleAndmoveMotorForwardSeconds(motorDriverDictNum, motorNum, pwmFreq, dutyCycle, moveSeconds):
print('\ntestChangeMotorPwmFreqAndDutyCycleAndmoveMotorForwardSeconds()')
motorDict = setupMotor(motorDriverDictNum, motorNum)
changeMotorPwmFreqAndDutyCycle(motorDict, pwmFreq, dutyCycle)
motorConfigDict = motorDict['MOTOR_CONFIG_DICT']
print('moveSeconds =', moveSeconds)
moveMotorForwardSeconds(motorConfigDict, moveSeconds)
stopMotor(motorConfigDict)
return
def testMeasureMotorSpeed(motorDriverDictNum, motorNum, pwmFreq, dutyCycle):
totalEncodeIntCount = readEncodeIntCount(motorDriverDictNum, motorNum, pwmFreq, dutyCycle, moveSeconds = 1)
print('motorNum =', motorNum, end = '')
print(' pwmFreq =', pwmFreq, end = '')
print(' dutyCycle =', dutyCycle, end = '')
print(' totalEncodeIntCount Per Second =', totalEncodeIntCount, end = '')
print(' motor speed rpm =', int(int(totalEncodeIntCount * 60)/100))
return
def testMoveMotorEncodeIntCount(motorDriverDictNum, motorNum, encodeIntCount):
print('testMoveMotorEncodeIntCount(), ...')
moveMotorEncodeIntCount(motorDriverDictNum, motorNum, encodeIntCount)
return
def testMoveMotorRevolutions(motorDriverDictNum, motorNum, revolutions):
print('testMoveMotorRevolutions(), ...')
moveMotorRevolutions(motorDriverDictNum, motorNum, revolutions)
return
def testMeasureEncodeIntCountMoveSeconds(motorDriverDictNum, motorNum, pwmFreq, dutyCycle, moveSeconds):
encodeIntCount = readEncodeIntCount(motorDriverDictNum, motorNum, pwmFreq, dutyCycle, moveSeconds)
print('MotorDriverDictNum =', motorDriverDictNum, ' ', end = '')
print('MotorNum =', motorNum, ' ', end = '')
print('PWM Freq =', pwmFreq, ' ', end = '')
print('DutyCycle =', dutyCycle, ' ', end = '')
print('MoveSeconds =,', moveSeconds, ' ', end = '')
print('encodeIntCount =', encodeIntCount)
return encodeIntCount
def testStopMotor(motorDriverDictNum, motorNum):
motorDict = setupMotor(motorDriverDictNum, motorNum)
motorConfigDict = motorDict['MOTOR_CONFIG_DICT']
stopMotor(motorConfigDict)
return
# *** Old Main Tests ***
'''
testMoveMotorForwardSeconds(motorDriverDictNum = 2, motorNum = 1, moveSeconds = 2)
testMoveMotorBackwardSeconds(motorDriverDictNum = 2, motorNum = 2, moveSeconds = 4)
testChangeMotorPwmFreqAndDutyCycleAndmoveMotorForwardSeconds(motorDriverDictNum = 2, motorNum = 1 , \ pwmFreq = 1000, dutyCycle = 10, moveSeconds = 2)
testChangeMotorPwmFreqAndDutyCycleAndmoveMotorForwardSeconds(motorDriverDictNum = 2, motorNum = 1 , \
pwmFreq = 1000, dutyCycle = 90, moveSeconds = 1)
testMeasureMotorSpeed(motorDriverDictNum = 2, motorNum = 1, pwmFreq = 1000, dutyCycle = 80)
testMeasureMotorSpeed(motorDriverDictNum = 2, motorNum = 1, pwmFreq = 1000, dutyCycle = 10)
testMoveMotorEncodeIntCount(motorDriverDictNum = 2, motorNum = 1, encodeIntCount = 1020)
testMoveMotorEncodeIntCount(motorDriverDictNum = 2, motorNum = 2, encodeIntCount = 1920)
testMoveMotorRevolutions(motorDriverDictNum = 2, motorNum = 1, revolutions = 1)
testMeasureEncodeIntCountMoveSeconds(motorDriverDictNum = 2, motorNum = 1, pwmFreq = 1000, dutyCycle = 100, moveSeconds = 4)
testStopMotor(motorDriverDictNum = 2, motorNum = 1)
'''
# ========= ========= ========= ========= ========= ========= ========= =========
# ========= ========= ========= ========= ========= ========= ========= =========
# ========= ========= ========= ========= ========= ========= ========= =========
# ========= ========= ========= ========= ========= ========= ========= =========
#
# *** Vehicle Level Config and Functions ***
vehicleDict01 = {
'MOTOR_DRIVER_DICT_NUM': 2,
}
vehicleDictDict = {
'1': vehicleDict01,
'2': vehicleDict01,
}
# *** Vehicle and Wheel Functions ***
'''
def encodeIntCallBack(pin):
global encodeIntCount
encodeIntCount = encodeIntCount + 1
return
def readEncodeIntCount(motorDriverDictNum, motorNum, pwmFreq, dutyCycle, moveSeconds):
motorDict = setupMotor(motorDriverDictNum, motorNum)
motorStateDict = motorDict['MOTOR_STATE_DICT']
motorConfigDict = motorDict['MOTOR_CONFIG_DICT']
changeMotorPwmFreqAndDutyCycle(motorDict, pwmFreq, dutyCycle)
motorConfigDict['Encode'].irq(encodeIntCallBack, Pin.IRQ_FALLING)
global encodeIntCount
encodeIntCount = 0
moveMotorForwardNonStop(motorConfigDict)
utime.sleep(moveSeconds)
stopMotor(motorConfigDict)
totalEncodeIntCount = encodeIntCount
return totalEncodeIntCount
motorDriverDict02 = {
'TITLE' : 'TB6612FNG Dual DC Motor Driver Dictionary v0.2 tlfong01 2021aug23hkt1009',
'STANDBY' : 5,
'1': {'IN1': 10, 'IN2': 11, 'PWM' : 3, 'ENCODE': 14, \
'DEFAULT_PWM_FREQ': 1000, 'DEFAULT_DUTY_CYCLE': 50, 'DEFAULT_ENCODE_INT_PULSE_PER_REVOLUTION': 980},
'2': {'IN1': 12, 'IN2': 13, 'PWM' : 4, 'ENCODE': 15, \
'DEFAULT_PWM_FREQ': 1000, 'DEFAULT_DUTY_CYCLE': 50, 'DEFAULT_ENCODE_INT_PULSE_PER_REVOLUTION': 980},
'3': {'IN1': 0, 'IN2': 0, 'PWM' : 0, 'ENCODE': 0, \
'DEFAULT_PWM_FREQ': 1000, 'DEFAULT_DUTY_CYCLE': 50, 'DEFAULT_ENCODE_INT_PULSE_PER_REVOLUTION': 980},
'4': {'IN1': 0, 'IN2': 0, 'PWM' : 0, 'ENCODE': 0, \
'DEFAULT_PWM_FREQ': 1000, 'DEFAULT_DUTY_CYCLE': 50, 'DEFAULT_ENCODE_INT_PULSE_PER_REVOLUTION': 980},
}
'''
def setupVehicle(vehicleNum):
motorDriverDictNum = vehicleDictDict[str(vehicleNum)]['MOTOR_DRIVER_DICT_NUM']
frontLeftMotorDict = setupMotor(motorDriverDictNum, 1)
frontRightMotorDict = setupMotor(motorDriverDictNum, 2)
motorDictDict = {'FRONT_LEFT_MOTOR': frontLeftMotorDict, 'FRONT_RIGHT_MOTOR': frontRightMotorDict}
return motorDictDict
def moveVehicleMotorListForwardHoldTime(vehicleNum, holdTime):
motorDictDict = setupVehicle(vehicleNum)
frontLeftMotorConfigDict = motorDictDict['FRONT_LEFT_MOTOR']['MOTOR_CONFIG_DICT']
frontRightMotorConfigDict = motorDictDict['FRONT_RIGHT_MOTOR']['MOTOR_CONFIG_DICT']
motorConfigDictList = [frontLeftMotorConfigDict, frontRightMotorConfigDict]
for motorConfigDict in motorConfigDictList:
moveMotorForwardNonStop(motorConfigDict)
utime.sleep(holdTime)
for motorConfigDict in motorConfigDictList:
stopMotor(motorConfigDict)
return
def moveVehicleMotorListBackwardHoldTime(vehicleNum, holdTime):
motorDictDict = setupVehicle(vehicleNum)
frontLeftMotorConfigDict = motorDictDict['FRONT_LEFT_MOTOR']['MOTOR_CONFIG_DICT']
frontRightMotorConfigDict = motorDictDict['FRONT_RIGHT_MOTOR']['MOTOR_CONFIG_DICT']
motorConfigDictList = [frontLeftMotorConfigDict, frontRightMotorConfigDict]
for motorConfigDict in motorConfigDictList:
moveMotorBackwardNonStop(motorConfigDict)
utime.sleep(holdTime)
for motorConfigDict in motorConfigDictList:
stopMotor(motorConfigDict)
return
def turnTwoMotorsLeftHoldTime(frontLeftMotorConfigDict, frontReghtConfigDict, holdTime):
moveMotorForwardNonStop(frontLeftMotorConfigDict)
moveMotorBackward(frontRightMotorConfigDict)
utime.sleep(holdTime)
stopMotor(frontLeftMotorConfigDict)
stopMotor(frontRightMotorConfigDict)
return
def turnVehicleLeftHoldTime(vehicleNum, holdTime):
motorDictDict = setupVehicle(vehicleNum)
frontLeftMotorConfigDict = motorDictDict['FRONT_LEFT_MOTOR']['MOTOR_CONFIG_DICT']
frontRightMotorConfigDict = motorDictDict['FRONT_RIGHT_MOTOR']['MOTOR_CONFIG_DICT']
moveMotorForwardNonStop(frontLeftMotorConfigDict)
moveMotorBackwardNonStop(frontRightMotorConfigDict)
utime.sleep(holdTime)
stopMotor(frontLeftMotorConfigDict)
stopMotor(frontRightMotorConfigDict)
return
def turnVehicleRightHoldTime(vehicleNum, holdTime):
motorDictDict = setupVehicle(vehicleNum)
frontLeftMotorConfigDict = motorDictDict['FRONT_LEFT_MOTOR']['MOTOR_CONFIG_DICT']
frontRightMotorConfigDict = motorDictDict['FRONT_RIGHT_MOTOR']['MOTOR_CONFIG_DICT']
moveMotorBackwardNonStop(frontLeftMotorConfigDict)
moveMotorForwardNonStop(frontRightMotorConfigDict)
utime.sleep(holdTime)
stopMotor(frontLeftMotorConfigDict)
stopMotor(frontRightMotorConfigDict)
return
snipped … to avoid 32k word limit
def setupVehicleV2(vehicleNum):
print(' setupVehicle(), ...')
motorDriverDictNum = vehicleDictDict[str(vehicleNum)]['MOTOR_DRIVER_DICT_NUM']
frontLeftMotorDict = setupMotorV2(motorDriverDictNum, 1)
frontRightMotorDict = setupMotorV2(motorDriverDictNum, 2)
frontLeftMotorInterruptPin = frontLeftMotorDict['MOTOR_CONFIG_DICT']['Encode']
frontRightMotorInterruptPin = frontRightMotorDict['MOTOR_CONFIG_DICT']['Encode']
motorInterruptPinList = [frontLeftMotorInterruptPin, frontRightMotorInterruptPin]
vehicleDict = {'FRONT_LEFT_MOTOR': frontLeftMotorDict, 'FRONT_RIGHT_MOTOR': frontRightMotorDict, 'INTERRUPT_PIN_LIST': motorInterruptPinList}
return vehicleDict
def testSyncTwoVehicleWheels():
print('testSyncTwoVehicleWheels(), ...')
# *** This function reads one of the interrupt count list ***
def readMotorEncodeIntCount(countNum):
return motorEncodeIntCount[countNum]
# *** motorEncodeCallBack ***
# Notes:
# This callback function is a bit too clever to understand. All motor interrupt pins will trigger this callback.
# The callback will find which interrupt pin interrupts, then increment the corresponding element of the int count list.
def motorEncodeIntCallBack(pin):
index = interruptPinList.index(pin)
motorEncodeIntCountList[index] += 1
return
vehicleDict = setupVehicleV2(vehicleNum = 1)
vehicleDict['INTERRUPT_PIN_LIST'][0].irq(motorEncodeIntCallBack, Pin.IRQ_FALLING)
vehicleDict['INTERRUPT_PIN_LIST'][1].irq(motorEncodeIntCallBack, Pin.IRQ_FALLING)
#print(' motorEncodeIntServiceRoutine[2] =', motorEncodeIntCountList[2])
return
# *** Main Tests ***
#testMoveVehicleForwardBackwardTurnLeftTurnRight()
#testSyncTwoVehicleWheels()
#testTurnVehicleLeftHoldTime()
testMoveMotorForwardSeconds(motorDriverDictNum = 2, motorNum = 1, moveSeconds = 10)
TM310 DC Motor Calibration
TT DC Gear Reduced Motor with Encoder for Smart Car DIY – AliExpress US$5aliexpress.com
4.8US $ |TT DC Gear Reduced Motor with Encoder for Smart Car DIY or Mecanum…
Smarter Shopping, Better Living! Aliexpress.com
Spec:
Rated voltage: DC 9V
No-load current: 100mA
Stall current: 1.2A
No-load speed: 8000 rpm
Suitable voltage: 6-12V
Reduction ratio: 1:48/1:90
tm310_test_2021sep0801800×480 145 KB
tm310_test_2021sep08011024×748 274 KB
TM310 Motor #1 and #2 Speed Discrepancy
So I calibrated the second motor. I found the speeds of the second motor is very close to the first one; both encoder signals measure almost “exactly” 300uS.
This is very good news, because it means that it is practical and easy to sync two motors (bought by same order, therefore very likely from the same production lot from the manufacturer), by adjusting PWM duty cycle.
The second motor’s encoder AB signals at 12V power are displayed below.
tm310_2_test_2021sep0801800×480 135 KB
Adding WS2812b NeoPixels LEDs to my 4WD
Now I am thinking of adding NeoPixels to my smart 4WD.Python Awesome – 8 Sep 21 1

A library for using WS2812b leds (aka neopixels) with Raspberry Pi Pico 1
A library for using WS2812b leds (aka neopixels) with Raspberry Pi Pico
This pico relay module looks good. I hope to get on and mount it on my smart pico.The Pi Hut
Industrial 8-Channel Relay Module for Raspberry Pi Pico
Utilise the Raspberry Pi Pico in industrial or home automation environments with this robust Industrial 8-Channel Relay Module! This module provides 8 relay channels which can each switch up to 10A 250VAC or 10A 30V DC max. The module offers safety…
Price: GBP 17.00
MT310 Encoder Motor #3 Calibration Notes
So I checked out MT310 #3. It seems too good to be true that this third motor’s encoder A signal is also almost exactly 300uS. Now I need to display all 4 motor’s encoder A signals together, at the same time, and and see if there is any tiny difference of the A signal periods. I still think now it is too good to be true, or there are some critical mistake I have made in the calibrations.tm310_3_test_2021sep0802800×480 142 KB
MT310 Motor #4 12V power Speed Measurement
So I checked out Motor 4. I was glad to see the that that encoder Signal is now 290us, not 300us as other three. If all 4 motors were axactly 300us, than is was too good to be true. Now (300 – 290) / 300 ~= 0.3% speed difference. I guess it should be easy to adjust the duty cycle of either motor to get same speed. (Apology: it should not be called “in sync” which is about time, but should be called speed matching, which is about speed.
tm310_04_test_2021sep1001800×480 137 KB
Note – I am hitting the forum’s 32k word limit again. So I need to make a new reply.

Speed measurement of 4 MT310 motors
The encoder A signal of Motor 4 has little glitches. I need to display all 4 A signals together, at the same time, to see if this switching noise/glitches is common to all 4 motors, or just Motor 4.
Now I am doing the following speed measurements.
- All 4 MT310 motors powered by the same 12V DC.
- All 4 MT310 motor encoder powered by the same 5VDC.
- Use 30MHz 4 channel scope to display the 4 encoder A signals.
- Check if the A signals have almost identical, say, 300uS period.
MT310 Encoder Motor x 4 powered by 12VDC moving at the same time

4WD TM310 1:90 Encoder 12ppr powered by 12VDC
I am happy to see my 4 channel scope displaying the 4 motors’ encoder A signals all showing roughly 300us period pulses. I am not going to take pulse period measurements by hand and then calculate the corresponding speeds, because my next step is to use Thonny micropython to detect the encoder A signals as interrupt events and count them to calculate very precise speed values.tm310_4wd_test_2021sep1001800×480 173 KB
/ to continue, …
Categories: Uncategorized