Verlichting voor een skelter

Hallo allemaal,

Ik ben nieuw hier op het forum en zal mij dus even voorstellen:
Ik ben René, loop alweer tegen de 50 en heb als opleiding technische computerkunde.
Ik ben in de zeefdruk en grootformaat printers terecht gekomen. Programma’s meestal geschreven voor PLC’s en hobbymatig ook PIC’s.

Nu kwam mijn zoon met de vraag om verlichting te maken op zijn skelter, ik had nog een LOGO van Siemens liggen en dacht: Dat moet kunnen! Maar ja, dan moet er een hoop (dure?) elektronica op de skelter dus dat moet ook anders kunnen, een PIC’je kan ook, of is er nog wat anders?

En ja, er is nog wat anders vond ik op internet en zo hier terecht gekomen.

Maar nu de vraag van mijn zoon, hoe ga ik dit oplossen?
Zie het PDF’je, dit is de eerste opzet.

Voor mijn werk ga ik overmorgen naar het buitenland en daar in de avonduren één en ander maar eens uitwerken!

[edit] (vele?) vragen zullen er ongetwijfeld komen.

Skelter.pdf (190 KB)

Om met je allerlaatste vraag te beginnen:

Kan je een uitgang ook inlezen? Bv. digitalWrite(10,!digitalRead(10)); om de uitgang te inverteren of moet je variabelen bijhouden?

Niet op deze manier. Als je pin 10 wilt lezen moet je deze eerst als INPUT definieren: pinMode(10,INPUT), daarna wil je naar dezelfde pin schrijven, dan moet je deze eerst als OUTPUT definieren: pinMode(10,OUTPUT), Je kunt ze dus niet combineren in een statement. Je zult altijd de waarde tussentijds moeten opslaan.

@cartoonist: Dank je. Jammer want zo moet je meer variabelen bijhouden. Maar eigenlijk kon ik het niet laten om het te testen:

void setup() { pinMode(13, OUTPUT); }

void loop() { digitalWrite(13, !digitalRead(13)); //inverteer uitgang 13 delay(100); }

Grappig, het onboard ledje knippert. Het zal wel niet netjes programmeren zijn, maar het werkt.

René.

Dit verhaal gaat inderdaad op bij de 8 bit atmels. Echter op de grotere cpu's (32 bit) zou ik niet zomaar vanuit gaan. Aan de andere kant wat is er fout aan de variabelen.... Je weet hoe te programmeren.... Je hebt 2K RAM ..... En over je aanpak twijfel ik al helemaal niet... wou dat er meer waren die zo beginnen :grin:

nicoverduin: Dit verhaal gaat inderdaad op bij de 8 bit atmels. Echter op de grotere cpu's (32 bit) zou ik niet zomaar vanuit gaan. Aan de andere kant wat is er fout aan de variabelen.... Je weet hoe te programmeren.... Je hebt 2K RAM ..... En over je aanpak twijfel ik al helemaal niet... wou dat er meer waren die zo beginnen :grin:

Helemaal mee eens. Een variabele is echt niks. Hier kan je het zelf met een byte doen. Dus zo kan je er 2000 hebben. Voor de verlichting van een skelter is dat ruim voldoende. Ik werk altijd met variabelen. Ik lees eerst de input pinnen uit. Dan reken ik uit hoe ik de output pinnen wil en dan zet ik ze. Als je dat combineerd met "goede" variabele namen maakt dat je code heel leesbaar.

Met vriendelijke groet Jantje

Duidelijk! Ik zal het gewoon met variabelen gaan bijhouden. Bedankt voor de input!

René

Dit gaat goed komen :) Ervaring met flowcharting, gestructureerde programma ontwerp met top-down benadering, PIC mcpu, doet dit al een paar weken :grin: :grin: ... gaat goed komen :grin:

Het wordt nog "leuker" (eigenlijk onduidelijker) als je de regel:

digitalWrite(9, !digitalRead(9)); digitalWrite(13, !digitalRead(13));

vervangt door:

bitSet(PINB,5);

320 bytes kleiner, geen variabel gebruik en volledig onleesbaar....... maar het werkt op de UNO voor Led pin13

Maar alle beginners en newbees zijn nu afgehaakt denk ik.

@cartoonist: Ik haak af, PINB,5 is input register van pin 13 maar is read-only? en daarheen schrijven?
Laat mij maar rijden in een skelter!

Nu even over de eerste subroutine van de flowchart, het inlezen van de schakelaars. Er moet natuurlijk ontdendert worden, maar hoe? Bij het spitten op het forum eigenlijk alleen maar oplossingen gevonden met “previous state” etc. etc. Dit geeft bij meerdere schakelaars nogal wat programmeerwerk en een boel variabelen. Kan dit niet eenvoudiger?

