How to write code to run program for 1 hour and cease for 1 hour, and keep going

Hi, I want to use Arduino as a function generator to output square wave. For example, it could output 1V 0.5Hz square wave for 1 hour and then stop for 1 hour, and then run for 1 hour ( and stop for 1 hour), repeat this circle for 24 hours.

I was wondering if anyone can help me to finish this code, especially about the circling part, at least give me a direction to learn?

Thank you very much!

Look at the BlinkWithoutDelay example

For 1V, you will need a couple of resistors to bring the 5V output down to 1V.

Vout = Vin * R2/(R1+R2) Select 1K for R2, solve for R1
1V = 5V * 1000/(R1 + 1000)
1VR1 + 10001V = 5V * 1000
R1 = (5V
1000 - 1V*1000)/1V = 4000

VoltageDivider.JPG

VoltageDivider.JPG

This sets the output pin HIGH for half of each second during odd-numbered hours.

void loop()
{
  unsigned long currentMillis = millis();
  unsigned long current_hour = currentMillis / (1000UL * 60UL * 60UL);
  unsigned long current_half_second = currentMillis / 500;

  // Turn on output only if hour and half_second are both EVEN numbers.
  if ((current_hour & 1) == 0 && (current_half_second & 1) == 0)
    digitalWrite(OutputPin, HIGH);
  else
     digitalWrite(OutputPin, LOW);
}

Too slow for tone() function, you can have a faster blink without delay running inside a faster blink without delay.
So maybe something like this.

unsigned long toneTimer;
unsigned long durationTimer;
unsigned long oneHour = 3600000; // 1000ms x 60 sec/min x 60 min/hr
unsigned long halfPeriod = 250; // one-fourth second
byte rumblePin = 2;
byte running = 1;
byte toneState = 0;

void setup(){
pinMode (rumblePin, OUTPUT);
}

void loop(){
currentTime = millis();
if ( (currentTime - durationTimer) >= oneHour ){ // change running state
running = 1 - running; // result is 1, 0, 1, 0
durationTimer = currentTime; // sets up next running state
}
if (running ==1){ 
if (currentTime - toneTimer >= halfPeriod){
toneState = 1 - toneState; // result is 1, 0, 1, 0, 
digitalWrite (rumblePin, toneState);
toneTimer = currentTime ; // sets up next toneState change
}
// do other stuff while those are trundling along keeping an eye on millis() for you.
}

Course, mine looks like it was written by a hardware engineer, not a software engineer :smiley:

Here's how I'd do the code..

#include "squareWave.h"
#include "blinker.h"


// First we start with creating a swithced waveform class out if the Legos we have avalible.
//
// switchedWave is a low frequency square wave that switches on and off a higher frequency
// square wave that  outputs on a digital pin.
//
// In the constructor you pass in..
// pin number for the resultant output wave form.
// The high freqency pulse width in ms
// The high freqency period in ms (high time + low time)
// The low freqency pulse width in ms
// The low freqency period in ms
//
// You start and stop the process by calling 
// setOnOff() with true or false for on & off.
//
class switchedWave :  public squareWave {

   public:
            switchedWave(int pin,float hfPulse,float hfPeriod,float lfPulse,float lfPeriod);
   virtual  ~switchedWave(void);

   virtual  void     pulseOn(void);
   virtual  void     pulseOff(void);

            blinker* hfWave;
};

// Contructor.
switchedWave::switchedWave(int pin,float hfPulse,float hfPeriod,float lfPulse,float lfPeriod)
   : squareWave(lfPeriod,lfPulse) { hfWave =  new blinker(pin,hfPulse,hfPeriod); }


// Destructor.
switchedWave::~switchedWave(void) { if (hfWave) delete(hfWave); }


// When LF pulse goes high, we tuen the HF waveform on.
void switchedWave::pulseOn(void) { hfWave->setOnOff(true); }


// When LF pulse goes high, we tuen the HF waveform off.
void switchedWave::pulseOff(void) { hfWave->setOnOff(false); }



// ***********************
// Sketch starts here.
// ***********************


// Create a switched wave object.
switchedWave ourWave(13,250,500,10000,20000);   // This gives 20 blinks for 10 seconds then 10 seconds with no blinks.

// For and hour on and an hour off try (13,250,500,3600000,7200000);

// 7,200,000 * 1000 = 7,200,000,000 microseconds.. Hmm I wonder if that's to many?


// In setup() switch it on.
void setup() {
   ourWave.setOnOff(true); // Fire it up.
}


// Call idle in loop(). Anything that runs in the background
// uses this. switchedWave would be one of those things.
void loop() {

   idle();     // Let me all have some idle time. 
}

Of course you'll need to grab LC_baseTools from the library manager. It has the bits that you use to put this together.

-jim lee

CrossRoads:
Course, mine looks like it was written by a hardware engineer, not a software engineer :smiley:

Thank you very much! That's really helpful!

johnwasser:
This sets the output pin HIGH for half of each second during odd-numbered hours.

void loop()

{
 unsigned long currentMillis = millis();
 unsigned long current_hour = currentMillis / (1000UL * 60UL * 60UL);
 unsigned long current_half_second = currentMillis / 500;

// Turn on output only if hour and half_second are both EVEN numbers.
 if ((current_hour & 1) == 0 && (current_half_second & 1) == 0)
   digitalWrite(OutputPin, HIGH);
 else
    digitalWrite(OutputPin, LOW);
}

I too wanted to stop my program after 1 hour or else.
Can I use this code but note that my program already use Millis(:))

