Alternatieve manier van doorlopen van verschillende stappen

algemene C code
Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Alternatieve manier van doorlopen van verschillende stappen

Berichtdoor nicoverduin » 03 Aug 2014, 23:52

Mogelijk een beetje een uitdaging, maar hier onder een stukje code dat het mogelijk maakt om verschillende stappen te doorlopen in een proces zonder gebruik te hoeven maken van allerlei if-then-else stappen om zo het programma overzichtelijker te maken. Daarnaast kun je eenvoudig de volgorde van de stappen wijzigen zonder veel ingrijpen in het programma. In dit voorbeeld zijn er 2 knipperende LEDS waarbij er eerst een LED 5 keer knippert met een tempo van 1x per seconde en daarna een andere LED met een tempo van elke halve seconde. Er wordt hierbij gebruik gemaakt van millis() om zodoende geen wachttijden in het programma te hebben.

Het feitelijke procesverloop wordt echter bepaald door een enumeratie van stappen. In de enumeratie staat welke processtappen er zijn waarbij elke stap bepaalt wanneer we naar de volgende stap kunnen (de variabele volgendeStap). Aanleiding om het op deze manier was in een opdracht waarbij de klant nog wel eens wisselde van volgorde van de stappen. Door nu de volgorde in de enumeratie te veranderen, kun je de flow automatisch wijzigen zonder verdere code wijzigingen.

Bijgaand de code:
Code: Alles selecteren

#define    LED1          12                   // een LED op pin 12
#define    LED2          13                   // een LED op Pin 13
#define    BLINKTIJD1 500                      // elke 1/2 seconden LED1 wisselen
#define    BLINKTIJD2 250                      // elke 1/4 seconden LED1 wisselen

unsigned long timer;                  // nodig om na een bepaalde tijd iets te doen
uint16_t         volgendeStap;          // geeft aan welke stap verwerkt moet worden
uint16_t         teller;                   // zomaar een tellertje

void setup()
{
   pinMode(LED1, OUTPUT);            // Zet de outputs
   pinMode(LED2, OUTPUT);
   volgendeStap   = 0;                  // we beginnen bij stap 0
   teller            = 0;                  // tellertje voor de eerste keer opzetten
   timer                = millis();          // timertje idem
}
   
/** Besturing van de stappen */
enum {
   initieerStap2   ,
   stap2               ,
   initieerStap1   ,
   stap1               ,
   beginOpnieuw
};

void loop()
{
   //
   // verwerk de relevante stap
   //
   switch (volgendeStap) {

      case initieerStap1:
         teller             = 0;                                 // reset de teller
         digitalWrite(LED2, LOW);                        // zet de LED uit
         volgendeStap++;
         break;

      case stap1:
         //
         // alleen uitvoeren als de tijd is verstreken
         //
         if (millis() > timer) {
            digitalWrite(LED1, !digitalRead(LED1));   // Flip led 1
            teller++;                                                // verhoog teller
            if (teller > 10) {                                  // alles gehad?
               volgendeStap++;                                     // we zijn hier klaar
            } else {
               timer = millis() + BLINKTIJD1;             // we zijn er nog niet dus de timer zetten
            }
         }
         break;
            
      case initieerStap2:
         teller             = 0;                                    // reset de teller
         digitalWrite(LED1, LOW);                            // zet de LED uit
         volgendeStap++;
         break;

      case stap2:
         //
         // alleen uitvoeren als de tijd is verstreken
         //
         if (millis() > timer) {
            digitalWrite(LED2, !digitalRead(LED2)); // Flip led 2
            teller++;                                                 // verhoog teller tot 10
            if (teller > 10) {                                 // alles gehad
               volgendeStap++;
            } else {
               timer = millis() + BLINKTIJD2;            // we zijn er nog niet dus de timer zetten
            }
         }
         break;

      case beginOpnieuw:
         volgendeStap = 0;                                       // begin bij de eerste stap
         break;

      default:
         break;
   }
}


Als er vragen zijn hoor ik het graag. in het voorbeeld is het wat overdone, maar het gaat om het proces. Ik weet ook wel dat Blink veel eenvoudiger kan. Maar het is een mooie manier om te laten zien hoe de flow van code eenvoudig veranderd kan worden. En als je bijvoorbeeld 36 stappen hebt (zoals ik in mijn opdracht), dan wil je wel een simpele manier hebben :)
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Advertisement

Berichten: 167
Geregistreerd: 19 Apr 2014, 15:03

Re: Alternatieve manier van doorlopen van verschillende stap

Berichtdoor Hanneman » 04 Aug 2014, 09:57

Hey Nico,

bedankt voor het delen!

Zou zomaar behulpzaam kunnen zijn voor het led game dingetje waar ik nu aan werk.
Met een mega lukt het wel, maar met die 74HC595 chips is het ff anders.

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: Alternatieve manier van doorlopen van verschillende stap

Berichtdoor nicoverduin » 04 Aug 2014, 11:09

Wat ik zelf doe met LED strips en met die shift registers doe je feitelijk hetzelfde. Ik creer in RAM een virtueel stream leds dis ik opbouw, wist etc. En elke keer als ik iets wijzig zet ik een vlaggetje aan "mustUpdate". Aan het einde van de loop test ik of deze vlag true is. Zo ja dan update ik de LEDS en dat zou je idem kunnen doen met de schuifregisters. Daarna zet ik de vlag weer op false. Zo beperk ik de overhead van het updaten en maak de code minder gecompliceerd.
Beetje hetzelfde als de oude mainframe tijd... Eerst de printregel opbouwen en dan in een routine printen en testen voor einde pagina, nieuwe kopregels etc.
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Berichten: 4068
Geregistreerd: 16 Okt 2013, 14:31
Woonplaats: s hertogenbosch

Re: Alternatieve manier van doorlopen van verschillende stap

Berichtdoor shooter » 04 Aug 2014, 20:06

nico ik zit nu met bijna precies dezelfde methode (een statemachine) een hefeiland die met hydraulische klemmen klimt te maken, maar dan in codesys (voor PLC)
Het grote voordeel is dat alleen de state die aanstaat wordt gedaan, en de rest wordt gewoon overgeslagen.
ik heb het zelfs nog een beetje versneld door alleen door de cases te gaan als er een interupt is geweest, en ik zet dus telkens de interupt op iets anders bijv, een tijd.
paul deelen
shooter@home.nl

Gebruikers-avatar
Berichten: 5043
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: Alternatieve manier van doorlopen van verschillende stap

Berichtdoor nicoverduin » 04 Aug 2014, 22:43

Je kan nog een stapje verder gaan door het te doen zoals ze vroeger de BIOS maakte onder CP/M en MsDos/. Gewoon een jump/call tabel maken met de enumeraties. Ach wie weet maak ik er nog eens een class van. Het werkt inb ieder geval prettig en overzichtelijk. Zeker als je een beetje veel stappen krijg.
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Berichten: 167
Geregistreerd: 19 Apr 2014, 15:03

Re: Alternatieve manier van doorlopen van verschillende stap

Berichtdoor Hanneman » 07 Aug 2014, 08:49

Yes! Nico, you are the man!

Ik heb het reactie spelletje voor elkaar dankzij jouw code. Daarvoor zat ik gigantisch te klooien en ging het nergens heen.

http://pastebin.com/4k7rz5Vz

Terug naar C code

Wie is er online?

Gebruikers in dit forum: Geen geregistreerde gebruikers en 2 gasten