Go Down

Topic: Demonstration code for several things at the same time (Read 141888 times) previous topic - next topic

PeterH


I think what has been confusing me (maybe still does) is your phrase "when there is any latency between the timed condition becoming true, and the code to detect that executing". I believe that by "saving" millis() at the start of each iteration of loop() it doesn't matter when the code actually gets around to executing the event. And the timing of the subsequent event is not linked to the actual time of execution of the previous event. Instead it is linked to the value of millis() at the time the loop() began its iteration.


I think you have understood the problem correctly.

The scope for latency within a specific sketch can be affected by the placement of the call to millis() relative to the call checking whether the time has elapsed, and by how frequently the loop executes, but the latency can never be reduced to zero.

This is a problem that has varying severity and varying impact. Arguably, in many cases it can be ignored. However, the issue of how to control multiple things independently, including controlling independently timed things, crops up so frequently, and is so fundamentally important for newcomers to understand, that I think having a really good example of 'best practice', together with an explanation of why that is the best practice, would be extremely useful. It's a great shame, and a lost opportunity, that the 'blink without delay' example is so poorly explained and so mediocre in implementation. This is why I'm so keen for you to develop your example to the point where it really does represent best practice, and not just 'good enough for simple examples'.

Coding Badly


A word of caution about the basic "mile marker" approach: an overrun will wreak havoc.  A while loop overcomes the problem.

An example from CrossRoads' snippet...

Code: [Select]
void setup()
{
 Serial.begin( 115200 );
}

void loop()
{
 unsigned long currentMicros;
 unsigned long elapsedMicros;
 static unsigned long nextMicros;
 const unsigned long duration = 1000000ul;

 currentMicros = micros();
 elapsedMicros = currentMicros - nextMicros;  
 if ( elapsedMicros >= duration )
 {
   nextMicros = nextMicros + duration;
   Serial.println( currentMicros );
 }
 // Pretend loop takes too long to execute
 delay( 1001 );
}


Change the if to a while.

Robin2

#32
Mar 12, 2014, 08:12 am Last Edit: Mar 12, 2014, 10:45 am by Robin2 Reason: 1
This is all provin' very stimulatin' to the few remaining grey cells ...

@CrossRoads, thank you, but I am not concerned with accuracy greater than you get from millis(). This is just intended as a simple learning device for newbies.

@PeterH and @CodingBadly, I hope you will have realized that my only objection to doing it "properly" was the risk that explaining the change would so confuse a newbie that all value from the demo code would be lost. I think I have now figured out a simple way to link the "+= interval" version to the "= currentMillis" version that's in Blink-Without-Delay without the need for a complex explanation.

I will modify my example and maybe post the updated version later today if I feel the change will be sufficiently unobtrusive. Edit to add ... I have now updated the code attached to the original post and the code in Reply #1.

@CrossRoads, I don't understand your use of the term "mile marker".

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

CrossRoads

"mile marker" refers to the event happening at regular intervals:
Code: [Select]

the comparison will still be at a multiple of "duration".

as I indicated in my code comments.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

Robin2

Sorry @Crossroads, but I still don't see how your comments (or @CodingBadly's comments on your comments) to relate to my demo sketch. I thought you were recommending using micros instead of millis for more accurate timing.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

cootcraig


I have prepared the attached example sketch in the hope that it will be a
suitable model. I have tested it on an Uno and a Mega. I have called it
"SeveralThingsAtTheSameTime.ino". (It seems to be too long to show the
code directly in this post)
...
It also uses the "state machine" concept to manage the various activities
and enable the different functions to determine what to do.
...
Comments are welcome.


Thank you for this, I will be studying it.

I'm new to Arduino coding and learning what and how can be fit in Arduino
IDE code.  My starting approach was to leverage this SimpleTimer code:

http://playground.arduino.cc/Code/SimpleTimer#.UyIPih_f9ic

Here is a code fragment where I do periodic Serial writes.  This not
really equivalent to what your code is doing, but this is my starting
point.

Code: [Select]

...
#include <SimpleTimer.h>
...
SimpleTimer timer;
...
void setup()
{
...
  timer.setInterval((5*1000), timerWrite);
...
}
void loop()
{
...
  timer.run();
...
}
// Periodic write to Serial to test RPi <-> Arduino
void timerWrite()
{
  // Code here that queues up some text to write on Serial
}


Robin2

@cootcraig, thank you for your kind words.

If you want get advice about the SimpleTimer library (about which I know nothing) I would appreciate it if you would start a new Thread as I would like to keep this thread to the one subject so as not to confuse newcomers.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

cootcraig


If you want get advice about the SimpleTimer library (about which I know nothing) I would appreciate it if you would start a new Thread as I would like to keep this thread to the one subject so as not to confuse newcomers.

...R

I'm not looking for help with SimpleTimer, sorry.  I'm learning how to multiple things on an Arduino myself., just not starting  with the same demo.  I will continue watching this thread.

evancleary

#38
Mar 14, 2014, 03:42 am Last Edit: Mar 14, 2014, 06:07 am by Coding Badly Reason: 1
hey guys,

i took your example and tried to apply it to a binary thermometer that i had already done
i got it to comply but it dosnt function like it should

Moderator edit: offensive phrase remove

any ideas?

cr0sh


any ideas?


I don't know about the code, but you have a serial.print() line in the loop() function that I would like to encourage you to edit, or the moderators may do it for you.

/remember, this forum caters to many age groups and such; let's try to keep it somewhat in line with that...
I will not respond to Arduino help PM's from random forum users; if you have such a question, start a new topic thread.

Coding Badly

...or the moderators may do it for you.


