Simple timer to stop Loop and run a Scan Function every 60 mins??

Hey everybody I’m new at Arduino programming so I’m looking for a little help with getting a function to run once every hour.

I have code that runs in the loop constantly to point a solar panel at the brightest point in the sky.

I have another piece of code that drives a servo from 0 to 180 degrees and logs the brightest point in the sweep and then moves the servo to that brightest position. After this sweep happens the normal loop starts again.

I just want the simplest code to interrupt my loop every 60 mins to run a seek function and then back to the loop for another 60 mins.

I’m looking for some simple example code to follow, any help is greatly appreciated.

Here is the code I want to call to run once every 60 mins:

#include <Servo.h> 
 
Servo myservo;  
 
// Control and feedback pins
int servoPin = 9;
int feedbackPin = A0;
 
// Calibration values
int minDegrees = 0;
int maxDegrees = 180;
int minFeedback = 130;
int maxFeedback = 490;
int tolerance = 11; // max feedback measurement error
int pos = 0; 
int luxPin = A1;
int maxLuxReading = 0;
int maxLuxPosition = 0;



void Seek(Servo servo, int analogPin, int pos)
{
  // Start the move...
  servo.write(pos);
  
  // Calculate the target feedback value for the final position
  int target = map(pos, minDegrees, maxDegrees, minFeedback, maxFeedback); 
  
  // Wait until it reaches the target
  while(abs(analogRead(analogPin) - target) > tolerance){} // wait...
}
 
 
void setup() 
{ 
  myservo.attach(servoPin); 
   Serial.begin(9600);      // open the serial port at 9600 bps: 

} 
 
void loop()
{

  
for (pos = 0; pos < 180; pos += 5)
{
  Seek(myservo, 0, pos);
  int luxReading = analogRead(luxPin);                                  // take a sensor reading here...
  if (luxReading > maxLuxReading)
  {
      maxLuxReading = luxReading;
      maxLuxPosition = pos;
  }
  Serial.print("luxReading--    ");
  Serial.print(luxReading);
  Serial.print("   ");
  Serial.print("maxLuxPosition --    ");
  Serial.print(maxLuxPosition);
  Serial.print("   ");
  Serial.print("position--     ");
  Serial.print(pos);
  Serial.println();
  delay(400);
  
}

}

I have code that runs in the loop constantly to point a solar panel at the brightest point in the sky.

How often does the brightest point in the sky really change?

I'm looking for some simple example code to follow,

That would be the blink without delay example. It shows how to do something periodically.

How often does the brightest point in the sky really change?

The solar tracking loop uses 2 light sensors to position the panel at direct sunlight over the course of the day from sunrise to sunset and it works really good.

The Seek function becomes useful in the morning when the solar panel is sitting at the sunset position when the sun is coming up directly behind the panel. The seek function will run, log the brightest light reading and then reset the servo/solar panel to that brightest point in the sky in the morning.

Cloudy weather will cause the brightest point in the sky to constantly change.

That would be the blink without delay example. It shows how to do something periodically.

In the example it says that it will allow the loop to continue to run which will interfere with the sweep function. I need to loop to stop while the sweep function runs. Any other suggestions?

I need to loop to stop while the sweep function runs. Any other suggestions?

I don't understand this. On any given pass through loop(), you can make decisions. Is it time to do A? If so, do A. Is it time to do B? If so, do B. Do C on every pass.

The blink without delay function shows how to determine if it is time to do something.

Here is what was recommend to me:

http://playground.arduino.cc/Code/Timer

I think the best thing for what I'm trying to do is the following:

int every(long period, callback)

 Run the 'callback' every 'period' milliseconds.
 Returns the ID of the timer event.

I should replace the Long Period with my delay in Milliseconds.

And I should put my function name where the callback is currently. ??

So I just need to put the Scan code into a function that looks something like the code below outside the loop:

void  Scan()
{
Scan code
}

Does this look right to you?

You cannot really "stop" the loop() function.

What you can do, is every 60 minutes, get the loop function to call your other function

michinyon:
You cannot really "stop" the loop() function.

What you can do, is every 60 minutes, get the loop function to call your other function

How would you go about this?

