Why is the button press seen ?

Op het "werk" probeer ik nu de verkeerslichten na te bouwen met een iets voor mij betere code.

Maar nu op de een of andere manier , als een gebruiker op de button drukt, blijft het groene verkeerslicht branden.

Kan iemand eens meekijken waar het probleem zit

Wokwi : https://wokwi.com/projects/448497770739272705

oke

Het lijkt te werken , alleen duurt het heel lang tussen dat je de button indrukt en het oranje licht aangaat.

Als ik tel , lijkt het wel 8 - 10 seconden te duren.
Is er een manier dat het wat sneller kan na een button druk ?

Jouw constatering is niet geheel juist.
Je moet net op het juiste moment op de knop drukken, of deze lang genoeg indrukken om geregistreerd te krijgen dat deze knop is ingedrukt.
Dat betekent dat jouw code toch een blokkerend deel er in moet hebben zitten.
Blokkerende code is niet alleen delay(), en die heb je ook niet als ik even snel door jouw code scan.
Maar er zitten wel for... loops in, en die zijn ook blokkerend.
Ik zie ook iets over timers voorbij komen, dus die moet je ook controleren of daar wat blokkeert.
Er staat toch iets over delay in je debounce deel, controleer dat ook.
En wat betekent keep debounced ?

oke, een hoop te controleren.

Ik bedoel daarmee dat de debounce moet blijven werken.

Leuke puzzel heb je gemaakt.

Zoals MAS3 al zei is je constatering niet juist.

Om te debuggen moet je veel meer print statements gebruiken. Verander om te beginnen je case st_Green_Cars_Red_Pedestrians naar

    case st_Green_Cars_Red_Pedestrians:
      digitalWrite2(pinsTL[2], pinsPL[0], HIGH);

      if (buttonList[0].currDebouncedState == ISPRESSED)
      {
        lastTimePressed = millis();
        Serial.print(F("button pressed @ "));
        Serial.print(lastTimePressed);
        
        Serial.print(F("\tcurrentState changed from "));
        Serial.print(stateTable[currentState].label);
        currentState = nextByTable(currentState);
        Serial.print(F(" to "));
        Serial.println(stateTable[currentState].label);
      }
      break;

en kijk naar het resultaat.

Volgens mij zijn die minimaal; misschien een paar microseconden voor iedere for-loop (niet getimed).

Ik zie al wat aparts

Entering state: Red/Red

Entering state: Green/Red

button pressed @ 17849	currentState changed from Green/Red to Green/Red

button pressed @ 17858	currentState changed from Green/Red to Green/Red

button pressed @ 17934	currentState changed from Green/Red to Green/Red

button pressed @ 18011	currentState changed from Green/Red to Green/Red

button pressed @ 18086	currentState changed from Green/Red to Green/Red

button pressed @ -6338	currentState changed from Green/RedEntering state: Crossing

 to Crossing

de laatste button press heeft een negatieve getal staan achter de @

Leuke puzzel nu waarom is die tijd negatief
Misschien omdat het een int is

Eens proberen met een long int

oke

maakt in ieder geval een positief getal

$
false false

Entering state: Red/Red

Entering state: Green/Red

button pressed @ 13248	currentState changed from Green/Red to Green/Red

button pressed @ 13257	currentState changed from Green/Red to Green/Red

button pressed @ 13333	currentState changed from Green/Red to Green/Red

button pressed @ 13410	currentState changed from Green/Red to Green/Red

button pressed @ 13486	currentState changed from Green/Red to Green/Red

button pressed @ 13561	currentState changed from Green/Red to Green/Red

button pressed @ 13638	currentState changed from Green/Red to Green/Red

button pressed @ 13714	currentState changed from Green/Red to Green/Red

button pressed @ 22011	currentState changed from Green/RedEntering state: Crossing

 to Crossing

Entering state: Orange/Red

Entering state: Red/Red

Entering state: Red/Green

Lijkt erop dat mijn button logic ergens niet klopt.
De eerste keren veranderd de state niet.

Ik ben blij dat je daar achter bent gekomen. Dat maakte het voor mij aanvankelijk moeilijk om het aantal seconden te kunnen tellen.

Dat is alleen uitstel :smiley:

Wat je moet opvallen is dat je niet van state verandert. Ik zou verwachten dat je onmiddellijk naar stX wilt schakelen als de knop ingedrukt wordt.

klopt. dat was het tweede wat mij opgevallen is.

Alleen nog geen idee waarom.

