HO Brandweer

Hallo forum leden,

Mijn naam is Stefan, ik ben 16 en al een paar jaar met Arduino aan de gang. Ik ben bezig met een brandweer auto te maken die op een modelbaan komt te rijden. ik heb alleen een probleem en hoop dat iemand me er mee kan helpen. het is de bedoeling dat hij gaat rijden zodra hij een input krijgt van een reed contact vervolgens als hij rijdt moet hij bij de volgende input van de zelfde reed contact gaan afremmen etc. ik ben van plan om dit te doen door van de ene status naar de andere te gaan omdat er ook nog verlichting moet worden ingeschakeld enzo. Maar krijg dat niet voor elkaar.

Alvast bedankt.

Met vriendelijke groet,

Stefan

Welcom,

Een schema en de code zover zal helpen om het probleem te analyseren.

Code graag in code tags => # button above smileys.

Tekening kan als attachment bij additional options

Hoi Stefan, welkom.

Je noemt reed contacten als input.
Maar een reed contact heeft een magneet nodig om te schakelen.
Komt er dus een magneet voorbij ofzo ?
Vertel eens meer over hoe je dat bedacht hebt ?

Je hebt al wel goed door dat je een state machine, zoals dat heet, kunt gebruiken om een aantal malen indrukken van een toets (of reed contact, is wat dat betreft hetzelfde) verschillende dingen te laten doen.
Je noemt dan ook nog iets over verlichting schakelen, maar ik zie niet helemaal het verband daarin.
Wat gebruik je om die verlichting te bedienen ?
Kijk je of het donker is, of een schakelaar of misschien ook zo'n reed contact (dan word het interessant) ?

En, zoals Rob al zei, als je al wat hebt waar je nu mee werkt, laat dat dan eens zien.
Dan kunnen we een antwoord geven op basis van dat wat je hebt in plaats van dat we iets geen bedenken wat een heel andere kant op gaat of misschien zelfs helemaal niet doet waar jij naar op zoek bent.

Hallo MAS3,

Het is een brandweer die via een systeem van Faller rijdt. Grofweg uitgelegd je hebt een staal draad dat net onder het wegdek ligt hierdoor kan het voertuig de weg volgen met een sleper waar een magneet opzit.

Het idee wat de brandweer zal moeten kunnen / doen:

Brandweer auto staat in een garage en merkt een magnetische veld op van een elektromagneet.
Dan zullen de koplampen en achterlampen aan gaan, Vervolgen naar ongeveer 1 half seconden zullen er zwaailampen aan gaan.
Weer 1 half seconden later sirene aan.
Nu gaat hij rijden zodra hij weer een input krijgt(dus een magnetische veld opmerkt van een elektromagneet in het weg dek)gaat hij stil staan. Daarna stapgewijs de sirene uitzetten en zwaailampen etc.
Brand is denkbeeldig ge blust en hij krijgt weer een input van de reed contact dat hij verder kan met het verhaal.

Sirene en zwaailampen zijn allemaal verdeelt onder aparte loops dit werkt wel.

Maar ik ben in tussen tijd dat ik het gepost heb even een simpele code aan het maken geweest voor alleen het leren van state machine's maar kom hier ook echter niet helemaal uit.

Hier de code.

int led = 13;
int state = 0;
int button = 2;
int buttonstate = 0;

void setup(){
  pinMode(button, INPUT);
  pinMode(led, OUTPUT);
  Serial.begin(9600);
}

void loop(){
  buttonstate = digitalRead(button);
  
  if(buttonstate == HIGH){
    delay(1000);
    state = 1;
    Serial.println("state 1");
  }
  
  while(state == 1){
    digitalWrite(led, HIGH);
    delay (200);
    digitalWrite(led, LOW);
    delay (200);
  if(buttonstate == HIGH){
    Serial.println("state 2");
    state = 2;
  }
  }
  
  while(state == 2){
    digitalWrite(led, LOW);
    delay(5000);
    Serial.println("state 1");
    state = 1;
  }
}

Het idee achter deze code is om een led te laten flikkeren wanneer 1 keer op een knop is gedrukt vervolgens als er voor 1 tweede keer op de knop word gedrukt moet hij voor 5 seconden uit blijfen en dan weer verder knipperen.
kunt u mij misschien eerst vertellen wat mij fout hier is want dan denk ik dat ik er wel uit kom.

Zobiezo alvast bedankt voor het lezen/helpen van mijn post.

Stefan.

Hoi Stefan.

Onder elk van mijn postings hier, heb ik een aantal algemene tips staan die bijna altijd geldig zijn.
De eerste is hier heel erg van toepassing.
Je gebruikt namelijk ernstig gebruik van blokkerende code.

