Herschrijven en opruimen van de verkeerslichten project

vervolg van : Why is the button press seen ? - #132 by sterretje

Dit compileert

statemachine.cpp

#include "StateMachine.h"

void resetState(bool lights = true) {
  //timers.flashCar.reset = true;
  //timers.flashPed.reset = true;
  //timers.loop.reset = true;

  //if (lights) allLightsOff();
}


// Retrieve a state entry by enum
const StateInfo* getStateInfo(StateNames state) {
  for (uint8_t i = 0; i < NUMELEMENTS(stateTable); i++)
    if (stateTable[i].name == state)
      return &stateTable[i];

  return nullptr;  // important fix
}

void enterState(StateNames state) {
  const StateInfo* info = getStateInfo(state);

  if (!info) {
    Serial.println(F("ERROR: Invalid state"));
    return;
  }

  
  Serial.print(F("Entering state: "));
  Serial.println(info->label);

  if (state == stX) {
    resetState(false);
  } else {
    resetState();
  }
}

StateNames nextStateByTimer(StateNames current) {
  const StateInfo* info = getStateInfo(current);
  if (!info) return current;

  /*
  if (timers.loop.expired(info->duration)) {

    Serial.print("Tijd voor entering state: ");
    Serial.println(millis()) ;
    //enterState(info->next);
    return info->next;  // fixed
  }
  */
  return current;
}

StateNames nextStateByButton(StateNames current) {
  return current;
}

Statemachine.h

#pragma once 

#include "Arduino.h"
#include "macros.h"

enum StateNames {
  st_Blink,
  st_Red_Cars_Red_Pedestrians,
  st_Green_Cars_Red_Pedestrians,
  stX,
  st_Orange_Cars_Red_Pedestrians,
  st_Red_Cars_Red_Pedestrians_After_Cars_Loop,
  st_Red_Cars_Green_Pedestrians,
  st_Red_Cars_Green_Blinking_Pedestrians,
  st_Red_Cars_Red_Pedestrians_after_Pedestrians_Loop
};

struct StateInfo
{
  const StateNames name;
  const char* label;
  unsigned long duration;
  StateNames (*getNextState)(StateNames);
};

// Declare functions
StateNames nextStateByTimer(StateNames current);
StateNames nextStateByButton(StateNames current);
void enterState(StateNames state); 
const StateInfo* getStateInfo(StateNames state);
void resetState(bool lights); 


StateInfo stateTable[] = {
  { st_Blink, "Blink", 6000, nextStateByTimer },
  { st_Red_Cars_Red_Pedestrians, "Red/Red", 5000, nextStateByTimer },
  { st_Green_Cars_Red_Pedestrians, "Green/Red", 0, nextStateByButton },
  { stX, "Crossing", 4000, nextStateByTimer },
};

macros.h

#pragma once

#define NUMELEMENTS(x) (sizeof(x) / sizeof(x[0]))

De timers moet ik nog even over nadenken.
En ook wat ik nu moet invullen in de plaats van ->next

Morgen weer een dag

of kan ik dit doen:

#include "StateMachine.h"
#include "timer.h"

void resetState(bool lights = true) {
  timers.flashCar.reset = true;
  timers.flashPed.reset = true;
  timers.loop.reset = true;

  //if (lights) allLightsOff();
}


// Retrieve a state entry by enum
const StateInfo* getStateInfo(StateNames state) {
  for (uint8_t i = 0; i < NUMELEMENTS(stateTable); i++)
    if (stateTable[i].name == state)
      return &stateTable[i];

  return nullptr;  // important fix
}

void enterState(StateNames state) {
  const StateInfo* info = getStateInfo(state);

  if (!info) {
    Serial.println(F("ERROR: Invalid state"));
    return;
  }


  Serial.print(F("Entering state: "));
  Serial.println(info->label);

  if (state == stX) {
    resetState(false);
  } else {
    resetState();
  }
}

StateNames nextStateByTimer(StateNames current) {
  const StateInfo* info = getStateInfo(current);
  if (!info) return current;


  if (timers.loop.expired(info->duration)) {

    Serial.print("Tijd voor entering state: ");
    Serial.println(millis());

    StateNames next;
    switch (current) {
      case st_Blink:
        next = st_Red_Cars_Red_Pedestrians;
        break;
    }

    enterState(next);
    return next;  // fixed
  }

  return current;
}

StateNames nextStateByButton(StateNames current) {
  return current;
}

@sterretje

heb even een frisse blik nodig om dit op te lossen.

C:\Users\rwobb\AppData\Local\arduino\sketches\7E627F0188FA596F45FA6EEBA9DC532E\sketch\traffic_light_with_different_files.ino.cpp.o (symbol from plugin): In function `setup':
(.text+0x0): multiple definition of `pinsTL'
C:\Users\rwobb\AppData\Local\arduino\sketches\7E627F0188FA596F45FA6EEBA9DC532E\sketch\lights.cpp.o (symbol from plugin):(.text+0x0): first defined here
C:\Users\rwobb\AppData\Local\arduino\sketches\7E627F0188FA596F45FA6EEBA9DC532E\sketch\traffic_light_with_different_files.ino.cpp.o (symbol from plugin): In function `setup':
(.text+0x0): multiple definition of `pinsPL'
C:\Users\rwobb\AppData\Local\arduino\sketches\7E627F0188FA596F45FA6EEBA9DC532E\sketch\lights.cpp.o (symbol from plugin):(.text+0x0): first defined here
C:\Users\rwobb\AppData\Local\arduino\sketches\7E627F0188FA596F45FA6EEBA9DC532E\sketch\traffic_light_with_different_files.ino.cpp.o (symbol from plugin): In function `setup':
(.text+0x0): multiple definition of `buttonList'
C:\Users\rwobb\AppData\Local\arduino\sketches\7E627F0188FA596F45FA6EEBA9DC532E\sketch\button.cpp.o (symbol from plugin):(.text+0x0): first defined here
collect2.exe: error: ld returned 1 exit status
exit status 1

