Variabele delay

Arduino specifieke Software
Berichten: 35
Geregistreerd: 19 Dec 2014, 00:06
Woonplaats: Heemskerk

Variabele delay

Berichtdoor McNes » 23 Dec 2014, 01:32

Beste forummers,

Ik heb acht ledjes in een ringopstelling. Via een schuifregister laat ik het lichtje "rondjes lopen. De richting en snelheid is afhankelijk van de stand van een potmeter. Voluit rechts draait het licht op maximale snelheid rechtsom. Draai ik de potmeter naar links, gaat het lichtje steeds langzamer rond. In het midden wisselt de draairichting. Verder naar links betekent sneller linksom draaien.

Het programmaatje draait prima, echter, de berekening van de draaisnelheid wordt in een delay verwerkt waardoor het programma bij langere delays niet snel op de potmeter reageert.
Is er een manier om de stand van de potmeter tussentijds af te lezen en de delay daarop aan te passen?

Mvg., Hans

p.s, Wellicht knullig geprogrammeerd?

Bijgevoegd de code:
Code: Alles selecteren
byte teller = 1 ;         // algemeen te gebruiken teller
byte vlag ;                 // links of rechts draaien
int sensor = A0;          // Init A0
int sensorValue = 0;    // input potmeter
int vertraging ;            // komt in de delay() te staan
int led =1 ;                // bevat schuifwaarde

void setup() { 
      teller = 1;
      while (teller != 9) {               // Initialiseer poorten 1 tm 8 als output
      pinMode(teller,OUTPUT);
      teller ++;
      }                                         // einde van de while 
}

void loop()
{
    sensorValue = analogRead(sensor);            // Inlezen potmeter
    sensorValue = sensorValue -512;                // schalen van de waarde
         
            if (sensorValue <0){
                sensorValue = abs (sensorValue) ;   // keert teken om indien negatief.
                vlag = 0 ;                                      // set draaivlag links, moet alleen gecheckt worden :)
               }
            else { vlag = 1 ; }                               // anders zet draaivlag rechts
            vertraging = 1026 - 2 * sensorValue ;    // vertragingsloop is nu van 2mS tot 1S
 
 if (vlag == 0) {
          teller = 0;
                while ( teller != 8){
                digitalWrite (teller+1,bitRead (led,teller));    // Schrijft alle bits van led naar de uitgangen
          teller ++ ; }
          delay (vertraging);                               // berekende vertraging, hoe verder de potmeter naar de uiterste standen gaat, hoe sneller de leds lopen
 
          led = led << 1;                                 // schuif 1 stap naar links
          bitWrite (led,0,bitRead (led,8));          // schuif bit 8 naar positie o
          bitWrite (led,8,0);                            // reset bit 8
        }
 
   
  else { 
        teller = 0;
            while ( teller != 8){
            digitalWrite (teller+1,bitRead (led,teller)); // zie boven
        teller ++ ; }
        delay (vertraging);
 
        bitWrite (led,8,bitRead (led,0)); led = led >> 1;  // schuift 1 stap naar rechts
  }


} // eind van de loop



Advertisement

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

Re: Variabele delay

Berichtdoor nicoverduin » 23 Dec 2014, 09:26

een timer en millis() gebruiken.

Voorbeeld:
cpp code
unsigned long timer = 0;  // 32 bits timer


in de setup():

cpp code
timer = millis();


in de loop()
cpp code
if ((millis() - timer) > vertraging){
//
// schuif een stap naar rechts
//
.......
//
// zet de timer weer voor de volgende keer
//
timer = millis();
}


Zo kan delay vervallen. Wat je doet is kijken of je voorbij de vertragingstijd bent. Zodra dat het geval is shuif je een bit op. Is dat niet het geval dan leest hij direct weer de potmeter.
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

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

Re: Variabele delay

Berichtdoor shooter » 23 Dec 2014, 10:17

dat kan met een timer, maar dan moet je wel je programma behoorlijk omdenken.
zorg ervoor dat de loop altijd draait, ofwel nooit een delay of een afhankelijkheid in zetten.

