diff --git a/include/dynamixel.h b/include/dynamixel.h index 22a42d8a2c1c70bab729ad64baeeec1faeed48ab..e842d55b38d8a5b233a707590aa791fc2263b2e6 100644 --- a/include/dynamixel.h +++ b/include/dynamixel.h @@ -38,11 +38,6 @@ class CDynamixel * */ void set_baudrate(int baudrate); - /** - * \brief - * - */ - void sync_packet_v2(unsigned char *data,unsigned int length,int *start); protected: /** @@ -71,6 +66,11 @@ class CDynamixel */ void handle_error(unsigned char error); public: + /** + * \brief + * + */ + void sync_packet_v2(unsigned char *data,unsigned int length,int *start); /** * \brief * diff --git a/include/dynamixelserver.h b/include/dynamixelserver.h index 535cd35c08e5e6ebafecad3ccb6c0a391e37b6f6..c7266d36644bde1f495e0d2c386b2a4b48af8a5a 100644 --- a/include/dynamixelserver.h +++ b/include/dynamixelserver.h @@ -244,7 +244,7 @@ class CDynamixelServer * \brief * */ - CDynamixel *get_device(int dev_id,dyn_version_t version=dyn_version1); + virtual CDynamixel *get_device(int dev_id,dyn_version_t version=dyn_version1); /** * \brief * diff --git a/src/dynamixel_can.cpp b/src/dynamixel_can.cpp index b403aba691eded67ee21f547d540bc9f12abbc6d..d023386cf78a4cb9bd94a6c5e11921738e135cbf 100644 --- a/src/dynamixel_can.cpp +++ b/src/dynamixel_can.cpp @@ -57,7 +57,49 @@ void CDynamixelCAN::send_instruction_packet_v1(dyn_inst_t inst,unsigned char *da void CDynamixelCAN::send_instruction_packet_v2(dyn_inst_t inst,unsigned char *data,unsigned short int len) { + unsigned char *packet=NULL; + int i,length,crc; + switch(inst) + { + case dyn_reg_write: + case dyn_write: + case dyn_read: length=10+len; + packet=new unsigned char[length]; + break; + default: throw CDynamixelException(_HERE_,"Instruction not supported",this->get_id()); + break; + } + packet[0]=0xFF; + packet[1]=0xFF; + packet[2]=0xFD; + packet[3]=0x00; + packet[4]=this->node_address; + packet[5]=(len+3)%256; + packet[6]=(len+3)/256; + packet[7]=inst; + for(i=0;i<len;i++) + packet[8+i]=data[i]; + packet[length-2]=0x00; + packet[length-1]=0x00; + crc=CDynamixelServer::compute_checksum_v2(packet,length-2); + packet[length-2]=crc%256; + packet[length-1]=crc/256; + if(this->comm_dev!=NULL) + { + try{ + ((CCAN *)this->comm_dev)->write(this->tx_frame_id,packet,length); + if(packet!=NULL) + delete[] packet; + }catch(CException &e){ + throw e; + } + } + else + { + /* handle exceptions */ + throw CDynamixelException(_HERE_,"The communication device is not properly configured",this->get_id()); + } } unsigned char CDynamixelCAN::receive_status_packet_v1(unsigned char **data,unsigned char *len) @@ -150,7 +192,85 @@ unsigned char CDynamixelCAN::receive_status_packet_v1(unsigned char **data,unsig unsigned char CDynamixelCAN::receive_status_packet_v2(unsigned char **data,unsigned short int *len) { + std::list<std::string> events; + unsigned char data_int[1024]; + int num=0,read=0,length=0,start=0; + unsigned short int crc; + if(this->comm_dev!=NULL) + { + try{ + events.push_back(((CCAN *)this->comm_dev)->get_new_frame_event_id()); + // read up to the length field + do{ + if((num=((CCAN *)this->comm_dev)->get_num_bytes(this->rx_frame_id))==0) + { + this->event_server->wait_all(events,100); + num=((CCAN *)this->comm_dev)->get_num_bytes(rx_frame_id); + } + if((read+num)>1024) + { + ((CCAN *)this->comm_dev)->read(rx_frame_id,&data_int[read],1024-read); + read=1024; + } + else + { + ((CCAN *)this->comm_dev)->read(rx_frame_id,&data_int[read],num); + read+=num; + } + this->sync_packet_v2(data_int,read,&start); + }while((read-start)<7); + length=data_int[start+5]+data_int[start+6]*256+7; + // read the remaining of the packet + while((read-start)<length) + { + if((num=((CCAN *)this->comm_dev)->get_num_bytes(this->rx_frame_id))==0) + { + this->event_server->wait_all(events,100); + num=this->comm_dev->get_num_data(); + } + if((read-start+num)>1024) + { + ((CCAN *)this->comm_dev)->read(rx_frame_id,&data_int[read],1024-read); + read=1024; + } + else + { + ((CCAN *)this->comm_dev)->read(rx_frame_id,&data_int[read],num); + read+=num; + } + } + // check the checksum + crc=CDynamixelServer::compute_checksum_v2(&data_int[start],length-2); + if((crc%256)!=data_int[start+length-2] || (crc/256)!=data_int[start+length-1]) + { + /* handle exceptions */ + throw CDynamixelException(_HERE_,"Invalid Checksum",this->node_address); + } + // return the error + if(length>10) + { + *data=new unsigned char[length-11]; + memcpy(*data,&data_int[start+9],length-11); + *len=length-11; + } + else + { + *data=NULL; + *len=0; + } + return data_int[start+8]; + }catch(CEventTimeoutException &e){ + throw e; + }catch(CException &e){ + throw e; + } + } + else + { + /* handle exceptions */ + throw CDynamixelException(_HERE_,"The communication device is not properly configured",this->node_address); + } } CDynamixelCAN::~CDynamixelCAN() diff --git a/src/dynamixelserver_can.cpp b/src/dynamixelserver_can.cpp index 767f386d7c0d8170be0d235de59761b0d9697a42..8ebe02bee1f887a7f61a6ef7ec3baf39b9573d63 100644 --- a/src/dynamixelserver_can.cpp +++ b/src/dynamixelserver_can.cpp @@ -85,7 +85,59 @@ void CDynamixelServerCAN::send_instruction_packet_v1(dyn_inst_t inst,unsigned ch void CDynamixelServerCAN::send_instruction_packet_v2(dyn_inst_t inst,unsigned char *data,unsigned short int len,unsigned char id) { + unsigned char *packet=NULL; + int i,length,crc; + switch(inst) + { + case dyn_action: id=0xFE;// set the broadcast address + case dyn_ping: length=10; + packet=new unsigned char[length]; + if(len!=0) + throw CDynamixelServerException(_HERE_,"Invalid data length"); + break; + case dyn_bulk_read: + case dyn_bulk_write: + case dyn_sync_read: + case dyn_sync_write: id=0xFE; + length=10+len; + packet=new unsigned char[length]; + break; + default: throw CDynamixelServerException(_HERE_,"Instruction not supported"); + break; + } + packet[0]=0xFF; + packet[1]=0xFF; + packet[2]=0xFD; + packet[3]=0x00; + packet[4]=id; + packet[5]=(len+3)%256; + packet[6]=(len+3)/256; + packet[7]=inst; + for(i=0;i<len;i++) + packet[8+i]=data[i]; + packet[length-2]=0x00; + packet[length-1]=0x00; + crc=this->compute_checksum_v2(packet,length-2); + packet[length-2]=crc%256; + packet[length-1]=crc/256; + if(this->comm_dev!=NULL) + { + try{ + ((CCAN *)this->comm_dev)->write(this->bus_info.tx_frame_id,packet,length); + if(packet!=NULL) + delete[] packet; + }catch(CException &e){ + throw e; + } + } + else + { + if(packet!=NULL) + delete[] packet; + /* handle exceptions */ + throw CDynamixelServerException(_HERE_,"The communication device is not properly configured"); + } } unsigned char CDynamixelServerCAN::receive_status_packet_v1(unsigned char **data,unsigned char *len) @@ -178,7 +230,85 @@ unsigned char CDynamixelServerCAN::receive_status_packet_v1(unsigned char **data unsigned char CDynamixelServerCAN::receive_status_packet_v2(unsigned char **data,unsigned short int *len) { + std::list<std::string> events; + unsigned char data_int[1024]; + int num=0,read=0,length,start=0; + unsigned short int crc; + if(this->comm_dev!=NULL) + { + try{ + events.push_back(((CCAN *)this->comm_dev)->get_new_frame_event_id()); + // read up to the length field + do{ + if((num=((CCAN *)this->comm_dev)->get_num_bytes(this->bus_info.rx_frame_id))==0) + { + this->event_server->wait_all(events,20); + num=((CCAN *)this->comm_dev)->get_num_bytes(this->bus_info.rx_frame_id); + } + if((read+num)>1024) + { + ((CCAN *)this->comm_dev)->read(this->bus_info.rx_frame_id,&data_int[read],1024-read); + read=1024; + } + else + { + ((CCAN *)this->comm_dev)->read(this->bus_info.rx_frame_id,&data_int[read],num); + read+=num; + } + this->sync_packet_v2(data_int,read,&start); + }while((read-start)<7); + length=data_int[start+5]+data_int[start+6]*256+7; + // read the remaining of the packet + while((read-start)<length) + { + if((num=((CCAN *)this->comm_dev)->get_num_bytes(this->bus_info.rx_frame_id))==0) + { + this->event_server->wait_all(events,20); + num=((CCAN *)this->comm_dev)->get_num_bytes(this->bus_info.rx_frame_id); + } + if((read-start+num)>length) + { + ((CCAN *)this->comm_dev)->read(this->bus_info.rx_frame_id,&data_int[read],length-read); + read=length; + } + else + { + ((CCAN *)this->comm_dev)->read(this->bus_info.rx_frame_id,&data_int[read],num); + read+=num; + } + } + // check the checksum + crc=this->compute_checksum_v2(&data_int[start],length-2); + if((crc%256)!=data_int[start+length-2] || (crc/256)!=data_int[start+length-1]) + { + /* handle exceptions */ + throw CDynamixelServerException(_HERE_,"Invalid Checksum"); + } + // return the error + if(length>11) + { + *data=new unsigned char[length-11]; + memcpy(*data,&data_int[start+9],length-11); + *len=length-11; + } + else + { + *data=NULL; + *len=0; + } + return data_int[start+8]; + }catch(CEventTimeoutException &e){ + throw e; + }catch(CException &e){ + throw e; + } + } + else + { + /* handle exceptions */ + throw CDynamixelServerException(_HERE_,"The communication device is not properly configured"); + } } void CDynamixelServerCAN::sync_packet_v1(unsigned char *data,unsigned int length,int *start)