Als er op een toets gedrukt word, doe je een hele seconde (!) helemaal niets.
Das hele dikke zonde van de tijd.
Vervolgens ga je aan de slag met een while.
Je zegt dat zolang (while) je daarnet gezien hebt dat er op een toets werd gedrukt, dat er dan geknipperd moet worden, 2 en een halve keer per seconde.
Een van de fouten die hier in zitten, is dat je voor eeuwig in de while blijft hangen.
Want tijdens die while zal buttonstate nooit veranderen, ook niet de volgende keer als dat gecontroleerd word.
Je hebt buttonstate gebruikt, maar daarin zit een waarde die vroeger ooit eens geldig was (inmiddels al bijna 1.5 seconden geleden).
buttonstate zal nooit veranderen tenzij je nog eens die digitalRead doet en het resultaat in buttonstate stopt.
Je gaat wel naar state 2, want de voorwaarde die daaraan gekoppeld is, is altijd waar (buttonstate was al 1 en dus altijd HIGH).
Je hebt dus je LED 1 keer kort zien flitsen, en dan blijft ie ruim 5 seconden uit.

De while loop is heel gevaarlijk, want je kunt erin verstrikt raken om er nooit meer uit te komen, Daarom moet je die zo veel mogelijk vermijden.
Je weet dat void.loop oneindig loopt, toch ?
Daar moet je gebruik van maken.
Je moet bijhouden wat je aan het doen bent (wel; of niet knipperen, dat doe je al met state).
Maar ook of de LED nou juist aan of uit is, want dat bepaalt wat de volgende stap zal worden.
En je moet bijhouden of er al voldoende tijd verstreken is om die volgende stap te zetten.
Die laatste 2 dingen houd je nu niet bij.
Dit is wat je leert als je de blink without delay sketch bestudeert.
Als je dat snapt, en dan ook echt begrijpt, zul je nooit meer die delay gebruiken, en ook die deathtrap van een while zul je niet meer gaan gebruiken, zeker weten.

Heb ik nog wat tips voor je waar je niet om gevraagd had.
Als je variabelen gebruikt en die een mooie naam geeft, maak dan consequent gebruik van hoofdletters.
Das een klein dingetje dat het lezen va de code ineens veel gemakkelijker maakt.
Elk nieuw woord krijgt dan een hoofdletter.
Of hoofdLetter dan dus, maar ook buttonState.
Je zult zien dat je dat overal zo tegen komt.

Andere tip,
Als je vraagt zoals daarstraks wat er mis gaat, is het wel een goed idee als je niet alleen vertelt wat je hebt, maar ook als je vertelt wat je verwachtte te zien, en wat je in plaats daarvan kreeg te zien.
Want dan word het beantwoorden van je vragen een stuk gemakkelijker, en eenvoudiger gericht te antwoorden.

Nu eerst maar eens aan de slag met Blink without delay, en zien dat je begrijpt wat daar gebeurt.
Dat kun je dan later toepassen op deze sketch en op het geheel voor je brandweer wagen.

Beste MAS3,

Ten eerste bedankt voor de algemene tips. Ten tweede ik snap de het prencipe van blink whitout delay wel want dit moest ik gebruiken om er voor te zorgen dat ik zowel zwaailampen kan laten knipperen en geluid voor een sirene kan maken(gewoon simpel tussen 2 tonen wisselen).

Verder is het de bedoeling om met die code die ik heb gemaakt te proberen hoe ik van state moet verwisselen bij een input. en precies zoals U zegt de led is heel kort aan en blijft dan 5 seconden uit en daarna weer heel even aan.... Ik zal later op de dag even een bijgewerkte versie plaatsen.

Ps: Ik weet dat een void loop continu loopt.

Met vriendelijke groet,

Stefan.

Hoi Stefan.

Als je echt begrepen hebt hoe het zit met blink without delay, dan zou je in ieder geval geen delay meer gebruiken.
Wellicht heb je begrepen hoe je dingen kunt bijhouden, en dat is een van de zaken die nodig is voor blink without delay.
Maar het gaat een stuk verder dan dat.
De sketch die je hier boven hebt geplaatst, draait miljoenen malen per seconde als je alle delays en de whiles eruit haalt.
Die whiles zijn helemaal niet nodig en de delays kun je dus veel beter anders doen.

Je vraag over het verwerken van de toets, daar moet je dus kijken of de toets is ingedrukt (of het reed contact), of die eerder ook al was ingedrukt, wat de waarde is van de variabele die daarvan afhankelijk is, wat die moet worden als er weer wat veranderen moet, en wat je eigenlijk aan het doen bent op dat moment.
Das niet alles denk ik, maar best veel om bij te houden voor een vrij eenvoudige handeling.
Maar wel nodig.
Dat stukje is dus wat ik vermoed dat je al kent, en dus ook hier toe te passen is.

Waar je bij schakelaars heel erg mee op moet passen, is contact dender.
In het Engels heet dat bouncing (letterlijk stuiteren).
Dat is dat een contact vaak niet direct een stabiele verbinding heeft of verbreekt.
Als dat gebeurt en je houdt er geen rekening mee, dan tel je dus vaker dat er een verbinding was, terwijl er slechts 1 keer was gedrukt of een magneet voorbij gekomen.
Door de constructie van een reed contact, is de kans op zulke contact dender een stuk groter.
Want dat is een verende constructie die in rust als het ware in evenwicht is, en dat evenwicht word verstoord door een magnetisch veld dat in de buurt komt en waardoor de contacten omschakelen.
Hierdoor is er een kans dat die contact dender je laat denken dat er vaker een magneet was dan werkelijk het geval was.
Dus moet je zien te voorkomen dat zo'n verkeerd contact word geregistreerd.
Je kunt hier wel informatie vinden op het forum over debouncing, waarmee je dit effect kunt tegengaan.