While the other function is executing the main loop program will not try to run at the same time right?

How would you go about this?

PaulS, has suggested you look at Blink without delay

http://bit.ly/18YTtrL
OR
http://www.gammon.com.au/forum/?id=11411

LarryD:

How would you go about this?

PaulS, has suggested you look at Blink without delay

http://bit.ly/18YTtrL
OR
Gammon Forum : Electronics : Microprocessors : How to do multiple things at once ... like cook bacon and eggs

I have looked over it but I’m not wanting to turn LED’s on and off. I want the timer to trigger a new line of code.

Here is the loop portion of the blink without delay code.

unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis > interval) {
    // save the last time you blinked the LED 
    previousMillis = currentMillis;   

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);

If I wanted to toggle LED states then this would work just fine and I could run with it. Instead of changing LED states I want to run the following code when the timer has reached it target. I’m basically trying to combine one sketch to run once every hour, into another sketch that loops constantly except for when the scan function is triggered every hour.

I’m sure the solution is simple and right in front of my face but when your education on programming has just begun its kinda like having blinders on to all the different ways of doing what I am trying to do. I’ve been searching how to do this all day and been reading in my Arduino Cookbook for answers but its still eluding me.

Any help is appreciated.

Now here is a sketch that I want to run 1 time per hour. How in the world do I go about integrating this with the Blink Without Delay Function? How do I make this run instead of blinking LED’s?

#include <Servo.h> 
 
Servo myservo;  
 
// Control and feedback pins
int servoPin = 9;
int feedbackPin = A0;
 
// Calibration values
int minDegrees = 0;
int maxDegrees = 180;
int minFeedback = 130;
int maxFeedback = 490;
int tolerance = 11; // max feedback measurement error
int pos = 0; 
int luxPin = A1;
int maxLuxReading = 0;
int maxLuxPosition = 0;



void Seek(Servo servo, int analogPin, int pos)
{
  // Start the move...
  servo.write(pos);
  
  // Calculate the target feedback value for the final position
  int target = map(pos, minDegrees, maxDegrees, minFeedback, maxFeedback); 
  
  // Wait until it reaches the target
  while(abs(analogRead(analogPin) - target) > tolerance){} // wait...
}
 
 
void setup() 
{ 
  myservo.attach(servoPin); 
   Serial.begin(9600);      // open the serial port at 9600 bps: 

} 
 
