Pagina1 van 1
Forum

Welkom bij de Tweaking4All gemeenschapsforums!
Voor je gaat deelnemen, bekijk de Forum Regels!

Specifieke onderwerpen: Start het onderwerp met de naam van het programma of systeem.
Bijvoorbeeld “MacOS X – Jouw vraag“, of bijvoorbeeld “MS Word – Jouw Tip of Truc“.

Merk op: Omschakelen naar een andere taal zal niet werken als je een post aan het lezen bent aangezien er waarschijnlijk geen vertaling beschikbaar is.



Hulp gevraagd bij s...
 
Deel:
Meldingen
Alles wissen

[Opgelost] Hulp gevraagd bij stappenmotor met rtc module!

40 Berichten
2 Gebruikers
0 Vind-ik-leuks
3,907 Bekeken
(@remko)
Eminent Member
Deelgenomen: 7 jaar geleden
Berichten: 23
Topic starter  

Hallo Allemaal,
Ik wil een stappen motor laten lopen per 1 stap per variable tijd, voorbeeld 1 stap per 90 sec (1,5 min) en dat dan in een continue (loop). 
Ik had eerst een simpele code met delay, maar dat werkt wel als je de tijd kort houd, 1ms - 3 sec bv. Maar het probleem ontstond helaas met langer tijden, bv 1 stap/1 min. Daar blijkt er een groter afwijking in te zitten als je het een paar uur laat lopen! Dus ben ik ga zoeken naar een oplossing, en dat is een RTC module gebruiken, heel mooi alleen ik ben nog een newbie, dus heb er gewoon moeite mee om een goed werkende code te schrijven. Ik heb zelf twee rtc modules de ds1307 en de ds3231. De ds3231 schijnt nog nauwkeurig te zijn en boven dien heeft ie ook een temperatuur sensor op te zitten. 
Heb ik een voor elkaar een code gekregen met rtc alleen zit daar ook iets vreemd  in. Gaat 4 stappen af en daarna 1min  weer pas opnieuw. Ik snap dat niet. 
Ik heb de twee code's bijgevoegd als bestanden.
Het zou fijn zijn als iemand mij goed kan helpen, met een nieuwe code !!!  Voor de duidelijkheid gaat dus om lange tijden, zie eerste zin!!


   
BeantwoordenCiteren
(@remko)
Eminent Member
Deelgenomen: 7 jaar geleden
Berichten: 23
Topic starter  

p.s. je kan natuurlijk zelf deze code's makkelijk testen ook als je geen stappenmotor plus driver hebt. Door 4 leds (vergeet de voorschakel weerstand van 220 ohm niet) en deze op een breaddboardje prikken op en de deze op de digitale pinnen( in mij geval 4,5,6 4 en 7) aan te sluiten. 


   
BeantwoordenCiteren
 Hans
(@hans)
Famed Member Admin
Deelgenomen: 11 jaar geleden
Berichten: 2678
 

De eerste gedachte die in me opkwam is dat je met delays werkt en daardoor steeds een vertraging "inbouwt".

Dus je laat de Arduino een actie doen (wat tijd kost) en vervolgens laat de de Arduino voor 60 seconden wachten. Dus de totaal geconsumeerde tijd is meer dan 60 seconden.

Een oplossing is het "millis()" statement gebruiken. In jouw code b.v.

unsigned long voorgaandeMillis = 0;        // laatste keer dat iets werd uitgevoerd
const long interval = 60000; // 1 minuut interval
int in1 = 4; // IN1-IN4= input is of your motorstepper driver (L298N MODULE)
int in2 = 5;
int in3 = 6;
int in4 = 7;
void setup()
{
 pinMode(in1, OUTPUT);
 pinMode(in2, OUTPUT);
 pinMode(in3, OUTPUT);
 pinMode(in4, OUTPUT);
}
void loop()
{
  unsigned long huidigeMillis = millis();
if (huidigeMillis - voorgaandeMillis >= interval) {
    // 1 minuut verstreken - reset tijd
    voorgaandeMillis = huidigeMillis;
    // stappen uitvoeren
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW); }
}

