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.
Diff: main.cpp
- Revision:
- 62:6fc0c683cb02
- Parent:
- 59:032005c5a495
- Child:
- 63:86f8dfa007ac
diff -r 032005c5a495 -r 6fc0c683cb02 main.cpp
--- a/main.cpp Thu Jun 21 17:55:51 2018 +0000
+++ b/main.cpp Mon Jun 25 10:43:54 2018 +0000
@@ -4,9 +4,13 @@
#include <string>
#include <iostream>
#include <vector>
+#include <fstream>
+#include <sstream>
using namespace std;
+
+LocalFileSystem local("local");
/******PINS AND DECLARATIONS*******/
@@ -35,7 +39,6 @@
DigitalIn station(p15); //Sensor in the middle of the station
//p16
-
//ENABLE - p17
DigitalOut enable(p17);
@@ -52,8 +55,7 @@
TextLCD lcd(p22,p21,p23,p24,p25,p26); // RS, E, A4, A5, A6, A7 // ldc.cls() to clear and printf(String up to 16char)
///p27
-
-//I2C - p28
+///p28
I2C i2c(p28,p27);
//LED1 - p29
@@ -92,7 +94,7 @@
#define D21 14
#define D22 15
-//Definition of the speeds trains can drive at. Will be interpreted as ints for the program's logic
+
#define STOP 0
#define SLOW 1
#define MEDIUM 2
@@ -101,6 +103,7 @@
#define R_MEDIUM 5
+
/**
*
*Position class.
@@ -113,11 +116,9 @@
*
*get_pos() -
*get_prev_cw() -
-*get_next_cw() -
-*add_prev_ccw() -
-*add_cnext_ccw() -
-*add_prev_ccw() -
+*get_ccw() -
*add_prev_cw() -
+*add_ccw() -
*
**/
class Position{
@@ -125,7 +126,6 @@
int position;
vector <int> previous_cw;
vector <int> previous_ccw;
-
public:
Position(int p){
position = p;
@@ -220,7 +220,6 @@
}
}
-
/**
*Defining areas for train detection and collision logic.
*area_A_arr/area_B_arr - Arrays that hold the Dsensors for each area, used to initialize the vectors.
@@ -233,35 +232,29 @@
const vector<int> area_B(area_B_arr,area_B_arr + sizeof(area_B_arr) / sizeof(int));
+
/**
*
*Train class.
*
-*@train_address -
*@position -
*@going_cw -
-*@speed -
*
*Train(int, bool) -
-*Train(address, s) -
+*Train(bool) -
*
-*set_speed(int) -
+*Vector get_next_sensors() -
*set_position(int) -
*set_goes_cw(bool) -
-*
-*Vector get_next_sensors() -
*Position get_position() -
*Int get_position_number() -
*Bool goes_cw() -
-*Bool is_in_A() -
-*Bool is_in_B() -
-*
-*run(int) -
*
**/
class Train{
- private:
+ private:
+
unsigned int train_address; //stop the train
Position *position;
bool going_cw;
@@ -275,19 +268,25 @@
}
/**
- *Constructor that takes the address of the train and the speed with default value MEDIUM.
- **/
- Train(unsigned int address, int s = MEDIUM){
-
+ * Contructor that takes the address of the train and the speed with default value MEDIUM.
+ */
+ Train(unsigned int address, int s=MEDIUM){
train_address = address;
speed = s;
}
-
+
+ Train(bool cw){ going_cw = cw; }
+
vector<int> get_next_sensors(){
//Checking direction
- if(going_cw){return position->get_next_cw();}
- else{return position->get_next_ccw();}
+ if(going_cw){
+
+ return position->get_next_cw();
+ }else{
+
+ return position->get_next_ccw();
+ }
}
void set_speed(int s){
@@ -298,7 +297,7 @@
* Sends a DCC command to the train with the speed indicaed by the attribute speed
* The number of times the command is sent can be indicated as an optional parameter. Default value is 1.
*/
- void run(int times = 1){
+ void run(int times=1){
const unsigned int DCCinst_forward_slow = 0x66; //forward slow speed (step 9)
const unsigned int DCCinst_forward_medium = 0x68; //forward half speed
@@ -308,27 +307,21 @@
const unsigned int DCCinst_stop = 0x50; //stop the train
switch(speed){
-
- case STOP:
+ case STOP:
DCC_send_command(train_address, DCCinst_stop,times);
break;
-
case SLOW:
DCC_send_command(train_address, DCCinst_forward_slow,times);
break;
-
case MEDIUM:
DCC_send_command(train_address, DCCinst_forward_medium,times);
break;
-
case FAST:
DCC_send_command(train_address, DCCinst_forward_fast,times);
break;
-
case FULL:
DCC_send_command(train_address, DCCinst_forward_full,times);
break;
-
case R_MEDIUM:
DCC_send_command(train_address, DCCinst_reverse_medium,times);
break;
@@ -360,6 +353,7 @@
return going_cw;
}
+
/**
*
*Checks if the element exists within the vector.
@@ -383,13 +377,13 @@
}
bool is_in_A(){
+ return in_vector(area_A,get_position_number());
- return in_vector(area_A, get_position_number());
}
bool is_in_B(){
- return in_vector(area_B, get_position_number());
+ return in_vector(area_B,get_position_number());
}
};
@@ -453,19 +447,131 @@
*Using boolean constructor because position initialization will be done after initializing all position vectors.
*DR_train = Dark Red train - LR_train = Light Red Train
**/
-Train DR_train(DCCaddressDR,MEDIUM);
+Train DR_train(DCCaddressDR,FAST);
Train LR_train(DCCaddressLR,MEDIUM);
//possibility of an array having {dr_train, lr_train}? for reuse and modularity of functions
+//****** SYSTEM LOGGER FUNCTIONS ******//
+
/**
-*Booleans that will determine if the train should be moving or not.
-*Booleans will switch to false to stop any of the trains and avoid collisions.
-*DR_run - Boolean for DR_train / LR_run - Boolean for LR_train
+*
+*
+*
+**/
+string train_dir_toString(Train* train){
+
+ string dir_string;
+
+ if(train->goes_cw()){
+
+ dir_string = "cw";
+ }else{
+
+ dir_string = "ccw";
+ }
+ return dir_string;
+}
+
+/**
+*
+*
+*
+**/
+string train_pos_toString(Train* train){
+
+ int i = train->get_position_number();
+ std::string tr_pos;
+ std::stringstream ss;
+
+ ss << i;
+ tr_pos = ss.str();
+
+ return tr_pos;
+}
+
+
+/**
+*
+*
+*
+**/
+void logger_add(string s){
+
+ FILE *fp = fopen("/local/sys_log.txt", "a");
+ fprintf(fp, "%s \n", s);
+ fclose(fp);
+
+}
+
+
+/**
+*
+*
+*
**/
-bool DR_run = true;
-bool LR_run = true;
+void init_logger(){
+
+ FILE *fp = fopen("/local/sys_log.txt", "w");
+
+ fprintf(fp, "Log for the main train program: \n");
+ fprintf(fp, "------------------------------- \n \n");
+
+ fclose(fp);
+
+}
+
+/**
+*
+*
+*
+**/
+void train_pos0_log(){
+
+ FILE *fp = fopen("/local/sys_log.txt", "a");
+
+ fprintf(fp, "DR_train START: D%s sensor, %s direction. \n", train_pos_toString(&DR_train), train_dir_toString(&DR_train));
+ fprintf(fp, "LR_train START: D%s sensor, %s direction. \n \n", train_pos_toString(&LR_train), train_dir_toString(&LR_train));
+
+ fprintf(fp, "..............Program Start................ \n");
+
+ fclose(fp);
+
+}
+
+void print_next_sensors(Train* train){
+
+ FILE *fp = fopen("/local/sys_log.txt", "a");
+
+ for(int i=0; i<train->get_next_sensors().size(); i++){
+
+ fprintf(fp, "%d" ,train->get_next_sensors()[i]);
+ }
+
+ fprintf(fp, "\n");
+ fclose(fp);
+
+}
+
+void trains_posn_log(int sensor){
+
+ FILE *fp = fopen("/local/sys_log.txt", "a");
+
+ fprintf(fp, "SIGNAL FROM SENSOR D%d \n", sensor);
+ fprintf(fp, "DR_train: D%s sensor, %s direction. // Next positions: ", train_pos_toString(&DR_train), train_dir_toString(&DR_train));
+ print_next_sensors(&DR_train);
+
+ fprintf(fp, "LR_train: D%s sensor, %s direction. // Next positions: ", train_pos_toString(&LR_train), train_dir_toString(&LR_train));
+ print_next_sensors(&LR_train);
+ fprintf(fp, "\n");
+
+ fclose(fp);
+}
+
+
+
+
@@ -618,6 +724,63 @@
return sensor;
}
+/**
+*
+*Method to flip the switches
+*
+*@switchId - (1-4)The ID of the switch we want to flip
+*@times - The number of times we want to send the command
+*@activate - True if the switch is going to be activated. False if it needs to go back to rest position.
+*
+**/
+void flip_switch(int switchId, int times, bool activate=true){
+
+ unsigned int SWBflip = SWBidle; //IDLE - Flip last activated SW.
+
+ switch(switchId){
+
+ case 1:
+ SWBflip = SWBflip_1; //FLIP SW1
+ break;
+
+ case 2:
+ SWBflip = SWBflip_2; //FLIP SW2
+ break;
+
+ case 3:
+ SWBflip = SWBflip_3; //FLIP SW3
+ break;
+
+ case 4:
+ SWBflip = SWBflip_4; //FLIP SW4
+ break;
+
+ default:
+ break;
+ }
+
+ //Security measure not to burn the switch.
+ if(times <=5){
+
+ DCC_send_command(SWBaddress,SWBflip,times); //Activating switch
+ if(!activate){
+
+ DCC_send_command(SWBaddress,SWBidle,times); //Sending IDLE to flip back.
+ }
+ }
+}
+
+/**
+* Action to do when NAC is detected
+* Booster is disabled and the buzz is activated
+*
+*/
+void NAC_action(){
+ enable = 0;
+ doBuzz();
+}
+
+
/**
*This method will check if there is a non-avoidable frontal collision(NAFC).
@@ -653,21 +816,34 @@
return NAC;
}
-
-/*
-void AFC_action(int switch_n, int sensor, Train *stop_train, Train * cont_train ){
+/**
+* Switch_n switch that needs to switch
+´* cont_sensor sensor that when activated the stopped train continues
+* switch_sensor sensor where the switch should be activated
+*/
+void AFC_action(int switch_n, int cont_sensor, int switch_sensor, Train *stop_train, Train * cont_train ){
+ bool send_pack_switch = false;
- flip_switch(switch_n,5); //Activate switch 5
+ //flip_switch(switch_n,5);
- while(cont_train->get_position_number() != sensor){
- DR_run = false; //DR has to stop
- LR_run = true; //LR continues
- send_command();
+ while(cont_train->get_position_number() != cont_sensor){
+ if(cont_train->get_position_number() == switch_sensor){
+ send_pack_switch = true;
+ }
+ stop_train->set_speed(STOP);
+ stop_train->run(); //Stopping train on sensor D4 or D10
+ cont_train->run();
+
+ if(send_pack_switch){
+ lcd.cls();
+ lcd.printf("Switching SW%d",switch_n);
+ flip_switch(switch_n,5);
+ }
}
- DR_run = true;
- LR_run = true; //Both trains start to run again
+
+ flip_switch(5,5); //Send IDLE command
+
}
-*/
@@ -679,51 +855,73 @@
*Train in area A(ccw) and train in D4(cw)
*Train in area A(cw) and train in D10(ccw)
*Train in area B(cw) and train in D4(ccw)
-*Train in area B(ccw) and train in D10(ccw)
+*Train in area B(ccw) and train in D10(ccw)
+*
+*stop_train is the train that is going to stop in sensors D4 or D10 until the other train passes
+*cont_train is the train that won't stop and will do the switch
*
**/
-void check_AFC(bool DR_in_A, bool DR_in_B,bool LR_in_A,bool LR_in_B){ //TODO - Add same for LR train
-
- if( DR_train.get_position_number() == D4){
+bool check_AFC(Train *stop_train, Train *cont_train){ //TODO - Add same for LR train
+ bool detected_AFC = false;
+ if( stop_train->get_position_number() == D4){
- if(DR_train.goes_cw()){
+ if(stop_train->goes_cw()){
- if(LR_in_A && !LR_train.goes_cw()){
+ if(cont_train->is_in_A() && !cont_train->goes_cw()){
+
+ lcd.cls();
+ lcd.printf("AFC!!! STOP D4 SW2 CONT D3");
- //Activate switch2
- //DR_train has to stop
- //When LR is at D3 DR continues
+ AFC_action(2,D3,D2,stop_train,cont_train);
+ //Activate switch2
+ //When cont_train is at D3 stop_train continues
+
+ detected_AFC = true;
}
}else{ //DR goes ccw
- if(LR_in_B && LR_train.goes_cw()){
+ if(cont_train->is_in_B() && cont_train->goes_cw()){
+ lcd.cls();
+ lcd.printf("AFC!!! STOP D4 SW3 CONT D5");
+
+ AFC_action(3,D5,D6,stop_train,cont_train);
//DR_train stops
//Activate switch3
//When LR is at D5 DR continues
+ detected_AFC = true;
}
}
- }else if(DR_train.get_position_number() == D10){
+ }else if(stop_train->get_position_number() == D10){
- if(DR_train.goes_cw()){
+ if(stop_train->goes_cw()){
- if(LR_in_B && !LR_train.goes_cw()){
+ if(cont_train->is_in_B() && !cont_train->goes_cw()){
+ lcd.cls();
+ lcd.printf("AFC!!! STOP D10 SW4 CONT D9");
+ AFC_action(4,D9,D8,stop_train,cont_train);
//DR train stops
//Activate switch4
//When LR is at D9 DR continues
+ detected_AFC = true;
}
}else{
- if(LR_in_A && LR_train.goes_cw()){
-
+ if(cont_train->is_in_A() && cont_train->goes_cw()){
+ lcd.cls();
+ lcd.printf("AFC!!! STOP D10 SW1 CONT D11");
+ AFC_action(1,D11,D12,stop_train,cont_train);
//DR train stops
//Activate switch1
- //When LR is at D9 DR continues
+ //When LR is at D11 DR continues
+ detected_AFC = true;
}
}
}
+
+ return detected_AFC;
}
@@ -738,7 +936,12 @@
if(check_NAC()){
lcd.cls();
lcd.printf("NAC!!!");
- }
+ NAC_action();
+ }
+ check_AFC(&DR_train,&LR_train);
+
+ check_AFC(&LR_train,&DR_train);
+
}
@@ -751,31 +954,33 @@
*
**/
void update_train_pos(int sensor){
+ led2 = 1;
bool found_DR = false;
bool found_LR = false;
- string DR_dir, LR_dir;
+
+ string DR_dir,LR_dir;
if(DR_train.goes_cw()){
-
DR_dir = "cw";
}else{
-
DR_dir = "ccw";
}
if(LR_train.goes_cw()){
-
LR_dir = "cw";
}else{
-
LR_dir = "ccw";
}
-
+
+
+ //wait(0.7);
+
if(sensor == DR_train.get_position_number() || sensor == LR_train.get_position_number()){
- //Ignore
+ led2 = 0;
+ }else{
- }else{
+ //trains_posn_log(sensor);
lcd.cls();
lcd.printf("S:D%d DR%d(",sensor,DR_train.get_position_number());
@@ -794,7 +999,8 @@
}
lcd.printf(")%s",LR_dir);
-
+
+
//Checking next sensors for DR train
for(int i=0; i<DR_train.get_next_sensors().size(); i++){
@@ -864,7 +1070,9 @@
lcd.printf("No train before :(");
}
*/
+
}
+
}
@@ -901,13 +1109,12 @@
update_train_pos(sensor);
}
-
/**
*
*Clear current interrupts
*
**/
-void init(){
+void init() {
mcp->_read(GPIOA);
mcp->_read(GPIOB); // Register callbacks
@@ -915,54 +1122,13 @@
int1.fall(&on_int1_change); // Enable interrupts on MCP
mcp->_write(GPINTENA, (unsigned char )0xff);
mcp->_write(GPINTENB, (unsigned char )0xff); // Ready to go!
-}
+ }
+
-/**
-*
-*Method to flip the switches
-*
-*@switchId - (1-4)The ID of the switch we want to flip
-*@times - The number of times we want to send the command
-*@activate - True if the switch is going to be activated. False if it needs to go back to rest position.
-*
-**/
-void flip_switch(int switchId, int times, bool activate=true){
-
- unsigned int SWBflip = SWBidle; //IDLE - Flip last activated SW.
-
- switch(switchId){
-
- case 1:
- SWBflip = SWBflip_1; //FLIP SW1
- break;
-
- case 2:
- SWBflip = SWBflip_2; //FLIP SW2
- break;
-
- case 3:
- SWBflip = SWBflip_3; //FLIP SW3
- break;
-
- case 4:
- SWBflip = SWBflip_4; //FLIP SW4
- break;
-
- default:
- break;
- }
+
- //Security measure not to burn the switch.
- if(times <=5){
-
- DCC_send_command(SWBaddress,SWBflip,times); //Activating switch
- if(!activate){
-
- DCC_send_command(SWBaddress,SWBidle,times); //Sending IDLE to flip back.
- }
- }
-}
+
/**
@@ -1015,33 +1181,29 @@
bool exit = false;
while(!exit){
-
if(switch3 == 0){
-
if(changed){
-
sensor++;
sensor=sensor%15; //Only sensors from 0 to 15.
changed=false;
lcd.cls();
lcd.printf("%s: D%d",train,sensor);
}
+
}else{
-
changed = true;
wait(0.2);
}
if(switch4 == 0){
-
exit = true;
wait(0.2);
}
}
+
return sensor;
}
-
/**
* Returns a boolean representing the direction. Everytimew switch3 is 0 it changes the direction.
* When switch4 is 0 the selection is confirmed.
@@ -1053,10 +1215,8 @@
string dir_string;
if(init_going_cw){
-
dir_string = "cw";
}else{
-
dir_string = "ccw";
}
@@ -1068,76 +1228,33 @@
bool changed = false;
while(!exit){
-
if(switch3 == 0){
-
if(changed){
-
going_cw = !going_cw;
changed = false;
string dir;
-
if(going_cw){
-
dir = "cw";
}else{
-
dir = "ccw";
}
-
lcd.cls();
lcd.printf("%s: %s",train,dir);
}
}else{
-
changed = true;
wait(0.2);
}
if(switch4 == 0){
-
exit = true;
wait(0.2);
}
}
+
return going_cw;
}
-
-/**
-*
-*
-*
-**/
-void adjustSpeed(){
-
- float f = pot.read();
- float vin = f * 3.3;
- lcd.cls();
- // lcd.printf("vin: %.4f",vin);
-
- if(0=< vin && vin< 0.60){
-
- //speed = slow
- lcd.printf("SLOW AF");
- }else if(0.60 < vin && vin< 1.20){
-
- //speed medium
- lcd.printf("MEDIUM");
- }else if(1.20 < vin && vin< 2.20){
-
- //speed fast
- lcd.printf("going fast boii");
- }else if(2.20 < vin && vin<3.20){
-
- //speed full
- lcd.printf("full POWAH BABY");
- }
-}
-
-
-
-
//**************** MAIN PROGRAM FOR DENVER TRAIN ****************//
@@ -1219,8 +1336,22 @@
lcd.printf("Ready to start");
wait(1);
+ //init_logger();
+ //train_pos0_log();
+ //logger_add("There we go lads this is the start of the program");
+
enable = 1;
+ flip_switch(5,5);//Send IDLE command at the beginning
+ flip_switch(1,5);
+ flip_switch(5,5);
+ flip_switch(2,5);
+ flip_switch(5,5);
+ flip_switch(3,5);
+ flip_switch(5,5);
+ flip_switch(4,5);
+ flip_switch(5,5);
+
//Demo for stopping at the station
while(1) {