Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: MX12 ServoRingBuffer mbed-src
Fork of SpindleBot by
Diff: main.cpp
- Revision:
- 4:e44ac08027bd
- Parent:
- 2:dfeadd6c651c
- Child:
- 5:72e92c721cd5
--- a/main.cpp Mon Jan 26 04:56:08 2015 +0000 +++ b/main.cpp Mon Apr 06 21:23:36 2015 +0000 @@ -24,6 +24,7 @@ // Specific to Dynamixels #ifdef USE_DYNAMIXELS #include "MX12.h" +#include "AD7730.h" #endif // Specific to SD Card @@ -39,6 +40,13 @@ #define M_PI_2 1.57079632679489661923 /* pi/2 */ #endif +// Create enum for the Jaw state (Closing, hold, opening) +enum jaw_state{ + STATE_CLOSING=0, + STATE_CLOSE_HOLD=1, + STATE_OPENING=2, + STATE_OPEN_HOLD=3 +}; // Define pins and interrupts @@ -46,7 +54,7 @@ DigitalOut led1(LED1); //Led 1 for debugging purposes DigitalOut led2(LED2); //Led 2 for debugging purposes DigitalOut led3(LED3); //Led 3 for debugging purposes -DigitalOut led4(LED4); //Led 4 for debugging purposes +//DigitalOut led4(LED4); //Led 4 for debugging purposes DigitalOut triggerOut(p11); Serial pc(USBTX, USBRX); //Set up serial connection to pc #ifdef USE_BLUETOOTH @@ -83,7 +91,7 @@ float g_theta; float g_theta_last=0; unsigned char g_current_mode=MODE_NULL; -unsigned char g_current_direction=DIRECTION_NULL; +jaw_state g_current_direction=STATE_OPEN_HOLD; unsigned char g_current_cycle=0; // Warning, this buffer is large! @@ -97,16 +105,20 @@ #ifdef USE_DYNAMIXELS //Dynamixels can only handle 500Hz for now. Working on it... - float samplingPeriod = 0.002; //This is the sampling period for the timer interrupt + float samplingPeriod = 0.005; //This is the sampling period for the timer interrupt #define LEFT_JAW_DYNAMIXEL_ID 3 #define RIGHT_JAW_DYNAMIXEL_ID 4 - #define MIN_SERVO_ANGLE_Da_VINCI 1600 //This is the open in encoder counts - #define MAX_SERVO_ANGLE_Da_VINCI 3200 //This is the closed in encoder counts + #define CLOSED_SERVO_ANGLE_LEFT 1121 //This is the closed in encoder counts + #define OPEN_SERVO_ANGLE_LEFT 2783 //This is the open in encoder counts + #define CLOSED_SERVO_ANGLE_RIGHT 3259 //This is the closed in encoder counts + #define OPEN_SERVO_ANGLE_RIGHT 1486 //This is the open in encoder counts // Dynamixel Object - MX12 mx12_left_jaw (p28, p27, LEFT_JAW_DYNAMIXEL_ID, 1000000); - MX12 mx12_right_jaw (p28, p27, RIGHT_JAW_DYNAMIXEL_ID, 1000000); + MX12 mx12_left_jaw (p28, p27, p30, p29, LEFT_JAW_DYNAMIXEL_ID, 1000000); + MX12 mx12_right_jaw (p28, p27, p30, p29, RIGHT_JAW_DYNAMIXEL_ID, 1000000); - /// Set these to outputs so that they don't interfere with the serial communication + AD7730 adc(p9, p26, p11, p12, p25); + + /// Set these to inputs so that they don't interfere with the serial communication DigitalIn nullOut1(p21); DigitalIn nullOut2(p22); DigitalIn nullOut3(p23); @@ -139,6 +151,48 @@ #endif +// Function trapezoidalTrajectory: Function that takes in a time (float in seconds) and outputs a float (0 to 1) that corresponds to a trapezoidal trajectory +float trapezoidalTrajectory(float t, jaw_state &state, unsigned char &cycle_num) { + // Define variables specific to this function + float y_trapezoid = 0.0; + float timeMod; + float modifiedFrequency = g_frequency/2.0; + float period = 1/modifiedFrequency; + cycle_num=t*modifiedFrequency; + + // Take the time and mod it with the period to be able to break up each cycle into 4 piecewise sections + timeMod = fmodf(t,period); + + // + if (timeMod < period/4.0) + { + y_trapezoid = (-4.0/period)*(timeMod)+1.0; + state = STATE_CLOSING; + } + else if (timeMod >= period/4.0 && timeMod < period/2.0) + { + y_trapezoid = 0.0; + state = STATE_CLOSE_HOLD; + } + else if (timeMod >= period/2.0 && timeMod < 3*period/4.0) + { + y_trapezoid = (4.0/period)*(timeMod)-2; + state = STATE_OPENING; + } + else if (timeMod >= 3*period/4.0) + { + y_trapezoid = 1.0; + state = STATE_OPEN_HOLD; + } + + return y_trapezoid; +} + +void sinusoidalTrajectory(float t, jaw_state &state, unsigned char &cycle_num) { + //Fill me with SCIENCE!!! +} + + // Function timerISRFunction: Timer ISR function to collect data and write to ring buffer void timerISRFunction() { if(collect_data){ @@ -152,23 +206,34 @@ // Warning, this calculation is in the ISR and as such is probably slower than we would prefer. // @todo The math could certainly be optimized with some precalculated constants. Lookup tables are faster than sin() - float angle=g_current_trajectory_time*g_frequency*2.0*M_PI-M_PI_2; - g_theta=(sin(angle)+1)/2.0*(MAX_SERVO_ANGLE_Da_VINCI-MIN_SERVO_ANGLE_Da_VINCI)+MIN_SERVO_ANGLE_Da_VINCI; - g_current_direction=(cos(angle)<0); - g_current_cycle=(angle+M_PI_2)/(2.0*M_PI); + float percent=trapezoidalTrajectory(g_current_trajectory_time,g_current_direction,g_current_cycle); + g_current_trajectory_time+=samplingPeriod; + + + //float angle=g_current_trajectory_time*g_frequency*2.0*M_PI-M_PI_2; + //g_current_direction=(cos(angle)<0); + //g_current_cycle=(angle+M_PI_2)/(2.0*M_PI); + #ifdef USE_DYNAMIXELS - tempSpindleData.myServoData[LEFT_SERVO_INDEX].force = AinLeftForce.read_u16(); - tempSpindleData.myServoData[LEFT_SERVO_INDEX].pos = mx12_left_jaw.GetRawPosition(); - tempSpindleData.myServoData[RIGHT_SERVO_INDEX].force = AinRightForce.read_u16(); - tempSpindleData.myServoData[RIGHT_SERVO_INDEX].pos = mx12_right_jaw.GetRawPosition(); - tempSpindleData.direction=g_current_direction; - tempSpindleData.cycle=g_current_cycle; - Buffer.write(tempSpindleData); - //mx12_right_jaw.write_short(MX12_REG_GOAL_POSITION,short(g_theta)); - //mx12_right_jaw.coordinated_move(LEFT_JAW_DYNAMIXEL_ID,(short)g_theta, 175, RIGHT_JAW_DYNAMIXEL_ID,(short)g_theta, 175); - g_current_trajectory_time+=samplingPeriod; + //float percent=(sin(angle)+1)/2.0; + if(adc.isReady()){ + adc.interruptRead(); + } + + short left_servo =percent*(CLOSED_SERVO_ANGLE_LEFT -OPEN_SERVO_ANGLE_LEFT )+OPEN_SERVO_ANGLE_LEFT ; + short right_servo=percent*(CLOSED_SERVO_ANGLE_RIGHT-OPEN_SERVO_ANGLE_RIGHT)+OPEN_SERVO_ANGLE_RIGHT; + mx12_right_jaw.coordinated_move(LEFT_JAW_DYNAMIXEL_ID,left_servo, 0, RIGHT_JAW_DYNAMIXEL_ID,right_servo, 0); + +// tempSpindleData.myServoData[LEFT_SERVO_INDEX].force = adc.read(); +// tempSpindleData.myServoData[LEFT_SERVO_INDEX].pos = mx12_left_jaw.GetRawPosition(); +// tempSpindleData.myServoData[RIGHT_SERVO_INDEX].force = AinRightForce.read_u16(); +// tempSpindleData.myServoData[RIGHT_SERVO_INDEX].pos = mx12_right_jaw.GetRawPosition(); +// tempSpindleData.direction=g_current_direction; +// tempSpindleData.cycle=g_current_cycle; +// Buffer.write(tempSpindleData); #else + g_theta=(1.0-percent)*(MAX_SERVO_ANGLE_Da_VINCI-MIN_SERVO_ANGLE_Da_VINCI)+MIN_SERVO_ANGLE_Da_VINCI; tempSpindleData.myServoData[LEFT_SERVO_INDEX].force = AinLeftForce.read_u16(); tempSpindleData.myServoData[LEFT_SERVO_INDEX].pos = AinLeftPosition.read_u16(); tempSpindleData.myServoData[RIGHT_SERVO_INDEX].force = AinRightForce.read_u16(); @@ -177,7 +242,6 @@ tempSpindleData.cycle=g_current_cycle; Buffer.write(tempSpindleData); - g_current_trajectory_time+=samplingPeriod; moveServoTo(g_theta); // in degrees, son @@ -235,15 +299,31 @@ pc.printf("\n\n"); #ifdef USE_DYNAMIXELS + mx12_left_jaw.Init(); //mx12_left_jaw.SetBaud(3000000); //mx12_left_jaw.SetBaud(1000000); //printf("Current Position=%1.3f\n",mx12_left_jaw.GetPosition()); - mx12_left_jaw.Set_Return_Delay_Time(0.002); - mx12_right_jaw.Set_Return_Delay_Time(0.002); - mx12_left_jaw.Set_Torque_Limit(30); - mx12_right_jaw.Set_Torque_Limit(30); + mx12_right_jaw.Set_Return_Delay_Time(0.050); printf("Current ReturnDelay=%f ms\n",mx12_left_jaw.Get_Return_Delay_Time()); - //mx12_right_jaw.SetReturnDelay(0); + mx12_left_jaw.Set_Return_Delay_Time(0.050); + //mx12_left_jaw.Set_Torque_Limit(99.9); + //mx12_right_jaw.Set_Torque_Limit(99.9); + mx12_left_jaw.write_short(MX12_REG_MAX_TORQUE,0x03FF); + mx12_right_jaw.write_short(MX12_REG_MAX_TORQUE,0x03FF); + mx12_left_jaw.Set_P_Gain(4); + mx12_right_jaw.Set_P_Gain(4); + mx12_left_jaw.Set_I_Gain(8); + mx12_right_jaw.Set_I_Gain(8); + mx12_left_jaw.Set_Alarm_Shutdown(0x04); + mx12_right_jaw.Set_Alarm_Shutdown(0x04); + + mx12_left_jaw.Dump_OD_to_Serial(pc); + mx12_right_jaw.Dump_OD_to_Serial(pc); + + + + adc.setFilter(256 , false, 1); + adc.start(); #else // Configure Servo for HiTec 422 myServoLeft.period_ms(20); @@ -276,6 +356,7 @@ g_max_force=newData[2]; g_num_cycles=newData[3]; g_current_trajectory_time=0; + g_current_cycle=0; g_current_mode=MODE_AUTOMATIC; #ifdef USE_SD_CARD int first_slash=file_name_in.find("/"); @@ -293,6 +374,7 @@ fprintf(fp, "%%Starting New Trajectory\n"); fprintf(fp, "%%File Name=\"%s\"\n",file_name.c_str()); fprintf(fp, "%%Current Mode=AUTOMATIC\n"); + fprintf(fp, "%%Trajectory Type=TRAPEZOIDAL\n"); fprintf(fp, "%%Frequency=%f Hz\n",g_frequency); fprintf(fp, "%%Max Force=%f ??\n",g_max_force); fprintf(fp, "%%Num Cycles=%d\n",g_num_cycles); @@ -303,7 +385,7 @@ collect_data=true; } - if( collect_data && g_current_trajectory_time * g_frequency > g_num_cycles) + if( collect_data && g_current_cycle >= g_num_cycles) { // STOOOOOOOOOP collect_data=false; @@ -328,14 +410,14 @@ if(AuxSerialTimer.read_ms()>100 && collect_data){ //Send some extra data for GUI purposes - printf("<%d,%d,%d,%d,%d,%d,%d>\n",tempSpindleData.myServoData[LEFT_SERVO_INDEX].pos, + printf("<%d,%d,%d,%d,%d,%d,%d> ",tempSpindleData.myServoData[LEFT_SERVO_INDEX].pos, tempSpindleData.myServoData[LEFT_SERVO_INDEX].force, tempSpindleData.myServoData[RIGHT_SERVO_INDEX].pos, tempSpindleData.myServoData[RIGHT_SERVO_INDEX].force, tempSpindleData.time, tempSpindleData.direction, tempSpindleData.cycle); - printf("The worst time taken was %d microseconds\n", worst_latency); + printf(" %dus\n", worst_latency); worst_latency=0; AuxSerialTimer.reset(); }