So,
Here we are again trying to make something that works well, work better!
Please view the video:
So, that is the bot but smaller. It is not a mower but has four, bidirectional DC Motors that work together to move the bot in an almost frictionless movement.
The software is here:
# /*
# * MotorBridge.py
# * This is a library for BBG/BBB motor bridge cape
# *
# * Copyright (c) 2015 seeed technology inc.
# * Author : Jiankai Li
# * Create Time : Nov 2015
# * Change Log : From #beagle on Freenode and my changes (Seth 2019)!
# *
# * The MIT License (MIT)
# *
# * Permission is hereby granted, free of charge, to any person obtaining a copy
# * of this software and associated documentation files (the "Software"), to deal
# * in the Software without restriction, including without limitation the rights
# * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# * copies of the Software, and to permit persons to whom the Software is
# * furnished to do so, subject to the following conditions:
# *
# * The above copyright notice and this permission notice shall be included in
# * all copies or substantial portions of the Software.
# *
# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# * THE SOFTWARE.
# */
# FileName : MotorBridge.py
# by Jiankai.li
# w/ help from additions from #beagle on what used to be Freenode and me (Seth)!
from smbus2 import SMBus
import time
import pathlib
# reset pin is P9.23, i.e. gpio1.17
reset_pin = pathlib.Path('/sys/class/gpio/gpio49/direction')
reset_pin.write_text('low')
MotorBridge = SMBus('/dev/i2c-2')
ReadMode = 0
WriteMode = 1
DeAddr = 0X4B
ConfigValid = 0x3a6fb67c
DelayTime = 0.005
# TB_WORKMODE
TB_SHORT_BREAK = 0
TB_CW = 1
TB_CCW = 2
TB_STOP = 3
TB_WORKMODE_NUM = 4
# TB_PORTMODE
TB_DCM = 0
TB_SPM = 1
TB_PORTMODE_NUM = 2
# SVM_PORT
SVM1 = 0
SVM2 = 1
SVM3 = 2
SVM4 = 3
SVM5 = 4
SVM6 = 5
SVM_PORT_NUM = 6
# SVM_STATE
SVM_DISABLE = 0
SVM_ENABLE = 1
SVM_STATE_NUM = 2
# IO_MODE
IO_IN = 0
IO_OUT = 1
IO_MODE_NUM = 2
# IO_PUPD
IO_PU = 0
IO_PD = 1
IO_NP = 2
IO_PUPD_NUM = 3
# IO_PPOD
IO_PP = 0
IO_OD = 1
IO_PPOD_NUM = 2
# IO_STATE
IO_LOW = 0
IO_HIGH = 1
IO_STATE_NUM = 2
# IO_PORT
IO1 = 0
IO2 = 1
IO3 = 2
IO4 = 3
IO5 = 4
IO6 = 5
IO_NUM = 6
# PARAM_REG
CONFIG_VALID = 0
CONFIG_TB_PWM_FREQ = CONFIG_VALID + 4
I2C_ADDRESS = CONFIG_TB_PWM_FREQ + 4
TB_1A_MODE = I2C_ADDRESS + 1
TB_1A_DIR = TB_1A_MODE + 1
TB_1A_DUTY = TB_1A_DIR + 1
TB_1A_SPM_SPEED = TB_1A_DUTY + 2
TB_1A_SPM_STEP = TB_1A_SPM_SPEED + 4
TB_1B_MODE = TB_1A_SPM_STEP + 4
TB_1B_DIR = TB_1B_MODE + 1
TB_1B_DUTY = TB_1B_DIR + 1
TB_1B_SPM_SPEED = TB_1B_DUTY + 2
TB_1B_SPM_STEP = TB_1B_SPM_SPEED + 4
TB_2A_MODE = TB_1B_SPM_STEP + 4
TB_2A_DIR = TB_2A_MODE + 1
TB_2A_DUTY = TB_2A_DIR + 1
TB_2A_SPM_SPEED = TB_2A_DUTY + 2
TB_2A_SPM_STEP = TB_2A_SPM_SPEED + 4
TB_2B_MODE = TB_2A_SPM_STEP + 4
TB_2B_DIR = TB_2B_MODE + 1
TB_2B_DUTY = TB_2B_DIR + 1
TB_2B_SPM_SPEED = TB_2B_DUTY + 2
TB_2B_SPM_STEP = TB_2B_SPM_SPEED + 4
SVM1_STATE = TB_2B_SPM_STEP + 4
SVM1_FREQ = SVM1_STATE + 1
SVM1_ANGLE = SVM1_FREQ + 2
SVM2_STATE = SVM1_ANGLE + 2
SVM2_FREQ = SVM2_STATE + 1
SVM2_ANGLE = SVM2_FREQ + 2
SVM3_STATE = SVM2_ANGLE + 2
SVM3_FREQ = SVM3_STATE + 1
SVM3_ANGLE = SVM3_FREQ + 2
SVM4_STATE = SVM3_ANGLE + 2
SVM4_FREQ = SVM4_STATE + 1
SVM4_ANGLE = SVM4_FREQ + 2
SVM5_STATE = SVM4_ANGLE + 2
SVM5_FREQ = SVM5_STATE + 1
SVM5_ANGLE = SVM5_FREQ + 2
SVM6_STATE = SVM5_ANGLE + 2
SVM6_FREQ = SVM6_STATE + 1
SVM6_ANGLE = SVM6_FREQ + 2
IO1_STATE = SVM6_ANGLE + 2
IO1_MODE = IO1_STATE + 1
IO1_PUPD = IO1_MODE + 1
IO1_PPOD = IO1_PUPD + 1
IO2_STATE = IO1_PPOD + 1
IO2_MODE = IO2_STATE + 1
IO2_PUPD = IO2_MODE + 1
IO2_PPOD = IO2_PUPD + 1
IO3_STATE = IO2_PPOD + 1
IO3_MODE = IO3_STATE + 1
IO3_PUPD = IO3_MODE + 1
IO3_PPOD = IO3_PUPD + 1
IO4_STATE = IO3_PPOD + 1
IO4_MODE = IO4_STATE + 1
IO4_PUPD = IO4_MODE + 1
IO4_PPOD = IO4_PUPD + 1
IO5_STATE = IO4_PPOD + 1
IO5_MODE = IO5_STATE + 1
IO5_PUPD = IO5_MODE + 1
IO5_PPOD = IO5_PUPD + 1
IO6_STATE = IO5_PPOD + 1
IO6_MODE = IO6_STATE + 1
IO6_PUPD = IO6_MODE + 1
IO6_PPOD = IO6_PUPD + 1
PARAM_REG_NUM = IO6_PPOD + 1
def WriteByte(Reg,Value):
data = [0 for i in range(2)]
data[0] = Reg
data[1] = Value
MotorBridge.write_i2c_block_data(0x4b, 1, data)
def WriteHalfWord(Reg,Value):
data = [0 for i in range(3)]
data[0] = Reg
data[1] = Value & 0xff
data[2] = (Value>>8) & 0xff
MotorBridge.write_i2c_block_data(0x4b, 1, data)
def WriteOneWord(Reg,Value):
data = [0 for i in range(5)]
data[0] = Reg
data[1] = Value & 0xff
data[2] = (Value>>8) & 0xff
data[3] = (Value>>16) & 0xff
data[4] = (Value>>24) & 0xff
MotorBridge.write_i2c_block_data(0x4b, 1, data)
def SetDefault():
WriteOneWord(CONFIG_VALID,0x00000000)
class MotorBridgeCape:
def __init__(self):
reset_pin.write_text('high')
time.sleep(1)
# init stepper motor A
def StepperMotorAInit(self):
WriteByte(TB_1A_MODE,TB_SPM) #Stepper
time.sleep(DelayTime)
WriteHalfWord(TB_1A_DUTY,1000) # voltage
time.sleep(DelayTime)
# MoveSteps > 0 CW
# MoveSteps < 0 CCW
# StepDelayTime : delay time for every step. uint us
def StepperMotorAMove(self,MoveSteps,StepDelayTime):
if MoveSteps > 0:
WriteByte(TB_1A_DIR,TB_CW) #CW
else:
WriteByte(TB_1A_DIR,TB_CCW) #CW
MoveSteps = -MoveSteps
time.sleep(DelayTime)
WriteOneWord(TB_1A_SPM_SPEED,StepDelayTime) # unit us
time.sleep(DelayTime)
WriteOneWord(TB_1A_SPM_STEP,MoveSteps)
time.sleep(DelayTime)
# init stepper motor B
def StepperMotorBInit(self):
WriteByte(TB_2A_MODE,TB_SPM) #Stepper
time.sleep(DelayTime)
WriteHalfWord(TB_2A_DUTY,1000) # voltage
time.sleep(DelayTime)
# MoveSteps > 0 CW
# MoveSteps < 0 CCW
# StepDelayTime : delay time for every step. uint us
def StepperMotorBMove(self,MoveSteps,StepDelayTime):
if MoveSteps > 0:
WriteByte(TB_2A_DIR,TB_CW) #CW
else:
WriteByte(TB_2A_DIR,TB_CCW) #CW
MoveSteps = -MoveSteps
time.sleep(DelayTime)
WriteOneWord(TB_2A_SPM_SPEED,StepDelayTime) # unit us
time.sleep(DelayTime)
WriteOneWord(TB_2A_SPM_STEP,MoveSteps)
time.sleep(DelayTime)
# Init DC Motor
def DCMotorInit(self,MotorName,Frequency):
# Init the DC Frequency
WriteOneWord(CONFIG_TB_PWM_FREQ,Frequency)
time.sleep(DelayTime)
# Set the port as DC Motor
if MotorName == 1 or MotorName == 2:
WriteByte(TB_1A_MODE,TB_DCM)
time.sleep(DelayTime)
WriteByte(TB_1A_DIR,TB_STOP)
time.sleep(DelayTime)
WriteByte(TB_1B_MODE,TB_DCM)
time.sleep(DelayTime)
WriteByte(TB_1B_DIR,TB_STOP)
time.sleep(DelayTime)
if MotorName == 3 or MotorName == 4:
WriteByte(TB_2A_MODE,TB_DCM)
time.sleep(DelayTime)
WriteByte(TB_2A_DIR,TB_STOP)
time.sleep(DelayTime)
WriteByte(TB_2B_MODE,TB_DCM)
time.sleep(DelayTime)
WriteByte(TB_2B_DIR,TB_STOP)
time.sleep(DelayTime)
# Drive the DC Motor
# Direction 1 CW | 2 CCW
# PWNDuty 0 ~ 100
def DCMotorMove(self, MotorName,Direction,PWMDuty):
if MotorName == 1:
WriteByte(TB_1B_DIR,Direction)
time.sleep(DelayTime)
WriteOneWord(TB_1B_DUTY,PWMDuty*10)
time.sleep(DelayTime)
if MotorName == 2:
WriteByte(TB_1A_DIR,Direction)
time.sleep(DelayTime)
WriteOneWord(TB_1A_DUTY,PWMDuty*10)
time.sleep(DelayTime)
if MotorName == 3:
WriteByte(TB_2B_DIR,Direction)
time.sleep(DelayTime)
WriteOneWord(TB_2B_DUTY,PWMDuty*10)
time.sleep(DelayTime)
if MotorName == 4:
WriteByte(TB_2A_DIR,Direction)
time.sleep(DelayTime)
WriteOneWord(TB_2A_DUTY,PWMDuty*10)
time.sleep(DelayTime)
# Stop the DC motor
def DCMotorStop(self, MotorName):
if MotorName == 1:
WriteByte(TB_1B_DIR,TB_STOP)
if MotorName == 2:
WriteByte(TB_1A_DIR,TB_STOP)
if MotorName == 3:
WriteByte(TB_2B_DIR,TB_STOP)
if MotorName == 4:
WriteByte(TB_2A_DIR,TB_STOP)
time.sleep(DelayTime)
# init the Servo
def ServoInit(self,ServoName,Frequency):
if ServoName == 1:
WriteHalfWord(SVM1_FREQ,Frequency)
time.sleep(DelayTime)
WriteByte(SVM1_STATE,SVM_ENABLE)
time.sleep(DelayTime)
if ServoName == 2:
WriteHalfWord(SVM2_FREQ,Frequency)
time.sleep(DelayTime)
WriteByte(SVM2_STATE,SVM_ENABLE)
time.sleep(DelayTime)
if ServoName == 3:
WriteHalfWord(SVM3_FREQ,Frequency)
time.sleep(DelayTime)
WriteByte(SVM3_STATE,SVM_ENABLE)
time.sleep(DelayTime)
if ServoName == 4:
WriteHalfWord(SVM4_FREQ,Frequency)
time.sleep(DelayTime)
WriteByte(SVM4_STATE,SVM_ENABLE)
time.sleep(DelayTime)
if ServoName == 5:
WriteHalfWord(SVM5_FREQ,Frequency)
time.sleep(DelayTime)
WriteByte(SVM5_STATE,SVM_ENABLE)
time.sleep(DelayTime)
if ServoName == 6:
WriteHalfWord(SVM6_FREQ,Frequency)
time.sleep(DelayTime)
WriteByte(SVM6_STATE,SVM_ENABLE)
time.sleep(DelayTime)
def ServoMoveAngle(self,ServoName,Angle):
if ServoName == 1:
WriteHalfWord(SVM1_ANGLE,Angle)
time.sleep(DelayTime)
if ServoName == 2:
WriteHalfWord(SVM2_ANGLE,Angle)
time.sleep(DelayTime)
if ServoName == 3:
WriteHalfWord(SVM3_ANGLE,Angle)
time.sleep(DelayTime)
if ServoName == 4:
WriteHalfWord(SVM4_ANGLE,Angle)
time.sleep(DelayTime)
if ServoName == 5:
WriteHalfWord(SVM5_ANGLE,Angle)
time.sleep(DelayTime)
if ServoName == 6:
WriteHalfWord(SVM6_ANGLE,Angle)
time.sleep(DelayTime)
if __name__=="__main__":
print( 'Hello From MotorBridge' )
#motor = MotorBridgeCape()
#motor.StepperMotorBInit()
#while True:
#motor.StepperMotorBMove(1000,1000) # 20 steppers 1000us every step
#time.sleep(1)
#motor.StepperMotorBMove(-1000,1000) # 20 steppers 1000us every step
#time.sleep(1)
This is the library to use called MotorBridge.py that calls for SMBus2 that can be installed via pip3 or by python3 -m pip install smbus2 .
There is a small write up on Github.com about this particular Cape for beagleboard.org am335x family of boards located here: silver2row/bbg: Motor Bridge Cape and BBG (BeagleBone Green)/Python Scripts (github.com) .
The MBC or Motor Bridge Cape is hard to find these days. It carries a STM32F0 on it. and can handle four DC Motors or two steppers and then can handle six servo motors.
Line 302 on smbus2.py needs to be changed to look like this:
filepath = "/dev/i2c-2".format(bus)
Anyway, that video was from a year back. Let us see if it works w/ the current set up:
uname -r: 4.19.94-ti-r71
cat /etc/dogtag: BeagleBoard.org Debian Buster IoT Image 2020-04-06
This image can be attained from the beagleboard.org/latest-images wesbite or you can use their forum for searching for the new images they produce.
So, if you have any questions, good. If not, see ya!
oh! The next video:
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.