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.
main.cpp
00001 #include "mbed.h" 00002 #include "TextLCD.h" 00003 #include "MCP23017.h" 00004 #include <string> 00005 #include <iostream> 00006 #include <vector> 00007 #include <fstream> 00008 #include <sstream> 00009 00010 using namespace std; 00011 00012 00013 /******PINS AND DECLARATIONS*******/ 00014 00015 //------PINS 00016 00017 //SWITCHES p5 - p8 00018 DigitalIn switch1(p5); 00019 DigitalIn switch2(p6); 00020 DigitalIn switch3(p7); 00021 DigitalIn switch4(p8); 00022 00023 //RAIL SENSORS - INT0,INT1 00024 //INT0 - p9 00025 InterruptIn int0(p9); 00026 //INT1 - p10 00027 InterruptIn int1(p10); 00028 00029 ///p11 - EMPTY 00030 ///p12 - EMPTY 00031 00032 //M0 - p13 00033 DigitalIn d21stat(p13); //Sensor right of the station 00034 //M1 - p14 00035 DigitalIn d22stat(p14); //Sensor left of the station 00036 //M2 - p15 00037 DigitalIn station(p15); //Sensor in the middle of the station 00038 00039 //p16 - EMPTY 00040 00041 //ENABLE - p17 00042 DigitalOut enable(p17); 00043 00044 //BUZZER - p18 00045 DigitalOut buzz(p18); // buzz=0 doesn't beep, buzz=1 beeps 00046 00047 //POTENTIOMETER - p19 00048 AnalogIn pot(p19); //Gives float value pot.read(). Convert analog input to V with f*3.3 00049 00050 //DAT - p20 00051 DigitalOut Track(p20); //Digital output bit used to drive track power via H-bridge 00052 00053 //LCD SCREEN - p21, p22, p23, p24, p25, p26 00054 TextLCD lcd(p22,p21,p23,p24,p25,p26); // RS, E, A4, A5, A6, A7 // ldc.cls() to clear and printf(String up to 16char) 00055 00056 //p27 - EMPTY 00057 00058 //12C - p28 00059 I2C i2c(p28,p27); 00060 00061 //LED1 - p29 00062 DigitalOut redled(p29); 00063 //LED2 - p30 00064 DigitalOut greenled(p30); 00065 00066 //MBED LEDS 00067 DigitalOut led1(LED1); 00068 DigitalOut led2(LED2); 00069 DigitalOut led3(LED3); 00070 DigitalOut led4(LED4); 00071 00072 //MCP 00073 MCP23017 *mcp; 00074 00075 00076 //------DEFINITIONS 00077 00078 //......SENSOR DEFS 00079 //Definition of D sensors, will be interpreted as ints for the program's logic 00080 #define D0 0 00081 #define D1 1 00082 #define D2 2 00083 #define D3 3 00084 #define D4 4 00085 #define D5 5 00086 #define D6 6 00087 #define D7 7 00088 #define D8 8 00089 #define D9 9 00090 #define D10 10 00091 #define D11 11 00092 #define D12 12 00093 #define D13 13 00094 #define D21 14 00095 #define D22 15 00096 00097 //......SPEED DEFS 00098 //Definition of the different train speeds, will be interpreted as ints for the program's logic 00099 #define STOP 0 00100 #define SLOW 1 00101 #define MEDIUM 2 00102 #define FAST 3 00103 #define FULL 4 00104 #define R_MEDIUM 5 00105 00106 00107 //--------DCC SEND COMMANDS 00108 00109 //01DCSSSS for speed, D is direction (fwd=1 and rev=0), C is speed(SSSSC) LSB 00110 const unsigned int DCCinst_forward = 0x68; //forward half speed 00111 const unsigned int DCCinst_forward_slow = 0x66; //forward slow speed (step 9) 00112 const unsigned int DCCinst_forward_fast = 0x6C; //Forward fast speed (step 22) 00113 const unsigned int DCCinst_forward_full = 0x6F; //Forward full speed 00114 const unsigned int DCCinst_reverse = 0x48; //reverse half speed 00115 const unsigned int DCCinst_stop = 0x50; //stop the train 00116 00117 //100DDDDD for basic headlight functions 00118 const unsigned int DCC_func_lighton = 0x90; //F0 turns on headlight function 00119 const unsigned int DCC_func_dimlight = 0x91; //F0 + F1 dims headlight 00120 00121 00122 //.....SWITCH COMMAND VARS 00123 00124 const unsigned int SWBaddress = 0x06; //Address for switch box 00125 00126 //100DDDDD where DDDDD is the switch command and 100 is constant: 00127 00128 //00001(F1 active)-00010(F2 active)-00100(F3 active)-01000(F4 active) 00129 //Example - 111111 0 00000101 0 10000000 0 10000101 1 - idle 00130 const unsigned int SWBidle = 0x80; //IDLE - Flip last activated SW. 00131 const unsigned int SWBflip_1 = 0x81; //Flip SW1 00132 const unsigned int SWBflip_2 = 0x82; //Flip SW2 00133 const unsigned int SWBflip_3 = 0x84; //Flip SW3 00134 const unsigned int SWBflip_4 = 0x88; //Flip SW4 00135 00136 00137 //.....DCC TRAIN COMMAND VARS 00138 00139 //typical out of box default engine DCC address is 3 (at least for Bachmann trains) 00140 //Note: A DCC controller can reprogram the address whenever needed 00141 const unsigned int DCCaddressDR = 0x01; //Address for train 1 DARK-RED 00142 const unsigned int DCCaddressLR = 0x03; //Address for train 3 LIGHT-RED 00143 00144 00145 /** 00146 * 00147 *Method to send DCC commands to train and switches. 00148 * 00149 *@address - (HEX)Address where the commands will be sent 00150 *@inst - (HEX)Number of instruction that will be commanded 00151 *@repeat_count - Number of times the command will be sent 00152 * 00153 **/ 00154 void DCC_send_command(unsigned int address, unsigned int inst, unsigned int repeat_count){ 00155 00156 unsigned __int64 command = 0x0000000000000000; // __int64 is the 64-bit integer type 00157 unsigned __int64 temp_command = 0x0000000000000000; 00158 unsigned __int64 prefix = 0x3FFF; // 14 "1" bits needed at start 00159 unsigned int error = 0x00; //error byte 00160 00161 //calculate error detection byte with xor 00162 error = address ^ inst; 00163 00164 //combine packet bits in basic DCC format 00165 command = (prefix<<28)|(address<<19)|(inst<<10)|((error)<<1)|0x01; 00166 //printf("\n\r %llx \n\r",command); 00167 00168 int i=0; 00169 //repeat DCC command lots of times 00170 while(i < repeat_count) { 00171 00172 temp_command = command; 00173 //loops through packet bits encoding and sending out digital pulses for a DCC command 00174 for (int j=0; j<64; j++) { 00175 00176 if((temp_command&0x8000000000000000)==0) { 00177 //test packet bit 00178 //send data for a "0" bit 00179 Track=0; 00180 wait_us(100); 00181 Track=1; 00182 wait_us(100); 00183 //printf("0011"); 00184 }else{ 00185 00186 //send data for a "1"bit 00187 Track=0; 00188 wait_us(58); 00189 Track=1; 00190 wait_us(58); 00191 //printf("01"); 00192 } 00193 // next bit in packet 00194 temp_command = temp_command<<1; 00195 } 00196 i++; 00197 } 00198 } 00199 00200 00201 00202 //------CLASSES 00203 00204 //......POSITION CLASS 00205 00206 /** 00207 * 00208 *Position class. 00209 * 00210 *@position - 00211 *@previous_cw - 00212 *@previous_ccw - 00213 * 00214 *Position(int) - 00215 * 00216 *get_pos() - 00217 *get_prev_cw() - 00218 *get_ccw() - 00219 *add_prev_cw() - 00220 *add_ccw() - 00221 * 00222 **/ 00223 class Position{ 00224 00225 private: 00226 00227 int position; 00228 vector <int> previous_cw; 00229 vector <int> previous_ccw; 00230 public: 00231 00232 Position(int p){ 00233 position = p; 00234 } 00235 00236 int get_pos(){ 00237 return position; 00238 } 00239 00240 vector<int> get_next_cw(){ 00241 return previous_ccw; 00242 } 00243 00244 vector<int> get_next_ccw(){ 00245 return previous_cw; 00246 } 00247 00248 vector <int> get_prev_cw(){ 00249 return previous_cw; 00250 } 00251 00252 vector <int> get_prev_ccw(){ 00253 return previous_ccw; 00254 } 00255 00256 void add_prev_cw(int pos){ 00257 previous_cw.push_back(pos); 00258 }; 00259 00260 void add_prev_ccw(int pos){ 00261 previous_ccw.push_back(pos); 00262 }; 00263 }; 00264 00265 //......INITS USED FOR CLASS TRAIN 00266 00267 //Creating a vector with all the positions. 00268 vector<Position> positions; 00269 00270 /** 00271 *Defining areas for train detection and collision logic. 00272 *area_A_arr/area_B_arr - Arrays that hold the Dsensors for each area, used to initialize the vectors. 00273 *area_A/area_B - Vectors that hold the different sensors of the corresponding areas of the track. 00274 **/ 00275 int area_A_arr[] = {D21,D2,D22,D1,D0,D13,D12}; 00276 int area_B_arr[] = {D6,D7,D8}; 00277 00278 const vector<int> area_A(area_A_arr,area_A_arr + sizeof(area_A_arr) / sizeof(int)); 00279 const vector<int> area_B(area_B_arr,area_B_arr + sizeof(area_B_arr) / sizeof(int)); 00280 00281 00282 //......TRAIN CLASS 00283 00284 /** 00285 * 00286 *Train class. 00287 * 00288 *@position - 00289 *@going_cw - 00290 * 00291 *Train(int, bool) - 00292 *Train(bool) - 00293 * 00294 *Vector get_next_sensors() - 00295 *set_position(int) - 00296 *set_goes_cw(bool) - 00297 *Position get_position() - 00298 *Int get_position_number() - 00299 *Bool goes_cw() - 00300 * 00301 **/ 00302 class Train{ 00303 00304 private: 00305 00306 unsigned int train_address; //stop the train 00307 Position *position; 00308 bool going_cw; 00309 int speed; 00310 00311 public: 00312 Train(int pos, bool cw){ 00313 00314 position = &positions[pos]; 00315 going_cw = cw; 00316 } 00317 00318 /** 00319 * Contructor that takes the address of the train and the speed with default value MEDIUM. 00320 */ 00321 Train(unsigned int address, int s=MEDIUM){ 00322 train_address = address; 00323 speed = s; 00324 } 00325 00326 Train(bool cw){ going_cw = cw; } 00327 00328 vector<int> get_next_sensors(){ 00329 00330 //Checking direction 00331 if(going_cw){ 00332 00333 return position->get_next_cw(); 00334 }else{ 00335 00336 return position->get_next_ccw(); 00337 } 00338 } 00339 00340 vector<int> get_previous_sensors(){ 00341 00342 //Checking direction 00343 if(going_cw){ 00344 00345 return position->get_next_ccw(); 00346 }else{ 00347 00348 return position->get_next_cw(); 00349 } 00350 } 00351 00352 void set_speed(int s){ 00353 speed = s; 00354 } 00355 00356 /** 00357 * Sends a DCC command to the train with the speed indicaed by the attribute speed 00358 * The number of times the command is sent can be indicated as an optional parameter. Default value is 1. 00359 */ 00360 void run(int times=1){ 00361 00362 const unsigned int DCCinst_forward_slow = 0x66; //forward slow speed (step 9) 00363 const unsigned int DCCinst_forward_medium = 0x68; //forward half speed 00364 const unsigned int DCCinst_forward_fast = 0x6C; //Forward fast speed (step 22) 00365 const unsigned int DCCinst_forward_full = 0x6F; //Forward full speed 00366 const unsigned int DCCinst_reverse_medium = 0x48; //reverse half speed 00367 const unsigned int DCCinst_stop = 0x50; //stop the train 00368 00369 switch(speed){ 00370 case STOP: 00371 DCC_send_command(train_address, DCCinst_stop,times); 00372 break; 00373 case SLOW: 00374 DCC_send_command(train_address, DCCinst_forward_slow,times); 00375 break; 00376 case MEDIUM: 00377 DCC_send_command(train_address, DCCinst_forward_medium,times); 00378 break; 00379 case FAST: 00380 DCC_send_command(train_address, DCCinst_forward_fast,times); 00381 break; 00382 case FULL: 00383 DCC_send_command(train_address, DCCinst_forward_full,times); 00384 break; 00385 case R_MEDIUM: 00386 DCC_send_command(train_address, DCCinst_reverse_medium,times); 00387 break; 00388 } 00389 } 00390 00391 void set_position(int pos){ 00392 00393 position = &positions[pos]; //Taking the new position from the positions vector 00394 } 00395 00396 void set_goes_cw(bool cw){ 00397 00398 going_cw = cw; 00399 } 00400 00401 Position get_position(){ 00402 00403 return *position; 00404 } 00405 00406 int get_position_number(){ 00407 00408 return position->get_pos(); 00409 } 00410 00411 bool goes_cw(){ 00412 00413 return going_cw; 00414 } 00415 00416 00417 /** 00418 * 00419 *Checks if the element exists within the vector. 00420 * 00421 *@v - The vector (of ints) the method will go through. 00422 *@element - The element the method will look for. 00423 * 00424 **/ 00425 bool in_vector(vector<int>v,int element){ 00426 00427 bool exist = false; 00428 00429 for(int i=0; i< v.size(); i++){ 00430 00431 if(v[i] == element){ 00432 00433 exist = true; 00434 } 00435 } 00436 return exist; 00437 } 00438 00439 bool is_in_A(){ 00440 return in_vector(area_A,get_position_number()); 00441 00442 } 00443 00444 bool is_in_B(){ 00445 00446 return in_vector(area_B,get_position_number()); 00447 } 00448 }; 00449 00450 00451 //------GLOBAL VARS AND INITS 00452 00453 //......POSITIONS INIT 00454 00455 //Creation of all the positions. One for every sensor on the table - Position name(mapping) 00456 Position d0(D0); 00457 Position d1(D1); 00458 Position d2(D2); 00459 Position d3(D3); 00460 Position d4(D4); 00461 Position d5(D5); 00462 Position d6(D6); 00463 Position d7(D7); 00464 Position d8(D8); 00465 Position d9(D9); 00466 Position d10(D10); 00467 Position d11(D11); 00468 Position d12(D12); 00469 Position d13(D13); 00470 Position d21(D21); 00471 Position d22(D22); 00472 00473 00474 //......TRAINS INIT 00475 00476 /** 00477 *Creation of 2 Train objects. 00478 *Using boolean constructor because position initialization will be done after initializing all position vectors. 00479 *DR_train = Dark Red train - LR_train = Light Red Train 00480 **/ 00481 Train DR_train(DCCaddressDR,MEDIUM); 00482 Train LR_train(DCCaddressLR,MEDIUM); 00483 00484 00485 //......FLAGS INIT 00486 00487 //possibility of an array having {dr_train, lr_train}? for reuse and modularity of functions 00488 00489 int speedcheck = 0; 00490 00491 bool station_stop = false; 00492 00493 00494 00495 //**************** FUNCTIONS FOR DENVER TRAIN ****************// 00496 00497 00498 /** 00499 * 00500 *Activates the buzzer for 0.5 seconds. 00501 * 00502 **/ 00503 void doBuzz(){ 00504 00505 buzz = 1; 00506 wait(0.5); 00507 buzz = 0; 00508 } 00509 00510 00511 /** 00512 * 00513 *Initializes every position's vectors (prev_cw and prev_ccw) with the corresponding sensors. 00514 *prev_cw - Sensors previous to the current in clockwise sense. 00515 *prev_ccw - Sensors previous to the current in counter-clockwise sense. 00516 * 00517 **/ 00518 void init_positions(){ 00519 00520 d0.add_prev_cw(D1); 00521 d0.add_prev_ccw(D13); 00522 00523 d1.add_prev_cw(D22); 00524 d1.add_prev_ccw(D0); 00525 00526 d22.add_prev_cw(D2); 00527 d22.add_prev_ccw(D1); 00528 00529 d2.add_prev_cw(D21); 00530 d2.add_prev_ccw(D22); 00531 00532 d21.add_prev_cw(D3); 00533 d21.add_prev_cw(D4); 00534 d21.add_prev_ccw(D2); 00535 00536 d3.add_prev_cw(D9); 00537 d3.add_prev_ccw(D21); 00538 00539 d4.add_prev_cw(D6); 00540 d4.add_prev_ccw(D21); 00541 00542 d5.add_prev_cw(D6); 00543 d5.add_prev_ccw(D11); 00544 00545 d6.add_prev_cw(D7); 00546 d6.add_prev_ccw(D4); 00547 d6.add_prev_ccw(D5); 00548 00549 d7.add_prev_cw(D8); 00550 d7.add_prev_ccw(D6); 00551 00552 d8.add_prev_cw(D9); 00553 d8.add_prev_cw(D10); 00554 d8.add_prev_ccw(D7); 00555 00556 d9.add_prev_cw(D3); 00557 d9.add_prev_ccw(D8); 00558 00559 d10.add_prev_cw(D12); 00560 d10.add_prev_ccw(D8); 00561 00562 d11.add_prev_cw(D12); 00563 d11.add_prev_ccw(D5); 00564 00565 d12.add_prev_cw(D13); 00566 d12.add_prev_ccw(D10); 00567 d12.add_prev_ccw(D11); 00568 00569 d13.add_prev_cw(D0); 00570 d13.add_prev_ccw(D12); 00571 00572 //Initialize array with positions 00573 positions.push_back(d0); 00574 positions.push_back(d1); 00575 positions.push_back(d2); 00576 positions.push_back(d3); 00577 positions.push_back(d4); 00578 positions.push_back(d5); 00579 positions.push_back(d6); 00580 positions.push_back(d7); 00581 positions.push_back(d8); 00582 positions.push_back(d9); 00583 positions.push_back(d10); 00584 positions.push_back(d11); 00585 positions.push_back(d12); 00586 positions.push_back(d13); 00587 positions.push_back(d21); 00588 positions.push_back(d22); 00589 } 00590 00591 00592 /** 00593 * 00594 *Here we initialize the mcp that will be used to manage the interrupts. 00595 * 00596 **/ 00597 void initialize_mcp(){ 00598 mcp = new MCP23017(i2c,0x40); //Connect to SCL - p28 and SDA - p27 and MPC I2C address 0x40 00599 00600 mcp->_write(IODIRA, (unsigned char )0xff); 00601 mcp->_write(IODIRB, (unsigned char )0xff); 00602 mcp->_write(IPOLA, (unsigned char )0x00); 00603 mcp->_write(IPOLB, (unsigned char )0x00); 00604 mcp->_write(DEFVALA, (unsigned char )0xff); 00605 mcp->_write(DEFVALB, (unsigned char )0xff); 00606 mcp->_write(INTCONA, (unsigned char )0xff); 00607 mcp->_write(INTCONB, (unsigned char )0xff); 00608 mcp->_write(IOCONA, (unsigned char )0x2); 00609 mcp->_write(IOCONB, (unsigned char )0x2); 00610 mcp->_write(GPPUA, (unsigned char )0xff); 00611 mcp->_write(GPPUB, (unsigned char )0xff); 00612 00613 } 00614 00615 00616 /** 00617 * 00618 *Returns the number of the sensor where the train was detected. 00619 * 00620 *@number - 00621 *@interrupt - 00622 * 00623 **/ 00624 int get_sensor(unsigned int number,int interrupt){ 00625 00626 int sensor = -1; 00627 00628 for(int i=0; i<8; i++){ 00629 00630 if(~number & 1<<i){ 00631 00632 sensor = i; 00633 } 00634 } 00635 00636 if(interrupt == 1){ 00637 00638 sensor+= 8; // Sensors caught by interreupt1 are identified from 8 to 15. 00639 } 00640 00641 return sensor; 00642 } 00643 00644 00645 /** 00646 * 00647 *Method to flip the switches 00648 * 00649 *@switchId - (1-4)The ID of the switch we want to flip 00650 *@times - The number of times we want to send the command 00651 *@activate - True if the switch is going to be activated. False if it needs to go back to rest position. 00652 * 00653 **/ 00654 void flip_switch(int switchId, int times, bool activate=true){ 00655 00656 unsigned int SWBflip = SWBidle; //IDLE - Flip last activated SW. 00657 00658 switch(switchId){ 00659 00660 case 1: 00661 SWBflip = SWBflip_1; //FLIP SW1 00662 break; 00663 00664 case 2: 00665 SWBflip = SWBflip_2; //FLIP SW2 00666 break; 00667 00668 case 3: 00669 SWBflip = SWBidle; //FLIP SW3 00670 break; 00671 00672 case 4: 00673 SWBflip = SWBflip_4; //FLIP SW4 00674 break; 00675 00676 default: 00677 break; 00678 } 00679 00680 //Security measure not to burn the switch. 00681 DCC_send_command(SWBaddress,SWBflip,times); //Activating switch 00682 00683 if(!activate){ 00684 if(switchId == 3){ 00685 DCC_send_command(SWBaddress,SWBflip_3,times); // Exception for switch 3 00686 }else{ 00687 DCC_send_command(SWBaddress,SWBidle,times); 00688 } 00689 } 00690 00691 } 00692 00693 00694 /** 00695 * Action to do when NAC is detected 00696 * Booster is disabled and the buzz is activated 00697 * 00698 */ 00699 void NAC_action(){ 00700 enable = 0; 00701 doBuzz(); 00702 } 00703 00704 00705 00706 /** 00707 * 00708 *This method will check if there is a non-avoidable frontal collision(NAFC). 00709 *A NAFC will happen if: 00710 * 00711 *Both trains in area A or B with different direction 00712 *Trains in (D11 and D5) or (D9 and D3) with same direction 00713 * 00714 **/ 00715 bool check_NAC(){ 00716 00717 bool NAC = false; 00718 00719 if((DR_train.is_in_A() && LR_train.is_in_A()) || (DR_train.is_in_B() && LR_train.is_in_B()) ){ //Check if both are in same area 00720 00721 if(DR_train.goes_cw() ^ LR_train.goes_cw()){ //XOR: They must have different values to be true (Different direction) 00722 lcd.cls(); 00723 lcd.printf("NAC Both area A or B"); 00724 NAC = true; 00725 } 00726 }else if(((DR_train.get_position_number() == D11) && (LR_train.get_position_number() == D5 ) ) || ((LR_train.get_position_number() == D5) && (DR_train.get_position_number() == D11 ))){ //Check if they are in position D11 and D5 00727 00728 if(!(DR_train.goes_cw() ^ LR_train.goes_cw())){ // NOT XOR: They must have same values to be true (Same direction) 00729 lcd.cls(); 00730 lcd.printf("NAC D11 and D5"); 00731 NAC = true; 00732 } 00733 }else if(((DR_train.get_position_number() == D9) && (LR_train.get_position_number() == D3)) || ((LR_train.get_position_number() == D9) && (DR_train.get_position_number() == D3)) ){//Check if they are in position D9 and D3 00734 00735 if(!(DR_train.goes_cw() ^ LR_train.goes_cw())){ // NOT XOR: They must have same values to be true (Same direction) 00736 lcd.cls(); 00737 lcd.printf("NAC D9 and D3"); 00738 NAC = true; 00739 } 00740 } 00741 return NAC; 00742 } 00743 00744 00745 /** 00746 * Switch_n switch that needs to switch 00747 * cont_sensor sensor that when activated the stopped train continues 00748 * switch_sensor sensor where the switch should be activated 00749 */ 00750 void AFC_action(int switch_n, int cont_sensor, int switch_sensor, Train *stop_train, Train * cont_train ){ 00751 00752 bool send_pack_switch = false; 00753 00754 if(switch_n == 3){ 00755 DCC_send_command(SWBaddress,SWBflip_3,15); //Activating switchç 00756 } 00757 00758 while(cont_train->get_position_number() != cont_sensor){ 00759 00760 if(cont_train->get_position_number() == switch_sensor){ 00761 00762 send_pack_switch = true; 00763 } 00764 stop_train->set_speed(STOP); 00765 stop_train->run(); //Stopping train on sensor D4 or D10 00766 cont_train->run(); 00767 00768 if(send_pack_switch){ 00769 00770 lcd.cls(); 00771 lcd.printf("Switching SW%d",switch_n); 00772 flip_switch(switch_n,5); 00773 } 00774 } 00775 00776 if(switch_n == 3){ 00777 00778 DCC_send_command(SWBaddress,SWBflip_3,15); //Activating switch 00779 }else{ 00780 00781 flip_switch(5,5); //Send IDLE command 00782 } 00783 stop_train->set_speed(MEDIUM); 00784 } 00785 00786 00787 /** 00788 * 00789 * Switch_n switch that needs to switch 00790 * cont_sensor sensor that when activated the stopped train continues 00791 * switch_sensor sensor where the switch should be activated 00792 * 00793 */ 00794 void ALC_action(int cont_sensor, Train *stop_train, Train * cont_train ){ 00795 00796 while(cont_train->get_position_number() != cont_sensor){ 00797 00798 stop_train->set_speed(STOP); 00799 stop_train->run(); //Stopping train on sensor D4 or D10 00800 cont_train->run(); 00801 } 00802 stop_train->set_speed(MEDIUM); 00803 } 00804 00805 00806 /** 00807 * 00808 *The function will check if there is an Avoidable Frontal Collision (AFC). 00809 *AFC will occur if: 00810 * 00811 *Train in area A(ccw) and train in D4(cw) 00812 *Train in area A(cw) and train in D10(ccw) 00813 *Train in area B(cw) and train in D4(ccw) 00814 *Train in area B(ccw) and train in D10(ccw) 00815 * 00816 *stop_train is the train that is going to stop in sensors D4 or D10 until the other train passes 00817 *cont_train is the train that won't stop and will do the switch 00818 * 00819 **/ 00820 bool check_AFC(Train *stop_train, Train *cont_train){ //TODO - Add same for LR train 00821 00822 bool detected_AFC = false; 00823 if( stop_train->get_position_number() == D4){ 00824 00825 if(stop_train->goes_cw()){ 00826 00827 if(cont_train->is_in_A() && !cont_train->goes_cw()){ 00828 00829 detected_AFC = true; 00830 lcd.cls(); 00831 lcd.printf("AFC!!! STOP D4 SW2 CONT D3"); 00832 00833 AFC_action(2,D3,D2,stop_train,cont_train); 00834 //Activate switch2 00835 //When cont_train is at D3 stop_train continues 00836 } 00837 }else{ //DR goes ccw 00838 00839 if(cont_train->is_in_B() && cont_train->goes_cw()){ 00840 00841 detected_AFC = true; 00842 lcd.cls(); 00843 lcd.printf("AFC!!! STOP D4 SW3 CONT D5"); 00844 00845 AFC_action(3,D5,D6,stop_train,cont_train); 00846 //DR_train stops 00847 //Activate switch3 00848 //When LR is at D5 DR continues 00849 } 00850 } 00851 }else if(stop_train->get_position_number() == D10){ 00852 00853 if(stop_train->goes_cw()){ 00854 00855 if(cont_train->is_in_B() && !cont_train->goes_cw()){ 00856 00857 detected_AFC = true; 00858 lcd.cls(); 00859 lcd.printf("AFC!!! STOP D10 SW4 CONT D9"); 00860 00861 AFC_action(4,D9,D8,stop_train,cont_train); 00862 //DR train stops 00863 //Activate switch4 00864 //When LR is at D9 DR continues 00865 } 00866 }else{ 00867 00868 if(cont_train->is_in_A() && cont_train->goes_cw()){ 00869 00870 detected_AFC = true; 00871 lcd.cls(); 00872 lcd.printf("AFC!!! STOP D10 SW1 CONT D11"); 00873 AFC_action(1,D11,D12,stop_train,cont_train); 00874 //DR train stops 00875 //Activate switch1 00876 //When LR is at D11 DR continues 00877 } 00878 } 00879 }else if(stop_train->get_position_number() == D9){ 00880 00881 if(stop_train->goes_cw()){ 00882 00883 if(cont_train->is_in_B() && !cont_train->goes_cw()){ 00884 00885 detected_AFC = true; 00886 lcd.cls(); 00887 lcd.printf("AFC!!! STOP D9 CONT D8"); 00888 AFC_action(5, D10, D4, stop_train, cont_train); 00889 //train in 9 stops 00890 //when cont_train is at d10 stop train continues 00891 } 00892 } 00893 }else if(stop_train->get_position_number() == D11){ 00894 00895 if(!stop_train->goes_cw()){ 00896 00897 if(cont_train->is_in_A() && cont_train->goes_cw()){ 00898 00899 detected_AFC = true; 00900 lcd.cls(); 00901 lcd.printf("AFC!!! STOP D11 CONT D12"); 00902 AFC_action(5, D10, D4, stop_train, cont_train); 00903 //train in 11 stops 00904 //when cont_train is at d10 stop train continues 00905 } 00906 } 00907 }else if(stop_train->get_position_number() == D3){ 00908 00909 if(stop_train->goes_cw()){ 00910 00911 if(cont_train->is_in_A() && !cont_train->goes_cw()){ 00912 00913 detected_AFC = true; 00914 lcd.cls(); 00915 lcd.printf("AFC!!! STOP D3 CONT D14"); 00916 AFC_action(5, D4, D10, stop_train, cont_train); 00917 //train in 3 stops 00918 //when cont_train is at d4 stop train continues 00919 } 00920 } 00921 00922 }else if(stop_train->get_position_number() == D5){ 00923 00924 if(!stop_train->goes_cw()){ 00925 00926 if(cont_train->is_in_B() && cont_train->goes_cw()){ 00927 00928 detected_AFC = true; 00929 lcd.cls(); 00930 lcd.printf("AFC!!! STOP D5 CONT D6"); 00931 AFC_action(5, D4, D10, stop_train, cont_train); 00932 //train in 5 stops 00933 //when cont_train is at d4 stop train continues 00934 } 00935 } 00936 } 00937 return detected_AFC; 00938 } 00939 00940 00941 /** 00942 * 00943 * 00944 * 00945 **/ 00946 bool check_ALC(Train *stop_train, Train *cont_train){ //TODO - Add same for LR train 00947 00948 bool detected_ALC = false; 00949 00950 if( stop_train->get_position_number() == D4){ 00951 00952 if(stop_train->goes_cw()){ 00953 00954 if(cont_train->get_position_number() == D3 && cont_train->goes_cw()){ 00955 00956 detected_ALC = true; 00957 lcd.cls(); 00958 lcd.printf("ALC!!! STOP D4 CONT D3"); 00959 ALC_action(2, stop_train, cont_train ); 00960 //When cont_train is at D22 stop_train continues 00961 } 00962 }else{ //DR goes ccw 00963 00964 if(cont_train->get_position_number() == D5 && !cont_train->goes_cw()){ 00965 00966 detected_ALC = true; 00967 lcd.cls(); 00968 lcd.printf("ALC!!! STOP D4 SW3 CONT D5"); 00969 ALC_action(7, stop_train, cont_train ); 00970 //Train stops 00971 //When CONT is at D6 DR continues 00972 } 00973 } 00974 }else if(stop_train->get_position_number() == D10){ 00975 00976 if(stop_train->goes_cw()){ 00977 00978 if(cont_train->get_position_number() == D9 && cont_train->goes_cw()){ 00979 00980 detected_ALC = true; 00981 lcd.cls(); 00982 lcd.printf("ALC!!! STOP D10 CONT D9"); 00983 ALC_action(8, stop_train, cont_train ); 00984 //D10 train stops 00985 //When CONT is at D8, D10 continues 00986 } 00987 }else{ 00988 00989 if(cont_train->get_position_number() == D11 && !cont_train->goes_cw()){ 00990 00991 detected_ALC = true; 00992 lcd.cls(); 00993 lcd.printf("ALC!!! STOP D10 CONT D11"); 00994 ALC_action(12, stop_train, cont_train ); 00995 //D10 train stops 00996 //When CONT is at D12, D10 continues 00997 } 00998 } 00999 } 01000 return detected_ALC; 01001 } 01002 01003 01004 /** 01005 * 01006 * 01007 * 01008 **/ 01009 void stay_at_distance(Train* train_front, Train* train_back){ 01010 01011 led1 = 0; 01012 led2 = 0; 01013 led3 = 0; 01014 01015 for(int i=0; i<train_back->get_next_sensors().size(); i++){ 01016 01017 for(int j=0; j<train_front->get_previous_sensors().size(); j++){ 01018 01019 while(train_back->get_next_sensors()[i] == train_front->get_previous_sensors()[j]){ 01020 01021 //lcd.cls(); 01022 //lcd.printf("TOO CLOSE! S %d", train_back->get_next_sensors()[i]); 01023 led1 = 1; 01024 led3 = 1; 01025 //stop back train 01026 train_back->set_speed(STOP); 01027 train_back->run(); 01028 train_front->run(); 01029 led1 = 0; 01030 led2 = 0; 01031 led3 = 0; 01032 } 01033 led1 = 1; 01034 led2 = 1; 01035 led3 = 1; 01036 train_back->set_speed(MEDIUM); 01037 train_back->run(); 01038 } 01039 } 01040 led1 = 0; 01041 led2 = 0; 01042 led3 = 0; 01043 } 01044 01045 01046 01047 /** 01048 * 01049 *The method check_position will check if any of the trains is in any of the areas. 01050 *It will go through all the area vectors (A,B) and call the function in_vector to check inside the vectors. 01051 * 01052 **/ 01053 void check_position(){ 01054 01055 //stay_at_distance(&DR_train,&LR_train); 01056 //stay_at_distance(&LR_train,&DR_train); 01057 01058 if(check_NAC()){ NAC_action(); } 01059 01060 check_AFC(&DR_train,&LR_train); 01061 check_AFC(&LR_train,&DR_train); 01062 check_ALC(&LR_train,&DR_train); 01063 check_ALC(&DR_train,&LR_train); 01064 } 01065 01066 01067 /** 01068 * 01069 * 01070 * 01071 **/ 01072 void printPos(int sensor){ 01073 01074 string DR_dir,LR_dir; 01075 01076 if(DR_train.goes_cw()){ DR_dir = "cw";} 01077 else{DR_dir = "ccw";} 01078 01079 if(LR_train.goes_cw()){LR_dir = "cw";} 01080 else{LR_dir = "ccw";} 01081 01082 lcd.cls(); 01083 lcd.printf("S:D%d DR%d(",sensor,DR_train.get_position_number()); 01084 01085 for(int i=0; i<DR_train.get_next_sensors().size(); i++){ 01086 01087 lcd.printf("%d,",DR_train.get_next_sensors()[i]); 01088 } 01089 01090 lcd.printf(")%s LR%d(",DR_dir,LR_train.get_position_number()); 01091 01092 for(int i=0; i<LR_train.get_next_sensors().size(); i++){ 01093 01094 lcd.printf("%d,",LR_train.get_next_sensors()[i]); 01095 } 01096 lcd.printf(")%s",LR_dir); 01097 } 01098 01099 01100 /** 01101 * 01102 *Description 01103 * 01104 *@sensor - 01105 * 01106 **/ 01107 void update_train_pos(int sensor){ 01108 01109 //bool found_DR = false; 01110 //bool found_LR = false; 01111 01112 01113 if(sensor == DR_train.get_position_number() || sensor == LR_train.get_position_number()){ 01114 redled = 1; 01115 }else{ 01116 01117 redled = 0; 01118 printPos(sensor); 01119 01120 //Checking next sensors for DR train 01121 for(int i=0; i<DR_train.get_next_sensors().size(); i++){ 01122 01123 if(DR_train.get_next_sensors()[i] == sensor){ //If the sensor is one expected to visit by the train we update the position 01124 01125 //found_DR = true; 01126 01127 if(DR_train.goes_cw()){ 01128 if(DR_train.get_position_number() == D5 || DR_train.get_position_number() == D11){ 01129 01130 DR_train.set_goes_cw(false); //If train goes cw and passes D5 or D11 we change orientation 01131 } 01132 }else{ 01133 01134 if(DR_train.get_position_number() == D9 || DR_train.get_position_number() == D3){ 01135 01136 DR_train.set_goes_cw(true); //If train goes ccw and passes D9 or D3 we change orientation 01137 } 01138 } 01139 01140 DR_train.set_position(sensor); 01141 01142 } 01143 } 01144 01145 //Checking next sensors for LR train 01146 for(int i=0; i<LR_train.get_next_sensors().size(); i++){ 01147 01148 if(LR_train.get_next_sensors()[i] == sensor){ 01149 01150 //found_LR = true; 01151 01152 if(LR_train.goes_cw()){ 01153 01154 if(LR_train.get_position_number() == D5 || LR_train.get_position_number() == D11){ 01155 LR_train.set_goes_cw(false); //If train goes cw and passes D5 or D11 we change orientation 01156 } 01157 }else{ 01158 01159 if(LR_train.get_position_number() == D9 || LR_train.get_position_number() == D3 ){ 01160 01161 LR_train.set_goes_cw(true); //If train goes ccw and passes D9 or D3 we change orientation 01162 } 01163 } 01164 LR_train.set_position(sensor); 01165 01166 if(sensor == D2 && station_stop){ 01167 01168 DR_train.set_speed(STOP); 01169 LR_train.set_speed(STOP); 01170 } 01171 } 01172 } 01173 } 01174 } 01175 01176 01177 /** 01178 * 01179 *Method to catch interrupts 0 01180 * 01181 **/ 01182 void on_int0_change(){ 01183 01184 wait_us(2000); 01185 int sensor_data = mcp->_read(INTCAPA); 01186 int sensor = get_sensor(sensor_data,0); 01187 update_train_pos(sensor); 01188 } 01189 01190 01191 /** 01192 * 01193 *Method to catch interrupts 1 01194 * 01195 **/ 01196 void on_int1_change(){ 01197 01198 wait_us(2000); 01199 int sensor_data = mcp->_read(INTCAPB); 01200 int sensor = get_sensor(sensor_data,1); 01201 update_train_pos(sensor); 01202 } 01203 01204 01205 /** 01206 * 01207 *Clear current interrupts 01208 * 01209 **/ 01210 void init() { 01211 01212 mcp->_read(GPIOA); 01213 mcp->_read(GPIOB); // Register callbacks 01214 int0.fall(&on_int0_change); 01215 int1.fall(&on_int1_change); // Enable interrupts on MCP 01216 mcp->_write(GPINTENA, (unsigned char )0xff); 01217 mcp->_write(GPINTENB, (unsigned char )0xff); // Ready to go! 01218 } 01219 01220 01221 /** 01222 * 01223 *Checks if any of the switches of the box has been activated. 01224 *Calls necessary function and displays LCD text. 01225 * 01226 **/ 01227 void checkSwitch(){ 01228 01229 if(switch1 == 1){ 01230 01231 //lcd.cls(); 01232 //lcd.printf("TRAIN NOW WILL STOP AT STATION"); 01233 station_stop = true; 01234 }else{ 01235 01236 station_stop = false; 01237 LR_train.set_speed(MEDIUM); 01238 DR_train.set_speed(MEDIUM); 01239 } 01240 if(switch2 == 1){ 01241 01242 //lcd.cls(); 01243 //lcd.printf("SPEEDCHECKMODE"); 01244 //change to speedcheckmode 01245 speedcheck = 1; 01246 }else{ 01247 01248 //lcd.cls(); 01249 //lcd.printf("NORMAL MODE"); 01250 speedcheck = 0; 01251 }if(switch3 == 0){ 01252 01253 if(speedcheck>0){ 01254 01255 //lcd.cls(); 01256 //lcd.printf("SPEED TRAIN DARK RED"); 01257 speedcheck = 2; 01258 } 01259 }else if(switch4 == 0){ 01260 01261 if(speedcheck>0){ 01262 01263 //lcd.cls(); 01264 //lcd.printf("SPEED TRAIN LIGHT RED"); 01265 speedcheck = 3; 01266 } 01267 } 01268 } 01269 01270 01271 /** 01272 * 01273 * Returns a sensor number depending on how many times switch3 flips. 01274 * When pressing switch4 it confirms the switch 01275 * Init_sensor is the value where we start counting. 01276 * string train is the name of the train that will be prited with the sensor 01277 * 01278 */ 01279 int select_sensor(int init_sensor, string train){ 01280 01281 lcd.cls(); 01282 lcd.printf("%s SENSOR D%d",train,init_sensor); 01283 01284 int sensor = init_sensor; 01285 bool changed = false; 01286 bool exit = false; 01287 01288 while(!exit){ 01289 01290 if(switch3 == 0){ 01291 01292 if(changed){ 01293 01294 sensor++; 01295 sensor=sensor%15; //Only sensors from 0 to 15. 01296 changed=false; 01297 lcd.cls(); 01298 lcd.printf("%s: D%d",train,sensor); 01299 } 01300 }else{ 01301 01302 changed = true; 01303 wait(0.2); 01304 } 01305 if(switch4 == 0){ 01306 01307 exit = true; 01308 wait(0.2); 01309 } 01310 } 01311 return sensor; 01312 } 01313 01314 01315 /** 01316 * Returns a boolean representing the direction. Everytimew switch3 is 0 it changes the direction. 01317 * When switch4 is 0 the selection is confirmed. 01318 * Init_going_cw is the initial direction. 01319 * Train is the string with the name of the train that will be printed next to the direction 01320 */ 01321 bool select_direction(bool init_going_cw,string train){ 01322 01323 string dir_string; 01324 01325 if(init_going_cw){dir_string = "cw";} 01326 else{dir_string = "ccw";} 01327 01328 lcd.cls(); 01329 lcd.printf("%s DIRECTION %s ",train,dir_string); 01330 01331 bool exit = false; 01332 bool going_cw = init_going_cw; 01333 bool changed = false; 01334 01335 while(!exit){ 01336 01337 if(switch3 == 0){ 01338 01339 if(changed){ 01340 01341 going_cw = !going_cw; 01342 changed = false; 01343 string dir; 01344 01345 if(going_cw){dir = "cw";} 01346 else{dir = "ccw";} 01347 01348 lcd.cls(); 01349 lcd.printf("%s: %s",train,dir); 01350 } 01351 }else{ 01352 01353 changed = true; 01354 wait(0.2); 01355 } 01356 if(switch4 == 0){ 01357 01358 exit = true; 01359 wait(0.2); 01360 } 01361 } 01362 return going_cw; 01363 } 01364 01365 01366 /** 01367 * 01368 * 01369 * 01370 **/ 01371 void adjustSpeed(Train* train){ 01372 01373 float f = pot.read(); 01374 float vin = f * 3.3; 01375 01376 if(0<=vin && vin<0.60){ 01377 01378 //speed = slow 01379 train->set_speed(SLOW); 01380 }else if(0.60<vin && vin<1.20){ 01381 01382 //speed medium 01383 train->set_speed(MEDIUM); 01384 }else if(1.20<vin && vin<2.20){ 01385 01386 //speed fast 01387 train->set_speed(FAST); 01388 }else if(2.20<vin && vin<3.20){ 01389 01390 //speed full 01391 train->set_speed(FULL); 01392 } 01393 } 01394 01395 /** 01396 * 01397 * 01398 * 01399 **/ 01400 void switch_toSpeed(){ 01401 01402 switch(speedcheck){ 01403 01404 case 1: 01405 adjustSpeed(&DR_train); 01406 adjustSpeed(&LR_train); 01407 01408 case 2: 01409 adjustSpeed(&DR_train); 01410 01411 case 3: 01412 adjustSpeed(&LR_train); 01413 01414 } 01415 } 01416 01417 01418 01419 //**************** MAIN PROGRAM FOR DENVER TRAIN ****************// 01420 01421 01422 int main() 01423 { 01424 01425 enable = 0; 01426 01427 //Led routine to start main program 01428 wait(0.2); 01429 led1 = 1; 01430 01431 init_positions(); 01432 initialize_mcp(); //mcp initialization for interrupts before train running 01433 init(); 01434 01435 int DR_init_sensor = select_sensor(D4,"DR"); 01436 bool DR_init_dir = select_direction(false,"DR"); 01437 01438 wait(0.5); 01439 01440 int LR_init_sensor = select_sensor(D10,"LR"); 01441 bool LR_init_dir = select_direction(false,"LR"); 01442 01443 DR_train.set_position(DR_init_sensor); 01444 DR_train.set_goes_cw(DR_init_dir); 01445 01446 LR_train.set_position(LR_init_sensor); 01447 LR_train.set_goes_cw(LR_init_dir); 01448 01449 string DR_print_dir, LR_print_dir; 01450 01451 if(DR_train.goes_cw()){DR_print_dir = "cw";} 01452 else{DR_print_dir = "ccw";} 01453 01454 if(LR_train.goes_cw()){LR_print_dir = "cw";} 01455 else{LR_print_dir = "ccw";} 01456 01457 lcd.cls(); 01458 lcd.printf("DR(%d)%s \n LR(%d)%s",DR_train.get_position_number(),DR_print_dir,LR_train.get_position_number(),LR_print_dir); 01459 01460 wait(2); 01461 01462 //LED2+LED3 Shows start of route + LCD notif 01463 led2 = 1; // Entering the while 01464 wait(0.4); 01465 led3 = 1; // Entering the while 01466 wait(0.4); 01467 01468 lcd.cls(); 01469 lcd.printf("Ready to start"); 01470 wait(1); 01471 01472 enable = 1; 01473 01474 led1 = 0; 01475 led2 = 0; 01476 led3 = 0; 01477 01478 //Demo for stopping at the station 01479 while(1) { 01480 01481 DR_train.run(); 01482 LR_train.run(); 01483 check_position(); 01484 //checkSwitch(); //Checks for switch commands everytime. 01485 //switch_toSpeed(); 01486 01487 } 01488 } 01489 01490 01491 //**********************SAVED CODE CHUNKS****************************// 01492 01493 01494 /**Flip switch-idle routine 01495 01496 flip_switch(5,15);//Send IDLE command at the beginning 01497 flip_switch(1,40); 01498 wait(0.5); 01499 flip_switch(5,15); 01500 flip_switch(2,15); 01501 wait(0.5); 01502 flip_switch(5,15); 01503 flip_switch(3,40); 01504 wait(0.5); 01505 flip_switch(5,15); 01506 flip_switch(4,15); 01507 wait(0.5); 01508 flip_switch(5,15); 01509 01510 **/ 01511 01512 /**Code for train to stop at station 01513 01514 if(station == 1){ //If train is on the sensor at the middle of the station it stops and displays LCD text. 01515 01516 lcd.cls(); 01517 lcd.printf("All aboard\n mind the gap"); 01518 DCC_send_command(DCCaddressDR,DCCinst_stop,400); 01519 lcd.cls(); 01520 01521 }else{ 01522 DR_train.run(); 01523 LR_train.run(); 01524 01525 } 01526 01527 **/ 01528 01529 01530 /**Train light routine to start running 01531 01532 01533 DCC_send_command(DCCaddressDR,DCC_func_lighton,200); // turn light on full 01534 DCC_send_command(DCCaddressDR,DCC_func_dimlight,400); // dim light 01535 DCC_send_command(DCCaddressDR,DCC_func_lighton,200); // light full again 01536 01537 01538 **/ 01539 01540 /**Print if train is found and updated in update_Train_pos(); 01541 if(found_DR){ 01542 01543 //doBuzz(); 01544 lcd.cls(); 01545 lcd.printf("DR is at D%d",DR_train.get_position_number()); 01546 } 01547 01548 if(found_LR){ 01549 01550 lcd.cls(); 01551 lcd.printf("LR is at D%d",LR_train.get_position_number()); 01552 } 01553 01554 if(!found_DR && !found_LR){ 01555 01556 lcd.cls(); 01557 lcd.printf("No train before :("); 01558 } 01559 **/ 01560 01561 01562 /**Print sensor interrupts in int0 and int1 functions 01563 01564 //lcd.cls(); 01565 //lcd.printf("int0 0x%x \n Sensor: %d",sensor_data,sensor); 01566 01567 **/ 01568 01569 /**Print the potentiometer value 01570 01571 //lcd.cls(); 01572 // lcd.printf("vin: %.4f",vin); 01573 01574 **/ 01575 01576 /** Chunk 1 of comments from main 01577 01578 //RISE FOR INTERRUPTS?? NOT WORKING ATM 01579 //int0.rise(&interrupt0); 01580 //int1.rise(&interrupt1); 01581 01582 //Read and display potentiometer 01583 //float f = pot.read(); 01584 //float vin = f * 3.3; 01585 //lcd.printf("vin: %.4f",vin); 01586 01587 //0xFFFC //1111111111111100 01588 01589 **/
Generated on Fri Jul 15 2022 07:12:37 by
1.7.2