Hello,
Hmm. I have been trying to get my Motor Bridge Cape to work recently for a Maker Faire coming up. If all else fails, I will try to get the BBBW and MotorCape working again.
…
So, w/out further ado, here is the source:
`
/*
* MotorBridge.py
* This is a library for BBG/BBB motor bridge cape
*
* Copyright © 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
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 listed source is the library from the MotorBridge.py file.
Next, I will provide the source just for regular DC Motor movement.
`
from MotorBridge import MotorBridge
from flask import Flask, render_template
import time
MotorName = 1
MotorName = 2
ClockWise = 1
CounterClockWise = 2
PwmDuty = 90
Frequency = 1000
app = Flask(name)
@app.route("/")
@app.route("/")
def updates(state=None):
#Straight/Forward!
if state == “F”:
motor = MotorBridgeCape()
motor.DCMotorInit(1, 1000)
motor.DCMotorInit(2, 1000)
motor.DCMotorMove(1, 1, 90)
motor.DCMotorMove(2, 1, 90)
#Left
if state == “L”:
motor = MotorBridgeCape()
motor.DCMotorInit(1, 1000)
motor.DCMotorInit(2, 1000)
motor.DCMotorMove(1, 2, 90)
motor.DCMotorMove(2, 1, 90)
#Right
if state == “R”:
motor = MotorBridgeCape()
motor.DCMotorInit(1, 1000)
motor.DCMotorInit(2, 1000)
motor.DCMotorMove(1, 1, 90)
motor.DCMotorMove(2, 2, 90)
#Stop!
if state == “S”:
motor = MotorBridgeCape()
motor.DCMotorInit(1, 0)
motor.DCMotorInit(2, 0)
motor.DCMotorMove(1, 0, 0)
motor.DCMotorMove(2, 0, 0)
#Reverse!
if state == “Rev”:
motor = MotorBridgeCape()
motor.DCMotorInit(1, 1000)
motor.DCMotorInit(2, 1000)
motor.DCMotorMove(1, 2, 90)
motor.DCMotorMove(2, 2, 90)
template_data = {
“title” : state,
}
return render_template(“Geaux.html”, **template_data)
if name == “main”:
app.run(host=“0.0.0.0”, port=5000, debug=True)
`
…
I have changed the source many times. I have put the motor.DCMotorInit and motor = MotorBridgeCape() calls under my function before calling motor.DCMotorMove in my if statements.
…
Anyway…here is the issue. Since i2c communication was cut short on the Adafruit_BBIO side and since the Adafruit_GPIO.I2C library is read only, I tried smbus2 via a pip install for i2c communication.
…
If you are still following along, thank you. So, my server works w/ the BBGW, Motor Bridge Cape, and power over WiFi but the served HTML page only allows me to control seconds of commands before it halts.
If you understand that the halting happens w/ forward and etc, then there should be an obvious reason for it (this reason bewilders me). I cannot find out why my source and library change create the halting of my program to run continuously.
Seth
P.S. If you made it this far, please reply. If you need me to post the smbus2 library, please let me know. It can easily be installed on our BeagleBoard.org board of choice w/ pip3 install smbus2.