RE: Trying to Get the Motor Bridge Cape to Work w/ the BBGW w/ smbus2, pathlib, and the MotorBridge.py library/BeagleBone Green Wireless

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.

Hello,

If you want, there is some source. If not, do not fret. Someone helped me along the way and I got things resolved.

Seth