Delay veranderen naar millis na schakelaar state change

algemene C code
Berichten: 37
Geregistreerd: 07 Okt 2016, 10:33

Delay veranderen naar millis na schakelaar state change

Berichtdoor maartentukker » 03 Dec 2020, 13:38

Hallo,
Ik ben al een tijdje bezig met arduino en heb al veel coderingen werkend voor mijn modelspoor automatisatie.
Echter ben ik erg aan het stoeien met een ogenschijnlijk simpel probleem, namelijk een delay vervangen door millis.
Ik wil namelijk dat een signaal (S3) dat LOW geschakeld is door een binnenkomende trein weer HIGH geschakeld kan worden door een schakelaar (wissel) om te zetten.
Dit gebeurd overigens prima, maar zodra ik daar een kleine vertraging in probeer te bouwen gaat het mis en blijft deze direct schakelen na de volgende veranderings detectie: (W1State != lastW1State).
Dit om te voorkomen dat de wissel nog niet in zijn uiterste stand staat terwijl de trein erover rijd.
Ik heb al vele mogelijkheden geprobeerd, maar het lijkt erop dat de vertraging gewoon overgeslagen wordt????

In de code staan nog delen van het hoofd programma wat verder uitstekend werkt, en heb als test de loop ingekort tot 3 blokken.


Code: Alles selecteren
[code]
/*
    Block detection, Activated Block -1 is isolated, -2 is set free
*/

// Hall sensors:
const int Ha1a = 3;
const int Ha1b = 4;
const int Ha2 = 5;
const int Ha3 = 6;
const int Ha4 = 7;
const int Ha5 = 8;
const int Ha6 = 9;
const int Ha7 = 10;
const int Ha8 = 11;
const int Ha9 = 12;
const int Ha10 = 13;

// Light signals:
const int L1arood = 16;     const int L1agroen = 17;
const int L1brood = 18;     const int L1bgroen = 19;
const int L8rood = 20;      const int L8groen = 21;

// Section isolate:
const int S1a = 30;         const int S1b = 31;
const int S2 = 32;
const int S3 = 33;
const int S4 = 34;
const int S5 = 35;
const int S6 = 36;
const int S7 = 37;
const int S8 = 38;
const int S9 = 39;
const int S10 = 40;

// Toggle switch input turnout 1
const int W1 = A1;

int W1State = 0;
int lastW1State = 0;
int lastHa1aState, lastHa1bState, lastHa2State, lastHa3State, lastHa4State, lastHa5State, lastHa6State, lastHa7State, lastHa8State, lastHa9State, lastHa10State;

unsigned long relaisMillis = 0;
unsigned long relaisDelay = 2000;


void setup()
{
  // Sensors
  pinMode(Ha1a, INPUT);       pinMode(Ha1b, INPUT);
  pinMode(Ha2, INPUT);
  pinMode(Ha3, INPUT);
  pinMode(Ha4, INPUT);
  pinMode(Ha5, INPUT);
  pinMode(Ha6, INPUT);
  pinMode(Ha7, INPUT);
  pinMode(Ha8, INPUT);
  pinMode(Ha9, INPUT);
  pinMode(Ha10, INPUT);

  // Signals
  pinMode(L1arood, OUTPUT); digitalWrite(L1arood, LOW);     pinMode(L1agroen, OUTPUT); digitalWrite(L1agroen, HIGH);
  pinMode(L1brood, OUTPUT); digitalWrite(L1brood, LOW);     pinMode(L1bgroen, OUTPUT); digitalWrite(L1bgroen, HIGH);
  pinMode(L8rood, OUTPUT);  digitalWrite(L8rood, LOW);      pinMode(L8groen, OUTPUT);  digitalWrite(L8groen, HIGH);

  // Section isolate     Power on all blocks at startup
  pinMode(S1a, OUTPUT); digitalWrite(S1a, HIGH);             pinMode(S1b, OUTPUT); digitalWrite(S1b, HIGH);
  pinMode(S2, OUTPUT);  digitalWrite(S2, HIGH);
  pinMode(S3, OUTPUT);  digitalWrite(S3, HIGH);
  pinMode(S4, OUTPUT);  digitalWrite(S4, HIGH);
  pinMode(S5, OUTPUT);  digitalWrite(S5, HIGH);
  pinMode(S6, OUTPUT);  digitalWrite(S6, HIGH);
  pinMode(S7, OUTPUT);  digitalWrite(S7, HIGH);
  pinMode(S8, OUTPUT);  digitalWrite(S8, HIGH);
  pinMode(S9, OUTPUT);  digitalWrite(S9, HIGH);
  pinMode(S10, OUTPUT); digitalWrite(S10, HIGH);

  // W1 is toggle switch position for turnout 1
  pinMode(W1, INPUT_PULLUP);

}