Dus wat hier gebeurt:
De loop blijft kijken of 60 seconden (interval) is verstreken sinds de laatste keer dat we de stappen motor aanstuurde.
Is dit het geval (dus nu - voorgaande tijdstip >= interval), dan zetten we als eerste de "voorgaandeMillis" op de huidige "tijd" en voeren we de stappen uit.
De loop blijft zo eindeloos doorgaan.

Is dat iets?


   
BeantwoordenCiteren
 Hans
(@hans)
Famed Member Admin
Deelgenomen: 11 jaar geleden
Berichten: 2678
 

Voor ik het vergeet: ik heb deze code niet getest ... ik zit op m'n werk en heb m'n spullen niet bij de hand. 

Oh en meer uitleg over "millis()" vindt je hier. Volgens de beschrijving houdt dit de tijd in milliseconden bij vanaf het moment dat de Arduino wordt aangezet. Na ongeveer 50 dagen gaat dit weer terug naar nul (omdat het nummer dan te groot is geworden).

Laat even weten of dit is wat je in gedachten had? 


   
BeantwoordenCiteren
(@remko)
Eminent Member
Deelgenomen: 7 jaar geleden
Berichten: 23
Topic starter  

Hai Hans,

Bedankt voor je reactie!!!   Met jou aan gepaste code gaat led1 aan na 60 sec en blijft het ook oneindig branden. Dit is nog niet de juiste bedoeling, want na 60 sec moet led 1 branden en daarna stap2 led2 branden en de anderen leds uit zijn. Daarna led 3 branden en de rest uit  enz. Maar deze code moet ik helemaal niet gebruiken volgens mij, want er wordt nu geen rtc gebruikt. Waarschijnlijk kan je deze opzet wel een beetje gebruiken want ik heb nu wel door dat je geen delay mag gebruiken. Waarschijnlijk kan je millis vervangen door now, maar dat snap ik nog niet veel van.  

Ik heb deze aangepaste code van je weer een beetje veranderd, maar ik weet dat het niet klopt maar heb met // een paar dingen erachter geschreven als notie voor jou en mijzelf. Volgens mij moet je dan vier verschillende functie creëren voor vier intervals

Trouwens dat else heb ik volgens mij ook nog niet helemaal correct toegepast in deze code omdat het nu errors geeft!!


   
BeantwoordenCiteren
 Hans
(@hans)
Famed Member Admin
Deelgenomen: 11 jaar geleden
Berichten: 2678
 

Hoi Remko,

Voor jouw toepassing heb je waarschijnlijk geen RTC nodig.
Maar ik zie wel waar ik de mist in gegaan ben ... ik schakel het zaakje niet om zoals in jouw code.

Dus even een correctie:

// Efficienter om deze als define's op te geven ipv een variable
#define in1 4
#define in2 5
#define in3 6
#define in4 7

// Bijhouden welke stap we doen, en wat het maximum aantal stappen is
#define currentNumberMax 4
byte currentNumber = 1;     

unsigned long voorgaandeMillis = 0;        // laatste keer dat iets werd uitgevoerd
const long interval = 60000; // 1 minuut interval

void setup()
{
 pinMode(in1, OUTPUT);
 pinMode(in2, OUTPUT);
 pinMode(in3, OUTPUT);
 pinMode(in4, OUTPUT);
}
void loop()
{
  unsigned long huidigeMillis = millis();
  if (huidigeMillis - voorgaandeMillis >= interval) {
    // 1 minuut verstreken - reset tijd
    voorgaandeMillis = huidigeMillis; // N.b.: Dit kan efficienter, maar dit is voor nu even beter leesbaar:
   switch (currentNumber) {
    case 1: 
      digitalWrite(in1, HIGH);
      digitalWrite(in2, LOW);
      digitalWrite(in3, LOW);
      digitalWrite(in4, LOW);
      break;
    case 2: 
      digitalWrite(in1, LOW);
      digitalWrite(in2, HIGH);
      digitalWrite(in3, LOW);
      digitalWrite(in4, LOW);
      break;
    case 3: 
      digitalWrite(in1, LOW);
      digitalWrite(in2, LOW);
      digitalWrite(in3, HIGH);
      digitalWrite(in4, LOW);
      break; 
    case 4: 
      digitalWrite(in1, LOW);
      digitalWrite(in2, LOW);
      digitalWrite(in3, LOW);
      digitalWrite(in4, HIGH);
      break; }
  if(currentNumberMax<currentNumberMax) {
    currentNumber++; // volgende stap
} else {
  currentNumber = 1; // terug naar 1
}
  } // if
} // loop

