Sampling Voltage by button - problem

Hey there guys.

I'm doing a little project using arduino nano.
I would like to press a button - to read (and print) Analog Voltage 10 times per second, for 1 minute - PRECISELY!

I've tried to use SimpleTimer library, and Timer library.
I wrote a little piece of code to test it (blink), but with no luck.
The callback function (the Analog read) was called only once.

Here is my code with SimpleTimer Library:

#include <SimpleTimer.h>
// Variables:
  SimpleTimer t; // The timer
  int TimerID;
  const int buttonPIN = 2; // D2 ;
  int buttonState = 0;
  int prevButtonState = 0;

// the setup function runs once when you press reset or power the board
void blinkk(){
    Serial.println("LIGHT");
    digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(1000);
    Serial.println("DARK");
    digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
    delay(1000);   
}

void setup() {
  pinMode(buttonPIN, INPUT);
    
  // Establishing Communication :
  Serial.begin(9600);
  Serial.println("Start Program");
  
  // Sampeling:
  TimerID = t.setTimer(5000,blinkk,3);
  t.disable(TimerID);
}

void loop() {
  buttonState = digitalRead(buttonPIN);
  //if button was pressed.
  if (buttonState == HIGH && prevButtonState == LOW) {
       Serial.println("Pushed!");
       Serial.println(" ");
       t.enable(TimerID);
  }
  prevButtonState = buttonState;

  t.run();
}

my first attempt was to put the Run method in the button pressed condition, but it only called "blinkk" once.

Can someone help me please?
mybe using a different library

Have a magical Week you guys :slight_smile:

What does PRECISELY! mean?

You don't need a timing library, this can be done using BWD BlinkWithoutDelay techniques.

.

Thank you for your comment.

I've heard that the delay function doesn't work that accurately, and I dont really know how much time each if condtition takes.
If the butten was pressed - I need to get 600 samples per minute, and I need it so be the most accurate in terms of time interval between each sample.

My little code test was supposed to implement :

If the butten was pressed - every 5 seconeds(percisely) do stuff - for total of 3 times.
Regardless of the time of the callback method, and only for a fixed amount of time.

I've read about the BWD and I don't belive this aproach will help me much.

If you have some more ideas, I would like to hear them.
thanks again :slight_smile: !

jokohavi:
I've heard that the delay function doesn't work that accurately, and I dont really know how much time each if condtition takes.

BlinkWithoutDelay.

I think you missed the "without" part.
Leo..

If you need shorter periods than 2 milliseconds, use micros() instead of millis() in the BWD

.

Wawa:
BlinkWithoutDelay.

I think you missed the "without" part.
Leo..

I actually did noticed it, but I wanted to explain myself better.
Again, I Do not know how much time does the If condition or the while condition takes.

Does the BWD technique ignores the time which takes to do the 'AnalogRead' and check the if and while condition?

One thing you need to do is define exactly what you mean by "precisely" - all processors execute a series of instructions to do things. Viewed over a minute, they appear to be instantaneous, however, depending on the clock speed, each instruction takes a small period of time ... a "step". So, anything you tell it to do will take some number of steps - whether or not those "steps" are small enough to meet your "precisely" only you can determine, but there will be some jitter in your sample times because it will always require some steps to do what you want. Very careful hand assembly of code with interrupts disabled can create quite accurate times (as in repeatable), but that is probably more "precise" than what you want (or need). You have to define what the time limits are - within a ms or 5 microseconds or ???

gpsmikey:
One thing you need to do is define exactly what you mean by "precisely" - all processors execute a series of instructions to do things. Viewed over a minute, they appear to be instantaneous, however, depending on the clock speed, each instruction takes a small period of time ... a "step". So, anything you tell it to do will take some number of steps - whether or not those "steps" are small enough to meet your "precisely" only you can determine, but there will be some jitter in your sample times because it will always require some steps to do what you want. Very careful hand assembly of code with interrupts disabled can create quite accurate times (as in repeatable), but that is probably more "precise" than what you want (or need). You have to define what the time limits are - within a ms or 5 microseconds or ???

Alright, thank you so much for your explanation.
So the solution for my problem is to use millis function.

Thank you all guys.
Have a nice week!

"So the solution for my problem is to use millis function."
Or micros()

This may help:

//Blink without Delay skeleton example using a structure.
//LarryD

//======================================================================
struct timer
{
  //lastMillis = the time this "timer" was (re)started
  //waitMillis = delay time (mS) we are looking for. You can use math 60*60*1000 for 1 hour
  //restart    = do we start "this timer" again and again  
  //enableFlag = is "this timer" enabled/allowed to be accessed
  //**********************
  //For each timer object you need: 
  //Example:
  //   timer myTimer = //give the timer a name "myTimer"
  //   {
  //     0, 200UL, true, true  //lastMillis, waitMillis, restart, enableFlag 
  //   };
  // You have access to: 
  // myTimer.lastMillis, myTimer.waitMillis, myTimer.restart, myTimer.enableFlag, myTimer.CheckTime() 
  //**********************

  unsigned long lastMillis; 
  unsigned long waitMillis; 
  bool          restart; 
  bool          enableFlag;
  
  bool CheckTime() //Delay time expired function "CheckTime()"
  {
    //is the time up for this task?
    if (enableFlag && millis() - lastMillis >= waitMillis) 
    //Note: if delays of < 2 millis are needed use micros() and adjust waitMillis as needed
    {
      //should this start again? 
      if(restart)
      {
        //get ready for the next iteration
        lastMillis += waitMillis;  
      }
      //time was reached
      return true;
    }
    //time was not reached
    return false;
  } //END of CheckTime()

}; //END of structure timer
//======================================================================