Een van de manieren om dat te doen, is door in een delayloze sketch gewoon een aantal malen achter elkaar te controleren of het contact nog steeds in dezelfde stand staat.
Ik raad je daarom aan dat zo ook te doen, waarmee je die delay van een hele seconde ook niet meer nodig hebt.
Overigens werkt die delay(1000) helemaal niet als ontdendering (in geval dat de reden was dat die daar stond), omdat je daarna niet nog eens controleert of het contact nog steeds in dezelfde stand staat.
Ook hiervoor moet je dingen bij gaan houden.

Ik ben benieuwd naar je volgende sketch.

ooit bij miwula geweest?
gebruik twee reeds, een voor motor (standaard)
en de andere voor je commando
als de reed aangaat dan ++ de state en een delay van 10 milliseconden voor debounce
dan de switch
voorbeeld
1:blauw aan
2: sirene aan
3: rijden naar brand
4 : sirene uit
5: blauw uit
6: naar kazerne

separaat natuurlijk blinkwithout delay

Hallo jongens,

Ten eerste sorry dat ik zo laat nog weer eens reageer. Ik Was/Ben zeer druk met me opleiding en heb nog geen seconden de tijd gehad om hier weer eens over na te denken.
Mijn excuses.

Shooter,
Ja ik ben daar al wel geweest en het gaat me er niet zo zeer om hoe het systeem werkt ik vind het wel fijn dat u mee denkt maar ik zit puur met die "state machine".

Nog maal bedankt voor Uw reactie.

MAS3,
Persoonlijk sorry aan U omdat ik had beloofd de volgende dag nog een nieuwe sketch te maken.
Om verder antwoord op U te geven ik had die delay van 1000 er staan om er voor te zorgen dat hij niet door het hele programma heen loopt bij een te lange input. (Dus wel als een soort van ontdenderen)

Ik zal verder nog wel op de forum actief zijn maar jammer genoeg denk ik niet met het project bezig zijn.

Met vriendelijke groet,

Stefan.

state machine is eigenlijk een grote statusbrij,
de eenvoudigste is een stappenplan waarbij er gewoon een aantal stappen onder elkaar staan.
begin bij stap=0
dus case 0:
als ingang1 aan is dan wordt de stap:=1
dus je programma blijft net zoalng hier ronddraaien tot je op de knop drukt

case 10:
(nu weet je dat er op de knop gedrukt is, dus
zet blauw aan
delay 5 seconden (ja ik weet is niet slim beter timer gebruiken.)
dan
timer2:=millis();
stap:=20;

case 20:
zet geluid aan
if millis()-timer2 > wachttijd){timer3:=millis();stap:=30}

enzovoorts
als je de stappen met 10 omhooglaat gaan dan kun je er nog stappen tussen plakken.
Zo kun je dus hele grote structuren bouwen

Pas wel op met hoe je iets gaat uitleggen.

Bovenstaande post kan voor verwarring zorgen door gebruik van het woord "case".
Hier kan niet worden bedoeld switch... case, wat een methode is die toegepast kan worden in je sketches.
Met switch... case kun je een if.. met heel veel else-es doen en das iets heel anders als wat er eigenlijk bedoeld was uit te leggen.

Ik vermoed dat het hier om een ongelukkige woordkeus gaat, dus haal deze twee zaken niet door mekaar.

Als je een een statemachine gaat bouwen werk dan alsjeblief met tekst

case De_Toeter_Staat_aan:
huidigeStatus=De_Toeter_Staat_uit;

zegt veel meer waar het over gaat dan

case 10:
huidigeStatus=20;

dan moet je ook niet met stappen van 10 werken en het wordt heel wat leesbaarder.
Hoe doe je dat met De_Toeter_Staat_aan?

Er zijn 2 opties.
De eerste is de makkelijkste
#define De_Toeter_Staat_aan 10
#define De_Toeter_Staat_uit 11
int huidigeStatus;
int nieuweStatus;

De 2de is beter maar iets moelijker
typedef enum
{
De_Toeter_Staat_aan,
De_Toeter_Staat_uit
} STATES;
STATES huidigeStatus;
STATES nieuweStatus;

Met vriendelijke groet
Jantje

Zoals shooter het omschrijft ben ik ook van plan het te gaan maken alleen kom ik er niet uit hoe ik van case 1 naar case 2 kom.

Ik heb de sketch van switchecase ook al beetje uit proberen te pluizen maar dan zit ik er zelf even mee te puzzelen en krijg het niet voor elkaar en dan heb ik het ook nog niet eens over hoe ik het voor elkaar krijg in
een behoorlijk complexe sketch.

Met vriendelijke groet,

Stefan

als je in case 1 staat en die is klaar dan verander je de avriabele van 1 naar 2.
dus in je case 1 komt te staan:
if (klaarmet deze case) {var=2;}