Save the value of millis() when the program starts and set a boolean to true. Do this in setup(). Run the code in loop() only when the boolean is true. At the end of loop() test whether 1 hour has passed by subtracting the start time from the time now and if so, set the boolean to false and save the start time. When another hour has passed change the boolean to true

UKHeliBob:
Save the value of millis() when the program starts and set a boolean to true. Do this in setup(). Run the code in loop() only when the boolean is true. At the end of loop() test whether 1 hour has passed by subtracting the start time from the time now and if so, set the boolean to false and save the start time. When another hour has passed change the boolean to true

bool running = false;
unsigned long startMillis;  //some global variables available anywhere in the program
unsigned long currentMillis;
unsigned long period = 2000;

unsigned long periodx = 30000;

int ledPin1 = 10;
int ledPin2 = 12;//using the built in LED 
int ledPin4 = 13;

byte count = 0;
int led1_State = LOW;
int led2_State = LOW;

void setup() {
//  pinMode(LEDpin, OUTPUT);
  //digitalWrite(LEDpin, HIGH);
  pinMode(ledPin1, OUTPUT);
 pinMode(ledPin2, OUTPUT);
   startMillis = millis();
  running = true;
  //pinMode(switchPin, INPUT);
  //digitalWrite(switchPin, HIGH);  // turn on pullup resistor
}

void loop() {
   
     currentMillis = millis();  //get the current "time" (actually the number of milliseconds since the program started)


if (running == true){
  if (currentMillis - startMillis >= period) //test whether the period has elapsed
 {
  //increment a counter variable: 0 => 1 => 2 => 3
  count++;

  //When the counter reaches 4, reset back to 0.
  if(count == 4){
    count = 0;
  }
switch (count) {
  case 0:
    led1_State = HIGH;
    period = 300;// or whatever delay you want for this cycle
    break;
  case 1:
    led2_State = LOW;
    period = 300; // 200ms added  // or whatever delay you want for this cycle
    break;
  case 2:
    led2_State = HIGH;
    period = 300; // or whatever delay you want for this cycle
    break;
  case 3:
    led1_State = LOW;
    period = 300; // 200ms added      // or whatever delay you want for this cycle
    break;
}
digitalWrite(ledPin1, led1_State);
digitalWrite(ledPin2, led2_State);
startMillis = currentMillis;
 }
}

if (currentMillis - startMillis >= periodx){
  running == false;
  digitalWrite(ledPin1, led1_State);
  digitalWrite(ledPin2, led2_State);
startMillis = currentMillis;
}
}

i used bool variable but not worked with this code. i tried for 30 seconds to test it.

You must use a separate variable for “startMillis” in your second timer from the first one.

This...

 running == false;

Is a comparison, not an assignment.
Assignment is a single = sign.