Bijvoorbeeld de ingangen maar eens in de bv 50 msec testen? Zie flowchart, even teruggebracht tot 2 schakelaars, of maak ik nu een grote denkfout?

Hoi Rene4312, welkom nog.

Je maakt een veel vaker gemaakte fout. Ik zie vrij vaak voorbij komen dat men een keer kijkt of er een contact gemaakt is, dan even wacht en vervolgens reageert op dat al dan niet gemaakte contact. Dat is geen ontdenderen, dat is gewoon wat tijd weggooien. Om te ontdenderen moet je twee keer kijken, waarbij bij beide keren kijken dezelfde staat gezien moet worden. In dit geval ga je waarschijnlijk maar 1 van de 2 knoppen gelijktijdig indrukken. Wellicht is het zelfs fysiek onmogelijk beide tegelijk in te drukken. Je kunt dan eerst kijken of er een knop is ingedrukt en een flag zetten. Even later kijk je welke knop is ingedrukt, en daar verbind je dan de bijbehorende actie aan. Dan heb je in ieder geval 1 variabele uitgespaard. Je kunt zo met 3 (globale) variabelen en een paar vergelijkingen betrouwbaar de knoptoestand afhandelen, zonder delay() graag.

Je moet er dan voor zorgen dat de flag "knopGedrukt" niet geset kan worden als "rechts" of "links" geset zijn. En dat "rechts" of "links" alleen geset kunnen worden als "knopGedrukt" ook geset is. En dat een set "rechts" of "links", een reset van "knopGedrukt" veroorzaken. Verder moet je kijken wanneer "rechts" geset is, of knop "rechts" dan nog steeds gedrukt is. Anders moet je "rechts" resetten. En dat moet dan ook met links. Als je dit laatste niet doet, dan kun je alleen registreren dat je de van de ene naar de andere kant gaat, maar niet dat je geen van beide kanten op gaat. Volgens mij valt het met de variabelen best mee zo. Maar dat ligt er ook wel aan wat je allemaal nog meer in petto hebt.

Brrr veel te laat weer. Voordat ik weer helemaal doorsla maar gauw het bed induiken. Morgen (straks eigenlijk) maar weer verder kijken.

Rene4312: Nu even over de eerste subroutine van de flowchart, het inlezen van de schakelaars. Er moet natuurlijk ontdendert worden, maar hoe?

Voor een luxe skelter zou ik kiezen voor een model schakelaar zoals toegepast in de meeste luxe auto's. Een drie standen schakelaar met een neutrale midden positie. Het centrale contact wordt geaard en de 2 contacten voor links of rechts worden verbonden met twee digitale ingangen die met de pinMode als PULLUP worden gedefinieerd. Kun je nooit zwevende ingangen krijgen.

Zolang de knipperschakelaar op een van de standen staat moet het daarbij behorende licht knipperen.

Nu moet je overdenken of het noodzakelijk is dat de arduino ook reageert op andere inputsignalen zolang een knippelicht knippert. (groot/klein licht en klaxon of zwaailicht)

Vind je niet noodzakelijk dat tijdens knipperen het programma reageert op andere input dan kun je zoiets maken als while(digitalRead(pinLinks)==0); { knipperlicht Links knippert} en hetzelfde voor rechts,

Wil je dat het programma ook reageert op andere input signalen dan moet je zeker geen while(digitalRead(pinX)==0) gebruiken Dan moet je echt wel een paar tijdelijke variabelen en de timer functie gebruiken. Immers je kunt dan , met goed fatsoen, ook geen delay meer gebruiken in je knipperlicht routine.

Maar debouncing lijkt mij met een driestanden schakelaar overbodig omdat je de loop zodanig kan maken dat de knipperlicht schakelaar steeds opnieuw wordt uitgelezen en dat zolang pinL==LOW of pinR==LOW , een LED knippert.

Simpele recht toe recht aan routine voor het lezen van de button. Je kan als parameter de pin meegegeven. En als return TRUE (knop is ingedrukt) of FALSE(knop is niet ingedrukt).

@Nico: Ja natuurlijk, dat ik daar gisteravond niet aan gedacht heb, was zeker te laat.

René

Dat is niet heel veel anders als wat ik eerder voorstelde, wel anders gepresenteerd. Verschil zit m in de uitwerking van het wachten. Als er alleen maar geknipperd (of niet) hoeft te worden dan maakt het allemaal niet zoveel uit. Als je meer wil doen dan dus wel. Zoals ik het voorstelde kun je het doen zodat wachten != niets doen.

In een flowchart staat een dergelijk detail niet vermeld (denk ik) dus dan kan het betekenen dat dat ook zo gedaan word.