Compilation error: exit status 1

Code :

button.zip (3,7 KB)

Je hebt een .h bestand waarin je pinsTL en pinsPL definieert. Deze include je in verschillende bestanden en als een resultaat heb twee verschillende sets van variabelen en C/C++ houdt daar niet van.

#pragma once voorkomt dat niet, det heeft slechts invloed op één compilatie unit (.cpp, .ino). Het voorkomt problemen als je twee keer hetzelfde bestand include (direct of indirect).

In één van je oudere topics hebben we extern gebruikt, kijk eens of dat de oplossing kan brengen.

Ben ik hier op de goede weg

button.zip (4,2 KB)

Het lijkt er wel op.

Ik ben bezig met een volledig herschrijven van je huidige verkeerslicht. Voor zover ik het kan zien zou dat vele malen makkelijker zijn om aan te passen.

Ik heb het (denk ik) werkend met een testprogramma, ik zal proberen morgen dat te veranderen naar het verkeerslicht.

Als dat werkt kan ik het presenteren (met beschrijving); het zal wel wat tijd in beslag nemen om de beschrijving te maken.

oke

ben dan wel nieuwsgierig.

Is het dan wel verstandig om door te gaan met mijn idee ?

Is het test programma klaar zo dat ik kan kijken in welke richting jij denkt ?

Van iedere stap leer je. Een misschien zijn er delen die je later opnieuw kunt gebruiken.
Ik heb bijv. je timer gebruikt (het is nu een class).

fsm_demo_04b.zip (6.5 KB)

Het programma schakelt LED_BUILTIN; off, blink en on.

Er zijn vier knoppen (dat is mijn opstelling) maar slechts één wordt op dit moment gebruikt (pin 3)

3 states

Overgangen

  1. Je kunt van stOff naar stBlink gaan door de knop in te drukken.
  2. Als je de knop binnen 4 seconden loslaat ga je terug naar stOff.
  3. Als je de knop niet loslaat gaat het programma na 4 seconden verder naar stON.
  4. stOn wordt verlaten na 3 seconden.
  5. Als je de knop niet losgelaten hebt gedurende deze cyclus moet je de knop loslaten en weer indrukken om naar stBlink te gaan.

Eerste oefening
In plaats van een timer voor stOn de knop gebruiken. De functie daarvoor (stOn_stOff_Button()) is al geschreven, je hoeft slechts één ding te veranderen in het .ino bestand.

Tweede oefening
stOn verlaten als de knop veranderd is EN de timer afgelopen is; volgorde maakt niet uit. Daarvoor moet je bool stOn_stOff_ButtonAndTimer() invullen en er later in het .ino bestand voor zorgen dat die inderdaad wordt aangeroepen (zie eerste oefening).
Als je extra variabelen nodig hebt mag je die alleen in de functie declareren, nergens anders.

libFsmA bevat de daadwerkelijke FSM. Je kunt hier in principe een echte bibliotheek van maken en in de libraries directory van de sketchbook directory plaatsen, vandaar de naam beginnend met lib.
:warning: Je hoeft niets te veranderen aan libFsmA.

Alle andere bestanden zijn bestanden die jij schrijft voor de benodigde functionaliteiten.

oke

Voor het eerst dat ik je een class zie gebruiken,

Als ik dit in wokwi wil gebruiken,dan heb ik dus 1 led nodig en 4 knopppen ?

ik heb nu zeker even tijd nodig om te zien hoe alles werkt.

ik denk voor de eerste oefening

deze code :

// transitions from state On
Transition stOn_Transitions[] = {
  { stOff, stOn_stOff_Timer },
};

op deze manier verandert moet worden:

// transitions from state On
Transition stOn_Transitions[] = {
  { stOff, stOn_stOff_Button },
};

Ben ik goed ??

Ja.

Ik weet niet of je dit al in wokwi hebt gezet maar dan is het makkelijk te controleren of het doet wat je verwacht / wat het moet doen.

nee,

Wilde eerst zeker weten of ik het goede idee heb.

zoals ik het zie ,hoef ik alleen 4 knoppen aan te sluiten.

Je hebt voor het programma zoals het is maar één knop nodig. Er zitten echter vier knoppen in (pinnen 2..5); dat is mijn opstelling en je hebt er later in je verkeerslicht met voetgangersoversteekplaats en fietsersoversteekplaats in ieder geval twee nodig.

Dan doe ik iets verkeerd , denk ik

Met deze opstelling: https://wokwi.com/projects/450314776602809345

Zie ik de led niet aan of uitgaan

En voor opdracht 2:

bool stOn_stOff_ButtonAndTimer()
{
  bool rb = false;
  buttons[stOnBtnIndex].update();
  if (buttons[stOnBtnIndex].changed() || stateTimer.expired(stOnDuration)) {
    rb = true;
  }
  return rb;
}

Er zit iets verkeerd in je bedrading.

Sloop je breadboard eruit en sluit de knop aan tussen GND en pin 3 (niet pin 2 !!). Net geprobeerd en het werkte.

Het was eigenlijk de bedoeling dat je de timer versie eerst probeerde maar OK.

Die moet je proberen maar ik denk niet dat dat gaat werken zoals ik bedoelde. De bedoeling was dat beide voorwaarden ooit eens waar geweest zijn terwijl je in stOn bent.

oke

Dan even in beide states duiken om te kijken welke functie's ik dan nodig heb.