Automatic loop execution and termination

Hi guys, I want to have this code set to execute automatically at 8pm and then stop around 1am. I have no clue how to do this so I was wondering if someone would be so kind as to help me out?

long time;                                                                    // variable for speed debug
float pwmSpeed[14] = {
 0, 0, 1.2, 1.3, 1.4, 1.9, .9, .8, .5, 1.2, 1.37, 1.47, .3, 3.2};             // these constants set the rate of dimming
int pwmVal[14];                                                               // PWM values for 12 channels - 0 & 1 included but not used
float pwmFloats[14];
int i, j, k, l, x, y, z, bufsize, pot;                                        // variables for various counters

unsigned char sinewave[] =        //256 values
{
  0x80,0x83,0x86,0x89,0x8c,0x8f,0x92,0x95,0x98,0x9c,0x9f,0xa2,0xa5,0xa8,0xab,0xae,

  0xb0,0xb3,0xb6,0xb9,0xbc,0xbf,0xc1,0xc4,0xc7,0xc9,0xcc,0xce,0xd1,0xd3,0xd5,0xd8,

  0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xed,0xef,0xf0,0xf2,0xf3,0xf5,

  0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfc,0xfd,0xfe,0xfe,0xff,0xff,0xff,0xff,0xff,

  0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,0xfd,0xfc,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,

  0xf6,0xf5,0xf3,0xf2,0xf0,0xef,0xed,0xec,0xea,0xe8,0xe6,0xe4,0xe2,0xe0,0xde,0xdc,

  0xda,0xd8,0xd5,0xd3,0xd1,0xce,0xcc,0xc9,0xc7,0xc4,0xc1,0xbf,0xbc,0xb9,0xb6,0xb3,

  0xb0,0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9c,0x98,0x95,0x92,0x8f,0x8c,0x89,0x86,0x83,

  0x80,0x7c,0x79,0x76,0x73,0x70,0x6d,0x6a,0x67,0x63,0x60,0x5d,0x5a,0x57,0x54,0x51,

  0x4f,0x4c,0x49,0x46,0x43,0x40,0x3e,0x3b,0x38,0x36,0x33,0x31,0x2e,0x2c,0x2a,0x27,

  0x25,0x23,0x21,0x1f,0x1d,0x1b,0x19,0x17,0x15,0x13,0x12,0x10,0x0f,0x0d,0x0c,0x0a,

  0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x03,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,

  0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x05,0x06,0x07,0x08,

  0x09,0x0a,0x0c,0x0d,0x0f,0x10,0x12,0x13,0x15,0x17,0x19,0x1b,0x1d,0x1f,0x21,0x23,

  0x25,0x27,0x2a,0x2c,0x2e,0x31,0x33,0x36,0x38,0x3b,0x3e,0x40,0x43,0x46,0x49,0x4c,

  0x4f,0x51,0x54,0x57,0x5a,0x5d,0x60,0x63,0x67,0x6a,0x6d,0x70,0x73,0x76,0x79,0x7c

};


void setup(){
  Serial.begin(9600);
  DDRD=0xFC;      // direction variable for port D - make em all outputs except serial pins 0 & 1
  DDRB=0xFF;      // direction variable for port B - all outputs 

}

void loop(){

  // time = millis();               // this was to test the loop speed 
  // for (z=0; z<1000; z++){        // ditto

  //  pot = analogRead(0);          // this implemented a potentiometer speed control to control speed of fading

  for (y=0; y<14; y++){             // calculate one new pwm value every time through the control loop
    j = (j + 1) % 12;              // calculate a new j every time - modulo operator makes it cycle back to 0 after 11
    k = j + 2;                      // add 2 tp tje result - this yields a cycle of 2 to 13 for the channel (pin) select numbers

    pwmFloats[k] =  (pwmFloats[k] + pwmSpeed[k]);
    // pwmFloats[k] =  (pwmFloats[k] + ((pwmSpeed[k]  * 15 * (float)pot) / 1023));    // implements potentiometer speed control - see line above

      if (pwmFloats[k] >= 256){                  // wrop around sinewave table index values that are larger than 256
      pwmFloats[k] = pwmFloats[k] - 256;
    }
    else if  (pwmFloats[k] < 0){
      pwmFloats[k] = pwmFloats[k] + 256;        // wrop around sinewave table index values that are less than 0
    }

    pwmVal[k] = sinewave[(int)pwmFloats[k]];                   // convert the float value to an integer and get the value out of the sinewave index
  }

  PORTD = 0xFC;              // all outputs except serial pins 0 & 1
  PORTB = 0xFF;              // turn on all pins of ports D & B

for (z=0; z<3; z++){         // this loop just adds some more repetitions of the loop below to cut down on the time overhead of loop above
                             // increase this until you start to preceive flicker - then back off - decrease for more responsive sensor input reads
  for (x=0; x<256; x++){
    for( i=2; i<14; i++){    // start with 2 to avoid serial pins
      if (x == pwmVal[i]){
        if (i < 8){    // corresponds to PORTD
          // bitshift a one into the proper bit then reverse the whole byte
          // equivalent to the line below but around 4 times faster
          // digitalWrite(i, LOW);
          PORTD = PORTD & (~(1 << i));
        }   
        else{   
          PORTB = PORTB & (~(1 << (i-8)));         // corresponds to PORTB - same as digitalWrite(pin, LOW); - on Port B pins
        }

      }
    }
  }
}
  //    }
  //    Serial.println((millis() - time), DEC);     // speed test code

}

