Eurobot2012_IRturret

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*************************************************************
00002      Eurobot 2012
00003      IR Localization Beacon Turret Control Code
00004 
00005      author: Shuto
00006 *************************************************************/
00007 
00008 /*
00009 NOTES
00010 
00011 IR identification is based on beacon period => may need to change this
00012 + ON time is coded
00013 + OFF time used to confirm read,
00014 
00015 ticker based stepper control could be unstable
00016 
00017 may need to slow down stepper, microstep less
00018 
00019 
00020 
00021 iterative average predictions
00022 
00023 
00024 */
00025 
00026 
00027 #include "mbed.h"
00028 
00029 // Pin Definitions ============================================================
00030 
00031 // IR sensor input
00032 InterruptIn    irt_pin_sensor     (p30);        // pull up to supply
00033 
00034 // stepper control pins
00035 DigitalOut    irt_pin_step    (p11);
00036 DigitalOut    irt_pin_dir     (p12);
00037 DigitalOut    StepperDisable  (p23);// Connects to Stepper controller !EN pin
00038 
00039 
00040 // data output
00041 Serial         mainMbed (p13,p14);
00042 
00043 // start interrupt
00044 DigitalIn      startTrig (p21);
00045 
00046 // start location signal
00047 //DigitalIn      startOnRed (p22);
00048 
00049 // debug
00050 Serial         pc        (USBTX, USBRX); // tx, rx
00051 DigitalOut     rx0     (LED1);
00052 DigitalOut     rx1     (LED2);
00053 DigitalOut     rx2     (LED3);
00054 DigitalOut     serialTx (LED4);
00055 
00056 
00057 // IR Beacon Settings =========================================================
00058 
00059 // IR signal coding: ON time in us
00060 // TODO need to adjust
00061 #define    IR0_ON        1000
00062 #define    IR1_ON        750
00063 #define    IR2_ON        500
00064 
00065 #define    IR0_OFF       500
00066 #define    IR1_OFF       750
00067 #define    IR2_OFF       1000
00068 
00069 #define    IR_TOR       100         // torrerence
00070 
00071 #define    IR_BUF_SIZE  100         // buffer size for sensor readings 
00072 #define    IR_INVALID   100000      // invalid angle 
00073 
00074 #define    IR_ANGLE_TOR 10
00075 
00076 #define    MIN_SC         5         // minimum sample count for valid recieve
00077 #define    NO_SIG_WINDOW  32        // need to adjust!  (NO_SIG_WINDOW * 1.8/16)
00078 
00079 // Stepper Motor Settings =====================================================
00080 
00081 #define STEPPER_DIV   3200    // number of steps per cycle = default * microstep
00082 #define STEP_PULSE    0.00005    // step pulse duration
00083 
00084 
00085 // Variables ==================================================================
00086 
00087 // stepper
00088 Ticker    irt_stepTicker;            // ticker triggering stepper motor step
00089 
00090 float    irt_STEPANGLE    = (float)360 / STEPPER_DIV;        // step angle of stepper
00091 
00092 float    irt_rps         = 5;
00093 float    irt_angle        = 0;    // current direction which the stepper is facing
00094 
00095 bool    irt_spin_dir = true;
00096 
00097 // IR sensor
00098 Timer    irt_timer_on, irt_timer_off;        // timer used to measure signal duration
00099 
00100 bool        irt_rx0_ON = false;
00101 bool        irt_rx1_ON = false;
00102 bool        irt_rx2_ON = false;
00103 
00104 //data buffer
00105 int   data0[IR_BUF_SIZE];
00106 int   data1[IR_BUF_SIZE];
00107 int   data2[IR_BUF_SIZE];
00108 int     sc0 = 0;
00109 int     sc1 = 0;
00110 int     sc2 = 0;
00111 int     acc0 = 0;
00112 int     acc1 = 0;
00113 int     acc2 = 0;
00114 
00115 int     nosig0 = 0;
00116 int     nosig1 = 0;
00117 int     nosig2 = 0;
00118 
00119 // game end
00120 Timeout gameEnd;
00121 bool    inGame = false;
00122 
00123 // functions ==================================================================
00124 
00125 // prototypes
00126 void irt_stepperStep ();
00127 void irt_sensorSetup ();
00128 void irt_sigStart ();
00129 void irt_sigEnd ();
00130 void sendSerial (int ID, float center, float var);
00131 void stopRobot ();
00132 float step2rad (int step);
00133 float radFormat (float in);
00134 
00135 //--- debug main --------------------------------
00136 int main () {
00137     mainMbed.baud(115200);
00138     mainMbed.format(8,Serial::Odd,1);
00139 
00140     StepperDisable = 0; //Enable stepper
00141 
00142     irt_sensorSetup();
00143     
00144     /*
00145     // change spin direction for different start locations
00146     if (startOnRed){
00147         irt_spin_dir = true;
00148     }else{
00149         irt_spin_dir = false;
00150     }
00151     */
00152     irt_pin_dir = irt_spin_dir;
00153     
00154 
00155     // reset buffer
00156     sc0 = 0;
00157     sc1 = 0;
00158     sc2 = 0;
00159     for (int i = 0; i < IR_BUF_SIZE; i++) {
00160         data0[i] = IR_INVALID;       // fill with invalid angle values
00161         data1[i] = IR_INVALID;
00162         data2[i] = IR_INVALID;
00163     }
00164     
00165     // calibration 5 sec
00166     for (int cv = 0; cv < (STEPPER_DIV * irt_rps)*5 ; cv++) {
00167         irt_stepperStep();
00168         wait(1/(STEPPER_DIV * irt_rps));
00169         rx0 = false;
00170         rx1 = false;
00171         rx2 = false;
00172     }
00173     
00174     // wait for start signal
00175     while(!startTrig){}
00176     
00177     // start off 90sec kill timer
00178     gameEnd.attach(&stopRobot, 87.0);
00179     inGame = true;
00180     
00181     // spin loop
00182     while (inGame) {
00183         irt_stepperStep();
00184         wait(1/(STEPPER_DIV * irt_rps));
00185         rx0 = false;
00186         rx1 = false;
00187         rx2 = false;
00188     }
00189 
00190 }
00191 
00192 
00193 //--- Stepper Control Functions -----------------
00194 void irt_stepperStep () {
00195 // function to handle stepper stepping
00196 // this function is repeatedly called by the ticker
00197 
00198     // generate step pulse
00199     irt_pin_step = true;
00200     wait(STEP_PULSE);
00201     irt_pin_step = false;
00202 
00203     // increment
00204     irt_angle ++;
00205     if (irt_angle >= STEPPER_DIV) {
00206         irt_angle = 0;
00207     }
00208 
00209     // check for signal end
00210     if (sc0) {
00211         nosig0++;
00212 
00213         // if signal not recieved for long enough
00214         if (nosig0 > NO_SIG_WINDOW) {
00215 
00216             // if enough samples obtained, valid signal
00217             if (sc0 > MIN_SC) {
00218                 float range = step2rad(data0[sc0-1] - data0[0]);
00219 
00220                 // if robot facing a beacon signal will be recieved accross 0
00221                 if (range < 0) {
00222                     acc0 = 0;
00223                     for (int i = 0; i < sc0; i++) {
00224                         if (data0[i] > STEPPER_DIV/2) {
00225                             acc0 += data0[i] - STEPPER_DIV;
00226                         } else {
00227                             acc0 += data0[i];
00228                         }
00229                     }
00230                 }
00231 
00232                 // send data packet
00233                 sendSerial (0, step2rad((float)acc0/sc0), range*range);
00234             }
00235             // if not, probably noise
00236 
00237             // reset
00238             nosig0 = 0;
00239             sc0 = 0;
00240             acc0 = 0;
00241         }
00242     }
00243 
00244     if (sc1) {
00245         nosig1++;
00246 
00247         // if signal not recieved for long enough
00248         if (nosig1 > NO_SIG_WINDOW) {
00249 
00250             // if enough samples obtained, valid signal
00251             if (sc1 > MIN_SC) {
00252                 float range = step2rad(data1[sc1-1] - data1[0]);
00253 
00254                 // if robot facing a beacon signal will be recieved accross 0
00255                 if (range < 0) {
00256                     acc1 = 0;
00257                     for (int i = 0; i < sc1; i++) {
00258                         if (data1[i] > STEPPER_DIV/2) {
00259                             acc1 += data1[i] - STEPPER_DIV;
00260                         } else {
00261                             acc1 += data1[i];
00262                         }
00263                     }
00264                 }
00265 
00266                 // send data packet
00267                 sendSerial (1, step2rad((float)acc1/sc1), range*range);
00268             }
00269             // if not, probably noise
00270 
00271             // reset
00272             nosig1 = 0;
00273             sc1 = 0;
00274             acc1 = 0;
00275         }
00276     }
00277 
00278     if (sc2) {
00279         nosig2++;
00280 
00281         // if signal not recieved for long enough
00282         if (nosig2 > NO_SIG_WINDOW) {
00283 
00284             // if enough samples obtained, valid signal
00285             if (sc2 > MIN_SC) {
00286                 float range = step2rad(data2[sc2-1] - data2[0]);
00287 
00288                 // if robot facing a beacon signal will be recieved accross 0
00289                 if (range < 0) {
00290                     acc2 = 0;
00291                     for (int i = 0; i < sc2; i++) {
00292                         if (data2[i] > STEPPER_DIV/2) {
00293                             acc2 += data2[i] - STEPPER_DIV;
00294                         } else {
00295                             acc2 += data2[i];
00296                         }
00297                     }
00298                 }
00299 
00300                 // send data packet
00301                 sendSerial (2, step2rad((float)acc2/sc2), range*range);
00302             }
00303             // if not, probably noise
00304 
00305             // reset
00306             nosig2 = 0;
00307             sc2 = 0;
00308             acc2 = 0;
00309         }
00310     }
00311 
00312 
00313     return;
00314 }
00315 
00316 
00317 //--- IR Signal Decode Functions ----------------
00318 void irt_sensorSetup () {
00319 // function to setup sensor ISRs
00320 
00321     // attach ISRs to sensor input
00322     irt_pin_sensor.fall(&irt_sigStart);        // ISR for sensor active (low value)
00323     irt_pin_sensor.rise(&irt_sigEnd);        // ISR for sensor inactive (high)
00324 
00325     // reset timer
00326     irt_timer_on.reset();
00327     irt_timer_off.reset();
00328 
00329     
00330 
00331     return;
00332 }
00333 
00334 
00335 void irt_sigStart () {
00336 // high to low transition
00337 
00338     // start ON timer
00339     irt_timer_on.reset();
00340     irt_timer_on.start();
00341 
00342     // stop OFF timer
00343     irt_timer_off.stop();
00344 
00345     // read timer
00346     int off_time = irt_timer_off.read_us();
00347 
00348     // check if signal recieved
00349 
00350     if (irt_angle != 0) {
00351         if (abs(off_time - IR0_OFF) < IR_TOR) {
00352             rx0 = irt_rx0_ON;
00353             if (irt_rx0_ON) {
00354                 data0[sc0] = irt_angle;
00355                 acc0 += irt_angle;
00356                 sc0++;
00357                 nosig0 = 0;
00358                 if (sc0 >= IR_BUF_SIZE) {
00359                     //pc.printf("buffer overflow \n");
00360                     acc0 = 0;
00361                     sc0 = 0;
00362                 }
00363             }
00364         }
00365 
00366         if (abs(off_time - IR1_OFF) < IR_TOR) {
00367             rx1 = irt_rx1_ON;
00368             if (irt_rx1_ON) {
00369                 data1[sc1] = irt_angle;
00370                 acc1 += irt_angle;
00371                 sc1++;
00372                 nosig1 = 0;
00373                 if (sc1 >= IR_BUF_SIZE) {
00374                     //pc.printf("buffer overflow \n");
00375                     acc1 = 0;
00376                     sc1 = 0;
00377                 }
00378             }
00379         }
00380 
00381         if (abs(off_time - IR2_OFF) < IR_TOR) {
00382             rx2 = irt_rx2_ON;
00383             if (irt_rx2_ON) {
00384                 data2[sc2] = irt_angle;
00385                 acc2 += irt_angle;
00386                 sc2++;
00387                 nosig2 = 0;
00388                 if (sc2 >= IR_BUF_SIZE) {
00389                     //pc.printf("buffer overflow \n");
00390                     acc2 = 0;
00391                     sc2 = 0;
00392                 }
00393             }
00394         }
00395     }
00396 
00397 
00398 
00399     return;
00400 }
00401 
00402 void irt_sigEnd () {
00403 // low to high transition
00404 
00405     // start OFF timer
00406     irt_timer_off.reset();
00407     irt_timer_off.start();
00408 
00409     // stop ON timer
00410     irt_timer_on.stop();
00411 
00412     // read timer
00413     int on_time = irt_timer_on.read_us();
00414 
00415     // check
00416     if (abs(on_time - IR0_ON) < IR_TOR) {
00417         irt_rx0_ON = true;
00418     } else {
00419         irt_rx0_ON = false;
00420     }
00421 
00422     if (abs(on_time - IR1_ON) < IR_TOR) {
00423         irt_rx1_ON = true;
00424     } else {
00425         irt_rx1_ON = false;
00426     }
00427 
00428     if (abs(on_time - IR2_ON) < IR_TOR) {
00429         irt_rx2_ON = true;
00430     } else {
00431         irt_rx2_ON = false;
00432     }
00433 
00434     return;
00435 }
00436 
00437 
00438 // send serial ----------------------------------------------------------------
00439 void sendSerial (int ID, float center, float var) {
00440 
00441     // bytes packing for IR turret serial comm
00442     union IRValue_t {
00443         int     IR_ints[4];
00444         float   IR_floats[4];
00445         unsigned char IR_chars[16];
00446     } IRValues;
00447 
00448     IRValues.IR_chars[0] = 0xFF;
00449     IRValues.IR_chars[1] = 0xFE;
00450     IRValues.IR_chars[2] = 0xFD;
00451     IRValues.IR_chars[3] = 0xFC;
00452 
00453     IRValues.IR_ints[1]     = ID;       // beacon ID
00454     IRValues.IR_floats[2]   = center;   // center
00455     IRValues.IR_floats[3]   = var;      // (max - min)^2
00456 
00457     // output sample to main board
00458     for (int i = 0; i < 16; i++) {
00459         mainMbed.putc(IRValues.IR_chars[i]);
00460     }
00461     
00462     // debug 
00463     //pc.printf("%d; %f; %f; \n",ID,center,var);
00464 }
00465 
00466 //--- end game ----------------------------------------------------------------
00467 void stopRobot (){
00468     inGame = false;
00469     StepperDisable = 1; //Disable Stepper Disable pin set High
00470 }
00471 
00472 
00473 //--- util --------------------------------------------------------------------
00474 float step2rad (int step) {
00475 // convert moter step count to rad format with correct range (defined in radFormat)
00476     return radFormat(step * irt_STEPANGLE * 3.14 / 180);
00477 }
00478 
00479 float radFormat (float in) {
00480     return in;
00481 // format angle range => currently -PI to PI
00482 /*
00483     if (in > 3.14)  {
00484         return in - 6.28;
00485     }
00486     if (in < -3.14) {
00487         return in + 6.28;
00488     }
00489     return in;
00490  */
00491 }
00492 
00493 
00494 
00495 
00496 
00497 
00498 // notes about the stepper controller =========================================
00499 /*
00500 *** timing info **********************************************
00501     STEP input pulse   min widths               1us
00502     setup and hold for MS inputs and RESET/DIR  0.2us
00503 
00504     FULL Step config        !MS1 !MS2 !MS3
00505     STEP number (for full step config) ==> 200
00506 
00507 *** stepper lead colors **************************************
00508     -> steps clockwise for DIR true
00509         1A          BLUE
00510         1B          RED
00511         2A          BLACK
00512         2B          GREEN
00513 
00514 *** stepper driver pin connection ****************************
00515         GND         ground
00516         5V          float
00517         Vdd         jump to 3.3v
00518         3V3         (jump to Vdd)
00519         GND         ground
00520         REF         floating
00521         !EN         GND
00522         MS1/2/3     floating (have pull down resistors)
00523         !RST        pull up to 3.3v (10k resistor)
00524         !SLP        connect to !RST (pull up to 3.3v)
00525         STEP        STEP data pin
00526         DIR         DIR data pin
00527 
00528         VMOT        connect to 12v supply
00529         GND         ground
00530         2B          motor lead - GREEN
00531         2A          motor lead - BLACK
00532         1A          motor lead - BLUE
00533         1B          motor lead - RED            (clock wise direction when DIR true)
00534         Vdd         float
00535         GND         ground
00536 
00537 *** current limit setting ************************************
00538     coil resistance = 3.3ohm
00539 
00540     check voltage output to motor  ==> set it to ~1v
00541         this will limit current to 0.333A
00542         (total current 0.66A, since two phase)
00543 
00544     higher currents needed for higher rotation speeds
00545         2v for 5 rps
00546 */
00547 
00548 
00549 
00550 
00551 
00552 
00553 
00554 
00555 
00556 
00557 
00558 
00559 
00560 
00561 
00562 
00563 
00564 
00565 
00566