Arduino interrupt

Gestart door bumper, 08 januari 2024, 21:29:55 PM

bumper

Beste specialisten,

Ik tracht de tijd te berekenen tussen twee hall sensoren, die op de baan gemonteerd zijn, als een loc passeert.
Aan de hand van hun afstand ken ik ook de snelheid van de loc.
Het ingangssignaal is hoog met een pull-down weerstand van 10kohm.
Het signaal wordt laag als de loc de sensor passeert omwille van de magneet die eronder is geplakt.
Dit werkt en is getest.
Om nu te testen of de interrupt voor sensor1 werkt heb ik volgend programma samengesteld.
In de pintoewijzing van mijn programma staat : const byte S1interrupt = 2;  // sensor1                             
                                               unsigned long int gemtijd_a;
                                               boolean sensor1 = false;
                                               const int led1 = 11;
                                               const int led2 = 12;

In de setup staat : attachInterrupt (digitalPinToInterrupt(S1interrupt),tijd_a,CHANGE);
                    pinMode (led1,OUTPUT);
                    pinMode (led2,OUTPUT);
In het programma staat :
void loop () {
  delay (5000);
  if (sensor1 == true) {
    digitalWrite (led1,LOW);
  }
  if (gemtijd_a > 0) {
    digitalWrite (led2,LOW);
  }
}
void tijd_a () {
  sensor1 = true;
  gemtijd_a = millis();
  digitalWrite (led1,HIGH);
  digitalWrite (led2,HIGH);
}
Probleem : het werkt niet.
Ik heb al verschillende codes uitgeprobeerd, maar ik krijg het niet werkende.
Wellicht zit ik op een verkeerd spoor.
Hopelijk kan iemand onder jullie mij helpen.
Dank op voorhand.

Ludo.
 
 

perk

Ik heb nog nooit interrupts gebruikt in mijn Arduino code, hiermee kan ik niet helpen.

Echter, als dit het enige is dat de arduino moet doen... waarom dan eigenlijk een interrupt met delay gaan gebruiken?

Waarom laat je 'em niet gewoon in de loop zonder enige delay continue de sensor in de gaten houden?  Ik zou denken dat de Arduino dat sneller kan dan je modeltrein kan rijden op de baan?


bumper

Patrick,
De arduino moet natuurlijk veel meer doen.
Maar als je dat ineens in een programma implementeerd, en uw programma werkt niet, begin dan maar te zoeken.
Vandaar de stap voor stap test van programma onderdelen die ik voor de eerste keer gebruik.
In totaal moeten er vier sensoren gemonitord worden naast een aantal andere opdrachten zoals wissels schakelen, seinen zetten enz.
Groeten.
Ludo.
 

perk

misschien zie ik erover, maar waar definieer je de input pin (als zijnde input)?

Ik zie 2 x pinmode met output maar niets met input ?

zie ook : https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/

=>   pinMode(interruptPin, INPUT_PULLUP);


bumper

Patrick,

Inderdaad, dat staat er niet bij in de setup.
Wel vreemd dat ik geen foutmelding kreeg bij de verificatie.
Ik ga morgen de aanpassing doorvoeren en kijken wat dat geeft.
Bedankt om mee te denken.

Ludo.
 

bumper

Ik heb het programma aangepast en in de setup pinMode (S1interrupt,INPUT); toegevoegd.
Helaas werkt niet.
Ik vraag mij af of het nodig is dat er een internetverbinding tijdens het uploaden nodig is. De draadloze verbinding op mijn zolder werkt niet en een vaste verbinding daar heb ik niet.
Als dat nodig is zal ik een wifi versterker moeten installeren denk ik.

Ludo.
 

patrick smout

Dag Ludo,

Als ik de code lees snap ik niet zo goed wat de bedoeling is. Wat doet je denken dat deze niet werkt? M.a.w. , wat verwacht je te zien?
Zoals ik de code lees wordt de led uitgang voor een fractie van een seconde (<5ms) hoog gezet telkens als de ingang van toestand gewijzigd is. Ik kan me niet voorstellen dat dit de bedoeling is. Haal beide codelijnen

 digitalWrite (led1,LOW);