Zoals ik de code begrijp , blijft die groen totdat er een knop is ingedrukt
En hebben we een soort van delay ingebouwd zodat een voetganger niet steeds het voetgangerslicht op groen en de auto's op rood laten staan.

if (millis() - lastTimePressed > getStateInfo(currentState)->duration) {
        currentState = nextByTable(currentState);
      } else {
        if (timers.loop.expired(getStateInfo(currentState)->duration)) {
          currentState = nextByTable(currentState);
        }
      }

Dit betekent voor zover ik het begrijp dat de knop pas verander als de tijd tussen dat die ingedrukt is en de vorige keer groter is dan een bepaalde tijd.

Zo niet, wacht dan een aantal seconden en ga naar het oranje licht.

oke,

Na wat experimenten , lijkt het erop dat pas op de button wordt gereageerd als de wachtijd voor die state afgelopen is.

Dat niet helemaal wat de bedoeling is, maar zie ook niet helemaal de oplossing.

case st_Green_Cars_Red_Pedestrians heeft geen timer nodig; je wilt onmiddellijk op de knop (kunnen) reageren.

Er moet wel ergens een soort vertraging in zitten die voorkomt dat als voetgangers constant die knop indrukken het verkeer geen kans heeft. Als ik me niet vergis hadden we dat opgelost in je andere verkeerslicht onderwerp (maar ik weet niet meer precies welke dat is of in welke bericht in dat onderwerp).
Volgens mij is dat waar lastTimePressed (misschien heette die in het verleden anders) voor bedoeld was.

Dat was dit project : https://wokwi.com/projects/444503847056527361

En ik gebruikte daar deze code :

 case stX:
      /*
        Geen verandering in lichten.
        Als een voetgangerscyclus niet recentelijk was gedaan (bv laatste 120 seconden) gaan we naar stOR.
        Anders wachten we 120 seconden en gaan naar stOR; dit voorkoomt dat motorvoertuigen geen kans krijgen.
        In deze stap moet je bijhouden wanneer deze de laatste keer was aangeroepen.
      */
      interval_loop = 4000;
      if (millis() - lastTimePressed > 4000) {
        currentState = stOR;
        clearCurrentState();
      } else {
        if (timer_loop(interval_loop)) {
          currentState = stOR;
          clearCurrentState();
        }
      }

      break;

De interval is nu in de list geregeld en heet nu resetState die wordt aangeroepen door enterState die door nextByTable wordt aangeroepen.

En die wordt hier aangeroepen :

case stX:

      if (millis() - lastTimePressed > getStateInfo(currentState)->duration) {
        currentState = nextByTable(currentState);
      } else {
        if (timers.loop.expired(getStateInfo(currentState)->duration)) {
          currentState = nextByTable(currentState);
        }
      }

      break;

in de nieuwe code

Krijg meer en meer het gevoel dat de timers en buttons van elkaar afhankelijk zijn en dat lijkt me niet goed.

Als ik de waarde van st_Green_Cars_Red_Pedestrians op nul zet, duurt het nog steeds 4 seconden voordat er een button click geregisteerd wordt.

Hopelijk krijgen we een goed idee hoe dit op te lossen

Toon de timers in je debug venster, dan kun je zien hoe ze er voor staan.
Dus de status van je drukknop, alle timers en eventuele vlaggen die je zet toon je dan in je debug venster.

vreemd

Als ik nu probeer met de timer op 0 voor rood/groen dan werkt alles zoals ik het in mijn hoofd heb.

De button wordt gevonden en na 4 seconden gaat de voetgangers cyclus aan.

Waarom is het vreemd? Zie dit commentaar

En zit er nu een beveiliging in die voorkomt dat als een voetganger de knop continue ingedrukt houdt het verkeer nog een kans heeft?

Voor zover ik het kan testen wel.
ik heb meerdere keren vlak na elkaar gedrukt en de eerste keer gaat die naar de voetgangers cyclus en daarna gaat die gewoon door.

Vlak na elkaar is niet helemaal de juiste benadering, denk ik. Dat werkt inderdaad omdat je de knop alleen in st_Green_Cars_Red_Pedestrians gebruikt.

Stel je bent een voetganger en je wilt autootje pesten. Je neemt een tandenstoker mee, druk de knop in en gebruik de tandenstoker zodat de knop ingedrukt blijft.

Dat is wat je zou moeten proberen in je wokwi.

Heb ik ook net geprobeerd door de knop te blijven indrukken en alles gaat zoals ik dacht.