First suggestion would be to edit your post to use the # button in the toolbar and paste your code inside the tags it generates for you so people can more readily read your code. You'll probably find people are a lot happier to review your code without eyestrain. :wink:

Thanks for the tip! I'm new at this :slight_smile:

Welcome. So, to be clear, you're happy with the execution of the code you posted excepting the fact that you want to constrain it to certain hours of the day?

If you're running this attached to a PC then you need something on the PC to send the current time to the Arduino to let it know what time it has started at. If you're running this without the PC then you need to get yourself a battery-backed real-time clock - I believe the DS1307 is the clock of choice for Arduino's because there's a handy-dandy library for reading from it and writing to it.

If there are other problems with your code then a description of what the aberrant behavior and what the desired behavior are would be useful in helping you troubleshoot.

I'm happy with the code and I'm planning on running with a battery. Would it be possible to put it on a loop of 86,400,000 milliseconds (number of milliseconds in 24 hours) and specify when it should and shouldn't run?

millis() will overflow a couple times a day so your timekeeping routine will need to take that into account. The other problem is that your program won't know what time it is when it is started without some external time source. You could work around this by having it assume that it gets turned on at 6pm or whatever and start keeping time from there. The DS1307 will cost you a few bucks or you can try requesting an engineering sample to get one free.

millis() will overflow a couple times a day

According to the reference, "millis" returns an unsigned long, so will overflow every 232 / 1000 / 3600 / 24 = a little over 49 days.

Ok. Thanks everyone. Would someone be able to tell me how I could get the LED's to light for a given length of time then shut off for a given length of time and then loop so they are back on?

I thought I could insert another void loop() ending with a delay(10000); but that messed everything up.

According to the reference, "millis" returns an unsigned long, so will overflow every 232 / 1000 / 3600 / 24 = a little over 49 days.

You are in fact correct. The reference I was using was for Arduino 12 which overflowed at a bit over nine and a half hours. Mea culpa.

jeffd, I think this is the kind of thing you need. Start the program at 8pm and it should run for the first 5 hours out of every 24. It also wouldn't be too hard to modify it for other starting times.

Mikal

unsigned long time_counter = 0;
unsigned long prev_time = 0;

void setup()
{
  ...
}

// if you start this program at 8pm
// it should "do_my_thing()" everyday from 8pm to 1am

const unsigned long millis_per_hour = 60UL * 60UL * 1000UL;

void loop()
{
  unsigned long new_time = millis();
  time_counter += (new_time - prev_time);
  prev_time = new_time;
  if (time_counter < 5UL * millis_per_hour) // before 1 am?
    do_my_thing();
  else if (time_counter > 24UL * millis_per_hour) // 24 hours roll over?
    time_counter -= 24UL * millis_per_hour;
}

Thank you so much Mikal, this is such a great start! Do you think you could show me how to integrate your code into mine?

Sure, jeffd: just take your old loop() function in post #1 and rename it do_my_thing() so that your program looks like:

... your variable declarations
... my variable declarations (time_counter and prev_time)

void setup()
{
  ... your setup code
}

void do_my_thing()
{
  ... your old loop code
}

void loop()
{
  ... my loop from above
}

Mikal

Hey thanks a lot Mikal! I've got it running now to test it out.