... TRCT5000 ... hoeken afgevlakt. Dit is de kant van de diode (ingang, pen 1 en 2)
#define DEBUG 0#include <Servo.h>enum SpoorState {leeg, sensor1komend, sensor2komend, sensor1gaand, sensor2gaand };////class AanUitSchakelaar{ private: int schakelPin; bool schakelState; unsigned long lastTime; public: // // Create new instance, connect it to the specified pin, and set the state // AanUitSchakelaar(int aPin) { schakelPin = aPin; schakelState = false; // Schakelaar uit lastTime = 0; pinMode(schakelPin, INPUT_PULLUP); } // // Monitor the physical switch and update its state accordingly // void heartBeat() { if (digitalRead(schakelPin) == LOW) {#if (DEBUG) if (schakelState != true) { Serial.println("[AanUitSchakelaar::heartBeat] switch goes on"); }#endif schakelState = true; // Switch goes ON lastTime = 0; // Reset interval timer } else // sensorPin = HIGH { if (schakelState != false) // Process this signal only when the current state is ON { if (lastTime == 0) { lastTime = millis(); // start Interval } else { unsigned long currTime = millis(); if ((currTime - lastTime) >= 100) // filter bouncing of the switch {#if (DEBUG) Serial.println("[AanUitSchakelaar::heartBeat] switch goes off");#endif schakelState = false; // sensor goes OFF lastTime = 0; // Reset interval timer } } } } } // // Return the current logical state of the switch // bool getState() { return schakelState; }};//// Class for a single (white) led which flickers 50 times per// minute when on//class SingleLed{ private: int ledPin; bool ledOn = false; public: // // Create a new instance of a (white) led, connect it to the specified // digital pin and put it in the specified state (true = on, false = off) // SingleLed(int aPin, bool state) { ledPin = aPin; ledOn = state; pinMode(ledPin, OUTPUT); } // // Set the state of the led (true = on, false = off) // void setState(bool state) {#if (DEBUG) if (ledOn != state) { Serial.print("[SingleLed::setOn]"); if (state) Serial.println(" aan"); else Serial.println(" uit"); }#endif ledOn = state; } // // Return the state of the led // bool getState() { return ledOn; } // // If the state is on, put power on the pin of the led, using timers // to make the flicker work. // If the led is off, remove the power from the pin of the led. // void heartBeat() { if (ledOn) // Do we need to light the led? {#if (DEBUG) Serial.println("[SingleLed::heartBeat] led aan");#endif digitalWrite(ledPin, HIGH); // No, so switch it on } else {#if (DEBUG) Serial.println("[SingleLed::heartBeat] led uit");#endif digitalWrite(ledPin, LOW); // Switch ir off } }};/* A wrapper class for controlling RC servo's*/class ArmServo{ private:#define REFRESH_TIME 30000 Servo *myServo; unsigned long timeOfLastStep; unsigned long lastTimeActive; unsigned int target; unsigned int current; unsigned int highPosition; // Arm position high unsigned int lowPosition; // Arm position low unsigned int servoWaitTime; // Wait time between 2 steps int servoPin; bool active = false; void attachServo() // Intialize the servo {#if (DEBUG) Serial.print("[ArmServo::attachServo] Servo pin: "); Serial.println(this->servoPin);#endif //DEBUG this->myServo->attach(this->servoPin); this->active = true; this->myServo->write(this->current); // Restore last known position } void detachServo() {#if (DEBUG) Serial.print("[ArmServo::detachServo] Servo pin: "); Serial.println(this->servoPin);#endif //DEBUG this->myServo->detach(); this->active = false; } public: ArmServo(int newServoPin, int newWaitTime, int newHighPosition, int newLowPosition) { this->active = false; this->myServo = new Servo(); this->servoPin = newServoPin; this->servoWaitTime = newWaitTime; this->highPosition = newHighPosition; this->lowPosition = newLowPosition; this->target = newHighPosition; // We asume that the arms are initial in their upper position if (this->highPosition > this->lowPosition) this->current = newHighPosition - 1; // But force a small initial movement else this->current = newHighPosition + 1; // But force a small initial movement this->active = false; } void laag() {#if (DEBUG) Serial.print("[ArmServo::laag] arm going to low position: "); Serial.println(lowPosition); Serial.flush();#endif //DEBUG target = lowPosition; } bool isLaag() { if (current == lowPosition) return true; else return false; } void hoog() {#if (DEBUG) Serial.print("[Armservo::hoog] arm going to high position: "); Serial.println(highPosition); Serial.flush();#endif //DEBUG target = highPosition; } bool isHoog() { if (current == highPosition) return true; else return false; } bool stepServo() { // // When the arm's position isn't at the target, we have to move the arm // if (this->target != this->current) { // // Is the servo active? if not attach it to it's pin so it can start moving // if (!this->active) {#if (DEBUG) Serial.println("{ArmServo::stepServo] attach"); Serial.flush();#endif // DEBUG this->attachServo(); } lastTimeActive = millis(); if ((lastTimeActive - this->timeOfLastStep) >= this->servoWaitTime) { // // The servo is moving to it's new location. //#if (DEBUG) Serial.print("[ArmServo::stepServo] target: "); Serial.print(this->target); Serial.print(", current: "); Serial.print(this->current);#endif //DEBUG if (this->target > this->current) { this->current++; } else { this->current--; }#if (DEBUG) Serial.print(", going to: "); Serial.println(this->current); Serial.flush();#endif // DEBUG this->myServo->write(this->current); this->timeOfLastStep = lastTimeActive; } return true; // The arm is still moving } else { if ((millis() - lastTimeActive) >= REFRESH_TIME) { // // Is the servo active? if not attach it to it's pin so it can start moving // if (!this->active) {#if (DEBUG) Serial.println("{ArmServo::stepServo] attach"); Serial.flush();#endif // DEBUG this->attachServo(); }#if (DEBUG) Serial.print(", refreshing to: "); Serial.println(this->current); Serial.flush();#endif // DEBUG this->myServo->write(this->current); this->lastTimeActive = millis(); } // // The arm reached it's position, so we can now detach the servo (if it was attached) // if (this->active) { this->detachServo(); } return false; // The arm has stopped moving } }};enum AkiStaat {aan, uit};//// A simple class that represents a complete AHOB with all its leds and two Servo's// for moving the arms//// TBD, the sound of the bells//class AHOB{ private: SingleLed *redLight; ArmServo *arm1; ArmServo *arm2; AkiStaat state = uit; public: // // Create an instance of the AHOB, using the specified Led and ArmServo objects // AHOB(SingleLed *aRedLed, ArmServo *aServo1, ArmServo *aServo2) { redLight = aRedLed; arm1 = aServo1; arm2 = aServo2; state = uit; // // AHOB is veilig, dus roodlicht uit en armen omhoog // redLight->setState(false); arm1->hoog(); arm2->hoog(); } // // Activate the connected leds and arm servo's. TBD: the sound // void heartBeat() { if (arm1->isHoog() && arm2->isHoog()) { redLight->setState(false); // Als de armen omhoog staan mag het rode licht niet branden } else { // // AHOB is dicht of gaat dicht, dus roodlicht aan // redLight->setState(true); } redLight->heartBeat(); arm1->stepServo(); arm2->stepServo(); } // // When both arms of the gate are high, return true, else return false // bool isHoog() { if (arm1->isHoog() && arm2->isHoog()) { return true; } else { return false; } } // // When both arms of the gate are low, return true, else return false // bool isLaag() { if (arm1->isLaag() && arm2->isLaag()) { return true; } else { return false; } } void set(AkiStaat aState) {#if (DEBUG) if (state != aState) { Serial.print("[AKI::set]"); if (aState == uit) Serial.println(" uit"); else Serial.println(" aan"); }#endif state = aState; if (state == uit) { // // AHOB is open, armen omhoog. Het rode licht stopt pas als de armen omhoog staan // arm1->hoog(); arm2->hoog(); } else { // // AHOB is dicht, dus armen omlaag, het rode licht volgt automatisch // arm1->laag(); arm2->laag(); } }};//// Some sensors use a digital signal and keep it high when not active and drop the signal// when the sensor trips, use in that case the "laag" setting. Others use a digital signal// and are low when not active and make the signal high when the sensor trips, use in that case// the "hoog" setting.// if the sensor doesn't generate a digital signal, you have to use a pullup resistor (or INPUT_PULLUP)// and in that case specify hoog.//// The Flying Fish proximity detectors, when used in reflective mode, need the "laag" setting, // when their sensors are removed and positioned opposit each other, they need the "hoog" setting//enum SensorTrigger {laag, hoog};//// A simple class which represents the state of a single sensor//class Sensor{ private: int sensorPin; SensorTrigger type = hoog; bool state = false; // true = on, false = off unsigned long lastTime = 0; // Timer to ignore short interrupts#define JITTER_TIME 1000 // wait a second before the sensor goes off public: // // Create a new instance // Sensor(int aPin) { sensorPin = aPin; pinMode(sensorPin, INPUT_PULLUP); } // // Create a new instance // Sensor(int aPin, SensorTrigger aType) { sensorPin = aPin; type = aType; pinMode(sensorPin, INPUT_PULLUP); } // // Return the current logical state of the sensor // bool getState() { return state; } // // Monitor the physical sensor and update the state accordingly // void heartBeat() { if (digitalRead(sensorPin) == HIGH) { if (type == laag) // For sensors type laag an high signal means they are in the off state { if (state != false) // Process this signal only when the current state is ON { if (lastTime == 0) { lastTime = millis(); // start Interval } else { unsigned long currTime = millis(); if ((currTime - lastTime) >= JITTER_TIME) {#if (DEBUG) Serial.println("[Sensor::heartBeat] sensor(laag) goes off");#endif state = false; // sensor goes OFF lastTime = 0; // Reset interval timer } } } } else {#if (DEBUG) if (state != true) { Serial.println("[Sensor::heartBeat] sensor(hoog) goes on"); }#endif state = true; // Sensor goes ON lastTime = 0; // Reset interval timer } } else // sensorPin = LOW { if (type == laag) {#if (DEBUG) if (state != true) { Serial.println("[Sensor::heartBeat] sensor(laag) goes on"); }#endif state = true; // Sensor goes ON lastTime = 0; // Reset interval timer; } else { if (state != false) // Process this signal only when the current state is ON { if (lastTime == 0) { lastTime = millis(); // start Interval } else { unsigned long currTime = millis(); if ((currTime - lastTime) >= JITTER_TIME) {#if (DEBUG) Serial.println("[Sensor::heartBeat] sensor(hoog) goes off");#endif state = false; // sensor goes OFF lastTime = 0; // Reset interval timer } } } } } }};//// A finite state machine that guards a occupance of a single track//class SpoorControl{ private: Sensor *sensor1; Sensor *sensor2; SpoorState state = leeg; // // Based on the state of sensor 1 and the current state of the FSM, a new state // is calculated. // void handleSensor1(bool trigger) { if (trigger) // Sensor 1 is ON { if (state == leeg) // If the state is "leeg" it means that a train enters the section {#if (DEBUG) Serial.println("[SpoorControl::handleSensor1] state is sensor1komend");#endif state = sensor1komend; // so set it to state komend } else if (state == sensor2komend) // if the other sensor tripped first {#if (DEBUG) Serial.println("[SpoorControl::handleSensor1] state is sensor1gaand");#endif state = sensor1gaand; // The train is starting to leave the section } } else { // Sensor went OFF if (state == sensor1gaand) // If the train started to leave via sensor 1 {#if (DEBUG) Serial.println("[SpoorControl::handleSensor1] state is leeg");#endif state = leeg; // the section is "leeg" } } } // // Based on the state of sensor 2 and the current state of the FSM, a new state // is calculated. // void handleSensor2(bool trigger) { if (trigger) // Sensor 2 is ON { if (state == leeg) // Is the section "leeg"? {#if (DEBUG) Serial.println("[SpoorControl::handleSensor2] state is sensor2komend");#endif state = sensor2komend; // A Train entered the section via sensor 2 } else if (state == sensor1komend) // No a train entered the section via the other sensor {#if (DEBUG) Serial.println("[SpoorControl::handleSensor2] state is sensor2gaand");#endif state = sensor2gaand; // Start the leaving process } } else { if (state == sensor2gaand) // A train is in the process of leaving {#if (DEBUG) Serial.println("[SpoorControl::handleSensor2] state is leeg");#endif state = leeg; // Section is empty again } } } public: // // Create an instance with two sensors // SpoorControl(Sensor *aSensor1, Sensor *aSensor2) { sensor1 = aSensor1; sensor2 = aSensor2; } // // Get give the sensors a kick and check their state so we can update our own // state. // void heartBeat() { sensor1->heartBeat(); sensor2->heartBeat(); handleSensor1(sensor1->getState()); handleSensor2(sensor2->getState()); } // // Return the current state of the section // SpoorState getState() { return state; }};