maak van je loop een functie.
telkens als de tijd voorbij is (zie nico) dan spring naar je functie. uiteraard moet je dan wel de delays verwijderen uit je functie.
dus op regel 3 van nico komt iets in de trant van functie()
en onder de loop void functie() met daar je programma.

trouwens prima vraagstelling compleet met programma.
paul deelen
shooter@home.nl

Berichten: 35
Geregistreerd: 19 Dec 2014, 00:06
Woonplaats: Heemskerk

Re: Variabele delay

Berichtdoor McNes » 23 Dec 2014, 11:21

Mijne heren, met dank. Ik ga weer aan het knutselen.

Mvg., Hans

Berichten: 35
Geregistreerd: 19 Dec 2014, 00:06
Woonplaats: Heemskerk

Re: Variabele delay

Berichtdoor McNes » 23 Dec 2014, 11:48

Ik denk dat ik heb snap. Volgens mij gaat dat goed werken, waarvoor mijn dank.
Als ik het echter goed heb, kan er na 2^32 milliseconden een probleem ontstaan doordat de 32 bits overschreden gaat worden. Klopt dat? En zo ja, kan ik op de een of ander manier de millis() resetten?

Duurt denk ik een beetje lag om dat te testen......

Of praat ik wartaal?? :o

Gr., Hans

Aha, laat maar, ik heb het al gezien. Ook millis() gebruikt een unsigned long. Dus bij een overflow gaat deze terug naar 0, en dus ook de timer.
:? Eerst denken en nakijken, dan pas vragen. Sorry!

Berichten: 22
Geregistreerd: 26 Okt 2014, 14:17

Re: Variabele delay

Berichtdoor stanleyvc » 23 Dec 2014, 18:32

Wat ik in die situatie 's doe; in de loop zet ik een vaste delay van 1mS en laat de loop een aantal malen (afhankelijk van de snelheid) een deel van de loop overslaan.

Code: Alles selecteren
unsigned int param_vertraging = 0 // Hier komt de vertraging 's waarde in
unsigned int timer_vertraging = 0 // Vertraging 's Timer

void setup() {
  param_vertraging = 500 // Startten met een vertraging van 500mS
 
}

void loop() {
  delay(1);
  timer_vertraging++;
  if (timer_vertraging > param_vertraging) {
    timer_vertraging = 0;
    // Code wat uitgevoerd moet worden
    // ...   
  }
}

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

Re: Variabele delay

Berichtdoor nicoverduin » 23 Dec 2014, 18:46

Tja het werkt, maar als je ooit een programma krijgt waarbij je alle pinnen van de Arduino nodig hebt of er moet direct gereageerd worden dan leer je deze manier gauw genoeg af.....
En zoals al eerder is aangeven, het is niet nodig. Daarnaast, als je echte timing nodig hebt wat nog een beetje betrouwbaar is dan gaat de afwijking groter worden naarmate je meer code hebt.... Immers die kosten ook tijd en tegelijkertijd pak je nog eens een milliseconde.
Het mooie van de aangegeven manier een heleboel (relatief) (on)afhankelijke delen code naast elkaar kan laten draaien (is natuurlijk niet zo maar...). Je schrijft gewoon een stukje code dat op enig moment iets moet doen. Je geeft het een timer en klaar. Dat stukje code wordt alleen actief als het nodig is.
Het kan nog anders maar dan ga je al heel erg richting een realtime OS en dat is een beetje veel van het goede voor de Arduino. Dit is een mooi compromis.
Docent HBO Technische Informatica, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

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

Re: Variabele delay

Berichtdoor shooter » 23 Dec 2014, 19:39

toch mcnes is het een heel goede vraag hoor.
zijn veel discussies over.
paul deelen
shooter@home.nl

Berichten: 22
Geregistreerd: 26 Okt 2014, 14:17

Re: Variabele delay

Berichtdoor stanleyvc » 23 Dec 2014, 21:54

Alleen de millis gaat naar een dag of 50 in overflow (0) dat kan ook weer, tot niet gewenste timing problemen lijden. Of je moet dit gaan ondervangen.


Trouwens, voor de millis methoden staat hier een mooi voorbeeld: http://arduino.cc/en/Tutorial/BlinkWithoutDelay