Too late.

Quote
/remember, this forum caters to many age groups and such; let's try to keep it somewhat in line with that...


Well stated @cr0sh.  Thank you for your post.

@evancleary, I make you this promise: I will not waste my time again cleaning up your mess.

Robin2

I take it that no input is required from me until there is some code to look at?

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

evancleary

apologies for the bad language in the last post guys
was messing about with the print function and forgot to remove the phrase before post

Code: [Select]
const int ledPin1= 13;
const int ledPin2= 12;
const int ledPin3= 11; 
const int ledPin4= 10;
const int ledPin5= 9;
int sensorValue = 0;

// ==================variables====================================

int degrees_21 = LOW;
int degrees_22 = LOW;
int degrees_23 = LOW;   // these are my seperate functions
int degrees_24 = LOW;   // kept the rang of temp around room temp for
int degrees_25 = LOW;   // trial run
int degrees_26 = LOW;

//===================================================================

void setup()

{
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  pinMode(ledPin3, OUTPUT); 
  pinMode(ledPin4, OUTPUT);
  pinMode(ledPin5, OUTPUT);
 
  Serial.begin(9600);
}

//========================================================================

void loop()

{
  sensorValue = analogRead(A0);
  Serial.println(sensorValue);
 

updatedegrees_21();
updatedegrees_22();
updatedegrees_23();
updatedegrees_24();
updatedegrees_25();
updatedegrees_26();


}

//=====================================================================

void updatedegrees_21()     
{
  if (degrees_21 == LOW)     // was thinking about putting an else (degrees_21 = LOW)
  {                              // but didnt think it was required
    if (sensorValue <= 43)//21
    degrees_21 = HIGH;
  }
        if (degrees_21 == HIGH)   
      { 
          digitalWrite(ledPin1, HIGH);
          digitalWrite(ledPin2, LOW);
          digitalWrite(ledPin3, HIGH);
          digitalWrite(ledPin4, LOW);
          digitalWrite(ledPin5, HIGH);
      }
   
}

 
//==================================================================

void updatedegrees_22()
{
  if (degrees_22 == LOW)
  {
    if (sensorValue > 43 && sensorValue <= 45)//22
    degrees_22 = HIGH;
  }
        if (degrees_22 == HIGH)
      {
          digitalWrite(ledPin1, HIGH);
          digitalWrite(ledPin2, LOW);
          digitalWrite(ledPin3, HIGH);
          digitalWrite(ledPin4, HIGH);
          digitalWrite(ledPin5, LOW);
       }
   
}
     
//======================================================================

void updatedegrees_23()
{
  if (degrees_23 == LOW)
  {
    if (sensorValue > 45 && sensorValue <= 47)
     degrees_23 = HIGH;
   }
        if (degrees_23 == HIGH);
        {
            digitalWrite(ledPin1, HIGH);
            digitalWrite(ledPin2, LOW);
            digitalWrite(ledPin3, HIGH);
            digitalWrite(ledPin4, HIGH);
            digitalWrite(ledPin5, HIGH);
        }
   
}
 
//==========================================================================

void updatedegrees_24()
{
  if (degrees_24 == LOW)
  {
    if (sensorValue > 45 && sensorValue <= 47)
     degrees_24 = HIGH;
   }
        if (degrees_24 == HIGH);
        {
            digitalWrite(ledPin1, HIGH);
            digitalWrite(ledPin2, HIGH);
            digitalWrite(ledPin3, LOW);
            digitalWrite(ledPin4, LOW);
            digitalWrite(ledPin5, LOW);
        }
   
}

//========================================================================

void updatedegrees_25()
{
  if (degrees_25 == LOW)
  {
    if (sensorValue > 49 && sensorValue <= 52)//25
    degrees_25 == HIGH;
  }
      if (degrees_25 == HIGH)
      {
          digitalWrite(ledPin1, HIGH);
          digitalWrite(ledPin2, HIGH);
          digitalWrite(ledPin3, LOW);
          digitalWrite(ledPin4, LOW);
          digitalWrite(ledPin5, HIGH);
      }
 
}

//===========================================================================

void updatedegrees_26()
{
  if (degrees_26 == LOW)
  {
     if (sensorValue > 52 && sensorValue <= 54)
     degrees_26 = HIGH;
  }
        if (degrees_26 == HIGH)
      {
          digitalWrite(ledPin1, HIGH);
          digitalWrite(ledPin2, HIGH);
          digitalWrite(ledPin3, LOW);
          digitalWrite(ledPin4, HIGH);
          digitalWrite(ledPin5, LOW);
      }
 


in the version of this code that i have working i basically have a load of if and else function on a delayed loop which constantly checks sensorValue, thought applying it with non-blocked architecture would be a good training exercise

@CodingBadly Im not looking for anyone to clean up my mess just looking for some advice or point in the right direction because i have a breathalyzer with multiple inputs/outputs and functions to have completed in the next 2 weeks

yet again folks my apologies

CrossRoads

For all these, you could simplify some:

void updatedegrees_25()
{
 if (degrees_25 == LOW)
 {
   if (sensorValue > 49 && sensorValue <= 52)//25
   degrees_25 == HIGH;
 }
     if (degrees_25 == HIGH)
     {
         digitalWrite(ledPin1, HIGH);
         digitalWrite(ledPin2, HIGH);
         digitalWrite(ledPin3, LOW);
         digitalWrite(ledPin4, LOW);
         digitalWrite(ledPin5, HIGH);
     }
 
}


What makes degrees_25 and the others Low again to allow another reading?
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

CrossRoads

(apparently strikeout does not work within code tags)
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

Go Up