// Update normal light sequence by checking the main counter int UpdateNormalSequence(int goLightTime) { int i = 1; while (mainCounter.GetCounter() > i * goLightTime) i++; // On Select Sequence Button, cycle through the sequences immediately if (btnSelectSequence.IsPressed()) { // reset the main counter to start of new sequence mainCounter.Reset(i * goLightTime); i++; } // if maximum sequences has reached reset the main counter if (i == MAX_SEQUENCES + 1) { mainCounter.Reset(); i = 1; } return i; }
void loop() { delay(50); boolean hotDay = ther.GetKelvinTempUsingHart() >= THER_CRITICAL_DEG; boolean nightMode = ldr.ReadADC() <= LDR_DARK_ADC; static int goLightTimeCalibed = DEFAULT_GO_LIGHT_TIME; static int orangeLightTimeCalibed = DEFAULT_ORANGE_LIGHT_TIME; // if both emergency button and road work are pressed activate the calibration if (btnEmergency.IsPressed() && btnRoadWork.IsPressed()) { goLightTimeCalibed = map(pot.ReadADC(), 0, 1023, DEFAULT_GO_LIGHT_TIME/2, DEFAULT_GO_LIGHT_TIME * 2); orangeLightTimeCalibed = map(pot.ReadADC(), 0, 1023, DEFAULT_ORANGE_LIGHT_TIME/2, DEFAULT_ORANGE_LIGHT_TIME * 2); } else { boolean emergencyMode = btnEmergency.ReadSwitch(); boolean roadWorkMode = btnRoadWork.ReadSwitch(); if (emergencyMode) { OnEmergencyMode(); } if (roadWorkMode) { FlashForRoadWork(); } // pause the main counter when one of the modes are activated if(roadWorkMode || emergencyMode) { mainCounter.Pause(); return; } } int goLightTime = goLightTimeCalibed; int orangeLightTime = orangeLightTimeCalibed; double multiplier = 1.0; if (nightMode) { multiplier += 0.4; } if(hotDay) { multiplier += 0.3; } // extended the go or green signal time and the orange light time int goLightTime = goLightTimeCalibed * multiplier; int orangeLightTime = orangeLightTimeCalibed * multiplier; // get the current state of the sequence int state = UpdateNormalSequence(goLightTime); // print out the state of the system for debugging Serial.print("Temperature: "); Serial.print(ther.GetKelvinTempUsingHart()); Serial.print(" LDR: "); Serial.print(ldr.ReadADC()); Serial.print(" PotADC: "); Serial.print(pot.ReadADC()); Serial.print(" Cross: "); Serial.print(btnPedCross0.IsPressed() || btnPedCross90.IsPressed() || btnPedCross270.IsPressed()); Serial.print(" main Counter: "); Serial.print(mainCounter.GetCounter()); Serial.print(" goTime: "); Serial.print(goLightTime); Serial.print(" Orange: "); Serial.print(orangeLightTime); Serial.print(" state: "); Serial.println(state); // if alarm is in progress, exit from normal sequence if (AddPedCrossStageOnRequest(state, goLightTime, orangeLightTime)) return; // unpause the main counter if it was paused mainCounter.UnPause(); // update the leds on the traffic light depending on the values in the sequence array trafficLight270.UpdateWithLightTransition(sequence[state - 1][0], sequence[state - 1][1], sequence[state - 1][2], orangeLightTime); trafficLight0.UpdateWithLightTransition(sequence[state - 1][3], sequence[state - 1][4], sequence[state - 1][5], orangeLightTime); trafficLight90.UpdateWithLightTransition(sequence[state - 1][6], sequence[state - 1][7], sequence[state - 1][8], orangeLightTime); }
// function to allow for ped crossing on the press of a button // ped crossing works by pausing the main counter at the end of a sequence // and resuming after the ped has crossed. // returns whether alarm is currently on progression or not bool AddPedCrossStageOnRequest(int state, int pedCrossTime, int orangeLightTime){ #define NO_PED_CROSS 0 #define PED_CROSS_BTN_PRESSED 1 #define PED_CROSS_IN_PROGRESS 2 static int alarmState = 0; // check for button presses at all the junctions if(btnPedCross0.IsPressed() || btnPedCross90.IsPressed() || btnPedCross270.IsPressed()) if (alarmState == NO_PED_CROSS) alarmState = PED_CROSS_BTN_PRESSED; // update the buzzer asyncronously trafficLight0.crossingBuzzer.UpdateAsync(); trafficLight90.crossingBuzzer.UpdateAsync(); trafficLight270.crossingBuzzer.UpdateAsync(); static int prevState = 0; static Counter pedCrossCounter; // check if the current sequence has ended if (prevState != state && alarmState == PED_CROSS_BTN_PRESSED) { // pause the timer mainCounter.Pause(); // reset the crossing counter to 0 pedCrossCounter.Reset(); // activate the flag to transition all the green signal to red first alarmState = PED_CROSS_IN_PROGRESS; return true; } if (alarmState == PED_CROSS_IN_PROGRESS) { if (pedCrossCounter.GetCounter() <= pedCrossTime) { // if there were no green lights from the previous sequence, directly turn on the red light if (trafficLight0.ledRed.IsOn() && trafficLight90.ledRed.IsOn() && trafficLight270.ledRed.IsOn()) { trafficLight270.UpdateWithLightTransition(0, 0, 1, orangeLightTime); trafficLight0.UpdateWithLightTransition(0, 0, 1, orangeLightTime); trafficLight90.UpdateWithLightTransition(0, 0, 1, orangeLightTime); trafficLight0.crossingBuzzer.TriggerAlarm(); trafficLight90.crossingBuzzer.TriggerAlarm(); trafficLight270.crossingBuzzer.TriggerAlarm(); } // if there were green lights on the previous sequence, transition to red first else { trafficLight270.UpdateWithLightTransition(0, 0, 0, orangeLightTime); trafficLight0.UpdateWithLightTransition(0, 0, 0, orangeLightTime); trafficLight90.UpdateWithLightTransition(0, 0, 0, orangeLightTime); trafficLight0.crossingBuzzer.TurnOffAlarm(); trafficLight90.crossingBuzzer.TurnOffAlarm(); trafficLight270.crossingBuzzer.TurnOffAlarm(); } return true; } // if ped cross time has finish blink the ped light as in australian ped crossing else if (pedCrossCounter.GetCounter() <= pedCrossTime + orangeLightTime) { FlashForPedCrossFinish(); trafficLight0.crossingBuzzer.TurnOffAlarm(); trafficLight90.crossingBuzzer.TurnOffAlarm(); trafficLight270.crossingBuzzer.TurnOffAlarm(); return true; } else { alarmState = NO_PED_CROSS; } } prevState = state; return false; }