Creation of a python driver


#1

Hi everybody!

I am currently trying to create a little python driver to control dobot, however I didn’t succeed to make it work. Could you please try to indicate me where are my errors? Particurlally, I am not sure about data strucure (byte order, units …).
Here is an example of an attemp of sending an order to dobot (position). I get an answer but no reaction at all …

import serial,time
import struct


def f2b(i):#convert python float into bytes
    return struct.pack('>f', i)# "<": little-endian, ">": big-endian, both tested unsucessfully


ser = serial.Serial(#serial connection
    port='COM3',
    baudrate=256000,
    parity=serial.PARITY_NONE,#serial.PARITY_ODD,
    stopbits=serial.STOPBITS_ONE,#serial.STOPBITS_TWO,
    bytesize=serial.EIGHTBITS#serial.SEVENBITS
)

ser.isOpen()

print "ok"

packet=[chr(0xa5),#packet creation
        f2b(3),#state
        f2b(0),
        f2b(3),#X  3cm?
        f2b(0),#Y
        f2b(0.2),#Z  0.2mm?
        f2b(0),#R
        f2b(0),#grab
        f2b(1),#MoveMode
        f2b(0),#griper
        f2b(0),#pause
        chr(0x5a)]#chr(90)

query = ""
for i in packet:
    query += i


print "[",query,"]"

ser.write(query)

time.sleep(1)
out = ""
while ser.inWaiting() > 0:#read answer
    out += ser.read(1)
    if len(out) == 42:
        break

print "[",out,"]"

Does anybody has an idea about that?

Thank you!


#2

Or is there another simple solution to create a software controlling Dobot?


#3

Hi Florent,

“<”: little-endian works.
use binascii.b2a_hex to show the detailed communicate data.

Here is the example( use 9600bps with version1.1 )

import serial
import struct
import time
import os
import binascii

cmd_str_10 = [ 0 for i in range(10) ]
cmd_str_42 = [ '\x00' for i in range(42) ]

ser = serial.Serial(#serial connection
    port='COM23',
    baudrate=9600,
    parity=serial.PARITY_NONE,#serial.PARITY_ODD,
    stopbits=serial.STOPBITS_ONE,#serial.STOPBITS_TWO,
    bytesize=serial.EIGHTBITS#serial.SEVENBITS
)

ser.isOpen()

# Open Serial port will reset dobot, wait seconds
print "Wait 3 seconds..."
time.sleep(3) 

def dobot_cmd_send( cmd_str_10 ):
    global cmd_str_42
    cmd_str_42 = [ '\x00' for i in range(42) ]
    cmd_str_42[0]  = '\xA5'
    cmd_str_42[41] = '\x5A'
    for i in range(10):
        str4 = struct.pack( '<f', float(cmd_str_10[i]) )
        cmd_str_42[4*i+1] = str4[0]
        cmd_str_42[4*i+2] = str4[1]
        cmd_str_42[4*i+3] = str4[2]
        cmd_str_42[4*i+4] = str4[3]
    cmd_str = ''.join( cmd_str_42 )
    print binascii.b2a_hex( cmd_str )
    
    ser.write( cmd_str )

#state 3
def dobot_cmd_send_3( x = 265, y = 0, z = -30 ):
    global cmd_str_10
    cmd_str_10 = [ 0 for i in range(10) ]
    cmd_str_10[0] = 3
    cmd_str_10[2] = x
    cmd_str_10[3] = y
    cmd_str_10[4] = z
    cmd_str_10[7] = 2 # MOVL
    dobot_cmd_send( cmd_str_10 )

def dobot_cmd_send_9():
    global cmd_str_10
    cmd_str_10 = [ 0 for i in range(10) ]
    cmd_str_10[0] = 9
    cmd_str_10[1] = 1
    cmd_str_10[2] = 200 #JointVel
    cmd_str_10[3] = 200 #JointAcc
    cmd_str_10[4] = 200 #ServoVel
    cmd_str_10[5] = 200 #ServoAcc
    cmd_str_10[6] = 800 #LinearVel
    cmd_str_10[7] = 1000 #LinearAcc
    dobot_cmd_send( cmd_str_10 )

def dobot_cmd_send_10( VelRat = 100, AccRat = 100 ):
    global cmd_str_10
    cmd_str_10 = [ 0 for i in range(10) ]
    cmd_str_10[0] = 10
    cmd_str_10[2] = VelRat
    cmd_str_10[3] = AccRat
    dobot_cmd_send( cmd_str_10 )


print "Dobot Test Begin"
dobot_cmd_send_9() #config
time.sleep( 0.1 )
dobot_cmd_send_10() #config
time.sleep( 0.1 )
dobot_cmd_send_3( 260, 0, 30 ) #MOVL
time.sleep( 0.1 )
dobot_cmd_send_3( 260, 0, 0 ) #MOVL
time.sleep( 0.1 )
print "Dobot Test End"

And printed like this:

Wait 3 seconds...
Dobot Test Begin
a5000010410000803f000048430000484300004843000048430000484400007a4400000000000000005a
a500002041000000000000c8420000c8420000000000000000000000000000000000000000000000005a
a5000040400000000000008243000000000000f04100000000000000000000004000000000000000005a
a5000040400000000000008243000000000000000000000000000000000000004000000000000000005a
Dobot Test End

#4

There is another way to control Dobot using socket to communicate with DobotServer, which is more convenient.

Here is the example, (need to run DobotServer.exe):

import socket
import struct
import time
import os
import binascii

cmd_str_10 = [ 0 for i in range(10) ]
cmd_str_42 = [ '\x00' for i in range(42) ]

sock = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
sock.connect_ex( ('localhost', 5555) )

def dobot_cmd_send( cmd_str_10 ):
    global cmd_str_42
    cmd_str_42 = [ '\x00' for i in range(42) ]
    cmd_str_42[0]  = '\xA5'
    cmd_str_42[41] = '\x5A'
    for i in range(10):
        str4 = struct.pack( '<f', float(cmd_str_10[i]) )
        cmd_str_42[4*i+1] = str4[0]
        cmd_str_42[4*i+2] = str4[1]
        cmd_str_42[4*i+3] = str4[2]
        cmd_str_42[4*i+4] = str4[3]
    cmd_str = ''.join( cmd_str_42 )
    print binascii.b2a_hex( cmd_str )

    sock.send( cmd_str )
    #sock.close()

#state 3
def dobot_cmd_send_3( x = 265, y = 0, z = -30 ):
    global cmd_str_10
    cmd_str_10 = [ 0 for i in range(10) ]
    cmd_str_10[0] = 3
    cmd_str_10[2] = x
    cmd_str_10[3] = y
    cmd_str_10[4] = z
    cmd_str_10[7] = 2 # MOVL
    dobot_cmd_send( cmd_str_10 )

#state 9
def dobot_cmd_send_9():
    global cmd_str_10
    cmd_str_10 = [ 0 for i in range(10) ]
    cmd_str_10[0] = 9
    cmd_str_10[1] = 1
    cmd_str_10[2] = 200 #JointVel
    cmd_str_10[3] = 200 #JointAcc
    cmd_str_10[4] = 200 #ServoVel
    cmd_str_10[5] = 200 #ServoAcc
    cmd_str_10[6] = 800 #LinearVel
    cmd_str_10[7] = 1000 #LinearAcc
    dobot_cmd_send( cmd_str_10 )

#state 10
def dobot_cmd_send_10( VelRat = 100, AccRat = 100 ):
    global cmd_str_10
    cmd_str_10 = [ 0 for i in range(10) ]
    cmd_str_10[0] = 10
    cmd_str_10[2] = VelRat
    cmd_str_10[3] = AccRat
    dobot_cmd_send( cmd_str_10 )


print "Dobot Test Begin"
dobot_cmd_send_9() #config
time.sleep( 0.1 )
dobot_cmd_send_10() #config
time.sleep( 0.1 )
dobot_cmd_send_3( 260, 0, 30 ) #MOVL
time.sleep( 0.1 )
dobot_cmd_send_3( 260, 0, 0 ) #MOVL
time.sleep( 0.1 )
print "Dobot Test End"

#5

Does the robot react to your commands? Are you working with the green or the the black board?


#6

Thank you Jeff for your answer and these great example. However, as in my last try, Dobot answer me but doesn’t move.
I would have used the server if it was possible, but until now I had an error saying that Dobot were not connected, whereas it was and the driver was well detected. I finally succeed to make it work (just 2min ago :smile:) : if I start the server first and then the client, it will fail, however if I let the client starting the server by itself, it works (I didn’t notice that the first time because the server process stay alive despite the error, and my first action was to start it…). I succeed to move Dobot with with your second exampleI, I will do this way, thank you!

@FooTheBar I have a green board. What’s the difference with the black one?


#7

@FooTheBar Both examples are tested ok.

@Florent Green and black boards are same. Black one comes with software version 1.1 using 9600bps which is more common as well green one with software 1.0 using 256000bps. Green one can be upgraded to software version 1.1 refering to https://github.com/DobotTeam/Dobot_Docs/tree/master/document


#8

I’m currently working on the python interface (reading back looks ok) and I’m going to create a repo on github. Is it ok if I take your functions as a starting point?


#9

I started a github here: https://github.com/NikolasE/pyDobot/
I allows to connect to the robot, reads the status (position, angles, gripperStatus) and moves the robot (thanks to the code posted already, I hope that’s ok).

The dobot currently does not start immediately, but only after some seconds, so give it some seconds.

This is tested on Ubuntu 14.04 with Python 2.x but should work on all systems as it’s only using a serial connection and the 9600 baud rate which has better support on different systems than the 256000.


#10

I will try it out in a couple of hours.


#11

Have a look at my last post at Try to get dobot processing sketch working under Linux

There is an open alternative firmware that gives you direct control of FPGA over USB with all existing hardware.

There is also a stable Python driver with which there is no need for time.sleep() and which enables you to make curves (unlike standard firmware - simply not possible, not even close).

All you need to do is the math to translate XYZ to the motor commands, which is pretty simple.

https://youtu.be/Z5N9ItgxR9M
Try to achieve this with original proprietary firmware :wink:


#12

Thank you so much, I missed this post. This is really interesting!!


#13

Hi! I have a question about moving mode. In Jeff’s code MOVL = 2 (cmd_str_10[7] = 2 # MOVL), but in Dobot_protocol_en_1.0_beta.pdf wrote 0:Jump 1:MovL 2: MovJ. Where is true?


#14

I remember 1 is Movj and 2 is Movl.


#15

I try to control two Dobot Arm (connected to OrangePI with Debian) from ruby code. It’s working then i send commands to robots without time delays. If I wait for a while between sending commands, one of the robots will stop moving, but continues to send data packets. I don’t use API, but it write about call PeriodicTask or read robot’s data in 0.5 sec interval or less. I was add to my code a thread, what read data from robot in 0.1 sec. It’s work betters, but sometimes one of a robot still stop moving. What does periodicTask function? Can I send some 42-bit command to robot what reset him?