Home Products Shop Articles Applications Learning Zone About Us

  • Up






  • Using a Raspberry Pi with MotorBee

     The following details show how to control a MotorBee using a program written in Python running under the Raspbian operating system on a Raspberry Pi model B single board Computer.
     ( If you are not familiar with basic Motor Bee functionality, more details can be found here )

    The Raspberry Pi has two standard USB sockets. One of them is usually dedicated to the keyboard (or keyboard and mouse where a small USB hub has been used). It is assumed the MotorBee is connected via a standard USB lead to one of these ports or to a free USB port on a hub if one is connected.

    The following simple example of Python Code is all that is required to turn on motor1, set it to half speed, set the servo to centre position, set the digital outputs and read the digital inputs on the MotorBee. Have a look at this code and then see the explanation that follows for detailed description of each of the lines.

    import usb.core

    dev = usb.core.find(idVendor=0x04d8, idProduct=0x005b)

    if dev is None:
        raise ValueError('Device not found')
    else:
        try:
            dev.detach_kernel_driver(0)
        except:
            pass
        dev.set_configuration()

        speed1 = 128
        speed2 = 0
        speed3 = 0
        speed4 = 0
        motoronoff = 0b11110001
        enable = 0x30
        servo = 128

        data=[4, speed1, speed2, speed3, speed4, motoronoff, enable, servo]
        dev.write(2,data)

        outputs = 0b11000011
        data=[8, outputs]
        dev.write(2,data)

        inputs = dev.read(0x81,1)
        print "Inputs = {}".format(inputs[0])

    import usb.core
        This line of code imports the very popular PyUSB library of functions for communicating with USB devices. It avoids having to write any of your own code to access USB devices and provides a good range of functions to meet many requirements. In our case we only need to use four of its functions. It is freely available to download and can be installed on your Raspberry Pi very easily. There is no point in duplicating install instructions here so I will just give you a link to follow....
    http://sourceforge.net/projects/pyusb/     (opens in new window)

    dev = usb.core.find(idVendor=0x04d8, idProduct=0x005b)
        This uses one of the PyUSB functions to "find" the attached MotorBee.  The way it finds the MotorBee is by checking all available USB ports to find the one with a device that has the unique identifier associated with the MotorBee. This identifier is made up to two parts: the Vendor ID and the Product ID.  For the MotorBee this is the two hexadecimal numbers 0x04d8 and 0x005b respectively. If the device is found, the "dev" object is created for the MotorBee and can then be used for susequent operations on the MotorBee. It is only necessary to use this statement once in your program, but obviously, it needs to be before any other use of the "dev" functions.

    if dev is None:
      
     raise ValueError('Device not found
    ')
        It is always good programming practice to check if the MotorBee has actually been found before continuing. This "if" statement will "raise" an exception and halt the program if it is not.
    Assuming it is found, execution continues with the statements after the else:

        try:
            dev.detach_kernel_driver(0)
       
    except:
           
    pass
     
        The function dev.detach_kernel_driver(0) gets round a possible problem with the operating system restricting the use of the MotorBee. When the MotorBee is first plugged into the USB port the operating system tries to be helpful and associates one of its standard drivers to deal with all operations to the board. We don't want this, but, with it "attached" to the MotorBee it won't then allow any other direct operations.  This line "detaches" this driver from the MotorBee allowing us to access it directly. Note that this only needs to be done the first time the program is run after connecting the MotorBee (or after reboot). If you try and detach the driver when it is already detached the program will raise an exception and halt the program. I have found the best way to deal with this is simply to put the detach function at the head of the program inside a "try... except" clause.  In this way it will detach the driver if necessary and ignore it if already detached.

    dev.set_configuration()
        USB devices have different "configurations" that they can be set to depending on the task they are required to perform. In the case of the MotorBee, it simply has one configuration which is it's default. However, this still needs to be "set" as the active one using the statement shown. This only needs to done once in your program and before any other code that communicates with the MotorBee.

     

    speed1 = 128
    speed2 = 0
    speed3 = 0
    speed4 = 0
    motoronoff = 0b11110001
    enable = 0x30
    servo = 128
    data=[4, speed1, speed2, speed3, speed4, motoronoff, enable, servo]

        The MotorBee obeys the usual rules of a standard USB device which requires data to be sent to it in the form of message blocks (in USB terms these are called Endpoints).  In Python we specifiy this message block by using a number sequence using the square brackets as shown.  A message block for the MotorBee consists of a message type number and seven 8-bit numbers that correspond to the required settings for motors etc.. The message type number is simply '4'. This indicates to the MotorBee that it should use the following 7 numbers to set its outputs (motor speed, servo position etc...). Each number has been given a named variable above but it could just as easily have been entered as simple numbers into the data array. For example the above is equivalent to .....
    data=[4, 128, 0, 0, 0, 0b11110001, 0x30, 128]
        The "speed" variables hold the speed of each motor output (motor 1 to 4). The speed is in the range 1 to 255.  Note that a speed of 0 is not allowed: To turn off the motor, you should use the on/off controls (described later).
        When the motorbee outputs are being used to drive a motor in bi-directional mode, two outputs are used per motor and the numbers then correspond to the speed in a given direction. For example:  If a motor is connected to the first two outputs so that it can be used in bi-directional mode the following example illustrates the principle ...
    speed1=255, speed2=0         --> this produces maximum speed  in the forward direction
    speed1=0,     speed2 =128    --> this produces half speed  in the reverse direction

    etc.. etc...
        Note that in bi-directional configuration one of the pair of motor outputs MUST be set to 0, otherwise the motor will be trying to drive in both directions at the same time and will probably just stall or overheat.
        The "motoronoff" variable uses the four least significant bits to turn the corresponding motor on or off (regardless of its speed). The bits associated with these outputs are shown below. Please note that the unused bits (bit4 - bit7) MUST be set to logic '1' as shown.

    Motor On/Off Control Bits



    A logic '1' corresponds to the associated motor being ON and logic '0' for OFF.

        The "enable" variable is not used but is reserved for future releases of the board firmware. For now, it should simply be set to 0x30 to ensure the board is fully enabled.

        The value of the "servo" variable specifies the position that the servo should go to and is in the range 1 to 255.  Note: it depends on the servo used how this corresponds to the actual range of movement. Typically, the centre position is specified with a value of 128,  -90degrees with 64 and +90 degrees with 192 .

    dev.write(2,data)
        Once the data sequence has been specified it is simply sent to the MotorBee using the "write" function within the "dev" object as shown. The number '2' used, is just the name of the internal buffer to use within the MotorBee, or , as previously mentioned, the USB "endpoint" number.  For the MotorBee this is always set to 2.   The MotorBee motor speeds, directions and servo position will now be set accordingly.

        In the above description its worth noting that the first few lines may look slightly complicated but, once your program has "found" the MotorBee, detached the kernel driver (if necessary) and set the MotorBee configuration, the control of the MotorBee motors and servo is simply a case of using the "dev.write" function (with the appropriate data in the data array) as often as you like.

    outputs = 0b11000011
    data=[8, outputs]
    dev.write(2,data)
    inputs = dev.read(0x81,1)

       The Motorbee also has some digital inputs and outputs which may be controlled. It has 4 digital outputs which are specified using a single byte of data with appropriate bits set. See diagram below....

    Setting Motorbee Digital Outputs

        This is then used as part of a message to be sent to the motorbee in the same way as the motors and servo were set previously. i.e. the message is simply two bytes in the data array...

    data = [8,outputs]

        The '8' is once again the message type which will be recognised by the motorbee as the command to set the outputs. The second byte being the output pattern to be used as already mentioned. The actual sending of the message is once again done using...

    dev.write(2,data)

         However, unlike the previous sending of the message to set the motors, this message has two functions. The first is to set the digital outputs as described. The second is to tell the MotorBee to read its digital inputs into a buffer and make that reading available to be read across the USB interface by a subsequent command.  Even if the input data is not required, it is necessary to read the inputs data buffer every time the outputs are set !!. The command that actually reads this data from the MotorBee is next....

     inputs = dev.read(0x81, 1)
        The inputs, made ready by the previous code, are now read by this statement. It is very similar to the "write" statement shown earlier. The 0x81 is just a hexadecimal number and corresponds to the internal USB buffer (or endpoint) associated with USB reads. It is always set to 0x81 for MotorBee reads.  The number '1' is the number of bytes of data to read from the MotorBee. i.e. since the MotorBee only has 5 digital inputs it only requires one 8-bit byte to hold the data..  The variable which we have called "inputs" will then hold the returned data.  i.e. inputs is a Python array with inputs[0] holding the returned data. Details of the bits corresponding to the inputs is shown below....

    A logic '1' corresponds to the input being HIGH (+5v), logic '0' corresponds to LOW (0v)

    print "Inputs = {}".format(inputs[0])
        This is not really required, but shows a convenient way of displaying the data returned (i.e. the current digital inputs) in your program while testing.

     Raspbian Note:   Always remember that running code in Raspbian that accesses USB devices requires you to be in "superuser" mode to have the necessary permissions. This may mean running your Python program with the usual "sudo ...." prefix or, if using the graphical environment with IDLE as your programming environment, you may need to run it from a terminal window (i.e.  typing "sudo idle" in the terminal window) for the programs created to work properly.

    Some examples:

    # set motor1 to 1/3 full speed (approx) and servo to -90 degrees
        data=[4, 84, 0, 0, 0, 0b11110001, 0x30, 64]
        dev.write(2,data)

    # set motors 2 and 4 to full speed and the servo to centre position
        data=[4, 0, 255, 0, 255, 0b11111010, 0x30, 128]
        dev.write(2,data)

    # set digital output 1 on then read and display the current inputs
        data=[8, 0b00000001]
        dev.write(2,data)
        inputs = dev.read(0x81, 1)
        print inputs

    See the article below for an example of using the Motor Bee with a Raspberry Pi   .......

    Pi-Mobile
    ( Autonomous Vehicle using Raspberry Pi and Motor Pack )
        Making a fully automatic intelligent robot/mobile using a Raspberry Pi and a Motorbee.
    by Ava L (UK)

      Disclaimer:   Please note that the above code and descriptions are designed to help our customers use our boards with the Raspberry Pi. We offer no warranty or guarantees to the suitability of the code for your application. We are also unable to enter into discussions about any errors your code may have and will not, under any curcumstances, attempt to look for programming errors in code sent to us. This applies equally to Python, PyUSB, LibUSB. Linux (all distros) and any Raspberry Pi specifics.

       
    Raspberry Pi is a trademark of the Raspberry Pi Foundation

     

     

     

    13152  

    Featured
    Items

     
    Automator
    Lowest Cost
    Control Board


    ConText
    Control by Text


    Security Camera:
    A new article
    by Brian M



    Microscope Control:
    A new article
    by Harald K. A.



     Use our boards with
    Raspberry Pi.


    Pi-Mobile:
    A new article
    by Ava L (UK)