Hallo,
hab mir folgendes überlegt, es funktioniert wie folgt. Irgendein Sensor wird aktiv und der Puls auf die Weiche wird entsprechend aktiviert. Dadurch wird die Ansteuerung auf den anderen Weichenpin automatisch gesperrt. Beide Weichenspulen können nicht zeitgleich mit einem Puls beaufschlagt werden. Das regelt das Flag pulsAktiv.
Ab jetzt läuft die Zeit pulsdauer runter. Wenn diese abgelaufen ist, wird die Zeit der 'ruhephase' aktiv. Das regelt das Flag pauseAktiv.
Da ich nur einen Timer verwenden durfte
, wird dieser eine Timer immer mit der benötigten Zeitspanne neu gestartet und geschaut ob diese Zeit abgelaufen ist.
Erst wenn auch die Ruhephase vorbei ist kann die Weiche erneut angesteuert werden. Damit wäre die Weichenspule schon einmal vorm durchbrennen geschützt. Das heißt jedoch auch, wenn der Sensor dauerhaft ein Signal liefert bekommt die Weiche permanent ein PWM Signal.
pulsAktiv pauseAktiv
__________
| |____________________
pulsdauer ruhephase
|<----------------------------->|
Periode
Die Ruhephase kann man der Zugfrequenz anpassen. ruhephase habe ich der Lesbarkeit wegen als Variable belassen. Ansonsten den Faktor direkt einsetzen.
Jetzt ist die Frage, soll das nicht lieber komplett verriegelt werden? Sollte Dauer PWM vermieden werden? PWM würde wiederum gegen leicht hängende Weichen helfen. Ich hätte Hunderte für und wieder im Kopf.
Oder überlassen wir das dem Nutzer für seine spezielle Zugsteuerung?
Letztlich kommt es auf den Einsatzzweck an. Ich weiß es nicht. Auf der anderen Seite kann man hier nicht alles zeigen was man sich ausdenken könnte.
Ich persönlich würde bestimmt mehrere Sensoren im Gleis verbauen. Einer zum Weiche schalten und der Nächste stoppt den Zug. Aber das kommt sicherlich auch wieder auf den Gleisplan an und was man wie steuern möchte.
/*
Doc_Arduino - german Arduino Forum
IDE 1.8.13
Arduino Mega2560
06.05.2021
https://forum.arduino.cc/t/anleitung-weichensteuerung-mit-klasse/856934/25
*/
#include <MobaTools.h> // Kann mittels Arduino-IDE installiert werden.
class Sensor
{
private:
const byte pin;
public:
Sensor(byte p) : pin {p}
{}
void init (void) { pinMode(pin, INPUT_PULLUP); }
bool istAktiv (void) { return !digitalRead(pin); }
};
class Weiche
{
private:
const byte pinGerade;
const byte pinAbzweig;
const uint16_t pulsdauer {300}; // in Millisekunden
const uint16_t ruhephase {pulsdauer*7}; // Ruhephase zum Spulenschutz vervielfachen
MoToTimer impuls;
bool pulsAktiv {false};
bool pauseAktiv {false};
void ein (const byte pin) { digitalWrite(pin, LOW); }
void aus (const byte pin) { digitalWrite(pin, HIGH); }
public:
Weiche(byte ger, byte abz) : pinGerade {ger}, pinAbzweig {abz}
{}
void init (void) {
digitalWrite(pinGerade, HIGH);
digitalWrite(pinAbzweig, HIGH);
pinMode(pinGerade, OUTPUT);
pinMode(pinAbzweig, OUTPUT);
}
void zuGerade (void) {
if (!pulsAktiv) { // gegenseitige Verriegelung aktiv?
impuls.setTime(pulsdauer); // Timer setzen und Puls starten
ein(pinGerade);
pulsAktiv = true; // Retriggerung verhindern, sich selbst und gegenseitig verriegeln
}
}
void zuAbzweig (void) {
if (!pulsAktiv) { // gegenseitige Verriegelung aktiv?
impuls.setTime(pulsdauer); // Timer setzen und Puls starten
ein(pinAbzweig);
pulsAktiv = true; // Retriggerung verhindern, sich selbst und gegenseitig verriegeln
}
}
void pulsControl (void)
{
// wenn Pulsdauer vorbei wird Ruhephase aktiv
if (pulsAktiv && !pauseAktiv && !impuls.running() ) // Pulsdauer abgelaufen?
{
aus(pinGerade);
aus(pinAbzweig);
impuls.setTime(ruhephase); // Timer setzen für AUS Dauer zum abkühlen
pauseAktiv = true; // Puls-Ruhephase zum Spulenschutz aktivieren
}
// erst wenn Ruhephase abgelaufen ist, kann die Weiche erneut angesteuert werden
if (pulsAktiv && pauseAktiv && !impuls.running() )
{
pulsAktiv = false;
pauseAktiv = false;
}
}
};
class Gleis
{
private:
const byte relais;
public:
Gleis(byte p) : relais {p}
{}
void init (void) {
digitalWrite(relais, HIGH);
pinMode(relais, OUTPUT);
}
void stromGleisAbzweig (void) { digitalWrite(relais, LOW); }
void stromGleisGerade (void) { digitalWrite(relais, HIGH); }
};
class Steuerung
{
private: // Die folgenden Objekte sind nur innerhalb der Klasse zugänglich. Am Anfang einer Klasse überflüssig.
// Objekt Deklarationen
Sensor sensorGerade;
Sensor sensorAbzweig;
Gleis gleis;
Weiche weiche;
public:
/* SensorGerade
| SensorAbzweig
| | RelaisGleisumschaltung
| | | ImpulsRelaisWeicheGerade
| | | | ImpulsRelaisWeicheAbzweig
| | | | | */
Steuerung(byte a, byte b, byte c, byte d, byte e):
// Initialisierungsliste, Objektreihenfolge wie Deklaration
sensorGerade{a},
sensorAbzweig{b},
gleis {c},
weiche{d, e}
{}
void init(void)
{
sensorGerade.init();
sensorAbzweig.init();
gleis.init();
weiche.init();
}
void control(void)
{
if (sensorGerade.istAktiv() ) {
gleis.stromGleisAbzweig(); // 'Gleis Abzweig' bestromt, 'Gleis Gerade' stromlos
weiche.zuAbzweig(); // Weichen Umschaltpuls starten auf 'Gleis Abzweig' ein
}
if (sensorAbzweig.istAktiv() ) {
gleis.stromGleisGerade(); // 'Gleis Gerade' bestromt, 'Gleis Abzweig' stromlos
weiche.zuGerade(); // Weichen Umschaltpuls starten auf Gleis Gerade ein
}
// muss immer aufgerufen werden können
weiche.pulsControl(); // Weichen Puls Überwachung
}
};
Steuerung steuerung[]
{
/* SensorGerade
| SensorAbzweig
| | RelaisGleisumschaltung
| | | ImpulsRelaisWeicheGerade
| | | | ImpulsRelaisWeicheAbzweig
| | | | | */
{ 2, 3, 28, 29 ,30}, // 1. Weiche, Gleis 1-2
{ 4, 5, 31, 32 ,33}, // 2. Weiche, Gleis 3-4
};
void setup(void)
{
for (Steuerung &s : steuerung) s.init();
}
void loop(void)
{
for (Steuerung &s : steuerung) s.control();
}
Meinungen? Korrekturen?
Pinzuordnung ist in der Initialisierung in der Reihenfolge gerade gezogen. Immer zuerst Gerade dann Abzweig. Falls das jemanden stört.