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 <string> 00003 #include <stdarg.h> 00004 #include "TextLCD.h" 00005 #include "MCP23017.h" 00006 #include "math.h" 00007 #include <list> 00008 00009 const bool test = false; 00010 int iter; 00011 std::list<int> passedMarkers; 00012 std::list<int>::iterator it; 00013 int speedsetting; 00014 00015 //BOX CONNECTIONS 00016 DigitalIn button1 (p8); 00017 DigitalIn button2 (p9); 00018 DigitalIn button3 (p10); 00019 DigitalIn button4 (p30); 00020 AnalogIn potentio (p15); // configures pin15 for analog input. Creates object Ain. It is the potentiometer. 00021 TextLCD lcd(p22, p21, p23, p24, p25, p26); // configures the LCD pins. Creates object lcd 00022 DigitalOut led1(LED1); 00023 DigitalOut led2(LED2); 00024 DigitalOut led3(LED3); 00025 DigitalOut led4(LED4); 00026 DigitalOut boxled1 (p19); 00027 DigitalOut boxled2 (p20); 00028 DigitalOut buzzer (p29); 00029 Serial pc(USBTX, USBRX); // Initialise the serial connection for terminal output 00030 InterruptIn int0(p13); 00031 InterruptIn int1(p14); 00032 I2C i2c(p28, p27); 00033 MCP23017 *mcp; //hall detectors 00034 DigitalOut data(p16); // configures pin16 for digital output. Creates object train. This signal should go to the booster 00035 DigitalOut enable(p17); //configures pin 17 for digital output. creates object enable, this enables the train track or disables it in case of emergency 00036 00037 //CONSTANTS 00038 const unsigned int DCCaddress_train1 = 0x01; 00039 const unsigned int DCCaddress_train2 = 0x02; 00040 const unsigned int DCCaddress_decoder = 0x06; 00041 const unsigned int DCCinst_stop = 0x70; //stop 01 1 1 0000 00042 const unsigned int DCCinst_estop = 0x71; //01 1 1 0001 00043 const unsigned int DCCswitchneutral = 0b10000000; 00044 const unsigned int DCCswitch1 = 0b10000001; 00045 const unsigned int DCCswitch2 = 0b10000010; 00046 const unsigned int DCCswitch3 = 0b10000100; 00047 const unsigned int DCCswitch4 = 0b10001000; 00048 const double stationWaitTime = 5.; 00049 const double switchsafety = 4.; //contant time limit between uses of same switch 00050 const int switchwait = 1500; //time inbetween different switch commands 00051 00052 //interrupt flags 00053 bool int0flag; 00054 bool int1flag; 00055 00056 //global variables for train1 00057 bool dir1; 00058 bool light1; 00059 int speed1; 00060 int prev1; 00061 int curr1; 00062 int next1; 00063 Timer station1; 00064 bool boarding1; 00065 bool command1; 00066 00067 bool collision; 00068 00069 //global variables for train2 00070 bool dir2; 00071 bool light2; 00072 int speed2; 00073 int prev2; 00074 int curr2; 00075 int next2; 00076 Timer station2; 00077 bool boarding2; 00078 bool command2; 00079 00080 //global variables for switches 00081 std::time_t switch1action; 00082 std::time_t switch2action; 00083 std::time_t switch3action; 00084 std::time_t switch4action; 00085 bool switch1; 00086 bool switch2; 00087 bool switch3; 00088 bool switch4; 00089 00090 //FUNCTION PROTOTYPES 00091 void init_mcp(void); 00092 void on_int0_change(void); 00093 void on_int1_change(void); 00094 std::list<int> circuit0markers(int sensor_data); 00095 std::list<int> circuit1markers(int sensor_data); 00096 00097 void displayTerminalStatus(void); 00098 void displayLCDstatus(void); 00099 00100 void init(void); 00101 void initSwitches(void); 00102 void startupWait(void); 00103 void emergencyStop(void); 00104 void handleInt0(void); 00105 void handleInt1(void); 00106 void trainCommand(void); 00107 void updateTrainStatus(int marker); 00108 int predictNextMarker(int prev, int curr); 00109 void iterAction(void); 00110 00111 void changeSwitch1(bool); 00112 void changeSwitch2(bool); 00113 void changeSwitch3(bool); 00114 void changeSwitch4(bool); 00115 void updateTrainPredictions(void); 00116 00117 unsigned int trainInstruction(bool direction, bool light, int speed); 00118 void DCC_send_command(unsigned int address, unsigned int inst, unsigned int repeat_count); 00119 00120 void driveTrain(int train); 00121 void reverseTrain(int train); 00122 void stopTrain(int train); 00123 00124 void atStation2(int train); 00125 void atStation12(int train); 00126 void atSwitch3(int train); 00127 void atSwitch4(int train); 00128 void headCollision(void); 00129 void sideCollision(void); 00130 void xCollision(void); 00131 bool isXCollision(void); 00132 void tailCollision(int backTrain); 00133 void atStation(int train); 00134 //void loopDeltaCrossing(int train); 00135 00136 int main() { 00137 buzzer = 0; 00138 wait_ms(1000); //safety wait when starting (power surge) 00139 enable = false; //track off while doing startup 00140 while(1){ 00141 init(); // initialize all the things to starting values 00142 startupWait(); //wait for user to press button 3 to begin 00143 enable = true; 00144 initSwitches(); //put switches in starting position 00145 wait_ms(2000); //power surge safety 00146 if(int0flag || int1flag){ 00147 pc.printf("WARNING: Initialization power surge! Sensor ignored\n\r"); 00148 if(int0flag){ 00149 int trash = mcp->_read(INTCAPA); 00150 int0flag = false; 00151 } 00152 if(int1flag){ 00153 int trash = mcp->_read(INTCAPB); 00154 int1flag = false; 00155 } 00156 } 00157 00158 if(!test){ 00159 iter = 0; //iter count 00160 while(enable){ 00161 if(!button4){ 00162 emergencyStop(); 00163 break; 00164 } 00165 00166 if(int0flag){ 00167 handleInt0(); //store passed circuit 0 markers in the list passed markers 00168 } 00169 00170 if(int1flag){ 00171 handleInt1(); //same for circuit 1 00172 } 00173 00174 if(!passedMarkers.empty()){ 00175 for (it=passedMarkers.begin(); it!=passedMarkers.end(); ++it){ 00176 if(*it != next1 && *it != next2 && *it != curr1 && *it != curr2){ //TODO check if safe 00177 pc.printf("ERROR: Unexpected marker %d. Expected train1: %d or train2: %d. Sensor failure or unknown object on track. Aborting.\n\r", *it, next1, next2); 00178 enable = false; 00179 break; 00180 } 00181 updateTrainStatus(*it); 00182 } 00183 passedMarkers.clear(); 00184 } 00185 00186 trainCommand(); //decides for a command to send to the track 00187 00188 iterAction(); //every X iterations display some stuff 00189 iter++; 00190 } 00191 } else { 00192 //test scripts 00193 } 00194 } 00195 } 00196 00197 //MAIN LOOP ROUTINES 00198 void init(){ 00199 command1 = false; 00200 command2 = false; 00201 collision = false; 00202 00203 //initialize clock time 00204 set_time(1); 00205 switch1action = time(NULL); 00206 switch2action = time(NULL); 00207 switch3action = time(NULL); 00208 switch4action = time(NULL); 00209 00210 led1 = 0; 00211 led2 = 0; 00212 led3 = 0; 00213 buzzer = 0; 00214 boxled1 = 0; 00215 boxled2 = 0; 00216 00217 speedsetting = 7; 00218 00219 //pc.baud(921600); //faster printing 00220 pc.baud(19200); 00221 00222 //initialize mcp //(initialize interrupt flags) 00223 init_mcp(); 00224 00225 //initialize train globals 00226 dir1 = true; 00227 light1 = true; 00228 speed1 = speedsetting; 00229 boarding1 = false; 00230 //train 1 starting position 00231 prev1 = 0; 00232 curr1 = 1; 00233 next1 = predictNextMarker(prev1, curr1); //2 00234 00235 //global variables for train2 00236 dir2 = true; 00237 light2 = true; 00238 speed2 = speedsetting; 00239 boarding2 = false; 00240 //train 2 starting position 00241 prev2 = 4; 00242 curr2 = 6; 00243 next2 = predictNextMarker(prev2, curr2); //7 00244 00245 //initialize presumed switch positions 00246 switch1 = false; 00247 switch2 = false; 00248 switch3 = false; 00249 switch4 = false; 00250 } 00251 00252 void startupWait(){ 00253 lcd.cls(); 00254 lcd.printf("Press START when ready"); 00255 pc.printf("Press START when ready. Starting position: train 1 between marker 1 and 2, train 2 between marker 6 and 7.\n\r"); 00256 while(button3){ 00257 //do nothing 00258 } 00259 pc.printf("Starting...\n\r"); 00260 } 00261 00262 void initSwitches(){ 00263 wait_ms(switchwait); 00264 changeSwitch1(switch1); 00265 wait_ms(switchwait); 00266 changeSwitch2(switch2); 00267 wait_ms(switchwait); 00268 changeSwitch3(switch3); 00269 wait_ms(switchwait); 00270 changeSwitch4(switch4); 00271 wait_ms(500); 00272 } 00273 00274 void emergencyStop(){ 00275 enable = false; 00276 pc.printf("Emergency stop! Press button 3 when ready to restart\n\r"); 00277 00278 lcd.cls(); 00279 lcd.printf("Press START when ready to restart"); 00280 while(button3){ 00281 //do nothing 00282 } 00283 } 00284 00285 void handleInt0(){ 00286 wait_us(2000); 00287 int sensor_data = mcp->_read(INTCAPA); 00288 int0flag = false; 00289 std::list<int> temp = circuit0markers(sensor_data); 00290 passedMarkers.splice(passedMarkers.end(), temp); 00291 } 00292 00293 void handleInt1(){ 00294 wait_us(2000); 00295 int sensor_data = mcp->_read(INTCAPB); 00296 int1flag = false; 00297 std::list<int> temp = circuit1markers(sensor_data); 00298 passedMarkers.splice(passedMarkers.end(), temp); 00299 } 00300 00301 void updateTrainStatus(int marker){ 00302 if(marker == 21){ 00303 return; //marker 21 is unused 00304 } 00305 00306 if(marker == next1){ 00307 prev1 = curr1; 00308 curr1 = next1; 00309 next1 = predictNextMarker(prev1, curr1); 00310 command1 = false; 00311 collision = false; 00312 pc.printf("STATUS: Train 1 reached marker %d from marker %d. Predicted marker %d\n\r", curr1, prev1, next1); 00313 } else { //marker == next2 00314 prev2 = curr2; 00315 curr2 = next2; 00316 next2 = predictNextMarker(prev2, curr2); 00317 command2 = false; 00318 collision = false; 00319 pc.printf("STATUS: Train 2 reached marker %d from marker %d. Predicted marker %d\n\r", curr2, prev2, next2); 00320 } 00321 } 00322 00323 int predictNextMarker(int prev, int curr){ 00324 switch(prev){ 00325 case 0: switch(curr){ 00326 case 1: return 2; 00327 case 13: return 12; 00328 } 00329 case 1: switch(curr){ 00330 case 2: return switch2?3:4; 00331 case 0: return 13; 00332 } 00333 case 2: switch(curr){ 00334 case 3: return 9; 00335 case 4: return 6; 00336 case 1: return 0; 00337 } 00338 case 3: switch(curr){ 00339 case 9: return 8; 00340 case 2: return 1; 00341 } 00342 case 4: switch(curr){ 00343 case 6: return 7; 00344 case 2: return 1; 00345 } 00346 case 5: switch(curr){ 00347 case 6: return 7; 00348 case 11: return 12; 00349 } 00350 case 6: switch(curr){ 00351 case 4: return 2; 00352 case 5: return 11; 00353 case 7: return 8; 00354 } 00355 case 7: switch(curr){ 00356 case 6: return switch3?5:4; 00357 case 8: return switch4?9:10; 00358 } 00359 case 8: switch(curr){ 00360 case 7: return 6; 00361 case 9: return 3; 00362 case 10: return 12; 00363 } 00364 case 9: switch(curr){ 00365 case 3: return 2; 00366 case 8: return 7; 00367 } 00368 case 10: switch(curr){ 00369 case 8: return 7; 00370 case 12: return 13; 00371 } 00372 case 11: switch(curr){ 00373 case 5: return 6; 00374 case 12: return 13; 00375 } 00376 case 12: switch(curr){ 00377 case 10: return 8; 00378 case 11: return 5; 00379 case 13: return 0; 00380 } 00381 case 13: switch(curr){ 00382 case 0: return 1; 00383 case 12: return switch1?11:10; 00384 } 00385 } 00386 return 666; //TODO default 00387 } 00388 00389 void iterAction(){ 00390 displayLCDstatus(); 00391 if(iter % 100 == 0){ 00392 displayTerminalStatus(); 00393 } 00394 } 00395 00396 //TRAIN COMMAND 00397 void trainCommand(){ 00398 float Vin = potentio.read() * 3.3; 00399 speedsetting = floor(Vin/0.22); //0.22 = 3.3/15 00400 00401 if(boarding1 || boarding2){ 00402 if(station1.read() > stationWaitTime){ //timer works? TODO 00403 boarding1 = false; 00404 led1 = 0; 00405 station1.stop(); 00406 } 00407 00408 if(station2.read() > stationWaitTime){ 00409 boarding2 = false; 00410 led2 = 0; 00411 station2.stop(); 00412 } 00413 } 00414 speed1 = boarding1?0:speedsetting; 00415 speed2 = boarding2?0:speedsetting; 00416 00417 if(next1 == next2 && !collision){ 00418 headCollision(); 00419 collision = true; 00420 } else if ((next1 == curr2 || next2 == curr1) && !collision){ 00421 sideCollision(); 00422 collision = true; 00423 } else if (isXCollision() && !collision){ 00424 xCollision(); 00425 collision = true; 00426 } else if (next1 == prev2 && !command1){ 00427 tailCollision(1); 00428 command1 = true; 00429 } else if (next2 == prev1 && !command1){ 00430 tailCollision(2); 00431 command1 = true; 00432 } else if (curr1 == 2 && !command1){ 00433 atStation2(1); 00434 command1 = true; 00435 } else if (curr1 == 6 && !command1){ 00436 atSwitch3(1); 00437 command1 = true; 00438 } else if (curr1 == 8 && !command1){ 00439 atSwitch4(1); 00440 command1 = true; 00441 } else if (curr1 == 12 && !command1){ 00442 atStation12(1); 00443 command1 = true; 00444 } else if (curr2 == 2 && !command2){ 00445 atStation2(1); 00446 command2 = true; 00447 } else if (curr2 == 6 && !command2){ 00448 atSwitch3(2); 00449 command2 = true; 00450 } else if (curr2 == 8 && !command2){ 00451 atSwitch4(2); 00452 command2 = true; 00453 } else if (curr2 == 12 && !command2){ 00454 atStation12(2); 00455 command2 = true; 00456 } 00457 00458 driveTrain(2); 00459 driveTrain(1); 00460 00461 /* 00462 else if (!command1 && (curr1 == 9 && next1 == 3) || (curr1 == 5 && next1 == 11)){ 00463 loopDeltaCrossing(1); 00464 command1 = true; 00465 } else if (!command2 && (curr2 == 9 && next2 == 3) || (curr2 == 5 && next2 == 11)){ 00466 loopDeltaCrossing(2); 00467 command2 = true; 00468 } 00469 */ 00470 } 00471 00472 bool isXCollision(){ 00473 return (curr1 == 3 && next1 == 9) && (next2 == 5 || next2 == 11) 00474 || (curr1 == 5 && next1 == 11) && (next2 == 3 || next2 == 9) 00475 || (curr1 == 9 && next1 == 3) && (next2 == 5 || next2 == 11) 00476 || (curr1 == 11 && next1 == 5) && (next2 == 3 || next2 == 9) 00477 || (curr2 == 3 && next2 == 9) && (next1 == 5 || next1 == 11) 00478 || (curr2 == 5 && next2 == 11) && (next1 == 3 || next1 == 9) 00479 || (curr2 == 9 && next2 == 3) && (next1 == 5 || next1 == 11) 00480 || (curr2 == 11 && next2 == 5) && (next1 == 3 || next1 == 9); 00481 } 00482 00483 void stopTrain(int train){ 00484 if(train == 1){ 00485 DCC_send_command(DCCaddress_train1, DCCinst_estop, 10); 00486 pc.printf("STATUS: Train 1 stopped\n\r"); 00487 } else { //train == 2 00488 DCC_send_command(DCCaddress_train2, DCCinst_estop, 10); 00489 pc.printf("STATUS: Train 2 stopped\n\r"); 00490 } 00491 } 00492 00493 void reverseTrain(int train){ //always stop before reversing 00494 if(train == 1){ 00495 int stupid; 00496 dir1 = !dir1; 00497 stupid = next1; 00498 next1 = curr1; 00499 curr1 = stupid; 00500 prev1 = predictNextMarker(curr1, next1); 00501 pc.printf("STATUS: Train 1 reversed\n\r"); 00502 } else { //train == 2 00503 int swap; 00504 dir2 = !dir2; 00505 swap = next2; 00506 next2 = curr2; 00507 curr2 = swap; 00508 prev2 = predictNextMarker(curr2, next2); 00509 pc.printf("STATUS: Train 2 reversed\n\r"); 00510 } 00511 } 00512 00513 void driveTrain(int train){ 00514 if(train == 1){ 00515 DCC_send_command(DCCaddress_train1, trainInstruction(dir1, light1, speed1), 25); 00516 } else { //train == 2 00517 DCC_send_command(DCCaddress_train2, trainInstruction(dir2, light2, speed2), 25); 00518 } 00519 } 00520 00521 void atStation2(int train){ 00522 if(train == 1){ 00523 if(next1 != 22){ 00524 pc.printf("STATUS: train 1 reached switch 2\n\r"); 00525 std::time_t current = time(NULL); 00526 if(difftime(current, switch2action) < switchsafety){ 00527 pc.printf("STATUS: Switch 2 on overheat cooldown!\n\r"); 00528 return; 00529 } 00530 stopTrain(1); 00531 if(curr2 == 6 || next2 == 6){ 00532 switch2 = true; 00533 } else if(curr2 == 9 || next2 == 9){ 00534 switch2 = false; 00535 } else { //other train far away 00536 switch2 = rand()%2; 00537 } 00538 changeSwitch2(switch2); 00539 switch2action = time(NULL); 00540 } 00541 atStation(1); 00542 } else { //train == 2 00543 if(next2 != 22){ 00544 pc.printf("STATUS: train 2 reached switch 2\n\r"); 00545 std::time_t current = time(NULL); 00546 if(difftime(current, switch2action) < switchsafety){ 00547 pc.printf("STATUS: Switch 2 on overheat cooldown!\n\r"); 00548 return; 00549 } 00550 stopTrain(2); 00551 if(curr1 == 6 || next1 == 6){ 00552 //switch2 = true; 00553 } else if(curr1 == 9 || next1 == 9){ 00554 //switch2 = false; 00555 } else { //other train far away 00556 switch2 = rand()%2; 00557 } 00558 changeSwitch2(switch2); 00559 switch2action = time(NULL); 00560 } 00561 atStation(2); 00562 } 00563 } 00564 00565 void atStation12(int train){ 00566 if(train == 1){ 00567 if(next1 != 22){ 00568 pc.printf("STATUS: train 1 reached switch 1\n\r"); 00569 std::time_t current = time(NULL); 00570 if(difftime(current, switch1action) < switchsafety){ 00571 pc.printf("STATUS: Switch 1 on overheat cooldown!\n\r"); 00572 return; 00573 } 00574 stopTrain(1); 00575 if(curr2 == 8 || next2 == 8){ 00576 //switch1 = true; 00577 } else if(curr2 == 5 || next2 == 5){ 00578 //switch1 = false; 00579 } else { //other train far away 00580 switch1 = rand()%2; 00581 } 00582 changeSwitch1(switch1); 00583 switch1action = time(NULL); 00584 } 00585 atStation(1); 00586 } else { //train == 2 00587 if(next2 != 22){ 00588 pc.printf("STATUS: train 2 reached switch 1\n\r"); 00589 std::time_t current = time(NULL); 00590 if(difftime(current, switch1action) < switchsafety){ 00591 pc.printf("STATUS: Switch 1 on overheat cooldown!\n\r"); 00592 return; 00593 } 00594 stopTrain(2); 00595 if(curr1 == 8 || next1 == 8){ 00596 //switch1 = true; 00597 } else if(curr1 == 5 || next1 == 5){ 00598 //switch1 = false; 00599 } else { //other train far away 00600 switch1 = rand()%2; 00601 } 00602 changeSwitch1(switch1); 00603 switch1action = time(NULL); 00604 } 00605 atStation(2); 00606 } 00607 } 00608 00609 void atStation(int train){ 00610 if(train == 1){ 00611 pc.printf("STATUS: Train 1 reached station!\n\r"); 00612 boxled1 = 1; 00613 speed1 = 0; 00614 station1.start(); 00615 boarding1 = true; 00616 } else { //train == 2 00617 pc.printf("STATUS: Train 2 reached station!\n\r"); 00618 boxled2 = 1; 00619 speed2 = 0; 00620 station2.start(); 00621 boarding2 = true; 00622 } 00623 } 00624 00625 void atSwitch3(int train){ 00626 if(train == 1){ 00627 if(next1 == 7){ return; } 00628 pc.printf("STATUS: train 1 reached switch 3\n\r"); 00629 std::time_t current = time(NULL); 00630 if(difftime(current, switch3action) < switchsafety){ 00631 pc.printf("STATUS: Switch 3 on overheat cooldown!\n\r"); 00632 return; 00633 } 00634 stopTrain(1); 00635 if(curr2 == 2 || next2 == 2){ 00636 //switch3 = true; TODO complicated 00637 } else if(curr2 == 11 || next2 == 11){ 00638 //switch3 = false; 00639 } else { //other train far away 00640 switch3 = rand()%2; 00641 } 00642 changeSwitch3(switch3); 00643 switch3action = time(NULL); 00644 } else { //train == 2 00645 if(next2 == 7){ return; } 00646 pc.printf("STATUS: train 2 reached switch 3\n\r"); 00647 std::time_t current = time(NULL); 00648 if(difftime(current, switch3action) < switchsafety){ 00649 pc.printf("STATUS: Switch 3 on overheat cooldown!\n\r"); 00650 return; 00651 } 00652 stopTrain(2); 00653 if(curr1 == 2 || next1 == 2){ 00654 //switch3 = true; 00655 } else if(curr1 == 11 || next1 == 11){ 00656 //switch3 = false; 00657 } else { //other train far away 00658 switch3 = rand()%2; 00659 } 00660 changeSwitch3(switch3); 00661 switch3action = time(NULL); 00662 } 00663 } 00664 00665 void atSwitch4(int train){ 00666 if(train == 1){ 00667 if(next1 == 7){ return; } 00668 pc.printf("STATUS: train 1 reached switch 4\n\r"); 00669 std::time_t current = time(NULL); 00670 if(difftime(current, switch4action) < switchsafety){ 00671 pc.printf("STATUS: Switch 4 on overheat cooldown!\n\r"); 00672 return; 00673 } 00674 stopTrain(1); 00675 if(curr2 == 2 || next2 == 2){ 00676 //switch4 = true; 00677 } else if(curr2 == 11 || next2 == 11){ 00678 //switch4 = false; 00679 } else { //other train far away 00680 switch4 = rand()%2; 00681 } 00682 changeSwitch4(switch4); 00683 switch4action = time(NULL); 00684 } else { //train == 2 00685 if(next2 == 7){ return; } 00686 pc.printf("STATUS: train 2 reached switch 4\n\r"); 00687 std::time_t current = time(NULL); 00688 if(difftime(current, switch4action) < switchsafety){ 00689 pc.printf("STATUS: Switch 4 on overheat cooldown!\n\r"); 00690 return; 00691 } 00692 stopTrain(2); 00693 if(curr1 == 2 || next1 == 2){ 00694 //switch4 = true; 00695 } else if(curr1 == 11 || next1 == 11){ 00696 //switch4 = false; 00697 } else { //other train far away 00698 switch4 = rand()%2; 00699 } 00700 changeSwitch4(switch4); 00701 switch4action = time(NULL); 00702 } 00703 } 00704 00705 void headCollision(void){ 00706 buzzer = 1; 00707 pc.printf("WARNING: inbound head collision\n\r"); 00708 stopTrain(1); 00709 stopTrain(2); 00710 reverseTrain(1); 00711 reverseTrain(2); 00712 buzzer = 0; 00713 } 00714 00715 void sideCollision(void){ 00716 buzzer = 1; 00717 pc.printf("WARNING: possible side collision\n\r"); 00718 stopTrain(1); 00719 stopTrain(2); 00720 reverseTrain(1); 00721 reverseTrain(2); 00722 buzzer = 0; 00723 } 00724 00725 void xCollision(void){ 00726 buzzer = 1; 00727 pc.printf("WARNING: possible cross collision\n\r"); 00728 stopTrain(1); 00729 stopTrain(2); 00730 reverseTrain(1); 00731 reverseTrain(2); 00732 buzzer = 0; 00733 } 00734 00735 void tailCollision(int backTrain){ 00736 buzzer = 1; 00737 pc.printf("WARNING: possible tail collision\n\r"); 00738 stopTrain(backTrain); 00739 reverseTrain(backTrain); 00740 buzzer = 0; 00741 } 00742 /* 00743 void loopDeltaCrossing(int train){ 00744 buzzer = 1; 00745 pc.printf("WARNING: attempting to exit the loop\n\r"); 00746 if(train == 1){ 00747 if(curr2 != 13 && curr2 != 0 && curr2 != 1 && curr2 != 2){ 00748 stopTrain(1); 00749 reverseTrain(1); 00750 } 00751 //if train 2 in loop 00752 //stop, reverse 00753 } else { //train == 2 00754 //if train 1 in loop 00755 //stop, reverse 00756 if(curr1 != 13 && curr1 != 0 && curr1 != 1 && curr1 != 2){ 00757 stopTrain(1); 00758 reverseTrain(1); 00759 } 00760 } 00761 buzzer = 0; 00762 } 00763 */ 00764 00765 00766 00767 00768 //TRACK COMMANDS 00769 //code from the tutorial, sends a message to the track through the train pin 00770 void DCC_send_command(unsigned int address, unsigned int inst, unsigned int repeat_count){ 00771 switch(address){ 00772 case DCCaddress_train1: led1 = 1; break; 00773 case DCCaddress_train2: led2 = 1; break; 00774 case DCCaddress_decoder: led3 = 1; break; 00775 } 00776 00777 unsigned __int64 command = 0x0000000000000000; // __int64 is the 64-bit integer type 00778 unsigned __int64 temp_command = 0x0000000000000000; 00779 unsigned __int64 prefix = 0x3FFF; // 14 "1" bits needed at start 00780 unsigned int error = 0x00; //error byte 00781 //calculate error detection byte with xor 00782 error = address ^ inst; 00783 //combine packet bits in basic DCC format 00784 command = (prefix<<28)|(address<<19)|(inst<<10)|((error)<<1)|0x01; 00785 //printf("\n\r %llx \n\r",command); 00786 int i=0; 00787 //repeat DCC command lots of times 00788 while(i < repeat_count) { 00789 temp_command = command; 00790 //loops through packet bits encoding and sending out digital pulses for a DCC command 00791 for (int j=0; j<64; j++) { 00792 if((temp_command&0x8000000000000000)==0) { //test packet bit 00793 //send data for a "0" bit 00794 data=0; 00795 wait_us(100); 00796 data=1; 00797 wait_us(100); 00798 //printf("0011"); 00799 } else { 00800 //send data for a "1"bit 00801 data=0; 00802 wait_us(58); 00803 data=1; 00804 wait_us(58); 00805 //printf("01"); 00806 } 00807 // next bit in packet 00808 temp_command = temp_command<<1; 00809 } 00810 i++; 00811 } 00812 00813 led1 = 0; 00814 led2 = 0; 00815 led3 = 0; 00816 } 00817 00818 void changeSwitch1(bool inwards){ 00819 if(inwards){ 00820 DCC_send_command(DCCaddress_decoder, DCCswitch1, 1); 00821 pc.printf("STATUS: Switch 1 changed inward\n\r"); 00822 } else { 00823 DCC_send_command(DCCaddress_decoder, DCCswitch1, 1); 00824 DCC_send_command(DCCaddress_decoder, DCCswitchneutral, 1); 00825 pc.printf("STATUS: Switch 1 changed outward\n\r"); 00826 } 00827 updateTrainPredictions(); 00828 } 00829 00830 void changeSwitch2(bool inwards){ 00831 if(inwards){ 00832 DCC_send_command(DCCaddress_decoder, DCCswitch2, 1); 00833 pc.printf("STATUS: Switch 2 changed inward\n\r"); 00834 } else { 00835 DCC_send_command(DCCaddress_decoder, DCCswitch2, 1); 00836 DCC_send_command(DCCaddress_decoder, DCCswitchneutral, 1); 00837 pc.printf("STATUS: Switch 2 changed outward\n\r"); 00838 } 00839 updateTrainPredictions(); 00840 } 00841 00842 void changeSwitch3(bool inwards){ 00843 if(inwards){ 00844 DCC_send_command(DCCaddress_decoder, DCCswitch3, 1); 00845 DCC_send_command(DCCaddress_decoder, DCCswitchneutral, 1); //switch 3 has reverse behavior 00846 pc.printf("STATUS: Switch 3 changed inward\n\r"); 00847 } else { 00848 DCC_send_command(DCCaddress_decoder, DCCswitch3, 1); 00849 pc.printf("STATUS: Switch 3 changed outward\n\r"); 00850 } 00851 updateTrainPredictions(); 00852 } 00853 00854 void changeSwitch4(bool inwards){ 00855 if(inwards){ 00856 DCC_send_command(DCCaddress_decoder, DCCswitch4, 1); 00857 pc.printf("STATUS: Switch 4 changed inward\n\r"); 00858 } else { 00859 DCC_send_command(DCCaddress_decoder, DCCswitch4, 1); 00860 DCC_send_command(DCCaddress_decoder, DCCswitchneutral, 1); 00861 pc.printf("STATUS: Switch 4 changed outward\n\r"); 00862 } 00863 updateTrainPredictions(); 00864 } 00865 00866 void updateTrainPredictions(){ 00867 next1 = predictNextMarker(prev1, curr1); 00868 next2 = predictNextMarker(prev2, curr2); 00869 } 00870 00871 unsigned int trainInstruction(bool direction, bool light, int speed){ 00872 unsigned int result = 0x40; //0100 0000 00873 if(direction){ 00874 result += 0x20; //0010 0000 00875 } 00876 if(light){ 00877 result += 0x10; //0001 0000 00878 } 00879 if(speed>0 && speed<15){ 00880 result += speed + 1; 00881 } 00882 return result; 00883 } 00884 00885 //INTERPRET INTERRUPT SIGNALS 00886 //INTERRUPTS 00887 //code from the tutorial, initializes MCP and sets it up for interrupts 00888 void init_mcp() { 00889 // Initialisation of MCP registers, documentation on registers is available at 00890 //Niels/Abel/Robert/Natalia 00891 mcp = new MCP23017(i2c, 0x40); 00892 mcp->_write(IODIRA, (unsigned char )0xff); 00893 mcp->_write(IODIRB, (unsigned char )0xff); 00894 mcp->_write(IPOLA, (unsigned char )0x00); 00895 mcp->_write(IPOLB, (unsigned char )0x00); 00896 mcp->_write(DEFVALA, (unsigned char )0xff); 00897 mcp->_write(DEFVALB, (unsigned char )0xff); 00898 mcp->_write(INTCONA, (unsigned char )0xff); 00899 mcp->_write(INTCONB, (unsigned char )0xff); 00900 mcp->_write(IOCONA, (unsigned char )0x2); 00901 mcp->_write(IOCONB, (unsigned char )0x2); 00902 mcp->_write(GPPUA, (unsigned char )0xff); 00903 mcp->_write(GPPUB, (unsigned char )0xff); 00904 00905 // Clear current interrupts 00906 mcp->_read(GPIOA); 00907 mcp->_read(GPIOB); 00908 // Register callbacks 00909 int0.fall(&on_int0_change); 00910 int1.fall(&on_int1_change); 00911 // Enable interrupts on the MCP 00912 mcp->_write(GPINTENA, (unsigned char )0xff); 00913 mcp->_write(GPINTENB, (unsigned char )0xff); 00914 00915 int0flag = false; 00916 int1flag = false; 00917 } 00918 00919 void on_int0_change() { 00920 int0flag = true; 00921 } 00922 00923 void on_int1_change() { 00924 int1flag = true; 00925 } 00926 00927 std::list<int> circuit0markers(int sensor_data){ 00928 std::list<int> result; 00929 sensor_data = ~sensor_data; 00930 if((sensor_data & 0b00000001) == 0b00000001){ 00931 result.push_back(0); 00932 } 00933 if((sensor_data & 0b00000010) == 0b00000010){ 00934 result.push_back(1); 00935 } 00936 if((sensor_data & 0b00000100) == 0b00000100){ 00937 result.push_back(2); 00938 } 00939 if((sensor_data & 0b00001000) == 0b00001000){ 00940 result.push_back(3); 00941 } 00942 if((sensor_data & 0b00010000) == 0b00010000){ 00943 result.push_back(4); 00944 } 00945 if((sensor_data & 0b00100000) == 0b00100000){ 00946 result.push_back(5); 00947 } 00948 if((sensor_data & 0b01000000) == 0b01000000){ 00949 result.push_back(6); 00950 } 00951 if((sensor_data & 0b10000000) == 0b10000000){ 00952 result.push_back(7); 00953 } 00954 return result; 00955 } 00956 00957 std::list<int> circuit1markers(int sensor_data){ 00958 std::list<int> result; 00959 sensor_data = ~sensor_data; 00960 if((sensor_data & 0b00000001) == 0b00000001){ 00961 result.push_back(8); 00962 } 00963 if((sensor_data & 0b00000010) == 0b00000010){ 00964 result.push_back(9); 00965 } 00966 if((sensor_data & 0b00000100) == 0b00000100){ 00967 result.push_back(10); 00968 } 00969 if((sensor_data & 0b00001000) == 0b00001000){ 00970 result.push_back(11); 00971 } 00972 if((sensor_data & 0b00010000) == 0b00010000){ 00973 result.push_back(12); 00974 } 00975 if((sensor_data & 0b00100000) == 0b00100000){ 00976 result.push_back(13); 00977 } 00978 if((sensor_data & 0b01000000) == 0b01000000){ 00979 //result.push_back(21); do nothing; sensor 21 badly positioned 00980 } 00981 if((sensor_data & 0b10000000) == 0b10000000){ 00982 //result.push_back(22); do nothing; too close 00983 } 00984 return result; 00985 } 00986 00987 //LOG OUTPUT 00988 void displayLCDstatus(){ 00989 lcd.cls(); 00990 lcd.printf("Train 1: %d \nTrain 2: %d", speed1, speed2); 00991 } 00992 00993 void displayTerminalStatus(){ 00994 string dir1Text = dir1?"forward":"reverse"; 00995 string dir2Text = dir2?"forward":"reverse"; 00996 string light1Text = light1?"on, ":"off,"; 00997 string light2Text = light2?"on, ":"off,"; 00998 pc.printf("SYSTEM: Iteration %d\n\r", iter); 00999 pc.printf("Train 1: dir %s, light %s spd %d\n\rTrain 2: dir %s, light %s spd %d\n\r", dir1Text.c_str(), light1Text.c_str(), speed1, dir2Text.c_str(), light2Text.c_str(), speed2); 01000 }
Generated on Tue Aug 2 2022 16:15:12 by
1.7.2