//**********************************************************************
//Let's create 6 timer objects and initialize them in this sketch
//**********************************************************************
timer pin13 = //create timer pin13
{
  0, 200UL, true, true //lastMillis, waitMillis, restart, enableFlag
};
//***************************
timer pin12 = //create timer pin12
{
  0, 3*1000UL, true, true //lastMillis, waitMillis, restart, enableFlag
};
//***************************
timer pin11 = //create timer pin11
{
  0, 10*1000UL, true, true //lastMillis, waitMillis, restart, enableFlag
};
//***************************
timer pin10 = //create timer pin10
{
  0, 6*1000UL, true, true //lastMillis, waitMillis, restart, enableFlag
};
//***************************
timer Toggle10 = //create timer Toggle10
{
  0, 50UL, true, true //lastMillis, waitMillis, restart, enableFlag
};
//***************************
timer checkSwitches = //create timer checkSwitches
{
  0, 50UL, true, true //lastMillis, waitMillis, restart, enableFlag
};
//***************************

byte lastMySwitchState = 1; //for mySwitch on Pin 2
byte counter           = 0; 

const byte Pin13 = 13;
const byte Pin12 = 12;
const byte Pin11 = 11;
const byte Pin10 = 10;
const byte Pin9  =  9;

const byte mySwitch = 2;

//**********************************************************************

void setup()
{
  Serial.begin(9600);

  pinMode(Pin13,OUTPUT);
  pinMode(Pin12,OUTPUT);
  pinMode(Pin11,OUTPUT);
  pinMode(Pin10,OUTPUT);
  pinMode(Pin9, OUTPUT);

  digitalWrite(Pin13,LOW);
  digitalWrite(Pin12,LOW);
  digitalWrite(Pin11,LOW);
  digitalWrite(Pin10,LOW);
  digitalWrite(Pin9, LOW);

  pinMode(mySwitch,INPUT_PULLUP);


} //  >>>>>>>>>>>>>> E N D  O F  s e t u p ( ) <<<<<<<<<<<<<<<<<


void loop()
{
  //Below are examples demonstrating different timing situations 

  //***************************
  //example 1    Toggle Pin13 every 200ms
  if (pin13.CheckTime())
  {
    //Toggle Pin13
    digitalWrite(Pin13,!digitalRead(Pin13));

    //if you only want this section of code to happen once
    //uncomment the next line 
    //pin13.enableFlag = false;
  }

  //***************************
  //example 2    After 3 seconds, Pin12 goes and stays HIGH 
  if (pin12.CheckTime())
  {
    //Make Pin12 HIGH now
    digitalWrite(Pin12,HIGH);
    //disable timing section of code 
    pin12.enableFlag = false;
  }

  //***************************
  //example 3    Pin11 is HIGH for 10 seconds, then goes and stays LOW
  if (pin11.enableFlag && !pin11.CheckTime())
  {
    digitalWrite(Pin11,HIGH);
  }
  //10 seconds is now up now, leave the Pin11 LOW
  else
  {
    digitalWrite(Pin11,LOW);
    //disable timing section of code 
    pin11.enableFlag = false;
  }

  //***************************
  //example 4    For 6 seconds, toggle Pin10
  if (pin10.enableFlag && !pin10.CheckTime())
  {
    //example 5  Toggling Pin10 every 50mS
    if(Toggle10.CheckTime())
    {  
      //toggle Pin10
      digitalWrite(Pin10,!digitalRead(Pin10));    
    }
  }
  //6 seconds is now up, toggling is stopped
  else
  {
    digitalWrite(Pin10,LOW);
    //disable timing section of code 
    pin10.enableFlag = false;
  }

  //***************************
  //example 6    Is it time to check the switches?
  if (checkSwitches.CheckTime())
  {
    //time to read the switches
    Switches();      
  } 

  //**********************************
  //Put other non-blocking stuff here
  //**********************************

} //  >>>>>>>>>>>>>> E N D  O F  l o o p ( ) <<<<<<<<<<<<<<<<<


//======================================================================
//                      F U N C T I O N S
//======================================================================


//**********************************************************************
//switches are checked every checkSwitches.waitMillis milli seconds 
//no minimum switch press time is validated with this code (i.e. No glitch filter)
void Switches()  
{
  boolean thisState; //re-usable for all the switches      

  //*************************** mySwitch Pin 2 code  
  //check if this switch has changed state
  thisState = digitalRead(mySwitch); 
  if (thisState != lastMySwitchState)
  {  
    //update the switch state
    lastMySwitchState = thisState;  

    //This switch position has changed, let's do some stuff

    //"HIGH condition code"
    //switch goes from LOW to HIGH
    if(thisState == HIGH)        
    {
      //example: LED on Pin9 is Push ON, Push OFF
      digitalWrite(Pin9,!digitalRead(Pin9)); 
    }

    //"LOW condition code"
    //switch goes from HIGH to LOW
    else                          
    {
      //example: display the current switch push count 
      Serial.println(++counter);      
    }
  } //END of mySwitch Pin 2 code

  //******************************************  
  //similar code for other switches goes here 
  //******************************************  

} //END of Switches()


//======================================================================
//                        E N D  O F  C O D E
//======================================================================

.

I'll look into your code.

Thank you so much! I am so thankful for your support, I greatly appreciate your help.
Have a nice week.