To alternate between ON and OFF each hour you need to invert the state of running....

running = !running;

pcbbc:
You must use a separate variable for “startMillis” in your second timer from the first one.

This...

 running == false;

Is a comparison, not an assignment.
Assignment is a single = sign.

To alternate between ON and OFF each hour you need to invert the state of running....

running = !running;

ok thank you i am done after using separate startmillis. :slight_smile:
and i wanted to just stop after the required duration not to repeat after.
Actually i started my request for help in this topic not created by me but someone else requesting for 1 hiur duration and i was looking for the same
so my job is done with this thank you again :smiley: now millis(:D)

pcbbc:
You must use a separate variable for “startMillis” in your second timer from the first one.

bool running = false;
unsigned long startMillis;
 unsigned long startMillis2;
 //some global variables available anywhere in the program
unsigned long currentMillis;
unsigned long period = 2000;

unsigned long periodx = 30000;

int ledPin1 = 10;
int ledPin2 = 12;//using the built in LED
int ledPin4 = 13;

byte count = 0;
int led1_State = LOW;
int led2_State = LOW;

void setup() {
//  pinMode(LEDpin, OUTPUT);
  //digitalWrite(LEDpin, HIGH);
  pinMode(ledPin1, OUTPUT);
 pinMode(ledPin2, OUTPUT);
   startMillis = millis();
startMillis2 = millis();
  running = true;
  //pinMode(switchPin, INPUT);
  //digitalWrite(switchPin, HIGH);  // turn on pullup resistor
}

void loop() {
  
     currentMillis = millis();  //get the current "time" (actually the number of milliseconds since the program started)


if (running == true){
  if (currentMillis - startMillis >= period) //test whether the period has elapsed
 {
  //increment a counter variable: 0 => 1 => 2 => 3
  count++;

  //When the counter reaches 4, reset back to 0.
  if(count == 4){
    count = 0;
  }
switch (count) {
  case 0:
    led1_State = HIGH;
    period = 300;// or whatever delay you want for this cycle
    break;
  case 1:
    led2_State = LOW;
    period = 300; // 200ms added  // or whatever delay you want for this cycle
    break;
  case 2:
    led2_State = HIGH;
    period = 300; // or whatever delay you want for this cycle
    break;
  case 3:
    led1_State = LOW;
    period = 300; // 200ms added      // or whatever delay you want for this cycle
    break;
}
digitalWrite(ledPin1, led1_State);
digitalWrite(ledPin2, led2_State);
startMillis2 = currentMillis;
 }
}

if (currentMillis - startMillis >= periodx){
  running = false;
  digitalWrite(ledPin1, led1_State);
  digitalWrite(ledPin2, led2_State);
startMillis2 = currentMillis;
}
}

@pcbbc
I tried worked but program stops 10secs earlier
Instead of complete 30 secs. I used this code and corrected it see above :smiley: :slight_smile:

What is the point of startMillis2 as it is never compared with anything ?

UKHeliBob:
What is the point of startMillis2 as it is never compared with anything ?

It was to have a separate timer for this instruction as I have already used millis()
For other I will remove it and check again