void loop()
{

  
for (pos = 0; pos < 180; pos += 5)
{
  Seek(myservo, 0, pos);
  int luxReading = analogRead(luxPin);                                  // take a sensor reading here...
  if (luxReading > maxLuxReading)
  {
      maxLuxReading = luxReading;
      maxLuxPosition = pos;
  }

This may help:

#include <Servo.h> 
unsigned long currentMillis; 
unsigned long previousMillis;
unsigned long mydelay = (60*60*1000); //one hour

Servo myservo;  

// Control and feedback pins
int servoPin = 9;
int feedbackPin = A0;

// Calibration values
int minDegrees = 0;
int maxDegrees = 180;
int minFeedback = 130;
int maxFeedback = 490;
int tolerance = 11; // max feedback measurement error
int pos = 0; 
int luxPin = A1;
int maxLuxReading = 0;
int maxLuxPosition = 0;

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

void setup() 
{ 
  myservo.attach(servoPin); 
  Serial.begin(9600);      // open the serial port at 9600 bps: 
  previousMillis = millis(); //<<<<<<<<  Add this line

}    //***** END OF setup() *****

void loop()
{
  unsigned long currentMillis = millis();

  if(currentMillis - previousMillis > mydelay)
  {
    previousMillis = currentMillis; // get ready for next hour  
    yourfunction();  //Call the code you want to run every hour
  }
  // do other stuff if you want

}  //****** END OF loop() *****



void yourfunction()
{
  // put your code you want to run here




}  //***** END OF yourfunction() *****

I have looked over it but I'm not wanting to turn LED's on and off. I want the timer to trigger a new line of code.

What you do (turn an LED on if its off, turn an LED off if its on, or call some other code) is completely irrelevant. If it's time to take the action, it is time to take the action.

That is why we tell people to read, understand, and embrace the example. You seem to have stopped after the first step.

Three links from LEONARDOMILIANI.com that may be of help:
Let’s schedule our jobs with millis()
looper, a software scheduler for Arduino
leOS, a simple OS for Arduino
I really like the looper, easy to use.

PaulS:

I have looked over it but I'm not wanting to turn LED's on and off. I want the timer to trigger a new line of code.

What you do (turn an LED on if its off, turn an LED off if its on, or call some other code) is completely irrelevant. If it's time to take the action, it is time to take the action.

That is why we tell people to read, understand, and embrace the example. You seem to have stopped after the first step.

Your assuming that I know and understand more than I actually do about the Arduino language. I understand the first part of the timing example, its the calling some other code instead of blinking LED's that I'm needing help with.

You understand the programming language way better than I do so your advice makes sense to you but its still not very helpful or clear to me, the advice is to vague. I'm trying to learn as quickly as possible but its kinda like trying to learn Chinese from scratch, its not something that happens overnight.

I truly appreciate your efforts to help point me in the right direction regardless.

elac:
Three links from LEONARDOMILIANI.com that may be of help:
Let’s schedule our jobs with millis()
looper, a software scheduler for Arduino
leOS, a simple OS for Arduino
I really like the looper, easy to use.

Now the looper link does look like it will get me where I'm wanting to go. I'll give it a try and report back. Thanks for the links!

I/we cannot urge you enough to understand the blink without delay example.
If you fully understand it and use the technique in your future sketches you will become comfortable with the language.
Although using prewritten libraries is OK, you will only become proficient if you do things yourself.

That said, this is a bit cleaner, but hides the code that does all the work.

/*
Using the TimedAction library for the Arduino.
 */

#include <TimedAction.h>   //see: http://playground.arduino.cc/Code/TimedAction

TimedAction hourCode = TimedAction((60*60*1000UL),myCode);  //each 1 hour Call myCode

//==========================================================================
void setup()
{
  pinMode(13,OUTPUT);    //remove if not needed

}  //********* END OF setup()*********************

//==========================================================================
void loop()
{
  hourCode.check();      //is it time to run the hour code?


  // Other things to be done goes here  

}  //********* END OF loop()**********************


// Functions
//==========================================================================
void myCode()      //Code you want to run  
{
  PINB |= _BV(PINB5);       // for example, toggle digital pin D13 LED



}  // **** END OF myCode() ****




// ***********************************************
//                  END OF CODE
// ***********************************************

Take a look at these:

http://www.gammon.com.au/forum/?id=12153&page=999
http://learn.adafruit.com/category/learn-arduino

LarryD:
This may help:

#include <Servo.h> 

unsigned long currentMillis;
unsigned long previousMillis;
unsigned long mydelay = (60601000); //one hour

Servo myservo;

// Control and feedback pins
int servoPin = 9;
int feedbackPin = A0;

// Calibration values
int minDegrees = 0;
int maxDegrees = 180;
int minFeedback = 130;
int maxFeedback = 490;
int tolerance = 11; // max feedback measurement error
int pos = 0;
int luxPin = A1;
int maxLuxReading = 0;
int maxLuxPosition = 0;

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

void setup()
{
  myservo.attach(servoPin);
  Serial.begin(9600);      // open the serial port at 9600 bps:
  previousMillis = millis(); //<<<<<<<<  Add this line

}    //***** END OF setup() *****

void loop()
{
  unsigned long currentMillis = millis();

if(currentMillis - previousMillis > mydelay)
  {
    previousMillis = currentMillis; // get ready for next hour 
    yourfunction();  //Call the code you want to run every hour
  }
  // do other stuff if you want

}  //****** END OF loop() *****

void yourfunction()
{
  // put your code you want to run here

}  //***** END OF yourfunction() *****

Yes that did help, it actually allowed me to get the timer working using the milli timer instead of the other recommended libraries. It is rather simple, I just had to learn how to use it to call other functions instead of LED’s, which I have learned so thats a step in the right direction.

Here is the code that works:

#include <Servo.h> 
unsigned long currentMillis; 
unsigned long previousMillis;
unsigned long mydelay = (30*1000); //one hour


Servo myservo;  

// Control and feedback pins
int servoPin = 9;
int feedbackPin = A0;

// Calibration values
int minDegrees = 0;
int maxDegrees = 180;
int minFeedback = 130;
int maxFeedback = 490;
int tolerance = 11; // max feedback measurement error
int pos = 0; 
int luxPin = A5;
int maxLuxReading = 0;
int maxLuxPosition = 0;

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

void Seek(Servo servo, int analogPin, int pos)
{
  // Start the move...
  myservo.write(pos);
  
  // Calculate the target feedback value for the final position
  int target = map(pos, minDegrees, maxDegrees, minFeedback, maxFeedback); 
  
  // Wait until it reaches the target
  while(abs(analogRead(analogPin) - target) > tolerance){} // wait...
  
}   //***** END OF yourfunction() *****

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

void setup() 
{ 
  Serial.begin(9600);      // open the serial port at 9600 bps:
  myservo.attach(servoPin);  
  previousMillis = millis(); //<<<<<<<<  Add this line


}    //***** END OF setup() *****

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

void loop()
{
  unsigned long currentMillis = millis();

  if(currentMillis - previousMillis > mydelay)
  {
    previousMillis = currentMillis; // get ready for next hour  
    sweepForPeak();  //Call the code you want to run every hour
  }
  
  // do other stuff if you want

}  //****** END OF loop() *****

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


int sweepForPeak()
{
   for (pos = 0; pos < 180; pos += 5)
   {
    Seek(myservo, 0, pos);
    int luxReading = analogRead(luxPin);  // take a sensor reading here
    if (luxReading > maxLuxReading)
   {
      maxLuxReading = luxReading;
      maxLuxPosition = pos;
   }
  Serial.print("luxReading--    ");
  Serial.print(luxReading);
  Serial.print("   ");
  Serial.print("maxLuxPosition --    ");
  Serial.print(maxLuxPosition);
  Serial.print("   ");
  Serial.print("position--     ");
  Serial.print(pos);
  Serial.println();
  delay(400);
 
}
} 
//***** END OF yourfunction() *****

Now I just need to figure out how to drive the servo to the recorded maxLuxPosition after the sweepForPeak for loop finishes the full servo sweep.

Here is what I want the servo to do after the for loop has completed and before it reverts back to the void loop routine: Seek(myservo, 0, maxLuxPosition);

I can’t just use a 2nd timer because the times to make the servo do the full scan sweep will vary depending on outside weather conditions since it is powered by a solar panel. I’m using Analog Feedback servos to track the actual position of the servo and to make sure servo actually gets to the position we tell it to reach.

I guess my question is. "How do I make this code Seek(myservo, 0, maxLuxPosition); run once at the end of this for loop without calling a new function to do it?

int sweepForPeak()
{
   for (pos = 0; pos < 180; pos += 5)
   {
    Seek(myservo, 0, pos);
    int luxReading = analogRead(luxPin);  // take a sensor reading here
    if (luxReading > maxLuxReading)
   {
      maxLuxReading = luxReading;
      maxLuxPosition = pos;
   }
  Serial.print("luxReading--    ");
  Serial.print(luxReading);
  Serial.print("   ");
  Serial.print("maxLuxPosition --    ");
  Serial.print(maxLuxPosition);
  Serial.print("   ");
  Serial.print("position--     ");
  Serial.print(pos);
  Serial.println();
  delay(400);
 
}
} 
//***** END OF yourfunction() *****

LarryD:
Take a look at these:

Gammon Forum : Electronics : Microprocessors : Arduino programming traps, tips and style guide
Adafruit Learning System
Arduino Tutorials | tronixstuff.com

Arduino Cookbook [Book]
Amazon.com: Arduino for Teens: 9781285420899: Patterson, Robert, Patterson, Kathleen: Books
Amazon.com: Book on C, A: Programming in C: 9780201183993: Kelley, Al, Pohl, Ira: Books

Thank you LarryD! The first link really helped me out on understanding a few different important things. And one of those I found most helpful was written by PaulS on the contractor and subcontractor explanation of the purpose of the void loop and functions.

I also have the Arduino Cookbook which indeed is a good book.

Thanks Again!