eens tijdelijk uit je programma. Zo kan je zien of de interrupt uitgevoerd wordt.
Met vriendelijke groeten,

Patrick Smout

perk

Ik doe een simpele println naar de seriële monitor als debug.   
gewoon een lijn afdrukken als een deel van het programma doorlopen word.  Soms doe ik daar dan ook de variabelen in, zo kan ik zien wat de berekeningen echt doen.

Achteraf haal ik die debug code er dan uit.

Het voordeel is dat je dan een hoop debug stapje voor stapje kan lezen en beter kan inzien hoe het programma loopt.

Ik denk ook niet dat je internet verbinding nodig hebt, tenzij je libraries gaat nodig hebben bij compilatie
maar dan zou je een fout moeten krijgen bij het compileren

Ik begrijp ook je testprogramma niet helemaal (maar ja, ik begrijp vaak mijn eigen programma's de volgende dag niet meer)

elke 5 seconden ga je de led1 afzetten, maar alleen als de interrupt al geweest is.
Want ik zie nergens een andere manier voor de led1 van status te veranderen.  Er is zelfs geen initiële status dus gaat ie aan bij het begin?

Dus we gaan van iets ongedefinieerd (geen idee hoe Arduino dat verwerkt, als 1 of 0)
zodra de trein erover gaat, gaat de led1 zeker aan.

Maar binnen de 5 seconden daarna, gaat ie weer uit.   Je kan wel niet voorspellen of dat binnen de 4, 4.5 of 0.00001 seconde is.

sensor1 gaat ook nooit meer naar false

In je interrupt definitie gebruik je 'CHANGE', dus als de trein over de magneet gaat - dan ga je 2 interupts genereren.
Wellicht is dit beter : 'FALLING' for when the pin goes from high to low.


patrick smout

Kleine correctie voor mijn posting na reactie van Perk.

Delay(5000) is inderdaad 5000ms of 5s en geen 5000us of 5ms, foutje van mij. Je zou dus wel iets moeten kunnen zien aan de LEDs dat de Arduino het grootste deel van de tijd in Delay aan het wachten is.

Println is een prima manier om te kijken wat er aan de hand is echter vanuit een interrupt routine aangeroepen zou dit toch wel wat neveneffecten kunnen hebben. Ledje aan of uit zetten in een interrupt routine lijkt me veiliger.

Ben je zeker dat je beide leds direct vanuit de hoofdlus aan en uit kan zetten? Zou dit als eerste werkende willen zien. Vervolgens digitale ingang aan led knopen zodat je kan zien dat de ingang werkt. Vervolgens ingang lezen via de interrupt. Heel eenvoudig starten en stap voor stap met kleine stapjes complexiteit toevoegen. Bedoeling is dat je de boel werkende houdt. Werkt het plots niet meer dan zit het probleem in de relatief kleine wijziging die je gemaakt hebt.


Met vriendelijke groeten,

Patrick Smout

bumper

Even wat meer toelichting.
Ik rij analoog DC.
Mijn baan is niet groot, het zichtbare gedeelte bestaat uit een dubbel spoor station met uitrijseinen.
Het overige is een schaduwstation met 9 opstelsporen.
Bedoeling is om treinen te laten stoppen in het station of voor het uitrijsignaal indien rood.
Het afremmen en stoppen via pwm heb ik reeds uitgetest en werkt.
Probleem is stoppen op de juiste plaats, aan het perron (reizigers) of voor het uitrijsein indien rood (reizigers en goederen).
Via een code weet ik op voorhand welke trein er komt en wat hij zal moeten doen afhankelijk van de seintoestand.
De voedings transfo heeft een vaste stand voor de snelheid.
Wat wil ik nu doen.
Ik heb 2 hall sensoren ingebouwd op een vaste afstand. Met de tijd tussen 2 pulsen kan ik de snelheid berekenen.
Ik heb voor elke type loc uitgetest hoeveel cm deze nodig heeft om te stoppen. Afhankelijk van de plaats waar moet gestopt worden kan ik kan ik dus berekenen hoeveel seconden er moet gewacht worden alvorens de afremprocedure in te zetten.
Alleen het werken met interrupts heb ik nog nooit gedaan.
De pulsen van de sensoren komen door, dat heb ik getest met een led. Deze is normaal aan en gaat uit als de loc de sensor passeert.
Wat ik dus nu wil nagaan is als het signaal nul wordt, de subroutine aangesproken wordt via het aanzetten van de led en het inlezen van de processor tijd door te controleren of de variabele groter is dan nul.
Als dat eenmaal werkt dan kan ik ook met de tweede sensor de processortijd opnemen. Het verschil tussen deze twee zijn dan toch het aantal seconden tussen de twee pulsen (uiteraard met de nodige berekeningen).
Het aantal seconden en de afstand geeft de snelheid en nadien deze snelheid en de af te leggen weg geven mij het aantal seconden dat na de tweede puls moet gewacht worden alvorens het remmen in te zetten.
Er bestaan wellicht andere technieken om dat te doen, maar ik dacht dat deze manier via eenvoudige code toch zou moeten werken, daar ik maar een amateur programmeur ben.
Dit is dus de laatste stap, maar precies niet de eenvoudigste.
Hopelijk begrijpen jullie mijn doelstelling.

Groeten.
Ludo.
 

dani

heel belangrijk om te weten is dat als je met interrupts werkt, je dan best NIET met  delay(x)   in parallel werkt, want als je arduino in een delay commando zit dan stop alles, dus ook de interrupts.

Ik heb dat zelf ook met schade en schande geleerd.
Ben nu aan het werk dus ik heb niet de tijd om je programma in detail te bekijken maar ik kom er op terug !!!

Dani
De kruik is te water gegaan...
De kruik is niet meer.

dani

"Het ingangssignaal is hoog met een pull-down weerstand van 10kohm."

Dat is al een tegenstrijdigheid ..; Je bedoelt waarschijnlijk pull_up weerstand.

Dat kan je ook in je code doen met   pinMode(<pin>, INPUT_PULLUP);
Dani zorgt de arduino zelf voor de weerstand , geen extra hardware nodig.

(maar dat is niet relevant voor je interrupt)



--- verder moet je in jouw geval met  "falling"  signalen werken op je sensor.
De kruik is te water gegaan...
De kruik is niet meer.

dani

Citaat van: bumper op 08 januari 2024, 22:04:52 PMIn totaal moeten er vier sensoren gemonitord worden naast een aantal andere opdrachten zoals wissels schakelen, seinen zetten enz.
Groeten.
Ludo.
Ook hier zie ik een probleem, een UNO / NANO / MINI heeft geloof ik maar 2 interrupts.

Arduino Uno, Nano, Mini     2, 3
Arduino Mega                   2, 3, 18, 19, 20, 21
Arduino Micro, Leonardo           0, 1, 2, 3, 7
Arduino Zero               All digital pins except 4
De kruik is te water gegaan...
De kruik is niet meer.

bumper

Dani,
Ik werk met een Mega.
Dat systeem met een Pull-UP weerstand ken ik, maar ik bedoel wel degelijk een PULL-DOWN weerstand extern dus.
Want als mijn signaal weg valt, moet de ingang naar nul of massa getrokken worden, anders is de ingang niet ondubbelzinnig gedefinieerd.
Dat van delay in parallel met interrupts wist ik niet, ik ga er in het definitieve programma rekening mee houden.
In mijn testprogramma is het enkel om de led duidelijk te zien branden.
Signaaltoestand falling ga ik aanpassen.
Groeten.
Ludo.
 

patrick smout

Dag Ludo,

probeer de hoofdlus eens als in onderstaand voorbeeld.
Alle credits naar Dani. Wat dit voorbeeld doet is ook met 5sec intervallen kijken of er interrupt geweest is.
Er wordt echter geen gebruik gemaakt van Delay() omdat die volgens info van Dani de interrupts uitschakelt zolang er gewacht wordt. Ik ben geen Arduino programmeur dus ben wel ik enorm verrast door dit gegeven en tegelijk ook weer iets bijgeleerd.

unsigned long basetime;

void loop () {

  if (millis() - basetime >= 5000)
  {
    basetime = millis();

    if (sensor1 == true) {
      digitalWrite (led1,LOW);
    }
    if (gemtijd_a > 0) {
      digitalWrite (led2,LOW);
    }
  }
}
Met vriendelijke groeten,

Patrick Smout