// shared block controller // Norbert Doerry // May 31 2015 // // Rev 1: Jul 2 2015: // Fixed bug wtih CAS sensor // // Rev 2: Dec 20 2015 // reduced coil pulse time from 1000 ms to 500 ms // reduced trip_debounce_off_time from 500 to 150 ms // in process_switch_coil, if entrance switch is in right direction, check exit switch. // // shared block controller // // 5 states // Auto - Reset: both control blocks are "on", waiting for an entrance trip. Enters when Reset button pressed // or trailing edge of exit trip // Auto - Curve: either digital or analog curve entrance trips detect a train in curve entrance block. // switches shifted to curve (if not already there) and straight entrance block is "off" // Auto - Straight: either digial or analog straight entrance trips dects a train in straight entrance block // switches shifted to straight (if not already there) and curve entrance block is "off" // Loccked-Curve: CAS switch is on Curve, straight block is off, switches set to surve (if not already there) // Locked-Straight: CAS switch is on Straight, curve block is off, switches set to straight (if not already there) // // // port assignments const int DO_shared_block_ctrl = 2; const int DO_straight_block_ctrl = 3; const int DO_curve_block_ctrl = 4; const int DO_ent_switch_str_coil = 5; const int DO_ent_switch_crv_coil = 6; const int DO_exit_switch_str_coil = 7; const int DO_exit_switch_crv_coil = 8; const int DI_ent_switch_dir = 9; const int DI_exit_switch_dir = 10; const int DI_exit_trip = 11; const int DI_str_ent_trip = A5; // Port 12 was not working const int DI_crv_ent_trip = 13; const int A_str_ent_trip = 0; const int A_crv_ent_trip = 1; const int A_CAS_switch = 2; const int A_reset_switch = 3; // time unsigned long now_time; // Current Sensor trip parameters const int CS_MIN_HITS = 10; const int CS_TIME_WINDOW = 50; // milliseconds const int CURRENT_LOW_VALUE = 492; // 2.5 volts is no current for sensor = 512 -- 0 = 0 Volts 1023 = 5 volts const int CURRENT_HIGH_VALUE = 532; // const int CURRENT_TIME_LOW_TO_HIGH = 200; // number of ms the sensor has to be high before registering a high const int CURRENT_TIME_HIGH_TO_LOW = 300; // number of ms the sensor has to be low before registering a low int A_str_ent_trip_raw = 512; int A_str_ent_trip_nbr_hits = 0; int A_str_ent_trip_transition = 0; int A_str_ent_trip_d_raw = 0; int A_str_ent_trip_val = 0; // for external use unsigned long A_str_ent_trip_window_start_time = 0; unsigned long A_str_ent_trip_trans_time = 0; int A_crv_ent_trip_raw = 512; int A_crv_ent_trip_nbr_hits = 0; int A_crv_ent_trip_transition = 0; int A_crv_ent_trip_d_raw = 0; int A_crv_ent_trip_val = 0; unsigned long A_crv_ent_trip_window_start_time =0; unsigned long A_crv_ent_trip_trans_time =0; // Curve Auto Straight HMI toggle Switch parameters const int CAS_LOW_VALUE = 340; const int CAS_HIGH_VALUE = 680; const int CAS_debounce_time = 20; // ms const int CAS_CRV = 0; const int CAS_AUTO = 1; const int CAS_STR = 2; int CAS_val = CAS_AUTO; //value to use externally int CAS_raw = 0; // current analog value read in int CAS_d_raw = CAS_AUTO; // translation of raw value into digital int CAS_trans_flag = 0; // if not in transition = 1 if in transition unsigned long CAS_trans_time = 0; // Auto Reset HMI pushbuttton parameters const int RESET_LOW_VALUE = 512; const int RESET_debounce_time = 20; // ms int RESET_val = 0; int RESET_raw = 0; // analog int RESET_d_raw = 0; int RESET_trans_flag = 0; unsigned long RESET_trans_time = 0; // // const int COIL_PULSE_TIME = 1000; // ms const int COIL_PULSE_TIME = 500; // ms -- modified rev 2 int ent_switch_str_coil_val = 0; // = 1 if coil is on, = 0 if off int ent_switch_str_coil_cmd = 0; // external interface command to energize coil unsigned long ent_switch_str_coil_on_time = 0; // time the coil was energized int ent_switch_crv_coil_val = 0; int ent_switch_crv_coil_cmd = 0; unsigned long ent_switch_crv_coil_on_time = 0; int exit_switch_str_coil_val = 0; int exit_switch_str_coil_cmd = 0; unsigned long exit_switch_str_coil_on_time = 0; int exit_switch_crv_coil_val = 0; int exit_switch_crv_coil_cmd = 0; unsigned long exit_switch_crv_coil_on_time = 0; // const int SDIR_UNK = 2; const int SDIR_STR = 0; const int SDIR_CRV = 1; int sdir_ent_val = SDIR_UNK; // value to use externallyy int sdir_exit_val = SDIR_UNK; int sdir_ent_raw = SDIR_UNK; // current value read in int sdir_exit_raw = SDIR_UNK; int sdir_ent_trans_flag = 0; // = 0 if not in transition, = 1 if in transition int sdir_exit_trans_flag = 0; unsigned long sdir_ent_trans_time = 0; // time transition started unsigned long sdir_exit_trans_time = 0; const int sdir_debounce_time = 20; // milliseconds // Trip paramenters const int trip_debounce_on_time = 20; // milliseconds // const int trip_debounce_off_time = 500; // milliseconds const int trip_debounce_off_time = 150; // milliseconds reduced in Rev 2 int dtrip_str_ent = 0; // value to use externally int dtrip_crv_ent = 0; int dtrip_exit = 0; int dtrip_exit_end_edge = 0; // 1 for a cycle after dtrip_exit changes from 1 to 0 int dtrip_str_ent_raw = 0; // value read in from port int dtrip_crv_ent_raw= 0; int dtrip_exit_raw = 0; int dtrip_str_ent_trans_flag = 0; // = 0 not in transistion = 1 in transition int dtrip_crv_ent_trans_flag = 0; int dtrip_exit_trans_flag = 0; unsigned long dtrip_str_ent_trans_time = 0; // time transition started unsigned long dtrip_crv_ent_trans_time = 0; unsigned long dtrip_exit_trans_time = 0; // control block values int shared_block_ctrl_val = 0; int straight_block_ctrl_val = 0; int curve_block_ctrl_val = 0; // display time unsigned long display_last_update_time = 0; const unsigned long DISPLAY_UPDATE_TIME = 350; //ms int clock_val; // control states const int STATE_A_RESET = 0; const int STATE_A_CURVE = 1; const int STATE_A_STRAIGHT = 2; const int STATE_L_CURVE = 3; const int STATE_L_STRAIGHT = 4; int state = 0; int state_new = 0; unsigned long s_time = 0; // time that coil was energized const int S_COIL_ON_TIME = 750; //ms void setup() { pinMode(DO_shared_block_ctrl,OUTPUT); pinMode(DO_straight_block_ctrl,OUTPUT); pinMode(DO_curve_block_ctrl,OUTPUT); pinMode(DO_ent_switch_str_coil,OUTPUT); pinMode(DO_ent_switch_crv_coil,OUTPUT); pinMode(DO_exit_switch_str_coil,OUTPUT); pinMode(DO_exit_switch_crv_coil,OUTPUT); pinMode(DI_ent_switch_dir,INPUT); pinMode(DI_exit_switch_dir,INPUT); pinMode(DI_exit_trip,INPUT); pinMode(DI_str_ent_trip,INPUT); pinMode(DI_crv_ent_trip, INPUT); digitalWrite(DO_shared_block_ctrl,0); digitalWrite(DO_straight_block_ctrl,0); digitalWrite(DO_curve_block_ctrl,0); digitalWrite(DO_ent_switch_str_coil,0); digitalWrite(DO_ent_switch_crv_coil,0); digitalWrite(DO_exit_switch_str_coil,0); digitalWrite(DO_exit_switch_crv_coil,0); // ensure pull up resistor is off digitalWrite(DI_ent_switch_dir,0); digitalWrite(DI_exit_switch_dir,0); digitalWrite(DI_exit_trip,0); digitalWrite(DI_str_ent_trip,0); digitalWrite(DI_crv_ent_trip,0); Serial.begin(9600); // clear the screen Serial.write(254); Serial.write(81); } void loop() { // Read the input values get_raw(); process_sdir(); process_dtrip(); process_atrip(); process_hmi(); calc_state(); process_switch_coil(); process_ctrl_block(); write_to_ports(); write_display(); } void get_raw(void) { now_time = millis(); sdir_ent_raw=digitalRead(DI_ent_switch_dir); sdir_exit_raw=digitalRead(DI_exit_switch_dir); dtrip_exit_raw=digitalRead(DI_exit_trip); dtrip_str_ent_raw=digitalRead(DI_str_ent_trip); dtrip_crv_ent_raw=digitalRead(DI_crv_ent_trip); A_str_ent_trip_raw= analogRead(A_str_ent_trip); A_crv_ent_trip_raw= analogRead(A_crv_ent_trip); CAS_raw= analogRead(A_CAS_switch); RESET_raw = analogRead(A_reset_switch); } void process_sdir(void) { unsigned long time_diff; if (sdir_ent_val == SDIR_UNK) // initialization { sdir_ent_val = sdir_ent_raw; sdir_ent_trans_flag = 0; sdir_ent_trans_time = now_time; } else if (sdir_ent_val == sdir_ent_raw) // see if no change, reset transition { sdir_ent_trans_flag = 0; sdir_ent_trans_time = now_time; } else // mismatch between raw and val { if (sdir_ent_trans_flag == 0) // see if first one { sdir_ent_trans_flag = 1; // start transition sdir_ent_trans_time = now_time; } else // sdir_ent_trans_flag == 1 { if (now_time <= sdir_ent_trans_time) { time_diff = 0; sdir_ent_trans_time = now_time; } else time_diff = now_time - sdir_ent_trans_time; if (time_diff >= sdir_debounce_time) // change state if value is consistent for debounce time { sdir_ent_val = sdir_ent_raw; sdir_ent_trans_flag = 0; sdir_ent_trans_time = now_time; } } } if (sdir_exit_val == SDIR_UNK) // initialization { sdir_exit_val = sdir_exit_raw; sdir_exit_trans_flag = 0; sdir_exit_trans_time = now_time; } else if (sdir_exit_val == sdir_exit_raw) // see if no change, reset transition { sdir_exit_trans_flag = 0; sdir_exit_trans_time = now_time; } else // mismatch between raw and val { if (sdir_exit_trans_flag == 0) // see if first one { sdir_exit_trans_flag = 1; // start transition sdir_exit_trans_time = now_time; } else // sdir_exit_trans_flag == 1 { if (now_time <= sdir_exit_trans_time) { time_diff = 0; sdir_exit_trans_time = now_time; } else time_diff = now_time - sdir_exit_trans_time; if (time_diff >= sdir_debounce_time) // change state if value is consistent for debounce time { sdir_exit_val = sdir_exit_raw; sdir_exit_trans_flag = 0; sdir_exit_trans_time = now_time; } } } } void process_dtrip(void) { unsigned long time_diff; // digital straight entrance trip if (dtrip_str_ent == dtrip_str_ent_raw) // see if no change, reset transition { dtrip_str_ent_trans_flag = 0; dtrip_str_ent_trans_time = now_time; } else // mismatch between raw and val { if (dtrip_str_ent_trans_flag == 0) // see if first one { dtrip_str_ent_trans_flag = 1; // start transition dtrip_str_ent_trans_time = now_time; } else // dtrip_str_ent_trans_flag == 1 { if (now_time <= dtrip_str_ent_trans_time) { time_diff = 0; dtrip_str_ent_trans_time = now_time; } else time_diff = now_time - dtrip_str_ent_trans_time; if (time_diff >= trip_debounce_on_time && dtrip_str_ent_raw == 1) // change state if value is consistent for debounce time { dtrip_str_ent = dtrip_str_ent_raw; dtrip_str_ent_trans_flag = 0; dtrip_str_ent_trans_time = now_time; } if (time_diff >= trip_debounce_off_time && dtrip_str_ent_raw == 0) // change state if value is consistent for debounce time { dtrip_str_ent = dtrip_str_ent_raw; dtrip_str_ent_trans_flag = 0; dtrip_str_ent_trans_time = now_time; } } } // digital curve entrance trip if (dtrip_crv_ent == dtrip_crv_ent_raw) // see if no change, reset transition { dtrip_crv_ent_trans_flag = 0; dtrip_crv_ent_trans_time = now_time; } else // mismatch between raw and val { if (dtrip_crv_ent_trans_flag == 0) // see if first one { dtrip_crv_ent_trans_flag = 1; // start transition dtrip_crv_ent_trans_time = now_time; } else // dtrip_crv_ent_trans_flag == 1 { if (now_time <= dtrip_crv_ent_trans_time) { time_diff = 0; dtrip_crv_ent_trans_time = now_time; } else time_diff = now_time - dtrip_crv_ent_trans_time; if (time_diff >= trip_debounce_on_time && dtrip_crv_ent_raw == 1) // change state if value is consistent for debounce time { dtrip_crv_ent = dtrip_crv_ent_raw; dtrip_crv_ent_trans_flag = 0; dtrip_crv_ent_trans_time = now_time; } if (time_diff >= trip_debounce_off_time && dtrip_crv_ent_raw == 0) // change state if value is consistent for debounce time { dtrip_crv_ent = dtrip_crv_ent_raw; dtrip_crv_ent_trans_flag = 0; dtrip_crv_ent_trans_time = now_time; } } } // exit trip dtrip_exit_end_edge = 0; // reset edge detect if (dtrip_exit == dtrip_exit_raw) // see if no change, reset transition { dtrip_exit_trans_flag = 0; dtrip_exit_trans_time = now_time; } else // mismatch between raw and val { if (dtrip_exit_trans_flag == 0) // see if first one { dtrip_exit_trans_flag = 1; // start transition dtrip_exit_trans_time = now_time; } else // dtrip_exit_trans_flag == 1 { if (now_time <= dtrip_exit_trans_time) { time_diff = 0; dtrip_exit_trans_time = now_time; } else time_diff = now_time - dtrip_exit_trans_time; if (time_diff >= trip_debounce_on_time && dtrip_exit_raw == 1) // change state if value is consistent for debounce time { dtrip_exit = dtrip_exit_raw; dtrip_exit_trans_flag = 0; dtrip_exit_trans_time = now_time; } if (time_diff >= trip_debounce_off_time && dtrip_exit_raw == 0) // change state if value is consistent for debounce time { dtrip_exit = dtrip_exit_raw; dtrip_exit_trans_flag = 0; dtrip_exit_trans_time = now_time; dtrip_exit_end_edge = 1; // edge detect } } } } void process_atrip(void) { unsigned long time_diff; // straight entrance current trip if (now_time <= A_str_ent_trip_window_start_time) { time_diff = 0; A_str_ent_trip_window_start_time = now_time; } else time_diff = now_time - A_str_ent_trip_window_start_time; if (time_diff > CS_TIME_WINDOW) // see if the time window has elapsed without sufficent hits -- write a 0 { A_str_ent_trip_d_raw = 0; A_str_ent_trip_window_start_time = now_time; A_str_ent_trip_nbr_hits = 0; } if (A_str_ent_trip_raw > CURRENT_HIGH_VALUE || A_str_ent_trip_raw < CURRENT_LOW_VALUE) { // a hit -- see if enough hits have been received in the time window to set the output high A_str_ent_trip_nbr_hits = A_str_ent_trip_nbr_hits + 1; if (A_str_ent_trip_nbr_hits >= CS_MIN_HITS) { A_str_ent_trip_d_raw = 1; A_str_ent_trip_window_start_time = now_time; A_str_ent_trip_nbr_hits = 0; } } // see if potentially is in a transition if (now_time < A_str_ent_trip_trans_time) A_str_ent_trip_trans_time = now_time; if (A_str_ent_trip_d_raw != A_str_ent_trip_val) { // see if first time in transition if (A_str_ent_trip_transition == 0) { A_str_ent_trip_trans_time = now_time; A_str_ent_trip_transition = 1; } else // not the first time { // see if transition period done if (A_str_ent_trip_val == 0) // check low to high transition { if (now_time - A_str_ent_trip_trans_time >= CURRENT_TIME_LOW_TO_HIGH) { A_str_ent_trip_val = 1; A_str_ent_trip_transition = 0; } } else // check high to low transition { if (now_time - A_str_ent_trip_trans_time >= CURRENT_TIME_HIGH_TO_LOW) { A_str_ent_trip_val = 0; A_str_ent_trip_transition = 0; } } } } else // not in transition { A_str_ent_trip_transition = 0; } // curve entrance current trip if (now_time <= A_crv_ent_trip_window_start_time) { time_diff = 0; A_crv_ent_trip_window_start_time = now_time; } else time_diff = now_time - A_crv_ent_trip_window_start_time; if (time_diff > CS_TIME_WINDOW) // see if the time window has elapsed without sufficent hits -- write a 0 { A_crv_ent_trip_d_raw = 0; A_crv_ent_trip_window_start_time = now_time; A_crv_ent_trip_nbr_hits = 0; } if (A_crv_ent_trip_raw > CURRENT_HIGH_VALUE || A_crv_ent_trip_raw < CURRENT_LOW_VALUE) { // a hit -- see if enough hits have been received in the time window to set the output high A_crv_ent_trip_nbr_hits = A_crv_ent_trip_nbr_hits + 1; if (A_crv_ent_trip_nbr_hits >= CS_MIN_HITS) { A_crv_ent_trip_d_raw = 1; A_crv_ent_trip_window_start_time = now_time; A_crv_ent_trip_nbr_hits = 0; } } // see if potentially is in a transition if (now_time < A_crv_ent_trip_trans_time) A_crv_ent_trip_trans_time = now_time; if (A_crv_ent_trip_d_raw != A_crv_ent_trip_val) { // see if first time in transition if (A_crv_ent_trip_transition == 0) { A_crv_ent_trip_trans_time = now_time; A_crv_ent_trip_transition = 1; } else // not the first time { // see if transition period done if (A_crv_ent_trip_val == 0) // check low to high transition { if (now_time - A_crv_ent_trip_trans_time >= CURRENT_TIME_LOW_TO_HIGH) { A_crv_ent_trip_val = 1; A_crv_ent_trip_transition = 0; } } else // check high to low transition { if (now_time - A_crv_ent_trip_trans_time >= CURRENT_TIME_HIGH_TO_LOW) { A_crv_ent_trip_val = 0; A_crv_ent_trip_transition = 0; } } } } else // not in transition { A_crv_ent_trip_transition = 0; } } void process_hmi(void) { unsigned long time_diff; // Curve Auto Straight HMI Toggle Switch if (CAS_raw <= CAS_LOW_VALUE) CAS_d_raw = CAS_STR; else if (CAS_raw < CAS_HIGH_VALUE) CAS_d_raw = CAS_AUTO; else CAS_d_raw = CAS_CRV; if (CAS_val == CAS_d_raw) // see if no change, reset transition { CAS_trans_flag = 0; CAS_trans_time = now_time; } else // mismatch between raw and val { if (CAS_trans_flag == 0) // see if first one { CAS_trans_flag = 1; // start transition CAS_trans_time = now_time; } else // CAS_trans_flag == 1 { if (now_time <= CAS_trans_time) { time_diff = 0; CAS_trans_time = now_time; } else time_diff = now_time - CAS_trans_time; if (time_diff >= CAS_debounce_time) // change state if value is consistent for debounce time { CAS_val = CAS_d_raw; CAS_trans_flag = 0; CAS_trans_time = now_time; } } } // Reset Button if (RESET_raw <= RESET_LOW_VALUE) RESET_d_raw = 1; else RESET_d_raw = 0; if (RESET_val == RESET_d_raw) // see if no change, reset transition { RESET_trans_flag = 0; RESET_trans_time = now_time; } else // mismatch between raw and val { if (RESET_trans_flag == 0) // see if first one { RESET_trans_flag = 1; // start transition RESET_trans_time = now_time; } else // RESET_trans_flag == 1 { if (now_time <= RESET_trans_time) { time_diff = 0; RESET_trans_time = now_time; } else time_diff = now_time - RESET_trans_time; if (time_diff >= RESET_debounce_time) // change state if value is consistent for debounce time { RESET_val = RESET_d_raw; RESET_trans_flag = 0; RESET_trans_time = now_time; } } } } void calc_state(void) { // intialize state_new to state state_new = state; if (state == STATE_A_RESET) { if (CAS_val == CAS_STR) state_new = STATE_L_STRAIGHT; else if (CAS_val == CAS_CRV) state_new = STATE_L_CURVE; else if (RESET_val == 1) state_new = STATE_A_RESET; else if (dtrip_str_ent == 1 || A_str_ent_trip_val == 1) state_new = STATE_A_STRAIGHT; else if (dtrip_crv_ent == 1 || A_crv_ent_trip_val == 1) state_new = STATE_A_CURVE; else state_new = STATE_A_RESET; } else if (state == STATE_A_CURVE) { if (CAS_val == CAS_STR) state_new = STATE_L_STRAIGHT; else if (CAS_val == CAS_CRV) state_new = STATE_L_CURVE; else if (RESET_val == 1) state_new = STATE_A_RESET; else if (dtrip_exit_end_edge == 1) state_new = STATE_A_RESET; else state_new = STATE_A_CURVE; } else if (state == STATE_A_STRAIGHT) { if (CAS_val == CAS_STR) state_new = STATE_L_STRAIGHT; else if (CAS_val == CAS_CRV) state_new = STATE_L_CURVE; else if (RESET_val == 1) state_new = STATE_A_RESET; else if (dtrip_exit_end_edge == 1) state_new = STATE_A_RESET; else state_new = STATE_A_STRAIGHT; } else if (state == STATE_L_CURVE) { if (CAS_val == CAS_STR) state_new = STATE_L_STRAIGHT; else if (CAS_val == CAS_CRV) state_new = STATE_L_CURVE; else state_new = STATE_A_RESET; } else if (state == STATE_L_STRAIGHT) { if (CAS_val == CAS_STR) state_new = STATE_L_STRAIGHT; else if (CAS_val == CAS_CRV) state_new = STATE_L_CURVE; else state_new = STATE_A_RESET; } else { state_new = STATE_A_RESET; } // if state_new is different from state, then initiate a transition if (state != state_new) { if (state_new == STATE_A_RESET) { straight_block_ctrl_val = 0; curve_block_ctrl_val = 0; } else if (state_new == STATE_A_CURVE) { shared_block_ctrl_val = 1; straight_block_ctrl_val = 1; curve_block_ctrl_val = 0; ent_switch_crv_coil_cmd = 1; } else if (state_new == STATE_A_STRAIGHT) { shared_block_ctrl_val = 0; straight_block_ctrl_val = 0; curve_block_ctrl_val = 1; ent_switch_str_coil_cmd = 1; } else if (state_new == STATE_L_CURVE) { shared_block_ctrl_val = 1; straight_block_ctrl_val = 1; curve_block_ctrl_val = 0; ent_switch_crv_coil_cmd = 1; } else if (state_new == STATE_L_STRAIGHT) { shared_block_ctrl_val = 0; straight_block_ctrl_val = 0; curve_block_ctrl_val = 1; ent_switch_str_coil_cmd = 1; } else { straight_block_ctrl_val = 1; curve_block_ctrl_val = 1; } } // update the state state = state_new; } void process_switch_coil(void) { unsigned long time_diff; // this routine uses the ent_swtch_xxx_coil_cmd variable to initiate energizing the entrance switch // when the COIL_PULSE_TIME has passed, the entrance switch is turned off and // the exit trip is turned on // after another COIL_PULSE_TIME has passed, the exit trip will turn off // a command to energize a coil when the coil is already energized is ignored // a command to energize a coil when another coil is energized will be saved until no coils are being energized if (ent_switch_str_coil_cmd == 1) exit_switch_str_coil_cmd = 1; // added for rev 2 if (ent_switch_crv_coil_cmd == 1) exit_switch_crv_coil_cmd = 1; // added for rev 2 if (ent_switch_str_coil_cmd == 1 && ent_switch_crv_coil_val == 0 && exit_switch_str_coil_val == 0 && exit_switch_crv_coil_val == 0) { if (ent_switch_str_coil_val == 0 && sdir_ent_val != SDIR_STR) // don't energize if switch is already in right direction { ent_switch_str_coil_on_time = now_time; ent_switch_str_coil_val = 1; } ent_switch_str_coil_cmd = 0; } else if (ent_switch_crv_coil_cmd == 1 && ent_switch_str_coil_val == 0 && exit_switch_str_coil_val == 0 && exit_switch_crv_coil_val == 0) { if(ent_switch_crv_coil_val == 0 && sdir_ent_val != SDIR_CRV) { ent_switch_crv_coil_on_time = now_time; ent_switch_crv_coil_val = 1; } ent_switch_crv_coil_cmd = 0; } if (ent_switch_str_coil_val == 1) { if (now_time <= ent_switch_str_coil_on_time) { time_diff = 0; ent_switch_str_coil_on_time = now_time; } else time_diff = now_time - ent_switch_str_coil_on_time; if (time_diff >= COIL_PULSE_TIME) { ent_switch_str_coil_val = 0; // exit_switch_str_coil_cmd = 1; removed for rev 2 } } if (ent_switch_crv_coil_val == 1) { if (now_time <= ent_switch_crv_coil_on_time) { time_diff = 0; ent_switch_crv_coil_on_time = now_time; } else time_diff = now_time - ent_switch_crv_coil_on_time; if (time_diff >= COIL_PULSE_TIME) { ent_switch_crv_coil_val = 0; // exit_switch_crv_coil_cmd = 1; removed for rev 2 } } if (exit_switch_str_coil_cmd == 1 && exit_switch_crv_coil_val == 0 && ent_switch_str_coil_val == 0 && ent_switch_crv_coil_val == 0) { if (exit_switch_str_coil_val == 0 && sdir_exit_val != SDIR_STR) { exit_switch_str_coil_on_time = now_time; exit_switch_str_coil_val = 1; } exit_switch_str_coil_cmd = 0; } else if (exit_switch_crv_coil_cmd == 1 && exit_switch_str_coil_val == 0 && ent_switch_str_coil_val == 0 && ent_switch_crv_coil_val == 0) { if(exit_switch_crv_coil_val == 0 && sdir_exit_val != SDIR_CRV) { exit_switch_crv_coil_on_time = now_time; exit_switch_crv_coil_val = 1; } exit_switch_crv_coil_cmd = 0; } if (exit_switch_str_coil_val == 1) { if (now_time <= exit_switch_str_coil_on_time) { time_diff = 0; exit_switch_str_coil_on_time = now_time; } else time_diff = now_time - exit_switch_str_coil_on_time; if (time_diff >= COIL_PULSE_TIME) { exit_switch_str_coil_val = 0; } } if (exit_switch_crv_coil_val == 1) { if (now_time <= exit_switch_crv_coil_on_time) { time_diff = 0; exit_switch_crv_coil_on_time = now_time; } else time_diff = now_time - exit_switch_crv_coil_on_time; if (time_diff >= COIL_PULSE_TIME) { exit_switch_crv_coil_val = 0; } } } void process_ctrl_block(void) { // nothing to do for now } void write_to_ports(void) { digitalWrite(DO_shared_block_ctrl,shared_block_ctrl_val); digitalWrite(DO_straight_block_ctrl,straight_block_ctrl_val); digitalWrite(DO_curve_block_ctrl,curve_block_ctrl_val); digitalWrite(DO_ent_switch_str_coil,ent_switch_str_coil_val); digitalWrite(DO_ent_switch_crv_coil,ent_switch_crv_coil_val); digitalWrite(DO_exit_switch_str_coil,exit_switch_str_coil_val); digitalWrite(DO_exit_switch_crv_coil,exit_switch_crv_coil_val); } void write_display(void) { unsigned long time_diff; if (now_time <= display_last_update_time) { display_last_update_time = now_time; time_diff = 0; } else time_diff = now_time - display_last_update_time; if (time_diff >= DISPLAY_UPDATE_TIME) { display_last_update_time = now_time; // home the cursor Serial.write(254); Serial.write(70); // Send the state if (state == STATE_A_RESET) Serial.write("A Rst"); else if (state == STATE_A_CURVE) Serial.write("A Crv"); else if (state == STATE_A_STRAIGHT) Serial.write("A Str"); else if (state == STATE_L_CURVE) Serial.write("L Crv"); else if (state == STATE_L_STRAIGHT) Serial.write("L Str"); else Serial.write("ERROR"); Serial.write(" "); // Entrance Switch Position if (sdir_ent_val == SDIR_UNK) Serial.write("U"); else if (sdir_ent_val == SDIR_STR) Serial.write("S"); else if (sdir_ent_val == SDIR_CRV) Serial.write("C"); else Serial.write("E"); // Entrance Switch Coil Enenrgized if (ent_switch_str_coil_val == 0) Serial.write("-"); else if (ent_switch_str_coil_val == 1) Serial.write("s"); else Serial.write("e"); if (ent_switch_crv_coil_val == 0) Serial.write("-"); else if (ent_switch_crv_coil_val == 1) Serial.write("c"); else Serial.write("e"); Serial.write(" "); // Exit Switch Position if (sdir_exit_val == SDIR_UNK) Serial.write("U"); else if (sdir_exit_val == SDIR_STR) Serial.write("S"); else if (sdir_exit_val == SDIR_CRV) Serial.write("C"); else Serial.write("E"); // Exit Switch Coil Enenrgized if (exit_switch_str_coil_val == 0) Serial.write("-"); else if (exit_switch_str_coil_val == 1) Serial.write("s"); else Serial.write("e"); if (exit_switch_crv_coil_val == 0) Serial.write("-"); else if (exit_switch_crv_coil_val == 1) Serial.write("c"); else Serial.write("e"); Serial.write(" "); // Reset Button if (RESET_val == 1) Serial.write("R"); else if (RESET_val == 0) Serial.write(" "); else Serial.write("E"); // CAS Switch if (CAS_val == CAS_CRV) Serial.write("C"); else if (CAS_val == CAS_AUTO) Serial.write("A"); else if (CAS_val == CAS_STR) Serial.write("S"); else Serial.write("E"); // move the cursor to the next line Serial.write(254); Serial.write(69); Serial.write(64); // Straight Entrance Trips if (A_str_ent_trip_val == 1 || dtrip_str_ent == 1) { Serial.write("Str"); if (dtrip_str_ent == 1) Serial.write("D"); else Serial.write(" "); if (A_str_ent_trip_val == 1) Serial.write("A"); else Serial.write(" "); } else Serial.write(" "); Serial.write(" "); // Curve Entrance Trip if (A_crv_ent_trip_val == 1 || dtrip_crv_ent == 1) { Serial.write("Crv"); if (dtrip_crv_ent == 1) Serial.write("D"); else Serial.write(" "); if (A_crv_ent_trip_val == 1) Serial.write("A"); else Serial.write(" "); } else Serial.write(" "); // Exit Trip if (dtrip_exit == 1) Serial.write("Exit"); else Serial.write(" "); } }