diff --git a/servo_firmware/ax12/src/CTRL_Dynamixel.c b/servo_firmware/ax12/src/CTRL_Dynamixel.c index b7ff64dbf8ef660a0d11fb73f7cdb37427cd300b..c9114f4047a46795caa85041c9e4124ffe4d54b2 100755 --- a/servo_firmware/ax12/src/CTRL_Dynamixel.c +++ b/servo_firmware/ax12/src/CTRL_Dynamixel.c @@ -7,6 +7,15 @@ #define INT16_MAX 0x7fff #define INT16_MIN (-INT16_MAX - 1) +// transform a 64 bit to a 16 bit + +int16_t int64_int16(int64_t a) +{ + int16_t c; + (a>32767)?(c = (int16_t)32767) : ((a<-32768)?(c = (int16_t)-32768):(c = (int16_t) a)); + + return c; +} //#define ADD_A_B(c,a,b) ({\ int32_t x = (int32_t)a+b; \ @@ -93,6 +102,8 @@ void Control_Cycle(void) int32_t Motor_Action_P=0; int32_t Motor_Action_D=0; //int32_t Motor_Action_I=0; + //int32_t Temp32=0; + int64_t Temp64=0; // update position sensor value Sensor_Value = Read_Sensor(CTRL_Encoder_Port); @@ -205,7 +216,10 @@ void Control_Cycle(void) //ADD_A_B(Motor_Action,Motor_Action_I,Motor_Action_D); //ADD_A_B(Motor_Action,Motor_Action,Motor_Action_P); //ADD_A_B(Motor_Action,Motor_Action_D,Motor_Action_P); - Motor_Action=ADD_A_B(Motor_Action_D,Motor_Action_P); + // Motor_Action=ADD_A_B(Motor_Action_D,Motor_Action_P); // error ... son int32 no int16 + Temp64=(int64_t)Motor_Action_D+Motor_Action_P; + Motor_Action=int64_int16(Temp64); + // range where small errors generate no action Error_Margin = Read_word_Dynamixel_RAM(Error_Margin_L); diff --git a/servo_firmware/ax12_2pos/include/MEM_Dynamixel.h b/servo_firmware/ax12_2pos/include/MEM_Dynamixel.h index c14dc7695c8308d47111c2f32bd400732c11c3fb..f45a32eece3ee3f57aaf1cbd6c96d078e715f63c 100755 --- a/servo_firmware/ax12_2pos/include/MEM_Dynamixel.h +++ b/servo_firmware/ax12_2pos/include/MEM_Dynamixel.h @@ -25,6 +25,7 @@ // not define in dynamixell #define Gate_Restore_Eeprom 0X0A // 10 0x01 R/W - Gate variable to restores eeprom factory values //19 => 23 not used + #define RAM_ID_correction 24 // to keep a sequence in the parameters ID between RAM and Eemprom a correction must be done // to read from ram_vector(parameterID - correction) @@ -101,6 +102,11 @@ // 4 Transition_Stage = 1 in stransition gap sensor value = 1023 came into gap CCW direction // 5 Transition_Stage = 2 in stransition gap sensor value =~ 1023 came into gap CCW direction // 6 Transition_Stage = 3 in stransition gap sensor value = 0 came into gap CCW direction +#define POS_A_L 0X58 //88 - 0X00 R/W - Position A low of game rubik flat +#define POS_A_H 0X59 //89 - 0X00 R/W - Position A high of game rubik flat +#define POS_B_L 0X5A //90 - 0X00 R/W - Position B low of game rubik flat +#define POS_B_H 0X5B //91 - 0X00 R/W - Position B high of game rubik flat + #define low(x) ((uint8_t)((x) & 0xFF)) #define high(x) ((uint8_t)(((x)>>8) & 0xFF)) diff --git a/servo_firmware/ax12_2pos/src/CTRL_Dynamixel.c b/servo_firmware/ax12_2pos/src/CTRL_Dynamixel.c index b7ff64dbf8ef660a0d11fb73f7cdb37427cd300b..95cbc7ff0269fcb6d7431cb3d28b0c997c06ddd3 100755 --- a/servo_firmware/ax12_2pos/src/CTRL_Dynamixel.c +++ b/servo_firmware/ax12_2pos/src/CTRL_Dynamixel.c @@ -8,6 +8,16 @@ #define INT16_MAX 0x7fff #define INT16_MIN (-INT16_MAX - 1) +// transform a 64 bit to a 16 bit +int16_t int64_int16(int64_t a) +{ + int16_t c; + (a>32767)?(c = (int16_t)32767) : ((a<-32768)?(c = (int16_t)-32768):(c = (int16_t) a)); + + return c; +} + + //#define ADD_A_B(c,a,b) ({\ int32_t x = (int32_t)a+b; \ (x>32767)?(c = (int16_t)32767) : ((x<-32768)?(c = (int16_t)-32768):(c = (int16_t) x)); \ @@ -48,6 +58,8 @@ void Ini_Position(void) int16_t Sensor_Value; // update position sensor value Sensor_Value=Read_Sensor(CTRL_Encoder_Port); + + Write_word_Dynamixel_RAM(Sensor_Value_L,Sensor_Value); Write_word_Dynamixel_RAM(Present_Position_L,Sensor_Value); Write_word_Dynamixel_RAM(Goal_Position_L,Sensor_Value); @@ -84,7 +96,7 @@ void Control_Cycle(void) int16_t Motor_Turns,Sensor_Value,Present_Position,Goal_Position; int16_t Motor_Action,MotorDir,Error_Vector_0,Error_Vector_1,Error_Vector_2; - //int16_t Error_Vector_3; + int16_t Error_Vector_3; int16_t Error_Margin,KP,KD,Sensor_Resol, Max_Sensor_Range; //int16_t Integral_Value,Max_Integral_Value,KI ; uint16_t PWM_Value; @@ -93,82 +105,86 @@ void Control_Cycle(void) int32_t Motor_Action_P=0; int32_t Motor_Action_D=0; //int32_t Motor_Action_I=0; + //int32_t Temp32=0; + int64_t Temp64=0; // update position sensor value Sensor_Value = Read_Sensor(CTRL_Encoder_Port); Write_word_Dynamixel_RAM(Sensor_Value_L,Sensor_Value); - // find direction of action - Motor_Action = Read_word_Dynamixel_RAM(Motor_Accion_L); - //Read_word_Dynamixel_RAM(Motor_Action,Motor_Accion_L); - if (Motor_Action<CTRL_ZERO){MotorDir=CTRL_Dir_CW;} - else{MotorDir=CTRL_Dir_CCW;} - - // update motor turns - Transition_Stage_Value = Read_byte_Dynamixel_RAM(Transition_Stage); - Motor_Turns=Read_word_Dynamixel_RAM(Motor_Turns_L); - //Read_word_Dynamixel_RAM(Motor_Turns,Motor_Turns_L); - // - switch(Transition_Stage_Value) { - case 0: //-3 - if (Sensor_Value!=1023){ - if (MotorDir==CTRL_Dir_CW){ Transition_Stage_Value=3; //0 - Motor_Turns=Motor_Turns-1; - }else { Transition_Stage_Value=1;} //-2 - } - break; //............................................... - case 1: //-2 - if (Sensor_Value==0){ Transition_Stage_Value=2; //-1 - }else if (Sensor_Value==1023){ Transition_Stage_Value=0;} //-3 - break; //............................................... - case 2: //-1 - if (Sensor_Value!=0){ - if (MotorDir==CTRL_Dir_CW){ Transition_Stage_Value=1; //-2 - }else { Transition_Stage_Value=3;} //0 - } - break; //............................................... - case 3: //0 - if (Sensor_Value==0) { Transition_Stage_Value=2; //-1 - }else if (Sensor_Value==1023) { Transition_Stage_Value=4;} //1 - break; //............................................... - case 4: //1 - if (Sensor_Value!=1023){ - if (MotorDir==CTRL_Dir_CCW){ Transition_Stage_Value=5; //2 - }else { Transition_Stage_Value=3;} //0 - } - break; //............................................... - case 5: //2 - if (Sensor_Value==1023){ Transition_Stage_Value=4; //1 - }else if (Sensor_Value==0){ Transition_Stage_Value=6;} //3 - break; //............................................... - case 6: //3 - if (Sensor_Value!=0){ - if (MotorDir==CTRL_Dir_CCW){ Transition_Stage_Value=3; //0 - Motor_Turns=Motor_Turns+1; - }else { Transition_Stage_Value=5;} //2 - } - break; //............................................... - default: - ; - break; //............................................... - } - Write_word_Dynamixel_RAM(Motor_Turns_L,Motor_Turns); - Write_byte_Dynamixel_RAM(Transition_Stage,Transition_Stage_Value); - - - // calc Position including motor turns - Sensor_Resol=Read_word_Dynamixel_RAM(Sensor_Resol_L); - //Read_word_Dynamixel_RAM(Sensor_Resol,Sensor_Resol_L); - Max_Sensor_Range=Read_word_Dynamixel_RAM(Max_Sensor_Range_L); - //Read_word_Dynamixel_RAM(Max_Sensor_Range,Max_Sensor_Range_L); - Present_Position = (int16_t) ((float)Motor_Turns*Sensor_Resol*360/ Max_Sensor_Range); // OJO max 26 vueltas +// // find direction of action +// Motor_Action = Read_word_Dynamixel_RAM(Motor_Accion_L); +// //Read_word_Dynamixel_RAM(Motor_Action,Motor_Accion_L); +// if (Motor_Action<CTRL_ZERO){MotorDir=CTRL_Dir_CW;} +// else{MotorDir=CTRL_Dir_CCW;} + +// // update motor turns +// Transition_Stage_Value = Read_byte_Dynamixel_RAM(Transition_Stage); +// Motor_Turns=Read_word_Dynamixel_RAM(Motor_Turns_L); +// //Read_word_Dynamixel_RAM(Motor_Turns,Motor_Turns_L); +// // +// switch(Transition_Stage_Value) { +// case 0: //-3 +// if (Sensor_Value!=1023){ +// if (MotorDir==CTRL_Dir_CW){ Transition_Stage_Value=3; //0 +// Motor_Turns=Motor_Turns-1; +// }else { Transition_Stage_Value=1;} //-2 +// } +// break; //............................................... +// case 1: //-2 +// if (Sensor_Value==0){ Transition_Stage_Value=2; //-1 +// }else if (Sensor_Value==1023){ Transition_Stage_Value=0;} //-3 +// break; //............................................... +// case 2: //-1 +// if (Sensor_Value!=0){ +// if (MotorDir==CTRL_Dir_CW){ Transition_Stage_Value=1; //-2 +// }else { Transition_Stage_Value=3;} //0 +// } +// break; //............................................... +// case 3: //0 +// if (Sensor_Value==0) { Transition_Stage_Value=2; //-1 +// }else if (Sensor_Value==1023) { Transition_Stage_Value=4;} //1 +// break; //............................................... +// case 4: //1 +// if (Sensor_Value!=1023){ +// if (MotorDir==CTRL_Dir_CCW){ Transition_Stage_Value=5; //2 +// }else { Transition_Stage_Value=3;} //0 +// } +// break; //............................................... +// case 5: //2 +// if (Sensor_Value==1023){ Transition_Stage_Value=4; //1 +// }else if (Sensor_Value==0){ Transition_Stage_Value=6;} //3 +// break; //............................................... +// case 6: //3 +// if (Sensor_Value!=0){ +// if (MotorDir==CTRL_Dir_CCW){ Transition_Stage_Value=3; //0 +// Motor_Turns=Motor_Turns+1; +// }else { Transition_Stage_Value=5;} //2 +// } +// break; //............................................... +// default: +// ; +// break; //............................................... +// } +// Write_word_Dynamixel_RAM(Motor_Turns_L,Motor_Turns); +// Write_byte_Dynamixel_RAM(Transition_Stage,Transition_Stage_Value); +// +// +// // calc Position including motor turns +// Sensor_Resol=Read_word_Dynamixel_RAM(Sensor_Resol_L); +// //Read_word_Dynamixel_RAM(Sensor_Resol,Sensor_Resol_L); +// Max_Sensor_Range=Read_word_Dynamixel_RAM(Max_Sensor_Range_L); +// //Read_word_Dynamixel_RAM(Max_Sensor_Range,Max_Sensor_Range_L); +// Present_Position = (int16_t) ((float)Motor_Turns*Sensor_Resol*360/ Max_Sensor_Range); // OJO max 26 vueltas //ADD_A_B(Present_Position,Present_Position,Sensor_Value); - Present_Position=ADD_A_B(Present_Position,Sensor_Value); +// Present_Position=ADD_A_B(Present_Position,Sensor_Value); + + Present_Position=Sensor_Value; Write_word_Dynamixel_RAM(Present_Position_L,Present_Position); // Update Error Vector 3 - //Error_Vector_3=Read_word_Dynamixel_RAM(Error_Vector_2_L); - //Write_word_Dynamixel_RAM(Error_Vector_3_L,Error_Vector_3); + Error_Vector_3=Read_word_Dynamixel_RAM(Error_Vector_2_L); + Write_word_Dynamixel_RAM(Error_Vector_3_L,Error_Vector_3); // Update Error Vector 2 Error_Vector_2=Read_word_Dynamixel_RAM(Error_Vector_1_L); //Read_word_Dynamixel_RAM(Error_Vector_2,Error_Vector_1_L); @@ -179,6 +195,53 @@ void Control_Cycle(void) Write_word_Dynamixel_RAM(Error_Vector_1_L,Error_Vector_1); // Update Error Vector 0 Goal_Position=Read_word_Dynamixel_RAM(Goal_Position_L); + +// // modifiy Goal position +// if ((Sensor_Value >900)&&(Goal_Position <-1100)){ +// POSB=Read_word_Dynamixel_RAM(POS_B_L); +// Goal_Position=POSB; +// Write_word_Dynamixel_RAM(Goal_Position_L,Goal_Position); +// } +// else if((Sensor_Value <100)&&(Goal_Position >1100)){ +// POSA=Read_word_Dynamixel_RAM(POS_A_L); +// Goal_Position=POSA; +// Write_word_Dynamixel_RAM(Goal_Position_L,Goal_Position); +// } + // is goal position out side range of sensor + direction + if (Goal_Position <-1100) { + // el error disminuye .. equivale a estar en la zona de funcionamiento del pote + // error negativo + if (Error_Vector_1 > Error_Vector_3){ + // estaba en POSA => cambiar goal a POSB + if (Sensor_Value >900){ + Goal_Position=Read_word_Dynamixel_RAM(POS_B_L); + Write_word_Dynamixel_RAM(Goal_Position_L,Goal_Position); + } + // estaba en POSB => cambiar goal a POSA + else if ((Sensor_Value < 600)&&(Sensor_Value > 300)){ + Goal_Position=Read_word_Dynamixel_RAM(POS_A_L); + Write_word_Dynamixel_RAM(Goal_Position_L,Goal_Position); + } + } + } + else if(Goal_Position >1100){ + // el error disminuye .. equivale a estar en la zona de funcionamiento del pote + if (Error_Vector_3 > Error_Vector_1){ + // estaba en POSB => cambiar goal a POSA + if (Sensor_Value <100){ + Goal_Position=Read_word_Dynamixel_RAM(POS_A_L); + Write_word_Dynamixel_RAM(Goal_Position_L,Goal_Position); + } + // estaba en POSA => cambiar goal a POSB + else if ((Sensor_Value < 600)&&(Sensor_Value > 300)){ + Goal_Position=Read_word_Dynamixel_RAM(POS_B_L); + Write_word_Dynamixel_RAM(Goal_Position_L,Goal_Position); + } + } + } + + + //Read_word_Dynamixel_RAM(Goal_Position,Goal_Position_L); //MULT_A_B(Present_Position,Present_Position,-1); Present_Position=MULT_A_B(Present_Position,-1); @@ -189,10 +252,14 @@ void Control_Cycle(void) // CTRL_Law - algorithm http://lorien.ncl.ac.uk/ming/digicont/digimath/dpid1.htm KP = Read_word_Dynamixel_RAM(KP_L); //Read_word_Dynamixel_RAM(KP,KP_L); - Motor_Action_P = ((int32_t)Error_Vector_0*KP)>>8;// coste de dividir /10 es mayor que shift 4 que equivale a dividir por 16; + Motor_Action_P = ((int32_t)Error_Vector_0*KP)>>7;// coste de dividir /10 es mayor que shift 4 que equivale a dividir por 16; + + KD = Read_word_Dynamixel_RAM(KD_L); //Read_word_Dynamixel_RAM(KD,KD_L); - Motor_Action_D= (((int32_t)Error_Vector_0- Error_Vector_1*2 + Error_Vector_2 )*KD)>>10;//coste de dividir /100 es mayor que shift 7 que equivale a dividir por 128; + Motor_Action_D = (((int32_t)Error_Vector_0- Error_Vector_1*2 + Error_Vector_2 )*KD)>>10;//coste de dividir /100 es mayor que shift 7 que equivale a dividir por 128; + + //KI = Read_word_Dynamixel_RAM(KI_L); //Integral_Value = Read_word_Dynamixel_RAM(Integral_Value_L); //ADD_A_B(Integral_Value,Integral_Value,Error_Vector_0); @@ -205,7 +272,8 @@ void Control_Cycle(void) //ADD_A_B(Motor_Action,Motor_Action_I,Motor_Action_D); //ADD_A_B(Motor_Action,Motor_Action,Motor_Action_P); //ADD_A_B(Motor_Action,Motor_Action_D,Motor_Action_P); - Motor_Action=ADD_A_B(Motor_Action_D,Motor_Action_P); + Temp64=(int64_t)Motor_Action_D+Motor_Action_P; + Motor_Action=int64_int16(Temp64); // range where small errors generate no action Error_Margin = Read_word_Dynamixel_RAM(Error_Margin_L); diff --git a/servo_firmware/ax12_2pos/src/MEM_Dynamixel.c b/servo_firmware/ax12_2pos/src/MEM_Dynamixel.c index 239d0a5d1a54e9db1ebffca371b6eda7ab57c172..cd6ab3de199af9d56d45022efed0f618065da839 100755 --- a/servo_firmware/ax12_2pos/src/MEM_Dynamixel.c +++ b/servo_firmware/ax12_2pos/src/MEM_Dynamixel.c @@ -102,7 +102,12 @@ uint8_t sramVAR[70]={ // Register Id RAM - declared in dynamixel 0x00, // Sensor_Value_H; 0X54 //84 - 0X00 R/W - fraction of turn value return by encoder HIGH 0x00, // Motor_Accion_L; 0X55 //85 - 0X00 R/W - PWM on Motor LOW 0x00, // Motor_Accion_H; 0X56 //86 - 0X00 R/W - PWM on Motor HIGH - 0x03 // Transition_Stage; 0X57 //87 - 0X00 R/W - Position inside transition stage between turns + 0x03, // Transition_Stage; 0X57 //87 - 0X00 R/W - Position inside transition stage between turns + 0xEA, // POS_A_L 0X58 //88 - 0X00 R/W - Position A of game rubik flat + 0x00, // POS_A_H 0X59 //89 - 0X00 R/W - Position B of game rubik flat + 0x1A, // POS_B_L 0X58 //88 - 0X00 R/W - Position A of game rubik flat + 0x03 // POS_B_H 0X59 //89 - 0X00 R/W - Position B of game rubik flat + }; // EEPROM READ AND WRITE diff --git a/servo_firmware/ax12_2pos/src/main.c b/servo_firmware/ax12_2pos/src/main.c index c8fea0e0f7767f7a96c5337348db97705ff49857..7d964325a40c35ad1c97048288fe08b1a2bae90b 100755 --- a/servo_firmware/ax12_2pos/src/main.c +++ b/servo_firmware/ax12_2pos/src/main.c @@ -86,6 +86,7 @@ int16_t main(void) { // end of initialization LedOFF; + //LedON; do_control = 0;