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

16 views
Skip to first unread message

Mala Dies

unread,
Jan 27, 2020, 6:41:43 AM1/27/20
to BeagleBoard
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 (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

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("/<state>")

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.






Mala Dies

unread,
Jan 27, 2020, 8:01:38 PM1/27/20
to BeagleBoard
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
Reply all
Reply to author
Forward
0 new messages