Hier een aangepaste versie die wel schakelt - sorry. Had dat even over het hoofd gezien.
Ik heb express het switch statement zo uitvoerig uitgeschreven zodat het wat leesbaarder is.
Oh en waarden niet veranderen tijdens een programma kunnen beter als constante of #define gedefinieerd worden. Vooral later als je grotere programma's gaat schrijven, bespaard dat geheugen ... 

Hopelijk werkt dit wel ... 


   
BeantwoordenCiteren
(@remko)
Eminent Member
Deelgenomen: 7 jaar geleden
Berichten: 23
Topic starter  

Wow dit ziet er heel anders uit nu, gaaf hoor. Ik moet het nog wel goed bestuderen want ik wil het natuurlijk wel zelf snappen wat er gebeurt. 

De code werkt nog niet helemaal, maar volgens mij heb ik het foutje gevonden. Led1 gaat branden na 1 min, maar daarna gebeurt er niets meer.(led1 blijft branden)

 if(currentNumberMax<currentNumberMax) {   moet veranderd worden in  if(currentNumber<currentNumberMax) {

Na de aanpassing brand led1 na 1 min en blijft ook 1 min branden, daarna gaat led2  1 min branden(de andere leds zijn uit) en daarna led3 enz en dan weer naar led1.

Bijna goed, alleen wil ik dat na 1 min led1 brandt en daarna (bijna)gelijk(bv 1 sec) led2 aan de anders leds uit en daarna(bijna) led3 enz. Daarna moet led1 weer aan.  Het moet wel nauwkeurig elke precies 1 min om 1 min, want wil natuurlijk geen afwijking hebben.  


   
BeantwoordenCiteren
 Hans
(@hans)
Famed Member Admin
Deelgenomen: 11 jaar geleden
Berichten: 2678
 

Nice catch! Dat krijg je als je als je alles uit het bolle hoofdje doet he? 

// Efficienter om deze als define's op te geven ipv een variable
#define in1 4
#define in2 5
#define in3 6
#define in4 7
// Bijhouden welke stap we doen, en wat het maximum aantal stappen is
#define currentNumberMax 4
byte currentNumber = 1;     
unsigned long voorgaandeMillis = 80000; // laatste keer dat iets werd uitgevoerd
const long interval = 60000; // 1 minuut interval
void setup()
{
 pinMode(in1, OUTPUT);
 pinMode(in2, OUTPUT);
 pinMode(in3, OUTPUT);
 pinMode(in4, OUTPUT);
}
void loop()
{
  unsigned long huidigeMillis = millis();
  if (huidigeMillis - voorgaandeMillis >= interval) {
    // 1 minuut verstreken - reset tijd
    voorgaandeMillis = huidigeMillis;
    // N.b.: Dit kan efficienter, maar dit is voor nu even beter leesbaar:
    switch (currentNumber) {
     case 1: 
       digitalWrite(in1, HIGH);
       digitalWrite(in2, LOW);
       digitalWrite(in3, LOW);
       digitalWrite(in4, LOW);
       break;
     case 2: 
       digitalWrite(in1, LOW);
       digitalWrite(in2, HIGH);
       digitalWrite(in3, LOW);
       digitalWrite(in4, LOW);
       break;
     case 3: 
       digitalWrite(in1, LOW);
       digitalWrite(in2, LOW);
       digitalWrite(in3, HIGH);
       digitalWrite(in4, LOW);
       break; 
     case 4: 
       digitalWrite(in1, LOW);
       digitalWrite(in2, LOW);
       digitalWrite(in3, LOW);
       digitalWrite(in4, HIGH);
       break;
     }
    if(currentNumber<currentNumberMax) {
      currentNumber++; // volgende stap
    } else {
      currentNumber = 1; // terug naar 1
    }
  } // if
} // loop

Ik heb nu voorgaandeMillis meteen (te) hoog gezet, zodat als de eerste keer de if bereikt wordt, meteen stap 1 wordt uitgevoerd.
Vervolgens ook de fout die jij gevonden had meegenomen ... ik denk dat ie het nu goed moet doen.
Overigens als je vragen hebt over de werking, dan leg ik het graag uit ... 

Ik ben alleen wel even de kluts kwijt voor wat je beschrijft in jouw laatste stukje tekst ("Bijna goed, alleen wil ik dat na 1 min led1 brandt en daarna (bijna)gelijk(bv 1 sec) led2 aan de anders leds uit ...").

Nu zou dit moeten gebeuren:

LED1 AAN (rest UIT) gedurende 1 minuut,
daarna LED2 AAN (rest UIT) gedurende 1 minuut,
daarna LED3 AAN (rest UIT) gedurende 1 minuut,
daarna LED4 AAN (rest UIT) gedurende 1 minuut,
dan weer opnieuw ... LED1 AAN (rest UIT) gedurende 1 minuut,
daarna LED2 AAN (rest UIT) gedurende 1 minuut,
daarna LED3 AAN (rest UIT) gedurende 1 minuut,
daarna LED4 AAN (rest UIT) gedurende 1 minuut,
etc.

Omschakelen zou instant moeten gaan, dus 2 LEDs branden nooit tegelijk ... dat is de bedoeling toch? Of heb ik dat verkeerd begrepen?


   
BeantwoordenCiteren
(@remko)
Eminent Member
Deelgenomen: 7 jaar geleden
Berichten: 23
Topic starter  

Hahaha, ik vind het knap hoor zo eventjes uit je bolle hoofd wat neerknallen. Ik hoop dat ik ooit deze materie onder de knie krijg. Ik vind het best moeilijk als er vooral berekeningen en vergelijkingen  bij komen kijken. Ik  heb normaal geen moeite met rekenen en wiskunde. Ik help mijn kids  ook altijd met hun huiswerk. Ik gisteren twee boeken gekocht, daar ga ik stap voor stap weer bij het begin beginnen, ook al weet ik het één en ander.

Nee dit bedoel ik niet helemaal, sorry ik heb het niet duidelijk uit gelegd denk ik. Goed formuleren is ook een kunst.

De bedoeling is telkens na 1 min de leds ff snel aan gaan en daarna weer gelijk uit. Dus de leds mogen niet 1 min lang branden maar heel kort 1sec of minder, want die leds zijn alleen maar om het makkelijke te kunnen zien wat er gebeurt. De bedoeling is natuurlijk de leds te vervangen door de stappenmotor. Dus de stappenmotor( 4 leds) moet elke na 1 min vier stappen maken zonder dat een tijds afwijking!!!!

Ik hoop dat ik nu duidelijke ben, zo niet zal ik proberen nog anders uit te leggen.


   
BeantwoordenCiteren
(@remko)
Eminent Member
Deelgenomen: 7 jaar geleden
Berichten: 23
Topic starter  
// Efficienter om deze als define's op te geven ipv een variable
#define in1 4
#define in2 5
#define in3 6
#define in4 7

// Bijhouden welke stap we doen, en wat het maximum aantal stappen is #define currentNumberMax 4 byte currentNumber = 1;
unsigned long voorgaandeMillis = 0; // laatste keer dat iets werd uitgevoerd const long interval = 60000; const long intervalleds = 1000; // 1 minuut interval
void setup() { pinMode(in1, OUTPUT); pinMode(in2, OUTPUT); pinMode(in3, OUTPUT); pinMode(in4, OUTPUT); }
void loop() { unsigned long huidigeMillis = millis(); if (huidigeMillis - voorgaandeMillis >= interval) { }
else { (huidigeMillis - voorgaandeMillis >= intervalleds)
// 1 minuut verstreken - reset tijd voorgaandeMillis = huidigeMillis;
// N.b.: Dit kan efficienter, maar dit is voor nu even beter leesbaar: switch (currentNumber) { case 1: digitalWrite(in1, HIGH); digitalWrite(in2, LOW); digitalWrite(in3, LOW); digitalWrite(in4, LOW); break; case 2: digitalWrite(in1, LOW); digitalWrite(in2, HIGH); digitalWrite(in3, LOW); digitalWrite(in4, LOW); break; case 3: digitalWrite(in1, LOW); digitalWrite(in2, LOW); digitalWrite(in3, HIGH); digitalWrite(in4, LOW); break; case 4: digitalWrite(in1, LOW); digitalWrite(in2, LOW); digitalWrite(in3, LOW); digitalWrite(in4, HIGH); break; }
if(currentNumber<currentNumberMax) { currentNumber++; // volgende stap } else { currentNumber = 1; // terug naar 1 } } // if } // loop

 Bijna dit denk ik, zit alleen wel een foutje in. " exit status 1expected ';' before 'voorgaandeMillis'. Lukt mij niet om die er uit te krijgen


   
BeantwoordenCiteren
 Hans
(@hans)
Famed Member Admin
Deelgenomen: 11 jaar geleden
Berichten: 2678
 

Ah OK, duidelijk (hoop ik) haha ... 

Dank je wel voor compliment, maar het uit het bolle koppie kunnen doen is niet al te moeilijk als je de materie onder de knie hebt. Dit zijn maar kleine programma's dus het is vaak een kwestie van denken welke stappen je wilt doen, en dan omzetten in code. Dat gaat jou vanzelf ook lukken, zeker als Wiskunde geen probleem is. Het makkelijkste is gewoon in normale taal ieder stap uit te schijven en dan omzetten naar code.

Als ik naar jouw code kijk dan is dit een andere versie dan die ik had geplaats? Geen idee of dat bewust was. 
Ik heb dus weer mijn versie gepakt en een wachttijd ingebakken voor we alle LEDs weer uitzetten:

// Efficienter om deze als define's op te geven ipv een variable
#define in1 4
#define in2 5
#define in3 6
#define in4 7
#define TijdsduurLEDAan 1000 #define interval 60000
// Bijhouden welke stap we doen, en wat het maximum aantal stappen is
#define currentNumberMax 4
byte currentNumber = 1;     
unsigned long voorgaandeMillis = 80000; // laatste keer dat iets werd uitgevoerd
void setup()
{
 pinMode(in1, OUTPUT);
 pinMode(in2, OUTPUT);
 pinMode(in3, OUTPUT);
 pinMode(in4, OUTPUT);
}
void loop()
{
  unsigned long huidigeMillis = millis();
  if (huidigeMillis - voorgaandeMillis >= interval) {
    // 1 minuut verstreken - reset tijd
    voorgaandeMillis = huidigeMillis;
    // N.b.: Dit kan efficienter, maar dit is voor nu even beter leesbaar:
    switch (currentNumber) {
     case 1: 
       digitalWrite(in1, HIGH);
       digitalWrite(in2, LOW);
       digitalWrite(in3, LOW);
       digitalWrite(in4, LOW);
       break;
     case 2: 
       digitalWrite(in1, LOW);
       digitalWrite(in2, HIGH);
       digitalWrite(in3, LOW);
       digitalWrite(in4, LOW);
       break;
     case 3: 
       digitalWrite(in1, LOW);
       digitalWrite(in2, LOW);
       digitalWrite(in3, HIGH);
       digitalWrite(in4, LOW);
       break; 
     case 4: 
       digitalWrite(in1, LOW);
       digitalWrite(in2, LOW);
       digitalWrite(in3, LOW);
       digitalWrite(in4, HIGH);
       break;
     }
    if(currentNumber<currentNumberMax) {
      currentNumber++; // volgende stap
    } else {
      currentNumber = 1; // terug naar 1
    }
    delay(TijdsduurLEDAan); // wachttijd voor we alle LEDs weer uitzetten
// Alle LEDs weer uitzetten     digitalWrite(in1, LOW);
    digitalWrite(in2, LOW);
    digitalWrite(in3, LOW);
    digitalWrite(in4, LOW);
  } // if
} // loop

Is dit wat je in gedachten had? na "TijdsduurLEDAan" milliseconden worden alle LEDs uitgezet. 

Dus ... in iedere hele minuut wordt 1x een LED gedurende "TijdsduurLEDAan" aangezet en dan weer uit gezet.

Ik heb overigens de variabele "interval" nu ook een constante gemaakt ... weer een waarde die we niet veranderen ... 

Overigens, als je code wilt plaatsen dan gaat dat het beste door eerst te code in dit editor te plakken en daarna de code in de editor the selecteren en te markeren als code. Mocht je code willen bewerken, dan resulteert op ENTER drukken in "breken" van de code. Gebruik Shift+ENTER als je het geheel bij elkaar wilt houden. 


   
BeantwoordenCiteren
 Hans
(@hans)
Famed Member Admin
Deelgenomen: 11 jaar geleden
Berichten: 2678
 

Overigens; ik heb net de code even door de compiler gegooid en die zegt dat alles OK is.
Mocht je nog steeds tegen een foutmelding aan lopen, overweeg dan de code eerst in Notepad te plakken, opnieuw daar te selecteren, kopiëren en daarna pas in de Arduino IDE plakken. Dat haalt de "extra" informatie weg die kopiëren van een webpagina met zich mee brengt.


   
BeantwoordenCiteren
(@remko)
Eminent Member
Deelgenomen: 7 jaar geleden
Berichten: 23
Topic starter  

Weerom bedankt Hans voor je inzet Deze code werkt wel, alleen denk ik helaas toch dat het niet goed is omdat er nu met DELAY(60000)1 min wordt gewerkt. Ik ben bang dat ik weer echt die tijdsafwijking  weer ga krijgen.  En volgens mij komt deze code ook op het zelfde neer alleen dan mooier(efficiënter) dan mijn eerst simpel code, die had tussen elke stap gewoon een delay er tussen zitten. Als je er niet mee eens ben hoor ik graag waarom? Ik denk echt, wat ik al eerder zei dat een rtc module erbij moet en die heb ik ook. Voorkeur gaat het uit naar  ds3231.

Sorry dat ik de vorige code verkeert op deze site heb toevoegt. Ik dacht juist dat ik het correct had gedaan, maar waarschijnlijk moet ik daarna even Shift+ENTER gebruiken om er geen regels tussen te krijgen.

Ik vind het ook trouwens leerzaam als je  deze code dan ook nog efficiënter schrijft, zoals je bij de commentaar hebt geschreven. Als het niet te veel moeite is hoor.

Ik ben nu flink aan het studeren uit mijn boeken, maar moet eerlijk toegeven dat als ik niet helemaal er uitkomt dat ik dan jou Adruino Cursus er op na lees! En vind het echt super deze beschrijven van jou  

Als testje, een klein stukje code bijgevoegd om het nu wel goed bij te voegen

  delay(TijdsduurLEDAan); // wachttijd voor we alle LEDs weer uitzetten
    // Alle LEDs weer uitzetten
    digitalWrite(in1, LOW);
    digitalWrite(in2, LOW);
    digitalWrite(in3, LOW);
    digitalWrite(in4, LOW);

   
BeantwoordenCiteren
 Hans
(@hans)
Famed Member Admin
Deelgenomen: 11 jaar geleden
Berichten: 2678
 

Hoi Remko,

Helaas, je hebt het mis voor wat de delay betreft, maar ik begrijp de verwarring.

De waarde die de functie millis() genereert komt van de internet klok van de Arduino. Nu is die klok niet een RTC clock, en daarmee bedoel ik dat het wel real time is maar niet een echte datum/tijd bijhoudt, maar in plaats daarvan het aantal milliseconden bijhoudt dat de Arduino aanstaat. Dus deze teller begint bij nul als de je Arduino van stroom voorziet.

We controleren dus steeds opnieuw waar die teller van de interne klok is gebleven, op zoek naar de volgende minuut.
Omdat onze interval 1 minuut is (60.000), hebben we ruwweg een minuut om te rommelen met dingen. Dus ook genoeg tijd om een kleine wachttijd van 1 second (1.000), die we in TijdsduurLEDAan definiëren, door delay() aan te roepen voor het aanhouden van het LEDje.

De delay(60000) is dus niet correct in jouw vorige bericht. Dat wordt namelijk effectief delay(1000). Misschien dat dit verwaaring veroorzaakt.

Ik hoop dat ik dat duidelijk heb uitgelegd ... het kan een beetje verwarrend zijn. Dus millis() en delay() werken onafhankelijk van elkaar, en we gebruiken de delay om de LEDs 1 seconde aan te laten staan, en millis() om te bepalen wanneer we weer de volgende minuut bereikt hebben.

Overigens; mochten er zich discrepanties in de tijd voordoen, dan zul je dezelfde discrepanties met een RTC ook ervaren. In zo'n geval moeten we de waarde 60.000 een beetje bijstellen.

Dan je wel voor het compliment voor wat betreft de cursus - ik had het eigenlijk geschreven voor m'n neefjes (die er uiteindelijk niks mee gedaan hebben haha) ... maar ik vindt het altijd erg leuk om dat soort zaken te schrijven en geniet er van als anderen er baat bij hebben. Dus dank je wel! 

Ik zal zo proberen tijd te maken voor een efficiëntere code ... met een beetje uitleg 
M'n werkdag begint net dus ik moet wat tijd in m'n pauze zien te vinden.


   
BeantwoordenCiteren
 Hans
(@hans)
Famed Member Admin
Deelgenomen: 11 jaar geleden
Berichten: 2678
 

OK, een aangepaste versie die een beetje netter en efficiënter is (snelheid en benodigde geheugen):

// Efficiënter om deze als define's op te geven ipv een variabele
// De compiler vervangt elk voorkomen van deze constanten meteen met de
// gedefinieerde waarde, en verbruikt dus geen geheugen voor variabelen
#define TijdsduurLEDAan 1000
#define interval 60000
// Bijhouden welke stap we doen, en wat het maximum aantal stappen is
// Hiervoor definiëren we Max aantal pinnen (4) en een array
// Dit maakt aanpassen makkelijk als je in de toekomst meer LEDs wilt toevoegen
#define MaxPins 4
int pins[MaxPins] = { 4, 5, 6, 7 }; // Definieer de 4 pinnen in een array
byte HuidigePin = 0; // Voor arrays start tellen bij nul en niet bij 1     
unsigned long voorgaandeMillis = 0; // laatste keer dat iets werd uitgevoerd
void setup()
{
  for(int Teller; Teller<MaxPins; Teller++) // tel van 0 t/m 3 om pinnen op 
  { // output te zetten  
    pinMode(pins[Teller], OUTPUT);
  }
}
void loop()
{
  unsigned long huidigeMillis = millis();
  if (huidigeMillis - voorgaandeMillis >= interval) {
    // 1 minuut verstreken - dus bewaar dit meteen voor detectie van de volgende ronde
    voorgaandeMillis = huidigeMillis;
    
    // Omdat alle pinnen al op LOW staan, hoeven we alleen maar deze pin op HIGH te zetten
    digitalWrite(pins[HuidigePin], HIGH);
    if(HuidigePin<MaxPins) {
      HuidigePin++; // volgende stap
    } else {
      HuidigePin = 0; // terug naar 1, maar arrays starten bij nul met tellen
    }
    delay(TijdsduurLEDAan); // 1 seconde wachttijd voor we de LED weer uitzetten
    
    // Huidige LED weer uitzetten, de anderen stonden al uit
    digitalWrite(pins[HuidigePin], LOW);
  } // if
}

Ik zal even kort door de code lopen, in gedachten houdende wat we al eerder hebben besproken.

Omdat we de pinnen niet erg handig kunnen aanspreken heb ik een array gebruikt.
Ideaal zou zijn als we gewoon met 1, 2, 3, en 4 zouden kunnen werken, als we een pin willen aanspreken, maar de gebruikte pinnen staan dit niet toe (4, 5, 6, 7). We zouden kunnen overwegen om het pin nummer steeds te berekenen maar daarmee maak je het jezelf wel moeilijk als er in de toekomst iets veranderd (meer pinnen of andere pinnen). 

We tellen 1, 2, 3, 4 omdat we posities tellen voor elke minuut.

digitalWrite(1,HIGH);   // dit zou ideaal zijn, maar dat komt niet overeen met de pinnen
digitalWrite(1+3,HIGH); // steeds 3 optellen bij het nummer van de positie zou werken, als we niks veranderen

Er zijn dus een aantal trucjes die erg snel en efficiënt zijn, maar ... als we de gebruikte pinnen veranderen (verwisselen of uitbreiden) dan werken deze trucjes ineens niet meer. Dus een recept om later in de problemen te raken.

Daarom heb ik een array van nummers gebruikt (arrays kan in het begin een lastig onderwerp zijn). Arrays beginnen niet bij 1 met tellen, maar bij 0 (nul), en dat loopt dus 1 uit de pas met onze posities. We kunnen dat corrigeren door steeds 1 af te trekken van de positie om dan de positie in de array te krijgen. Of ... we gaan onze posities ook tellen door bij nul te beginnen.

In de "Setup()" gebruik ik een for-lus om sneller de pinnen op OUTPUT te zetten. Ik heb het wat uitgebreid weggeschreven maar een for-lus kan nog korter geschreven worden, maar dat neemt weer weg aan de leesbaarheid van de code - wat ik zelf altijd wel belangrijk vindt, zeker als je een paar maanden later nog eens terug gaat kijken om iets te wijzigen ...

Stel nu dat je in de toekomst 6 LEDs gaat gebruiken dan hoef je alleen maar deze 2 regels aan te passen:

#define MaxPins 6
int pins[MaxPins] = { 4, 5, 6, 7, 8, 9 }; // Definieer nu de 6 pinnen in een array

We zetten MaxPins op het aantal werkelijk gebruikte pinnen, en in de volgende regel voegen we de 2 extra pin nummers toe tussen de accolades.
Handig he?

Je ziet dat hierdoor het hele switch() statement niet meer nodig is en dat was een tweede doel die ik in gedachten had.

Ik heb ook het zetten van LOW en HIGH veranderd. Alle pinnen beginnen in een LOW state en gaan alleen maar naar HIGH als wij dat zeggen.
Dus als we een pin HIGH zetten en een seconde wachten dan weten we 100% zeker dat alleen die pin weer op LOW gezet moet worden.

Nu zie je misschien waarom ik eerst de uitgebreide code heb gegeven - het is stukken duidelijker wat er aan de hand is.
Maar, en zo werk ik nog weleens, daarna gaan we kijken hoe we dit efficiënter kunnen doen.
Blokken code die erg op elkaar lijken en meerdere keren herhaald worden nodige vaak uit voor een efficiëntere manier - maar dat leer je vanzelf naarmate je beter wordt met het lezen en denken in code.

Overigens, na het weghalen van een aantal commentaar regels zie je dat de code ook een stuk korter is geworden;

#define TijdsduurLEDAan 1000
#define interval 60000
#define MaxPins 4
int pins[MaxPins] = { 4, 5, 6, 7 }; // Definieer de 4 pinnen in een array
byte HuidigePin = 0; // Voor arrays start tellen bij nul en niet bij 1     
unsigned long voorgaandeMillis = 0; // laatste keer dat iets werd uitgevoerd
void setup()
{
  for(int Teller; Teller<MaxPins; Teller++) // tel van 0 t/m 3 om pinnen op 
  { // output te zetten  
    pinMode(pins[Teller], OUTPUT);
  }
}
void loop()
{
  unsigned long huidigeMillis = millis();
  if (huidigeMillis - voorgaandeMillis >= interval) {
    voorgaandeMillis = huidigeMillis;
    digitalWrite(pins[HuidigePin], HIGH);
    if(HuidigePin<MaxPins) {
      HuidigePin++; // volgende stap
    } else {
      HuidigePin = 0; // terug naar 1, maar arrays starten bij nul met tellen
    }
    delay(TijdsduurLEDAan); // 1 seconde wachttijd voor we de LED weer uitzetten
    digitalWrite(pins[HuidigePin], LOW);
  } // if

Merk op:
ik heb een aantal variabelen even een andere naam gegeven ivm leesbaarheid (ik woon en werk in de VS dus neig nog weleens naar de Engelse taal haha). Daarnaast heb ik de code niet kunnen testen (zit op m'n werk), maar de Arduino software zegt dat alles goed compileert. 


   
BeantwoordenCiteren
Pagina 1 / 3
Deel: