Porting Robotis Dynamixel SDK to mbed.org

10 Feb 2014

Hello all,

I started this over in the Questions section (http://mbed.org/questions/2501/Help-port-Dynamixel-library-for-the-comm/) but thought it would maybe fit better over here.

Robotis provides a dynamixel SDK template that you can use to port it to other platforms. I'd like to port this to mbed.org so the community will have a robost dynamixel SDK.

http://support.robotis.com/en/software/dynamixel_sdk/sourcestructure.htm

it's a single file with function templates that one must fill in:

// Dynamixel SDK platform dependent source
#include "dxl_hal.h"

int dxl_hal_open( int devIndex, float baudrate )
{
    // Opening device
    // devIndex: Device index
    // baudrate: Real baudrate (ex> 115200, 57600, 38400...)
    // Return: 0(Failed), 1(Succeed)
}
 
void dxl_hal_close()
{
    // Closing device
}
 
void dxl_hal_clear(void)
{
    // Clear communication buffer
}
 
int dxl_hal_tx( unsigned char *pPacket, int numPacket )
{
    // Transmiting date
    // *pPacket: data array pointer
    // numPacket: number of data array
    // Return: number of data transmitted. -1 is error.
}
 
int dxl_hal_rx( unsigned char *pPacket, int numPacket )
{
    // Recieving date
    // *pPacket: data array pointer
    // numPacket: number of data array
    // Return: number of data recieved. -1 is error.
}
 
void dxl_hal_set_timeout( int NumRcvByte )
{
    // Start stop watch
    // NumRcvByte: number of recieving data(to calculate maximum waiting time)
}
 
int dxl_hal_timeout(void)
{
    // Check timeout
    // Return: 0 is false, 1 is true(timeout occurred)
}

Here's what I have so far:

// Dynamixel SDK platform dependent source
#include "dxl_hal.h"
#include "mbed.h"
#include "SerialHalfDuplex.h"

SerialHalfDuplex dxl(P0_0, P0_1);    // UART3 TX, RX for LPC4088, wire them together

Timer t;

float   gfRcvWaitTime   = 0.0f;
float   gfByteTransTime = 0.0f;

int dxl_hal_open( int devIndex, float baudrate )
{
	// Opening device
	// devIndex: Device index
	// baudrate: Real baudrate (ex> 115200, 57600, 38400...)
	// Return: 0(Failed), 1(Succeed)
	
	//it'd be cool to be able to select UARTs by parameter, but too many different device configurations...
	dxl.baud(baudrate);
	
	//is there a way to check serial initialization health/status for return?
	return 1;
}

void dxl_hal_close()
{
	// Closing device
	
	//is there a close method for Serial class?
}

void dxl_hal_clear(void)
{
	// Clear communication buffer
    //dxl.flush(); //.flush() method doesn't exist
    char dumpster; 
    while (dxl.readable()) { 
        dumpster = dxl.getc(); 
    } 
}

int dxl_hal_tx( unsigned char *pPacket, int numPacket )
{
	// Transmiting date
	// *pPacket: data array pointer
	// numPacket: number of data array
	// Return: number of data transmitted. -1 is error.
	
	int i;
 
    for (i=0; i<numPacket; i++) {
       while ( !dxl.writeable() );  // wait until you can write, may want to add timeout here
       dxl.putc(pPacket[i]);  //write
    }   
 
    return numPacket;
}

int dxl_hal_rx( unsigned char *pPacket, int numPacket )
{
	// Recieving date
	// *pPacket: data array pointer
	// numPacket: number of data array
	// Return: number of data recieved. -1 is error.
	
	int i;
 
    for (i=0; i<numPacket; i++) {
    	while ( !dxl.readable() );  // wait until you can read, may want to add timeout here
       	pPacket[i] = dxl.getc();  // read
    }   
    //this assuming the number of data to be read matches the expected number to be read (numPacket). 
    //should i read all available data and compare its length to numPacket? Looks like they want me to 
    //return the actual number of data received. if they don't match, is that -1 error?
 
	return numPacket; //should i return expected or acutal number of data received?
}

void dxl_hal_set_timeout( int NumRcvByte )
{
	// Start stop watch
	// NumRcvByte: number of recieving data(to calculate maximum waiting time)
	
	gfRcvWaitTime = (float)(gfByteTransTime*(float)NumRcvByte + 5.0f); // assuming units of (us), copied from linux SDK
	t.start(); //start timer

}

int dxl_hal_timeout(void)
{
	// Check timeout
	// Return: 0 is false (no timeout), 1 is true(timeout occurred)
	
	long time;
	time = t.read_us();
	
	if(t.read_us() > gfRcvWaitTime){ //I'm assuming wait gfRcvWaitTime and gfByteTransTime are in units of (us)
		return 1; // timeout!
	} 
	else if(time < 0){		//why would time ever be negative? from linux SDK
		t.stop();
		t.reset();
	}
	
	return 0;
}

I'm getting there. Please feel free to critique and help answer any of the questions i have in the comments. Thanks a lot!

03 Sep 2014

Hi Dan,

I think everything seems correct. Though, I've some hints about some of your code.

        while ( !dxl.readable() );  // wait until you can read, may want to add timeout here

readable is set to 1 when a data is in the RX buffer. The problem is that it'll come to 0 the first time you read (with getc()) So if you've multiples char in your buffer, you won't be able to get them all off the buffer.

As for the solution, I've searched all night for a project and I havn't found one yet.

    else if(time < 0){      //why would time ever be negative? from linux SDK

As for this question, time can be negative when the time counter goes off the limit of the integer.

Hope it helps,

Romain