Motor Controller for BeagleBone Black

We are building a robot and we want to use the BeagleBone Black.
We want a motor controller that is cabable of:

  • Control of two DC brushed motors
  • 12V nominal
  • 2.5A continuous, 4A peak
  • PWM
  • with Encoders

Any ideas where we can find such motor controller? We looked in the capes and there is no one available with our specifications

Did you look here?

http://circuitco.com/support/index.php?title=BeagleBoneBlack#BeagleBone_Capes

Gerald

We want a motor controller that is cabable of:
- Control of two DC brushed motors
- 12V nominal
- 2.5A continuous, 4A peak
- PWM
- with Encoders

You can take a look at this one:
http://www.robot-electronics.co.uk/htm/md25tech.htm

I’m using an Arduino Motor & Servo Shield. It’s obviously not pin compatible, but it’s cheap ($20).
The only fiddly part is controlling the on-board 74595 shift-register. I used the following Python script.

import Adafruit_BBIO.GPIO as GPIO

Beaglebone pin names for interface to 74HCT595 latch

(Arduino lib name = shield name = BBB pin)

MOTORENABLE = DIR_EN = “P8_15”
MOTORDATA = DIR_SER = “P8_16”
MOTORCLK = DIR_CLK = “P8_9”
MOTORLATCH = DIR_LATCH = “P8_10”

def bit(n): return 1<<n

class ShiftRegister(object):

def init(self, d):
self.data = d
GPIO.setup(DIR_EN,GPIO.OUT)
GPIO.setup(DIR_SER,GPIO.OUT)
GPIO.setup(DIR_CLK,GPIO.OUT)
GPIO.setup(DIR_LATCH,GPIO.OUT)
GPIO.output(DIR_EN,GPIO.LOW) # Enable shift register
self.transmit() # Switch off (RELEASE) all motors

def string(self): return ‘{0:08b}’.format(self.data)
def bit(self, n): return GPIO.HIGH if (self.data & bit(n)) else GPIO.LOW
def set(self, n, x): # Set the nth bit on or off
if x:
self.data |= bit(n)
else:
self.data &= ~bit(n)
def setall(self, d): self.data = d

Copy self.data to the 74HCT595 shift register one bit at a time via the

serial data bit (DIR_SER). Each time the serial clock (DIR_CLK) goes from

low to high, the current contents of the 74HCT595’s register are shited

one bit to the left and DIR_SER is copied into the rightmost bit.

When DIR_LATCH goes from low to high the contents of the shift register

are moved to the chip’s 8 output pins.

(These 8 bits control the motor shield’s 4 H-bridges.)

def transmit(self):
GPIO.output(DIR_LATCH,GPIO.LOW) # - Set latch trigger low
GPIO.output(DIR_SER,GPIO.LOW) # - Set serial data bit low
for i in xrange(0,8): # - For each bit of motor_register:
GPIO.output(DIR_CLK,GPIO.LOW) # - Set serial clock trigger low
GPIO.output(DIR_SER, self.bit(7-i)) # - Copy register bit(7-i) to the serial data bit
GPIO.output(DIR_CLK,GPIO.HIGH) # - Set serial clock trigger high; the

rising edge shifts the serial data bit

into the 74HCT595’s shift register.

GPIO.output(DIR_LATCH,GPIO.HIGH) # - Set the latch trigger high; the

rising edge sends the stored

bits to the 74HCT595’s parallel outputs.

GPIO.output(DIR_SER,GPIO.LOW)
GPIO.output(DIR_CLK,GPIO.LOW)
GPIO.output(DIR_LATCH,GPIO.LOW)

and call with:

Shift register bits motor control bits (from AFmotor.h)

(Bit positions in the 74HCT595 shift register output.)

MOTOR1_A = 2
MOTOR1_B = 3
MOTOR2_A = 1
MOTOR2_B = 4
MOTOR3_A = 5
MOTOR3_B = 7
MOTOR4_A = 0
MOTOR4_B = 6
MOTOR_BITS = [(MOTOR1_A,MOTOR1_B), (MOTOR2_A,MOTOR2_B), (MOTOR3_A,MOTOR3_B), (MOTOR4_A,MOTOR4_B)]

74HCT595 output bits

7 6 5 4 3 2 1 0

3B, 4B, 3A, 2B, 1B, 1A, 2A, 4A

class Robot(object):

def init(self):
self.control_bits = shift_register.ShiftRegister(0)

Switch motor’s control bits depending on command.

def run(self, motornum, cmd):

Find the control bits (74HCT595 output pins) corresponding to the given motor.

a, b = MOTOR_BITS[motornum -1] # Arduino library uses 1…4

Translate the given command into a pair of control bits

x, y = COMMAND_BITS[cmd -1] # Arduino library uses 1…4

self.control_bits.set(a, x) # Set bit MOTORn_A
self.control_bits.set(b, y) # and bit MOTORn_B.
self.control_bits.transmit() # Send the control bits to the 74HCT595.

We finally have our web store launched and we are producing the Dual Motor Controller Cape in decent quantity (making 100 in this batch).
The spec are:

  • Dual motor control of DC brushed motor
  • 5V to 28V
  • 7A Max continuous
  • Quadrature encoder interface
  • PID with programmable Kp, Ki, Kd constants
  • Velocity PID
  • Simple ‘C’ interface
  • Stackable cape allowing up to 4 capes to be used on a single Beaglebone black.

You can find more information at http://exadler.blogspot.com, and our webstore is live at https://exadler.myshopify.com.

Paul Tan.

Hey! Nice board! Is the motor control done through the onboard hardware, or is there a microcontroller in it?

  • Nathaniel Lewis

It looks like he is using Microchip microcontroller on it. I’m curious if anyone tried to use PRU-ICSS unit to control more than 3 motion channels (there are “only” 3 QEI channels on TI AM335x).

It is probably not too difficult, especially if using the lines directly attached to the PRUs. However, you’d be sacrificing one of your PRUs. One of mine is dedicated to sonar timing.

The motor control and quadrature encoder is done using an onboard Microchip dsPIC processor. The communication with the Beaglebone is done using i2c, that way we can stack multiple DMCC boards on top of a single Beaglebone.

Paul Tan.
Exadler Technologies Inc.
http://www.exadler.com

Hi Morgan,

How is the Motor shield wired to the beaglebone? I see that you are using P8_9,10,15, and 16, wondering what pins on the shield are the hooked up to.

The pin names in the Python code match the signal names on the schematic at http://osepp.com/wp-content/uploads/2013/07/OSEPP_motor_shield_v1-0.pdf.

So, DIR_SER=Arduino.D8, DIR_EN=Arduino.D7, DIR_ CLK=Arduino.D4 and DIR_LATCH=Arduino.D12.

When I get round to it, I’m going to replace the motor shield and Beaglebone PWM outputs with a purpose-built daughterboard.

I’ll use an ATmega328p with a couple of H-bridge drivers controlled via I2C from the BBB.

I found that the BBB is too susceptible to noise and motor startup current drain to interface to servos directly.
I’ll have the BBB and sensors running on separate 3.3V supply from the daughterboard, motors and servos on 5V.

Good luck.