Ooops. You forgot to change this “startMillis”...

 if (currentMillis - startMillis >= periodx){

:slight_smile: oh I will rectify it

It was to have a separate timer for this instruction as I have already used millis()

I guessed what it was for, hence my prompt that you had not used it

pcbbc:
Ooops. You forgot to change this “startMillis”...

 if (currentMillis - startMillis >= periodx){
const int ledPin1 = 10; // PCBBC suggestion
const int ledPin2 = 11;
const int ledPin3 = 12;
const int ledPin4 = 13;   // the pin numbers for the LEDs

int Reset = 4;
int Received = 0;
int count = 0;


unsigned long startMillis;  //some global variables available anywhere in the program
unsigned long startMillis2;
unsigned long currentMillis;
unsigned long period = 3000;  // number of millisecs that Motor is OFF
unsigned long periodx = 30000;
  
//------- VARIABLES (will change)

byte led1_State = LOW;             // used to record whether the LEDs are on or off
byte led2_State = LOW;           //   LOW = off
byte led3_State = LOW;          
byte led4_State = LOW;            // so that it can be activated (HIGH)by digitalWrite
bool running = false;

//=====
void setup() {
 Serial.begin(9600);
 
 //Serial.println("Starting SeveralThingsAtTheSameTimeRev1.ino");  // so we know what sketch is running
 
 //-------  set the Led pins as output:
 pinMode(ledPin1, OUTPUT);
 pinMode(ledPin2, OUTPUT);
 pinMode(ledPin3, OUTPUT);
 pinMode(ledPin4, OUTPUT);
 
 startMillis = millis();  //initial start time
 startMillis2 = millis();
 running = true;
 //=====
  digitalWrite(ledPin1, HIGH);
  digitalWrite(ledPin2, HIGH);
  digitalWrite(ledPin4, HIGH);   // deenergise relay to save power when microcontroller is powered ON.
  digitalWrite(ledPin3, HIGH);   // deenergise to enable manual mode as default.
  digitalWrite(Reset, HIGH);    // as  my relay is ACTIVE LOW. 
  delay(200);
  pinMode(Reset, OUTPUT);
  Serial.println("wait");
  
}

//=====
void loop()  {
  if (Serial.available()>0){
    Received = Serial.read();
  }
  
 currentMillis = millis();  //get the current "time" (actually the number of milliseconds since the program started)
 if (running == true){ 
 if (currentMillis - startMillis >= period) //test whether the period has elapsed
 {
  //increment a counter variable: 0 => 1 => 2 => 3
  count++;

  //When the counter reaches 4, reset back to 0.
  if(count == 4){
    count = 0;
  }
switch (count) {
  case 0:
    led1_State = HIGH;
    period = 3000; // or whatever delay you want for this cycle
    break;
  case 1:
    led2_State = LOW;
    period = 2200; // 200ms added  // or whatever delay you want for this cycle
    break;
  case 2:
    led2_State = HIGH;
    period = 3000; // or whatever delay you want for this cycle
    break;
  case 3:
    led1_State = LOW;
    period = 2200; // 200ms added      // or whatever delay you want for this cycle
    break;
}
//digitalWrite(ledPin1, led1_State);
//digitalWrite(ledPin2, led2_State);
startMillis = currentMillis;
 }
 }
 if (currentMillis - startMillis2 >= periodx){
  running = false;
 
  digitalWrite(ledPin1, LOW);
  digitalWrite(ledPin2, LOW);
  startMillis2 = currentMillis;
 }
  
if (Received == 'd'){
    led3_State = LOW; // to enable device mode.
    led4_State = LOW;
 digitalWrite(ledPin3, LOW);
 digitalWrite(ledPin4, LOW);
 }
  
 if (Received == 'b'){
  led3_State = HIGH;
  led4_State = HIGH;
  led1_State = HIGH;
  led2_State = HIGH;
  digitalWrite(ledPin3, HIGH);
  digitalWrite(ledPin4, HIGH);
  digitalWrite(ledPin1, HIGH);
  digitalWrite(ledPin2, HIGH);
  // digitalWrite(Reset, LOW);
   //digitalWrite(Reset, HIGH);
  
   }
   
 if (Received == '1'){
  
    
// this is the code that actually switches the LEDs on and off

 digitalWrite(ledPin1, led1_State);
 digitalWrite(ledPin2, led2_State);
// digitalWrite(ledPin3, led3_State);
// digitalWrite(ledPin4, led4_State);

 }
else if(Received == 'a'){
  digitalWrite(ledPin1, HIGH);
  digitalWrite(ledPin2, HIGH); // if not received anything keep all HIGH 
  digitalWrite(ledPin3, HIGH);
  digitalWrite(ledPin4, HIGH); //to deenergise relays being Active LOW.
  
}

 //-------- Program Reset both android app and arduino program. 
 if (Received == '9'){
   Serial.println("wait");
   digitalWrite(Reset, LOW);
   digitalWrite(Reset, HIGH);
   delay(200);
 }

 

}//===END===\\

yes the code works fine in simple led blink code with switch case but here in the above code (my original code)

it does not work at all.
do find issue with this otherwise your suggestions work good.