@mas: Nee hoor die processor doet inderdaad letterlijk 25mS geen bal… En voor een projectje met een paar knipperlampies en druk knoppies… Zou ik me het niet ingewikkelder maken dan nodig.
't is dat er tussentijds ook nog gereageerd moet worden op de koplampen of omschakelen links/rechts.
‘t is geen examen “Wie kan het meest slimme, snelste en vaak daarmee voor andere onleesbare programma maken” :grin: :grin: Daar heb ik er al door de jaren genoeg van gezien :grin: En helaas begin ik ze weer steeds meer tegen te komen :’(

En deze aanpak is al heeeeeeel oud… onderstaand een stukje assembly van mijn eerste microcomputer (1976). Daar deden ze het eigenlijk niet anders :grin:

[pre]TTYKB jsr SCAND ; wait until NO key pressed
	bne START ; if pressed, wait again ->
TTYKB1 lda #1 ; check KB/TTY mode
	bit SAD ; TTY?
	beq START ; yes ->

	jsr SCAND ; Wait for key...
	beq TTYKB1 ; no key ->

	jsr SCAND ; debounce key
	beq TTYKB1 ; no key ->
Gewoon 2x lezen :grin:

Ik kan de meeste opcodes die daar staan wel lezen. Alleen BIT was mij onbekend. Die heb ik eens opgepikt toen ik wat zat te rommelen met de commodore 64 (die ik nog steeds heb).

Mijn KIM staat ook nog op zolder. Moet hem alleen nog een keer in plexiglas zetten :) BIT is in feite vergelijkbaar met de AND functie. En het is inderdaad de zelfde processor 6502.

Dank iedereen voor de reacties.

Ik blijf echter toch nog een vraag houden over het ontdenderen. Punt 1 is natuurlijk: Wat is denderen.
In mijn opinie is dat als je een druktoets of een schakelaar indrukt dat de contacten elkaar verschillende keren kunnen raken voordat ze in een stabiele toestand staan.

Je moet dus wachten (liefst zonder delay, dat klinkt raar) voordat je actie onderneemt omdat die actie anders meerdere keren kan plaatsvinden, de schakelaar moet weer stabiel zijn.

Maar als je ingang 1 keer hoog wordt, dan weet je toch zeker dat de schakelaar ingedrukt is geweest?
En dan nu mijn vraag: Waarom zou je hem nog een keer controleren?

Op dit moment ontgaat de logica hiervan mij een beetje. Als ik dit in mijn Uno stop:

int done = 0;

void setup() {
  pinMode(13, OUTPUT);      
  pinMode(2, INPUT_PULLUP);     
}

void loop(){
   if (digitalRead(2) == LOW) {
     delay(25);
     if (done == 0) {
       digitalWrite(13, !digitalRead(13));
       done =1;
     }
   }
   else {
      done = 0;
   }
}

En ik stop een stukje stroomdraad in de ground en een stukje op pin 2 en ik raak de draden aan dan werkt dit prima. Eén keer aanraken en de LED gaat aan, nog een keer en de LED gaat uit. Verlaag je de delay naar 0 dan blijft het een gok hoe de led naar één keer (dender dender) reageert. Een delay van 50 geeft een zeer stabiel beeld met de draadjes en een schakelaar zal beter contact maken dan ik met 2 draadjes.

Dus: Waarom voor de tweede keer je button inlezen en vergelijken met de eerste keer?

Alvast bedankt voor de reacties!

René.

Er zijn verschillende typen drukknop schakelaars: (momentary) moment schakelaar indrukken is de ene toestand (meestal aan ) en niet ingedrukt is de andere toestand (meestal open) (toggle) een keer indrukken de schakelaar is gesloten, nog een keer indrukken en de schakelaar is geopend. (impuls) een speciaal type wat een impuls (van min-of-meer gedefinieerde lengte) geeft bij indrukken.

Hoe je in de software de schakelaar gaat uitlezen hangt dus sterk af van het type schakelaar/drukknop.

Zoals ik uit je verhaal begrijp gebruik je een simpele type moment schakelaar. Zoals MAS3 enige discussies terug ook al eens haarfijntjes opmerkte is het bij dit type schakelaar haast onmogelijk om korter in te drukken dan enige tienden van een seconde. Dus voor het weet denkt je programma dat je de toets twee keer hebt ingedrukt. Je moet dus eigenlijk een routine hebben die de toets(en) steeds leest en pas als de/een toets weer is losgelaten de daaraan gekoppelde opdracht uitvoert. In deze routine moet een debounce zitten die de kortstondige willekeurige veranderingen in de eerste 25 of 50 millis negeert.

Dat snap ik, maar waarom wordt de toets na de wachtcyclus nog een keer ingelezen?

En naar mijn idee moet je programma niet pas reageren als de drukknop weer losgelaten wordt, maar als het programma zeker weet dat het denderen voorbij is.

Ik zal wel een denkfout maken maar ik heb hem nog niet ontdekt.

René.