Hello Ernie
Even if another forum member doesn't like it, I will propose a solution for modeltrain block control with C++ programming for you.
In this case, all the common information is declared in a data structure:
struct BLOCKCONTROL {
byte sensorPin; // portPin o---|button|---GND
byte ledPin; // portPin o---|220|---|LED|---GND
int sensorOldState;
TIMER ledDelay;
scan TIMER;
};
This data structure can be used to initialise any number of track blocks:
BLOCKCONTROL blockControls [] {.
{A0, 8, false, SomeDelay, 0, false, 20, 0, false},
{A1, 9, false, SomeDelay, 0, false, 20, 0, false},
{A2, 10, false, SomeDelay, 0, false, 20, 0, false},
{A3, 11, false, SomeDelay, 0, false, 20, 0, false},
{A4, 12, false, SomeDelay, 0, false, 20, 0, false},
};
In the loop(), a service takes care of the processing.
What else is conceivable here is to use a PWM output to accelerate a locomotive?
Just try it out and play around with the sketch.
/* BLOCK COMMENT
ATTENTION: This Sketch contains elements of C++.
https://www.learncpp.com/cpp-tutorial/
Many thanks to LarryD
https://europe1.discourse-cdn.com/arduino/original/4X/7/e/0/7e0ee1e51f1df32e30893550c85f0dd33244fb0e.jpeg
https://forum.arduino.cc/t/press-a-button-and-when-released-switch-off-led-with-delay/1005935
Tested with Arduino: Mega[x] - UNO [ ] - Nano [ ]
*/
#define ProjectName "Press a button and when released switch off led with delay"
// HARDWARE AND TIMER SETTINGS
// YOU MAY NEED TO CHANGE THESE CONSTANTS TO YOUR HARDWARE AND NEEDS
#define OutPutTest
constexpr unsigned long OutPutTestTime {1000};
constexpr unsigned long SomeDelay {500};
// VARIABLE DECLARATION AND DEFINITION
unsigned long currentTime;
// -- objects -----------------------------------------
struct TIMER { // has the following members
unsigned long duration; // memory for interval time
unsigned long stamp; // memory for actual time
int onOff; // control for stop/start/repeat
};
struct BLOCKCONTROL {
byte sensorPin; // portPin o---|button|---GND
byte ledPin; // portPin o---|220|---|LED|---GND
int sensorOldState;
TIMER ledDelay;
TIMER scan;
};
BLOCKCONTROL blockControls [] {
{A0, 8, false, SomeDelay, 0, false, 20, 0, false},
{A1, 9, false, SomeDelay, 0, false, 20, 0, false},
{A2, 10, false, SomeDelay, 0, false, 20, 0, false},
{A3, 11, false, SomeDelay, 0, false, 20, 0, false},
{A4, 12, false, SomeDelay, 0, false, 20, 0, false},
};
// -------------------------------------------------------------------
void setup() {
Serial.begin(9600);
Serial.println(F("."));
Serial.print(F("File : ")), Serial.println(__FILE__);
Serial.print(F("Date : ")), Serial.println(__DATE__);
Serial.print(F("Project: ")), Serial.println(ProjectName);
pinMode (LED_BUILTIN, OUTPUT); // used as heartbeat indicator
// https://www.learncpp.com/cpp-tutorial/for-each-loops/
for (auto blockControl : blockControls) pinMode(blockControl.sensorPin, INPUT_PULLUP);
for (auto blockControl : blockControls) pinMode(blockControl.ledPin, OUTPUT);
#ifdef OutPutTest
// check outputs
for (auto blockControl : blockControls) digitalWrite(blockControl.ledPin, HIGH), delay(OutPutTestTime);
for (auto blockControl : blockControls) digitalWrite(blockControl.ledPin, LOW), delay(OutPutTestTime);
#endif
}
void loop () {
currentTime = millis();
digitalWrite(LED_BUILTIN, (currentTime / 500) % 2);
for (auto &blockControl : blockControls) {
if ( currentTime - blockControl.scan.stamp >= blockControl.scan.duration) {
blockControl.scan.stamp = currentTime;
int stateNew = !digitalRead(blockControl.sensorPin);
if (blockControl.sensorOldState != stateNew) {
blockControl.sensorOldState = stateNew;
if (!stateNew) {
blockControl.ledDelay.onOff = true;
blockControl.ledDelay.stamp = currentTime;
digitalWrite(blockControl.ledPin, HIGH);
}
}
}
if ( currentTime - blockControl.ledDelay.stamp >= blockControl.ledDelay.duration && blockControl.ledDelay.onOff) {
blockControl.ledDelay.onOff = false;
digitalWrite(blockControl.ledPin, LOW);
}
}
}
Have a nice day and enjoy programming in C++ and learning.
Errors and omissions excepted.
Дайте миру шанс!