void loop()
{

  // read the Hall sensor (Block) input pin:
  int Ha1aState = digitalRead(Ha1a);      int Ha1bState = digitalRead(Ha1b);
  int Ha2State = digitalRead(Ha2);
  int Ha3State = digitalRead(Ha3);
  int Ha4State = digitalRead(Ha4);
  int Ha5State = digitalRead(Ha5);
  int Ha6State = digitalRead(Ha6);
  int Ha7State = digitalRead(Ha7);
  int Ha8State = digitalRead(Ha8);
  int Ha9State = digitalRead(Ha9);
  int Ha10State = digitalRead(Ha10);

  // read the turnout (toggle switch) position)
  int W1State = digitalRead(W1);


  // Block 2 occupied
  if (Ha2State == HIGH && lastHa2State == LOW)
  {
    digitalWrite(S3, HIGH);      // 35
    digitalWrite(S1a, LOW);    // 30
    digitalWrite(S1b, LOW);    // 31
    digitalWrite(L1arood, HIGH);   digitalWrite(L1agroen, LOW); // 16  17
    digitalWrite(L1brood, HIGH);   digitalWrite(L1bgroen, LOW); // 18  19
    delay(10);
  }

  // Block 3 occupied
  if (Ha3State == HIGH && lastHa3State == LOW)
  {
    digitalWrite(S1a, HIGH);     // 30
    digitalWrite(S1b, HIGH);     // 31
    digitalWrite(S2, LOW);     // 32
    digitalWrite(L1arood, LOW);   digitalWrite(L1agroen, HIGH); // 16  17
    digitalWrite(L1brood, LOW);   digitalWrite(L1bgroen, HIGH); // 18  19
    delay(10);
  }

  // Block 1 occupied  = Block 1 is double track with 2 light signals.
  if ((Ha1aState == HIGH && lastHa1aState == LOW) || (Ha1bState == HIGH && lastHa1bState == LOW))
  {
    digitalWrite(S2, HIGH);      // 32
    digitalWrite(S3, LOW);     // 33
    delay(10);
    lastHa1aState = Ha1aState;
    lastHa1bState = Ha1bState;
  }

  unsigned long currentMillis = millis();
[color=#FF0000]
  if (W1State != lastW1State) {                               // Checks if turnout 1 has shifted since last position (which the train used to occupy track Ha1a or Ha1b)
    if ((currentMillis - relaisMillis) >= relaisDelay) {      // Set timer for activating the relais to put power on the track
      digitalWrite(S3, HIGH);     // 33                          switch relais
      relaisMillis = millis();
    }
  }[/color]


  // Save last state change
  lastHa1aState = Ha1aState;    lastHa1bState = Ha1bState;
  lastHa2State = Ha2State;
  lastHa3State = Ha3State;
  lastHa4State = Ha4State;
  lastHa5State = Ha5State;
  lastHa6State = Ha6State;
  lastHa7State = Ha7State;
  lastHa8State = Ha8State;
  lastHa9State = Ha9State;
  lastHa10State = Ha10State;
  lastW1State = W1State;


  delay(10);  //debounce
}
[/code]

Advertisement

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: Delay veranderen naar millis na schakelaar state change

Berichtdoor Koepel » 03 Dec 2020, 14:01

Als wij schrijven dat het beter is om millis() te gebruiken in plaats van delay(), dan bedoelen we dat de hele sketch omgebouwd moet worden om millis() te gaan gebruiken.
Je kunt millis() niet gebruiken zoals je delay() gebruikt.

Met millis() is het alsof je steeds op de klok kijkt of er nog iets gedaan moet worden.
Stel je doet een ei in kokend water en je wilt het ei er na drie minuten uit halen. Dan kijk je steeds op de klok om te kijken of er drie minuten voorbij zijn. Het geeft niet hoe vaak je op de klok kijkt. Als het ei er uit is, dan is dat een eenmalige gebeurtenis. Je wilt niet het ei er honderden keren per seconde uit halen.

Dat is een single shot timer. Met millis() gaat dat zo: https://github.com/Koepel/Fun_with_millis/blob/master/millis_single_delay.ino.

Lees eens de BlinkWithoutDelay pagina: https://www.arduino.cc/en/Tutorial/BuiltInExamples/BlinkWithoutDelay.
De single shot timer is een millis-timer die zichzelf uit zet met de 'enabled' variabele.

Er is een moment dat je de millis-timer aan zet. Dan doe je relaisMillis = millis(); en je zet de timer aan met enabled = true;.
Vanaf dat moment loopt de millis-timer op zichzelf in de loop().
Je zou die 'enabled' anders kunnen noemen, bijvoorbeeld 'enableRelaisTimer'.

Jij wilt een millis-timer laten lopen achter een if (W1State != lastW1State), maar dat geeft meteen problemen.
Het gaat er om dat de loop() honderden keren per seconde wordt uitgevoerd en dat honderden keren per seconden wordt gekeken naar de millis-timer of er al iets gedaan moet worden.

Als je tientallen aparte dingen wilt vertragen, dan krijg je ook tientallen aparte millis-timers. Ze hebben elk hun eigen 'enabled' en eigen 'previousMillis' variabele.

Berichten: 37
Geregistreerd: 07 Okt 2016, 10:33

Re: Delay veranderen naar millis na schakelaar state change

Berichtdoor maartentukker » 03 Dec 2020, 17:50

Het werkt! Idd met de enabled functie, dit had ik nog niet zo geprobeerd, maar duidelijk dat je nu voor elk wissel een eigen naam moet creeren.
Bedankt!

Terug naar C code

Wie is er online?

Gebruikers in dit forum: Geen geregistreerde gebruikers en 6 gasten