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:
- 57:ee5da8a011e0
- Parent:
- 56:fe999806787d
- Child:
- 58:b60db1092088
- Child:
- 60:a1b987ad45fb
--- a/main.cpp Thu Jun 21 12:22:36 2018 +0000 +++ b/main.cpp Thu Jun 21 15:39:05 2018 +0000 @@ -91,6 +91,12 @@ #define D22 15 +#define STOP 0 +#define SLOW 1 +#define MEDIUM 2 +#define FAST 3 +#define FULL 4 +#define R_MEDIUM 5 /** @@ -156,6 +162,74 @@ /** * +*Method to send DCC commands to train and switches. +* +*@address - (HEX)Address where the commands will be sent +*@inst - (HEX)Number of instruction that will be commanded +*@repeat_count - Number of times the command will be sent +* +**/ +void DCC_send_command(unsigned int address, unsigned int inst, unsigned int repeat_count){ + + unsigned __int64 command = 0x0000000000000000; // __int64 is the 64-bit integer type + unsigned __int64 temp_command = 0x0000000000000000; + unsigned __int64 prefix = 0x3FFF; // 14 "1" bits needed at start + unsigned int error = 0x00; //error byte + + //calculate error detection byte with xor + error = address ^ inst; + + //combine packet bits in basic DCC format + command = (prefix<<28)|(address<<19)|(inst<<10)|((error)<<1)|0x01; + //printf("\n\r %llx \n\r",command); + + int i=0; + //repeat DCC command lots of times + while(i < repeat_count) { + + temp_command = command; + //loops through packet bits encoding and sending out digital pulses for a DCC command + for (int j=0; j<64; j++) { + + if((temp_command&0x8000000000000000)==0) { + //test packet bit + //send data for a "0" bit + Track=0; + wait_us(100); + Track=1; + wait_us(100); + //printf("0011"); + }else{ + + //send data for a "1"bit + Track=0; + wait_us(58); + Track=1; + wait_us(58); + //printf("01"); + } + // next bit in packet + temp_command = temp_command<<1; + } + i++; + } +} + +/** +*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. +*area_A/area_B - Vectors that hold the different sensors of the corresponding areas of the track. +**/ +int area_A_arr[] = {D21,D2,D22,D1,D0,D13,D12}; +int area_B_arr[] = {D6,D7,D8}; + +const vector<int> area_A(area_A_arr,area_A_arr + sizeof(area_A_arr) / sizeof(int)); +const vector<int> area_B(area_B_arr,area_B_arr + sizeof(area_B_arr) / sizeof(int)); + + + +/** +* *Train class. * *@position - @@ -174,10 +248,12 @@ **/ class Train{ - private: - int mode; + private: + + unsigned int train_address; //stop the train Position *position; bool going_cw; + int speed; public: Train(int pos, bool cw){ @@ -186,8 +262,16 @@ going_cw = cw; } + /** + * 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 @@ -200,6 +284,45 @@ } } + void set_speed(int s){ + speed = s; + } + + /** + * 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){ + + const unsigned int DCCinst_forward_slow = 0x66; //forward slow speed (step 9) + const unsigned int DCCinst_forward_medium = 0x68; //forward half speed + const unsigned int DCCinst_forward_fast = 0x6C; //Forward fast speed (step 22) + const unsigned int DCCinst_forward_full = 0x6F; //Forward full speed + const unsigned int DCCinst_reverse_medium = 0x48; //reverse half speed + const unsigned int DCCinst_stop = 0x50; //stop the train + + switch(speed){ + 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; + } + } + void set_position(int pos){ position = &positions[pos]; //Taking the new position from the positions vector @@ -224,6 +347,39 @@ return going_cw; } + + + /** + * + *Checks if the element exists within the vector. + * + *@v - The vector (of ints) the method will go through. + *@element - The element the method will look for. + * + **/ + bool in_vector(vector<int>v,int element){ + + bool exist = false; + + for(int i=0; i< v.size(); i++){ + + if(v[i] == element){ + + exist = true; + } + } + return exist; + } + + bool is_in_A(){ + return in_vector(area_A,get_position_number()); + + } + + bool is_in_B(){ + + return in_vector(area_B,get_position_number()); + } }; @@ -245,25 +401,11 @@ Position d21(D21); Position d22(D22); -/** -*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. -*area_A/area_B - Vectors that hold the different sensors of the corresponding areas of the track. -**/ -int area_A_arr[] = {D21,D2,D22,D1,D0,D13,D12}; -int area_B_arr[] = {D6,D7,D8}; - -const vector<int> area_A(area_A_arr,area_A_arr + sizeof(area_A_arr) / sizeof(int)); -const vector<int> area_B(area_B_arr,area_B_arr + sizeof(area_B_arr) / sizeof(int)); -//.....DCC TRAIN COMMAND VARS -//typical out of box default engine DCC address is 3 (at least for Bachmann trains) -//Note: A DCC controller can reprogram the address whenever needed -const unsigned int DCCaddressDR = 0x01; //Address for train 1 DARK-RED -const unsigned int DCCaddressLR = 0x03; //Address for train 3 LIGHT-RED + //01DCSSSS for speed, D is direction (fwd=1 and rev=0), C is speed(SSSSC) LSB const unsigned int DCCinst_forward = 0x68; //forward half speed @@ -293,13 +435,20 @@ const unsigned int SWBflip_4 = 0x88; //Flip SW4 +//.....DCC TRAIN COMMAND VARS + +//typical out of box default engine DCC address is 3 (at least for Bachmann trains) +//Note: A DCC controller can reprogram the address whenever needed +const unsigned int DCCaddressDR = 0x01; //Address for train 1 DARK-RED +const unsigned int DCCaddressLR = 0x03; //Address for train 3 LIGHT-RED + /** *Creation of 2 Train objects. *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(true); //Position and going_cw -Train LR_train(true); +Train DR_train(DCCaddressDR,MEDIUM); +Train LR_train(DCCaddressLR,MEDIUM); //possibility of an array having {dr_train, lr_train}? for reuse and modularity of functions @@ -464,42 +613,22 @@ } -/** -* -*Checks if the element exists within the vector. -* -*@v - The vector (of ints) the method will go through. -*@element - The element the method will look for. -* -**/ -bool in_vector(vector<int>v,int element){ - - bool exist = false; - - for(int i=0; i< v.size(); i++){ - - if(v[i] == element){ - - exist = true; - } - } - return exist; -} + /** -*This method will checks if there is a non-avoidable frontal collision(NAFC). +*This method will check if there is a non-avoidable frontal collision(NAFC). *A NAFC will happen if: * *Both trains in area A or B with different direction *Trains in (D11 and D5) or (D9 and D3) with same direction * */ -bool check_NAC(bool DR_in_A, bool DR_in_B,bool LR_in_A,bool LR_in_B){ +bool check_NAC(){ bool NAC = false; - if((DR_in_A && LR_in_A) || (DR_in_B && LR_in_B) ){ //Check if both are in same area + 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 if(DR_train.goes_cw() ^ LR_train.goes_cw()){ //XOR: They must have different values to be true (Different direction) @@ -598,16 +727,9 @@ *It will go through all the area vectors (A,B) and call the function in_vector to check inside the vectors. * **/ -void check_position(){ - - bool DR_in_A, DR_in_B, LR_in_A, LR_in_B; - - DR_in_A = in_vector(area_A,DR_train.get_position_number()); //Check if DR train is in area A - DR_in_B = in_vector(area_B,DR_train.get_position_number()); - LR_in_A = in_vector(area_A,LR_train.get_position_number()); - LR_in_B = in_vector(area_B,LR_train.get_position_number()); - - if(check_NAC(DR_in_A,DR_in_B,LR_in_A,LR_in_B)){ +void check_position(){ + + if(check_NAC()){ lcd.cls(); lcd.printf("NAC!!!"); } @@ -791,60 +913,7 @@ } -/** -* -*Method to send DCC commands to train and switches. -* -*@address - (HEX)Address where the commands will be sent -*@inst - (HEX)Number of instruction that will be commanded -*@repeat_count - Number of times the command will be sent -* -**/ -void DCC_send_command(unsigned int address, unsigned int inst, unsigned int repeat_count){ - - unsigned __int64 command = 0x0000000000000000; // __int64 is the 64-bit integer type - unsigned __int64 temp_command = 0x0000000000000000; - unsigned __int64 prefix = 0x3FFF; // 14 "1" bits needed at start - unsigned int error = 0x00; //error byte - - //calculate error detection byte with xor - error = address ^ inst; - - //combine packet bits in basic DCC format - command = (prefix<<28)|(address<<19)|(inst<<10)|((error)<<1)|0x01; - //printf("\n\r %llx \n\r",command); - - int i=0; - //repeat DCC command lots of times - while(i < repeat_count) { - - temp_command = command; - //loops through packet bits encoding and sending out digital pulses for a DCC command - for (int j=0; j<64; j++) { - - if((temp_command&0x8000000000000000)==0) { - //test packet bit - //send data for a "0" bit - Track=0; - wait_us(100); - Track=1; - wait_us(100); - //printf("0011"); - }else{ - - //send data for a "1"bit - Track=0; - wait_us(58); - Track=1; - wait_us(58); - //printf("01"); - } - // next bit in packet - temp_command = temp_command<<1; - } - i++; - } -} + /** @@ -926,29 +995,6 @@ } -/** -* -* -* -**/ -void send_command(){ - - if(DR_run){ - - DCC_send_command(DCCaddressDR,DCCinst_forward,1); // Forward half speed train addres DARK-RED - }else{ - - DCC_send_command(DCCaddressDR,DCCinst_stop,400); - } - - if(LR_run){ - - DCC_send_command(DCCaddressLR,DCCinst_forward_fast,1); // Forward half speed train addres DARK-RED - }else{ - - DCC_send_command(DCCaddressLR,DCCinst_stop,400); - } -} /** @@ -960,7 +1006,7 @@ int select_sensor(int init_sensor, string train){ lcd.cls(); - lcd.printf("%s SENSOR",train); + lcd.printf("%s SENSOR D%d",train,init_sensor); int sensor = init_sensor; bool changed = false; @@ -998,8 +1044,17 @@ */ bool select_direction(bool init_going_cw,string train){ + string dir_string; + + if(init_going_cw){ + dir_string = "cw"; + }else{ + dir_string = "ccw"; + } + lcd.cls(); - lcd.printf("%s DIRECTION",train); + lcd.printf("%s DIRECTION %s ",train,dir_string); + bool exit = false; bool going_cw = init_going_cw; bool changed = false; @@ -1061,8 +1116,7 @@ initialize_mcp(); //mcp initialization for interrupts before train running init(); - - + int DR_init_sensor = select_sensor(D9,"DR"); bool DR_init_dir = select_direction(false,"DR"); @@ -1105,7 +1159,9 @@ DCC_send_command(DCCaddressDR,DCC_func_dimlight,400); // dim light DCC_send_command(DCCaddressDR,DCC_func_lighton,200); // light full again */ - + + + //LED3 Shows start of route + LCD notif led3 = 1; // Entering the while lcd.cls(); @@ -1129,7 +1185,8 @@ lcd.cls(); }else{ - send_command(); + DR_train.run(); + LR_train.run(); } }