Berichten: 35
Geregistreerd: 19 Dec 2014, 00:06
Woonplaats: Heemskerk

Re: Variabele delay

Berichtdoor McNes » 23 Dec 2014, 23:45

Met dank, het werkt fraai. Ik houd er niet van als er loze loops of dergelijke in zitten waarin niets gebeurt. Zonde van de (processor)tijd. Moest vroeger op alle manieren tijd winnen op de "trage" Z80 en 6502 processoren....

Kon nu het programma nog verder inkorten door het schuiven van het register in een if else loop te vangen, met daaroverheen de timerloop. Houd van lean programmeren.

Inderdaad gaat na 49 dagen een hik optreden omdat de millis() dan naar 0 gaat. Voor nu nog geen probleem want na vanavond gaat hij weer uit :mrgreen:

Ik ben weer geholpen. Kan weer verder knoeien....

Thx!

Mvg., Hans

p.s., met de timer = millis() in de setup loop ging iets niet goed. De timer bleef op 0. Ik heb nu een startsignaal gemaakt aan het begin van de void loop() en dan doet hij het wel. :geek: :?:

p.s., dit is het nu geworden. Wat veel commentaar, maar dat vind ik zelf erg makkelijk.

Code: Alles selecteren
//            byte strt = 1 ;           // moet een startwaarde creeeren voor in de loop --> eruit gegooid, gaat toch ook zonder
byte teller = 1 ;         // algemeen te gebruiken teller
byte vlag ;                // links of rechts draaien
int sensor = A0;        // Init A0
int sensorValue = 0;  // input potmeter
int vertraging ;          // komt in de delay() te staan
int led =1 ;               // bevat schuifwaarde
unsigned long timer;  // waarde voor de millis()

void setup() { 
      teller = 6;
      while (teller != 14) {         // Initialiseer poorten 1 tm 8 als output
      pinMode(teller,OUTPUT);
      teller ++;
      } // einde van de while 
}


void loop()
{
//     if (strt == 1) { timer = millis();}       // eruit gegooid, gaat toch ook zonder
//      strt = 2;                                          // Verwijderd, werkt toch?
 
    sensorValue = analogRead(sensor);             // Inlezen potmeter
    sensorValue = sensorValue -512;                 // schalen van de waarde
               if (sensorValue <0){
                   sensorValue = abs (sensorValue) ; // keert teken om indien negatief.
                   vlag = 0 ;                                    // set draaivlag links, moet alleen gecheckt worden :)
               }
           
               else { vlag = 1 ; }                                // anders zet draaivlag rechts
               vertraging = 1026 - 2 * sensorValue ;    // vertragingsloop is nu van 2mS tot 1S
 
 // Volgende deel is om de bits naar de pins te sturen. Hier van pin 6 tot en met 13
 
          teller = 6;
                while ( teller != 14){
                digitalWrite (teller,bitRead (led,teller-6));    // Schrijft alle bits van led naar de uitgangen
          teller ++ ; }
         
 // Hier start het testen op de vertragingstijd met behulp van millis()
 
      if (millis()- timer > vertraging) {       // vertragingsloop met behulp van de timer
 
  // Hier schuift het register, naar links als de vlag nul is, naar rechts als de vlag 1 is. Alleen als de wachttijd overschreven wordt.
     
                if (vlag == 0) {
                     led = led << 1;                         // schuif 1 stap naar links
                     bitWrite (led,0,bitRead (led,8));  // schuif bit 8 naar positie o
                     bitWrite (led,8,0);                     // reset bit 8
                }
                else { 
                       bitWrite (led,8,bitRead (led,0)); led = led >> 1;   // schuift 1 stap naar rechts
                       }
               
               timer = millis(); // reset de timer
 
               } // einde van de vertragingsloop

} // eind van de loop

Laatst gewijzigd door McNes op 24 Dec 2014, 00:34, in totaal 2 keer gewijzigd.

Volgende

Terug naar Arduino software

Wie is er online?

Gebruikers in dit forum: apkulefo, arahokol, olonoowkej, patmivaolot en 22 gasten