#include <Servo.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define lcdaddress 0x27
LiquidCrystal_I2C lcd(lcdaddress, 20, 4);
// Settings slagboom
Servo slagboom1;
Servo slagboom2;
#define servoSturing1 10 //SERVO bediening slagboom (PWM pin)
#define servoSturing2 9 //SERVO bediening slagboom (PWM pin)
#define servo1Min 90 // servo 1 minimum (closed)
#define servo2Min 90 // servo 2 minimum (closed)
#define servo1Max 180 // servo 1 maximum (opened)
#define servo2Max 180 // servo 2 maximum (opened)
#define slagboomsnelheid 10 // 5 = fast, 25 = medium, 50 = slow (maximale waarde is 255)
byte myServoPosition[2] = { 80, 80} ; // stores current servo positions
boolean OpentDeSlagBoom = true;
boolean SluitDeSlagBoom = false;
unsigned long IntervalRodeledsSlagbomenSluiten;
unsigned long IntervalSlagbomenOpenenWitteleds;
unsigned long WachttijdRodeledsSlagbomenSluiten = 1200; // tijd die moet verlopen tussen beginnen knipperen van de rode leds en het in beweging komen van de slagbomen
unsigned long WachttijdSlagbomenOpenenWitteleds = 750; // tijd die moet verlopen tussen hetopens staan van de slagbomen en het beginnen knipperen van de witte leds
unsigned long servoTimer;
// Instellingen leds
#define LedAan 0
#define LedUit 1
boolean KnippertDeWitteLed = true;
boolean KnippertDeRodeLed = false;
byte RodeLedPin[2] = { 5 , 7 };
byte WitteLedPin[1] = { 3 };
unsigned int KnippertijdWitteLed[2] = {250 , 350};
unsigned int KnippertijdRodeLed[2] = {200 , 300};
unsigned long WhiteTimer = 0;
unsigned long RedTimer = 0;
// Instellingen sensoren
byte sensorPin[2] = { 2 , 4 };
uint16_t btndbc[2] = {0xAAAA , 0xAAAA};
byte ButtonState[2] = { 2 , 2 };
byte DisplayButtonState[2] = { 2 , 2 };
byte ButtonPreviousState[2] = { 2 , 2 };
// Instellingen geluidssignaal
#define mp3 11 // mp3 speler reset voor belgeluid
byte OverwegStatus = 0;
byte HuidigeUitgevoerdeOverwegStatus = 0;
byte GewensteOverwegStatus = 0;
byte SystemStep = 0;
byte SystemStepold = 0;
void debounce(byte Sensornr)
{
btndbc[Sensornr]=(btndbc[Sensornr]<<1) | digitalRead(sensorPin[Sensornr]) | 0xe000;
if (btndbc[Sensornr] == 0xFFFF) ButtonState[Sensornr] = 1;
if (btndbc[Sensornr] == 0xE000) ButtonState[Sensornr] = 0;
if (DisplayButtonState[Sensornr] != ButtonState[Sensornr])
{
lcd.setCursor(8+2*Sensornr, 3);
lcd.print(ButtonState[Sensornr]);
DisplayButtonState[Sensornr] = ButtonState[Sensornr];
}
}
void openSlagboom()
{
if (myServoPosition[0] < servo1Max) myServoPosition[0]++;
slagboom1.write(myServoPosition[0]);
if (myServoPosition[1] < servo2Max) myServoPosition[1]++;
slagboom2.write(myServoPosition[1]);
servoTimer = millis() + slagboomsnelheid;
}
void sluitSlagboom()
{
if (myServoPosition[0] > servo1Min) myServoPosition[0]--;
slagboom1.write(myServoPosition[0]);
if (myServoPosition[1] > servo2Min) myServoPosition[1]--;
slagboom2.write(myServoPosition[1]);
servoTimer = millis() + slagboomsnelheid;
}
void KnipperLicht ( byte Pin )
{
digitalWrite(Pin , !digitalRead(Pin));
}
void KnipperenWitteLed()
{
KnipperLicht ( WitteLedPin[0] );
WhiteTimer = millis() + KnippertijdWitteLed[digitalRead(WitteLedPin[0])] ;
lcd.setCursor( 10 , 0 );
if (digitalRead(WitteLedPin[0]) == 1) lcd.print("uit "); else lcd.print("aan ");
}
void KnipperenRodeLeds()
{
static int LedNr = 0;
KnipperLicht ( RodeLedPin[LedNr] );
if (digitalRead(RodeLedPin[LedNr]) != 0) LedNr = 1 - LedNr ; // led uit dan veranderen van knipperende led
RedTimer = millis() + KnippertijdRodeLed[digitalRead(RodeLedPin[LedNr])];
lcd.setCursor( 9 , 1 );
if ((digitalRead(RodeLedPin[0]) == 1) && (digitalRead(RodeLedPin[1]) == 1)) lcd.print("uit "); else lcd.print("aan ");
}
byte OverwegBeheer( byte GewensteOverwegStatus)
{
static unsigned long MyTime;
// lijnen 139 - 148 te verwijderen indien logging weg moet
static byte GewensteOverwegStatusold = 0;
if ((GewensteOverwegStatusold != GewensteOverwegStatus) || (HuidigeUitgevoerdeOverwegStatus != OverwegStatus))
{
Serial.print ("Overwegbeheer GewensteOverwegStatus: ");
Serial.print (GewensteOverwegStatus);
Serial.print (" OverwegStatus: ");
Serial.println (OverwegStatus);
GewensteOverwegStatusold = GewensteOverwegStatus;
}
HuidigeUitgevoerdeOverwegStatus = OverwegStatus;
switch (OverwegStatus)
{
case 0:
// Initialisatie: Alle lichten uit, slagboom open
digitalWrite(WitteLedPin[0] , HIGH);
digitalWrite(RodeLedPin[0] , HIGH);
digitalWrite(RodeLedPin[1] , HIGH);
KnippertDeWitteLed = false;
lcd.setCursor( 10 , 0 );
lcd.print("gestopt ");
KnippertDeRodeLed = true;
OpentDeSlagBoom = true;
lcd.setCursor( 9 , 2 );
lcd.print("openen ");
SluitDeSlagBoom = false;
if (GewensteOverwegStatus > OverwegStatus) OverwegStatus = 10;
break;
case 10:
// Wachten tot slagboom open is
if ((myServoPosition[0] == servo1Max) && (myServoPosition[1] == servo2Max) && (GewensteOverwegStatus > OverwegStatus)) OverwegStatus = 15;
break;
case 15:
// Bericht weergeven
lcd.setCursor( 9 , 2 );
lcd.print("is geopend ");
Serial.println ("Slagboom is geopend.");
Serial.println ("Druk op 1 van de knoppen en wacht.");
OverwegStatus = 20;
break;
case 20:
// wit knipperlicht
KnippertDeWitteLed = true;
KnippertDeRodeLed = false;
OpentDeSlagBoom = true;
SluitDeSlagBoom = false;
OverwegStatus = 30;
break;
case 30: // wachten tot de witte led gedoofd is
if ((digitalRead(WitteLedPin[0]) == LedUit) && (GewensteOverwegStatus > OverwegStatus))
{
KnippertDeWitteLed = false; // witte led mag niet meer knipperen
lcd.setCursor( 10 , 0 );
lcd.print("gestopt ");
lcd.setCursor( 9 , 1 );
lcd.print("uit ");
Serial.println ("Knipperen witte led gestopt.");
MyTime = WhiteTimer ; // even wachten
OverwegStatus = 40;
}
if ((digitalRead(RodeLedPin[0]) == LedUit) && (digitalRead(RodeLedPin[1]) == LedUit) && (GewensteOverwegStatus < OverwegStatus))
{
// wachten totdat de rode led gedoofd is
KnippertDeRodeLed = false; // Rode led mag niet meer knipperen
lcd.setCursor( 9 , 1 );
lcd.print("gestopt ");
lcd.setCursor( 10 , 0 );
lcd.print("uit ");
Serial.println ("Knipperen rode led gestopt.");
MyTime = RedTimer ; // even wachten
OverwegStatus = 40;
}
break;
case 40:
if (GewensteOverwegStatus > OverwegStatus)
{
if (millis() > MyTime) {OverwegStatus = 50;}
}
if (GewensteOverwegStatus < OverwegStatus)
{
if (millis() > MyTime) {OverwegStatus = 50;}
}
break;
case 50: // Rode knipperlichten aan en instellen wchttijd slagbomen
if (GewensteOverwegStatus > OverwegStatus)
{
KnippertDeRodeLed = true;
Serial.println ("Knipperen rode leds gestart.");
OverwegStatus = 60;
}
if (GewensteOverwegStatus < OverwegStatus)
{
KnippertDeWitteLed = true;
Serial.println ("Knipperen witte led gestart.");
OverwegStatus = 20;
}
break;
case 60:
if (GewensteOverwegStatus > OverwegStatus)
{
// instellen wchttijd tussen aangaan rode leds en naar beneden gaan slagbomen
lcd.setCursor( 9 , 2 );
lcd.print("zal sluiten");
Serial.println ("Wachten op sluiten slagbomen.");
IntervalRodeledsSlagbomenSluiten = millis() + WachttijdRodeledsSlagbomenSluiten;
OverwegStatus = 80;
}
if (GewensteOverwegStatus < OverwegStatus)
{
IntervalSlagbomenOpenenWitteleds = millis() + WachttijdSlagbomenOpenenWitteleds;
OverwegStatus = 80;
}
break;
case 80:
// wachttijd voor het inbeweging zetten van de slagbomen laten voorbijgaan
if ((millis()> IntervalRodeledsSlagbomenSluiten) && (GewensteOverwegStatus > OverwegStatus))
{
OverwegStatus = 90;
}
if ((millis()> IntervalSlagbomenOpenenWitteleds) && (GewensteOverwegStatus < OverwegStatus))
{
OverwegStatus = 30;
}
break;
case 90:
if (GewensteOverwegStatus > OverwegStatus)
{
SluitDeSlagBoom = false;
OpentDeSlagBoom = false;
lcd.setCursor( 9 , 2 );
lcd.print("sluit ");
Serial.println ("slagbomen worden gesloten.");
SluitDeSlagBoom = true;
OverwegStatus = 100;
}
if (GewensteOverwegStatus < OverwegStatus)
{
SluitDeSlagBoom = false;
OpentDeSlagBoom = false;
lcd.setCursor( 9 , 2 );
lcd.print("is geopend ");
Serial.println ("Slagbomen zijn geopend.");
OverwegStatus = 60;
}
break;
case 100: // slagbomen in beweging zetten
if (GewensteOverwegStatus > OverwegStatus)
{
SluitDeSlagBoom = true; // Deze 2 lijnen moeten erbij, anders kan het programma in bepaalde TESTomstandigheden vastlopen
OpentDeSlagBoom = false;
lcd.setCursor( 9 , 2 );
lcd.print("sluit ");
if ((myServoPosition[0] == servo1Min) && (myServoPosition[1] == servo2Min)) OverwegStatus = 110;
}
if (GewensteOverwegStatus < OverwegStatus)
{
SluitDeSlagBoom = false; // Deze 2 lijnen moeten erbij, anders kan het programma in bepaalde TESTomstandigheden vastlopen
OpentDeSlagBoom = true;
lcd.setCursor( 9 , 2 );
lcd.print("opent ");
if ((myServoPosition[0] == servo1Max) && (myServoPosition[1] == servo2Max)) OverwegStatus = 90;
}
break;
case 110:
if (GewensteOverwegStatus > OverwegStatus)
{
SluitDeSlagBoom = false;
OpentDeSlagBoom = false;
lcd.setCursor( 9 , 2 );
lcd.print("is gesloten");
Serial.println ("Slagbomen zijn gesloten.");
Serial.println ("Druk op de andere knop. Pas bij loslaten verlaat de trein de overweg en zullen de slagbomen openen.");
OverwegStatus = 120;
}
if (GewensteOverwegStatus < OverwegStatus)
{
SluitDeSlagBoom = false;
lcd.setCursor( 9 , 2 );
lcd.print("opent ");
Serial.println ("Slagbomen worden geopend.");
OpentDeSlagBoom = true;
OverwegStatus = 100;
}
break;
case 120: // slagbomen zijn naar beneden
if (GewensteOverwegStatus < OverwegStatus) OverwegStatus = 110;
break;
}
return (HuidigeUitgevoerdeOverwegStatus);
}
void SensorHandler()
{
// lijnen 378 - 383 te verwijderen indien logging weg moet
if (SystemStepold != SystemStep)
{
Serial.print ("SystemStep: ");
Serial.println (SystemStep);
}
SystemStepold = SystemStep;
switch (SystemStep)
{
case 0:
ButtonPreviousState[0] = ButtonState[0];
ButtonPreviousState[1] = ButtonState[1];
if ((ButtonState[0] == LOW) && (ButtonState[1] == LOW)) SystemStep = 10;
break;
case 10:
if ((ButtonState[0] != ButtonPreviousState[0]) && (ButtonState[0] == HIGH)) { SystemStep = 20; ButtonPreviousState[0] = ButtonState[0]; }
if ((ButtonState[1] != ButtonPreviousState[1]) && (ButtonState[1] == HIGH)) { SystemStep = 30; ButtonPreviousState[1] = ButtonState[1];}
break;
case 20:
GewensteOverwegStatus = 120;
// Vorige sensor die slagbomen liet neergaan moet eerst terug vrijgegeven worden
if ((ButtonState[0] != ButtonPreviousState[0]) && (ButtonState[0] == LOW)) { SystemStep = 40; ButtonPreviousState[0] = ButtonState[0]; ButtonPreviousState[1] = ButtonState[1];}
break;
case 30:
GewensteOverwegStatus = 120;
// Vorige sensor die slagbomen liet neergaan moet eerst terug vrijgegeven worden
if ((ButtonState[1] != ButtonPreviousState[1]) && (ButtonState[1] == LOW)) { SystemStep = 50; ButtonPreviousState[1] = ButtonState[1]; ButtonPreviousState[0] = ButtonState[0];}
break;
case 40:
if ((ButtonState[1] != ButtonPreviousState[1]) && (ButtonState[1] == HIGH)) { SystemStep = 60; ButtonPreviousState[1] = ButtonState[1]; ButtonPreviousState[0] = ButtonState[0];}
break;
case 50:
if ((ButtonState[0] != ButtonPreviousState[0]) && (ButtonState[0] == HIGH)) { SystemStep = 70; ButtonPreviousState[0] = ButtonState[0]; ButtonPreviousState[1] = ButtonState[1];}
break;
case 60:
if ((ButtonState[1] != ButtonPreviousState[1]) && (ButtonState[1] == LOW)) { SystemStep = 80; ButtonPreviousState[1] = ButtonState[1]; ButtonPreviousState[0] = ButtonState[0];}
break;
case 70:
if ((ButtonState[0] != ButtonPreviousState[0]) && (ButtonState[0] ==LOW)) { SystemStep = 90; ButtonPreviousState[0] = ButtonState[0]; ButtonPreviousState[1] = ButtonState[1];}
break;
case 80:
GewensteOverwegStatus = 20;
SystemStep = 0;
break;
case 90:
GewensteOverwegStatus = 20;
SystemStep = 0;
break;
default:
Serial.println ("Error in sensorhandler voor ");
Serial.println (SystemStepold);
}
}
void setup()
{
Serial.begin ( 115200 ); // starts the serial communication
while ( !Serial ) {} ;
// Display settings
lcd.init();
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Witte led ");
lcd.setCursor(0, 1);
lcd.print("Rode led gestopt ");
lcd.setCursor(0, 2);
lcd.print("Slagboom opent ");
lcd.setCursor(0, 3);
lcd.print("Sensor: ");
slagboom1.attach(servoSturing1);
slagboom2.attach(servoSturing2);
// pinMode(servoSturing1, OUTPUT); // Onnodig wordt bij de attach Servo al gedaan
// pinMode(servoSturing2, OUTPUT);
pinMode(WitteLedPin[0], OUTPUT);
pinMode(RodeLedPin[0], OUTPUT);
pinMode(RodeLedPin[1], OUTPUT);
pinMode(sensorPin[0], INPUT);
pinMode(sensorPin[1], INPUT);
while (ButtonState[0] > 1) { debounce(0); };
ButtonPreviousState[0] = ButtonState[0];
while (ButtonState[1] > 1) { debounce(1); };
ButtonPreviousState[1] = ButtonState[1];
GewensteOverwegStatus = 20;
SystemStep = 10;
lcd.setCursor(8, 3);
lcd.print(ButtonState[0]);
lcd.setCursor(10, 3);
lcd.print(ButtonState[1]);
Serial.println("Einde setup");
}
void loop()
{
// Knipperen van de leds
if ((KnippertDeWitteLed) && (millis() > WhiteTimer)) KnipperenWitteLed();
if ((KnippertDeRodeLed) && (millis() > RedTimer)) KnipperenRodeLeds();
// Opvragen sensoren en behandeling van de sensorsignalen
debounce(0);
debounce(1);
if ((ButtonState[0] != ButtonPreviousState[0]) || (ButtonState[1] != ButtonPreviousState[1]) || (SystemStepold != SystemStep)) SensorHandler();
// Beheer van de overweg
if (GewensteOverwegStatus != HuidigeUitgevoerdeOverwegStatus) OverwegBeheer( GewensteOverwegStatus );
// Aansturen van de slagbomen
if ((OpentDeSlagBoom) && (servoTimer < millis())) openSlagboom();
if ((SluitDeSlagBoom) && (servoTimer < millis())) sluitSlagboom();
}