Anyone who has a Kondo KHR3-HV will know all the instructions are in Japanese so I am posting a few code snippets. This will hopefully get you started with talking to the Eprom in Windows allowing you to get those servos moving. So once you have connect the Eprom to your USB port your going to want to first establish a connection via the com port it has been issued. If this is the first time you have connected the board it should be on COM3, however I suggest you look inside your device manager to make sure.
int initCOM(int COMPort){
char myNum[2];
sprintf_s(myNum, "%d", COMPort);
char myCom[5] = "COM";
myCom[3] = myNum[0];
myCom[4] = myNum[1];
if ((commport = CreateFile(myCom, // open com:
GENERIC_READ | GENERIC_WRITE, // for reading and writing
0, // exclusive access
NULL, // no security attributes
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL)) == INVALID_HANDLE_VALUE) {
printf("Error: Can not open COM Port\n");
}
//set comms
comSettings.BaudRate = 115200;
comSettings.StopBits = ONESTOPBIT;
comSettings.ByteSize = 8;
comSettings.Parity = EVENPARITY;
comSettings.fParity = TRUE;
// Set Port parameters.
bStatus = SetCommState(commport, &comSettings);
if (bStatus == 0){
printf("Error: failed to set Comm state.\n");
}
//set timeouts (this is required. to read more than one byte)
commTimeout.ReadIntervalTimeout = 50;
commTimeout.ReadTotalTimeoutConstant = 50;
commTimeout.ReadTotalTimeoutMultiplier = 10;
commTimeout.WriteTotalTimeoutConstant = 50;
commTimeout.WriteTotalTimeoutMultiplier = 10;
bStatus = SetCommTimeouts(commport, &commTimeout);
if (bStatus == 0) {
printf("Error: failed to set Comm timeouts.\n");
}
return bStatus;
}
Above shows a simple connection method, it has some very simple error handling as it is just an example. Next on the list of things you will want to be able to do is send data to the RCB4, before we can do this we need to set up some buffers that are accessible by all methods.
unsigned char INBUFFER[256];
unsigned char OUTBUFFER[256];
unsigned char SERVOS[35];
DWORD bytes_read = 0; // Number of bytes read from port
DWORD bytes_written = 0; // Number of bytes written to the port
HANDLE commport = NULL; // Handle COM port
int bStatus;
DCB comSettings; // Contains various port settings
COMMTIMEOUTS commTimeout;
int returnVal = 0; // Used for the return value of functions
unsigned int FREE_POS = 32768;
unsigned int HOLD_POS = 32767;
The next method shows you how to write and receive data back from the RCB4, this could be achieved with a single buffer. However, for demonstration purposes this way allows you to see both input and output of the RCB4 communication.
/*
* Functon kondo_send - writes byte code instructions to the RCB4
* Also receives the returning ack.
* @param bytesToRead - The number of bytes expecded back from the RCB4
*/
int kondo_send( int bytesToRead ){
bStatus = WriteFile(commport, // Handle
&OUTBUFFER, // Outgoing data
OUTBUFFER[0], // Number of bytes to write
&bytes_written, // Number of bytes written
NULL);
if (bStatus == 0 || (bytes_written != OUTBUFFER[0])){
printf("Error: Could not write to Comm port - DEBUG: %d.\n", bStatus);
}
bStatus = ReadFile(commport, // Handle
&INBUFFER, // Incoming data
bytesToRead, // Number of bytes to read
&bytes_read, // Number of bytes read
NULL);
if (bStatus == 0){
printf("Error: Could not Read from Comm port - DEBUG: %d.\n", bStatus);
}
else {
printf("Received: ");
for(int i = 0; i < bytesToRead; i++){
printf("%X ", INBUFFER[i]);
}
printf("\n");
}
return 0;
}
Now were going to send a simple acknowledgement to the RCB4 and hopefully receive the positive acknowledgement back as as response, 0×06 or a negative acknowledgement which is 0×15. Another command that is used in this method is the RCB4_CMD_ACK command which is 0xFE. Before you can send the data you must calculate the checksum and include it as the last byte. the checksum is the sum of all the bytes being sent.
/*
* Function kondo_checksum - returns the sum on n-1 bytes of the OUTBUFFER[]
* This function only needs to return the lower byte of the checksum.
* @param UCHAR OUTBUFFER[] - The array of byte codes to send to the RCB4
* @param int nBytes - number of bytes from OUTBUFFER to sum
*/
int kondo_checksum(UCHAR OUTBUFFER[], int nBytes){
unsigned int sum = 0;
// loop and add together bytes beig sent
for(int i = 0; i < nBytes; i++){
sum += OUTBUFFER[i];
} return sum; }
/* Function kondo_ack - send and receives an acknowledgement from the RCB4 */
int kondo_ack() {
OUTBUFFER[0] = 4;
OUTBUFFER[1] = RCB4_CMD_ACK;
OUTBUFFER[2] = RCB4_ACK_BYTE;
OUTBUFFER[3] = kondo_checksum(OUTBUFFER, 3);
returnVal = kondo_send(4);
if(INBUFFER[2] == RCB4_ACK_BYTE){
return returnVal; // All OK }
else if(INBUFFER[2] == RCB4_NCK_BYTE){
return -1; // Non-ack but RCB4 present
}
else{
return -2; // No RCB4 connected
}
}
Ok! … well I hope that’s the response you got back. If you did then you can start making other things happen. Lets start with turning the green LED on and off.
/* Function kondo_led switches on/off the RCB4 Green LED
* @param bool isLED - a boolean value true = on; false = off
*/
int kondo_led(bool isLED) {
int light_on = 0;
if(isLED) {
light_on = 128;
}
OUTBUFFER[0] = 9;
OUTBUFFER[1] = 0;
OUTBUFFER[2] = 2;
OUTBUFFER[3] = 0;
OUTBUFFER[4] = 0;
OUTBUFFER[5] = 0;
OUTBUFFER[6] = 31;
OUTBUFFER[7] = light_on;
OUTBUFFER[8] = kondo_checksum(OUTBUFFER, 8);
returnVal = kondo_send(4);
return returnVal; }
This method should turn the green light which is located on the Eprom on when you pass true, and off when you pass false. If that is all working we can move onto addressing and initialising the servos.
/*Function kondo_servo_ID_address - Sets a single servo Address
* @param int Servo_ID - the ID number of the servo
* @param bool SIO - which SIO channel (i.e. false = lower, true = upper)
*/
int kondo_servo_ID_address(int Servo_ID, bool SIO) {
unsigned int servo_address = (Servo_ID*2) * SERVO_SIZE + SERVO_START;
if(SIO) {
servo_address += 20;
}
unsigned int ADDH = (unsigned int) servo_address >> 8;
unsigned int ADDL = (unsigned int) servo_address & 0x00FF;
OUTBUFFER[0] = 0x1B;
OUTBUFFER[1] = 0x00;
OUTBUFFER[2] = 0x02;
OUTBUFFER[3] = ADDL; // Address L
OUTBUFFER[4] = ADDH; // Address H
OUTBUFFER[5] = 0x00;
OUTBUFFER[6] = 0x00;
OUTBUFFER[7] = Servo_ID; // ID of servo
OUTBUFFER[8] = 0x00;
OUTBUFFER[9] = 0x00;
OUTBUFFER[10] = 0x00;
OUTBUFFER[11] = 0x00;
OUTBUFFER[12] = 0x4C;
OUTBUFFER[13] = 0x1D;
OUTBUFFER[14] = 0x00;
OUTBUFFER[15] = 0x00;
OUTBUFFER[16] = 0x00;
OUTBUFFER[17] = 0x00;
OUTBUFFER[18] = 0x00;
OUTBUFFER[19] = 0x00;
OUTBUFFER[20] = 0xFF;
OUTBUFFER[21] = 0xFF;
OUTBUFFER[22] = 0x01;
OUTBUFFER[23] = 0xFF;
OUTBUFFER[24] = 0xFF;
OUTBUFFER[25] = 0x01;
OUTBUFFER[26] = kondo_checksum(OUTBUFFER, 26); // Checksum
returnVal = kondo_send(4);
return returnVal;
}
This method accepts the servo id and a bool for SIO depending on which pin you have the servo connected. If your not sure just send the function once with true and false
. To activate the servos you have selected you send the following command. It is the same no matter how many, or which servos you wish to activate. If successful after running this command the red light on the back of the servo will illuminate.
/*
* Function kondo_servo_on - This powers on any servos selected
* by the function kondo_init_servo_ID.
*/
int kondo_servo_on( void ){
OUTBUFFER[0] = 0x09;
OUTBUFFER[1] = 0x00;
OUTBUFFER[2] = 0x02;
OUTBUFFER[3] = 0x00;
OUTBUFFER[4] = 0x00;
OUTBUFFER[5] = 0x00;
OUTBUFFER[6] = 0x11;
OUTBUFFER[7] = 0x00;
OUTBUFFER[8] = 0x1C; // Hardcoded checksum (as this doesn't change)
returnVal = kondo_send(4);
return 0;
}
If the red light has now come on the servo is now ready to move to whatever position you wish.
/**
* Function kondo_set_servo_ID_pos - This function sets the position of
* the servo indexed by IDX to the position set by aPOS.
*
* @param int IDX - the IDX of the servo:
* note this is NOT its ID but it's count, i.e. servo's 6 are @ 12 & 13
* @param int SIO - to serial IO channel the servo sits on (i.e. 0 or 1)
* @param unsigned int aPos - the position to move the servo to (i.e. 7500)
*/
int kondo_set_servo_ID_pos(int IDX, int SIO, unsigned int aPos) {
IDX = IDX *2;
if (SIO == 1){
IDX++;
}
unsigned int POSH = (unsigned int) aPos >> 8;
unsigned int POSL = (unsigned int) aPos & 0x00FF;
OUTBUFFER[0] = 0x0A;
OUTBUFFER[1] = 0x00;
OUTBUFFER[2] = 0x12;
OUTBUFFER[3] = 0x06;
OUTBUFFER[4] = IDX;
OUTBUFFER[5] = 0x00;
OUTBUFFER[6] = POSL;
OUTBUFFER[7] = POSH;
OUTBUFFER[8] = 0x00;
OUTBUFFER[9] = kondo_checksum(OUTBUFFER, 9);
returnVal = kondo_send(4);
return returnVal;
}
Hopefully everything on this page worked accordingly
have fun with you new RCB4 robot.