Sketch slowing down... General noob proggie questions

Hey All,
I'm a noob, and I am now on the 3rd version of my project. It keeps getting better, so I guess I am getting the hang of it :wink: I am building an "analog" clock, with a pendulum...

I'm working with the Dream Pixels (self-contained RGB LED & LPD6803 controller, on a string), 72 pixels long.

thanks to a Moderator's coaxing, I've rebuilt some of my code to speed things up for the pendulum.

As I develop the sketch further, it's starting to bog down under some long 'if' statements.

I have a ton of these 'if' statements, and as I add more it gets slower - obviously - but much more than I expected.

What am I doing wrong?
Should all the stuff that gets done under true "if" conditions be turned into separate functions?

I did consider trying to construct an array, and then doing all the calcs into the array, but then I realized that I already am doing that, with the strip.SetPixel(x,x,x,x), AND i'd have not only the same calculations, but then I have to take more time just to transfer from my array into the array set up in the library.

I know the code is a bit messy, and possibly over-commented (is there such a thing?) but I'm still learning. I trimmed out some stuff from the code, just to keep it simper here. Mainly alarm-type colorful-swirly function calls during which time isn't displayed or calculated, and those functions are working properly anyway. So if you see a call to a function like "rainbowCycle()" or "colorUnwipe((r,g,b), x)" they exist, I just didn't post them.

(due to message limits I had to chop the code in half)
First, there are all the libraries and inits.
Then the main loop.

And with that, thanks in advance any and all feedback. This is a great community, indeed!

/*


This uses 71 LPD6803 pixels
 arduino Mega 
SPI in hardware mode - data = 51  clock = 52

added 4/12 -- rainbow qaurter routine with identical or rotating rainbow
              cleaned up pendulum routine and added a colorWipe to clear face after rainbowcycle
      4/18 -- built hourMarks routine, toggle, color by RGB settings, rainbow, and rainbow cycle
              built colorFadein and colorFadeout routines
              added to quarterMarks routine: toggle, color by RGB settings, rainbow, and rainbow cycle
              added options to select hour,min,sec colors via RGB setting
              added pendulum lag (zero'd for flashing on1st PedulumLED)
              
      4/21 -- built updated rainbow routines: 
                rainbowCycface  cycles face only, == around face
                rainbowCycpend  cycles pend only, == across pend
                rainbowCycboth  cycles face & pend == across both



*/ // end comments
//Pins 11 (hour), 12 (min) buttons


// Libraries
#include <TimerOne.h>          // TimerOne for PWM for LPD6803 library
#include <Neophob_LPD6803.h>   // LPD6803 library
#include <SPI.h>               // SPI Library
#include <Wire.h>              // Wire library
#include <Arduino.h>           // Arduino library

#define LED_MODULES 71            // # of LED's

Neophob_LPD6803 strip = Neophob_LPD6803(LED_MODULES);   // assign 'strip' to LPD6803 strip X LEDs long


// init pins for hour and minute buttons
const int hourButtonPin = 11;  const int minButtonPin = 12;


// init variables
    int hours = 4;  //   testing
    int minutes = 8; // testing
    int seconds = 25;
    int hundreds;
    
// init buttons
    int hourButtonState;  
    int minButtonState;
    
// init timing variables   
    long interval = 10;
    long previousMillis = 0;
    
// init startup variable    
    int tested = 0;
    
// init variable for 15-min displays tracking
    int fifteen = 0;

// init options
    
// ints timekeeping variables
    int LastMinute;
    int ThisMinute;

    unsigned long lastSecond;
    unsigned long thisSecond;
    
// ints sweep return for pendulum
    int SweepReturn;
    int pendulumLED;
    unsigned long pendulumDuration;

// ints quarterCounter
    int quarterCount;
    int quarterCounter;
    const int quarterStepper = 10;
    const int quarterMarks = 1;      //0 = off, 1 = hourR/G/B below, 2 = rainbow w/ qaurter
    const int quarterRainbow = 0;    // 0 = rainbows all quarters identical, 1 = wheels    
    const int quarterRed = 28;
    const int quarterGreen = 0;
    const int quarterBlue = 28;
  
// ints hourmarks
    int hourCount;
    int hourCounter;
    const int hourStepper = 10;
    const int hourMarks = 1;         // 0 = off, 1 = hourR/G/B below, 2 = rainbow w/ qaurter
    const int hourRainbow = 0;        // 0 = rainbows all hours identical, 1 = wheels
    const int hourBlinks = 1;        // blinks hourMarks @ blink rate
    const int hourRed = 1;          
    const int hourGreen = 0;
    const int hourBlue = 1;
  
// ints hour, min, sec colors
    int     hrColor [ ] = {31, 0, 0};
    int    minColor [ ] = { 0, 0,28};
    int    secColor [ ] = { 0,28, 0};
//    int hrRed, hrBlue, hrGreen, minRed, minBlue, minGreen, secBlue,secRed, secGreen;

    
// ints array to track of the pendulum LED to light up (L-->R-->L)
    int pendulumLight [ ] = {60,61,62,63,64,65,66,67,68,69,70,69,68,67,66,65,64,63,62,61,60};

// ints array for delay between pendulum lights (L-->R-->L)
// array contains time from LED to next LED, swing in both directions, defined in milliseconds:
//  int pendulumTime [ ] = {120, 95, 81, 68, 55, 47 , 55, 68, 81, 95,120, 95, 81, 68, 55, 47, 55, 68, 81, 95, 120}; 
    int pendulumTime [ ] = {140,110, 80, 60, 45, 35, 45, 60, 80,110,180,110, 80, 60, 45, 35, 45, 60, 80,110,120};
   
   

void setup()
{
  // configs strip and clears all LEDS
    strip.setCPUmax(90);
    strip.begin();
    strip.show();

  // start Wire
    Wire.begin();

// clear /EOSC bit
// Sometimes necessary to ensure that the clock
// keeps running on just battery power. Once set,
// it shouldn't need to be reset but it's a good
// idea to make sure.
    Wire.beginTransmission(0x68); // address DS3231
    Wire.write(0x0E); // select register
    Wire.write(0b00011100); // write register bitmap, bit 7 is /EOSC
    Wire.endTransmission();

// sets hr and min button pins to inputs
    pinMode(hourButtonPin,INPUT);
    hourButtonState = 0;

    pinMode(minButtonPin,INPUT);
    minButtonState = 0;
    
    
//
// startup display  -- for testing various effects as built -- 
    
    colorWipe(Color( 0, 0, 0),0);
     //strip.show();
     
 /*  rainbowCycle(5);
   rainbowCycle(5);
    
    colorWipe(Color( 26, 0, 0),20);
    delay(100);
     
    colorUnwipe(Color( 6, 6, 0),0);
    delay(100);
     
   colorWipe(Color( 0, 26, 0),20);
   delay(100);
     
   colorUnwipe(Color( 0, 6, 6),0);
   delay(100);
   
   colorWipe(Color( 0, 0, 26), 20);
   delay(100);
     
   colorUnwipe(Color( 0, 0, 0), 10);

   colorFadein(Color( 0, 0, 0), 60);
   colorFadeout(Color(31,31,31),60);
   colorFadein(Color( 0, 0, 0), 60);
   colorFadeout(Color(31,31,31),60);
   colorFadein(Color( 0, 0, 0), 60);
   colorFadeout(Color(31,31,31),60);

  // colorSpin(Color(31, 0, 0),10);
  // colorSpin(Color(31,31, 0),10);
  // colorSpin(Color( 0,31, 0),10);
  // colorSpin(Color( 0,31,31),10);
  // colorSpin(Color( 0, 0,31),10);

  // colorWipe(Color( 31,31,31),20);
  // colorWipe(Color(0,0,0),20);
  // delay(1000);
   
   //rainbowCycle(10);
*/   
   
   colorWipe((0,0,0),0);
   delay(250);
   rainbowCycface(25);
   delay(250);
   rainbowCycpend(25);
   delay(250);
   rainbowCycboth(25);
    }
The main loop


[code]
void loop()
  {

    

// high speed testing routine
//  delay(0);
    if (millis() >= lastSecond) 
      {
      lastSecond = lastSecond + 1000; 
      strip.setPixelColor(seconds, 0, 0, 0);
      strip.setPixelColor(minutes, 0, 0, 0);
      seconds++;
//      strip.show();
    }
    if (seconds > 59) {minutes++; seconds = 0;}
    if (minutes > 59) {hours++; minutes = 0; seconds = 0;}
  
  
/*    
//  request time
//  send request to receive data starting at register 0
      Wire.beginTransmission(0x68); // 0x68 is DS3231 device address
      Wire.write(byte(0)); // start at register 0
      Wire.endTransmission();
      Wire.requestFrom(0x68, 3); // request three bytes (seconds, minutes, hours)
  
      while(Wire.available())
      {
        seconds = Wire.read(); // get seconds
        minutes = Wire.read(); // get minutes
        hours = Wire.read(); // get hours

    // convert BCD to decimal
        
        seconds = (((seconds & 0b11110000)>>4)*10 + (seconds & 0b00001111)); // convert BCD to decimal
        minutes = (((minutes & 0b11110000)>>4)*10 + (minutes & 0b00001111)); // convert BCD to decimal
        hours = (((hours & 0b00110000)>>4)*10 + (hours & 0b00001111)); // convert BCD to decimal (assume 24 hour mode)
      
*/

// show 12,3,6,9 marks


    if (quarterMarks == 2) 
    {
      quarterCounter = quarterCounter +1;
      if ( quarterCounter > quarterStepper )
        { quarterCounter = 0; 
          quarterCount++; }
        
      if ( quarterCount > 96)
        {quarterCount = 0;}

      strip.setPixelColor( 0, Wheel( (( ( 0 * quarterRainbow) * 96 / strip.numPixels()) + quarterCount) % 96) );
      strip.setPixelColor(15, Wheel( (( (15 * quarterRainbow) * 96 / strip.numPixels()) + quarterCount) % 96) );
      strip.setPixelColor(30, Wheel( (( (30 * quarterRainbow) * 96 / strip.numPixels()) + quarterCount) % 96) );
      strip.setPixelColor(45, Wheel( (( (45 * quarterRainbow) * 96 / strip.numPixels()) + quarterCount) % 96) );

    }
    
      if (quarterMarks == 1)
      {
      strip.setPixelColor( 0, (quarterBlue && seconds!= 0), (quarterRed && seconds!= 0), (quarterGreen && seconds!= 0) );
      strip.setPixelColor(15, (quarterBlue && seconds!=15), (quarterRed && seconds!=15), (quarterGreen && seconds!=15) );
      strip.setPixelColor(30, (quarterBlue && seconds!=30), (quarterRed && seconds!=30), (quarterGreen && seconds!=30) );
      strip.setPixelColor(45, (quarterBlue && seconds!=45), (quarterRed && seconds!=45), (quarterGreen && seconds!=45) );
      }
        
// show hourMarks

if (hourMarks == 2 ) 
    {
      hourCounter = hourCounter +1;
      if ( hourCounter > hourStepper )
        {
          hourCounter = 0; 
          hourCount++; 
        }
        
      if ( hourCount > 96)
         {
          hourCount = 0;
        }

      strip.setPixelColor( 5, Wheel( (( (( 5 * hourRainbow) * 96 / strip.numPixels()) + hourCount) % 96)) );
      strip.setPixelColor(10, Wheel( (( ((10 * hourRainbow) * 96 / strip.numPixels()) + hourCount) % 96)) );
      strip.setPixelColor(20, Wheel( (( ((20 * hourRainbow) * 96 / strip.numPixels()) + hourCount) % 96)) );
      strip.setPixelColor(25, Wheel( (( ((25 * hourRainbow) * 96 / strip.numPixels()) + hourCount) % 96)) );
      strip.setPixelColor(35, Wheel( (( ((35 * hourRainbow) * 96 / strip.numPixels()) + hourCount) % 96)) );
      strip.setPixelColor(40, Wheel( (( ((40 * hourRainbow) * 96 / strip.numPixels()) + hourCount) % 96)) );
      strip.setPixelColor(50, Wheel( (( ((50 * hourRainbow) * 96 / strip.numPixels()) + hourCount) % 96)) );
      strip.setPixelColor(55, Wheel( (( ((55 * hourRainbow) * 96 / strip.numPixels()) + hourCount) % 96)) );
      
    }
    if (hourMarks == 1)
    {
      strip.setPixelColor( 5, hourBlue, hourRed, hourGreen );
      strip.setPixelColor(10, hourBlue, hourRed, hourGreen );
      strip.setPixelColor(20, hourBlue, hourRed, hourGreen );
      strip.setPixelColor(25, hourBlue, hourRed, hourGreen );
      strip.setPixelColor(35, hourBlue, hourRed, hourGreen );
      strip.setPixelColor(40, hourBlue, hourRed, hourGreen );
      strip.setPixelColor(50, hourBlue, hourRed, hourGreen );
      strip.setPixelColor(55, hourBlue, hourRed, hourGreen );
    }

// calc and rainbowCycle :15 alarms includes resetting the toggle 1 minute later

// runs alarm animation 4x on the hour
  if ( ( minutes == 0 ) && ( fifteen == 0 ) )
    {
      rainbowCycle(30); // rainbowCycle(30); rainbowCycle(30); rainbowCycle(30);
      fifteen++;
    }
// runs alarm animation 2x on the half hour
  if ( ( minutes == 30 ) && ( fifteen == 0 ) )
    {
      rainbowCycle(30); rainbowCycle(30);
      fifteen++;
    }
// runs alarm animation once on :15 & :45
  if ( ( minutes == 15 || minutes == 45 ) && ( fifteen == 0 ) )
    {
      rainbowCycle(30);
      fifteen++;
    }
//resets fifteen on :01, :16, :31, :46
  if ( ( minutes == 1 ) || ( minutes == 16 ) || ( minutes == 31 ) || ( minutes == 46 ) )
    {
      fifteen = 0;
    }
  
  
// Hours, Mins, Seconds calc + pixel-set
        
// converts 12hr time to 12 hr time
      if ( hours > 11 ) 
        { hours = hours - 12 ; }
      
// calc + pixel-set for center hour mark only if not on 12,3,6,9      
      if( (hours != 0) && ( hours != 3 ) && ( hours != 6 ) && ( hours != 9 ) ) 
             { strip.setPixelColor( hours*5, 28, 0, 0); }         
             
             
// calc & pixel-set for hour mark -1, except at 12:00.
      if (hours > 0) 
            { strip.setPixelColor((hours*5)-1, 8, 0, 0); }
            
            
//  sets hour-1 pixel when at 12:00 for led59
      else 
            {strip.setPixelColor( 59, 8, 0, 0); }
            
// sets hour+1 pixel always
             strip.setPixelColor( (hours*5)+1, 8, 0, 0);   
      
      
    
// sets minutes
        strip.setPixelColor( minutes, 0, 0,20); 

// sets seconds
        strip.setPixelColor( seconds, 0,20, 0); 
//     
//pendulum routine
   
   if (millis() >= pendulumDuration)
   {
     if(pendulumLED > 1)  // turn off prior LED
     {
      strip.setPixelColor(pendulumLight[pendulumLED-2], 0, 0, 0);
     }
  if(pendulumLED >0) 
     {
      strip.setPixelColor(pendulumLight[pendulumLED-1], 3, 2, 1);
     }
strip.setPixelColor(pendulumLight[pendulumLED]  , 6, 5, 4);


// set for next led
pendulumLED = pendulumLED+1;

// if back at start, reset the counter 
if (pendulumLED == 22){ pendulumLED = 0; } // LEDs, back & forth: 0-1-2-3-4-5-6-7-8-9-10-9-8-7-6-5-4-3-2-1

// turn on the next LED
strip.setPixelColor(pendulumLight[pendulumLED], 31, 30, 25);
//strip.setPixelColor(pendulumLight[pendulumLED], Wheel(  ( pendulumLED * 96 / strip.numPixels()) + pendulumLED) % 96);

// set the time to watch for the next change
pendulumDuration = pendulumDuration + pendulumTime[pendulumLED];
   
   
   
// show all LEDs

      strip.show();
      
      
} // end of main loop

      
      }


  


// Create a 15 bit color value from R,G,B
unsigned int Color(byte g, byte b, byte r)
{
  //Take the lowest 5 bits of each value and append them end to end
  return( ((unsigned int)g & 0x1F )<<10 | ((unsigned int)b & 0x1F)<<5 | (unsigned int)r & 0x1F);
}


//Input a value 0 to 127 to get a color value.
//The colours are a transition r - g -b - back to r
unsigned int Wheel(byte WheelPos)
{
  byte r,g,b;
  switch(WheelPos >> 5)
  {
    case 0:
      r=31- WheelPos % 32;   //Red down
      g=WheelPos % 32;      // Green up
      b=0;                  //blue off
      break; 
    case 1:
      g=31- WheelPos % 32;  //green down
      b=WheelPos % 32;      //blue up
      r=0;                  //red off
      break; 
    case 2:
      b=31- WheelPos % 32;  //blue down 
      r=WheelPos % 32;      //red up
      g=0;                  //green off
      break; 
  }
  return(Color(r,g,b));
}

[/code]

Clearly, all that commented out code has nothing to do with your problem, so, why did you take two posts to post it? Delete it, so we can concentrate on the code that is actually related to the problem.

GoolGaul:
As I develop the sketch further, it's starting to bog down under some long 'if' statements.

I have a ton of these 'if' statements, and as I add more it gets slower - obviously - but much more than I expected.

What am I doing wrong?

What are the symptoms of it "bogging down"?

funky LED flickers and some glitchy second-advances. It's consistent flickering when the second hand is on calculated points -- :00, :15, :30, :45, -- with :00 having the most flicker, and :45 having the least

sorry about all the comments. Since I'm obviously doing something incorrectly or inefficiently, the comments might help peeps see what I am trying to do.

What is a "proggie"? My English isn't very good so I'm not familiar with it, except that it sounds like the food popular in Poland. I'm not sure what they would have to do with electronics.

GoolGaul:
As I develop the sketch further, it's starting to bog down under some long 'if' statements.

The Arduino / ATmega328 doesn't get slower the more code you add, unless that code slows down execution. This usually happens because either a) you've added so many delays it causes things to actually slow down or 2) code starts doing unexpected things.

For example...

      while(Wire.available())
        seconds = Wire.read(); // get seconds
        minutes = Wire.read(); // get minutes
        hours = Wire.read(); // get hours

This is interesting. What if Wire.available() only returns 1? In that case there is 1 byte available and you read 3. See a problem there? Or after on iteration of the while() loop another byte is available. All of the previous values will get destroyed. (Hint read the very first sentence of the Wire.available reference page.)

If you keep adding if-statements and more of those if-statements are true during execution, one would expect things to slow down. Especially if that code contains slow processes (like delay).

I stayed away from using delay() statements in my main loop, that is what the pendulum arrays are for, to just watch the time go by, and do something at (or after) xxxx milliseconds.

the "Wire.read" statements aren't the issue, as the issues occur regardless of whether that section of code is active or commented out.

I think the problem is the number of IF's and (possibly of bigger concern) the true actions that follow...

are there any more effective ways of coding those all those conditional statements?
(switch/case doesn't seem to apply to all those conditions)

I started reviewing the code to try to figure out what it was supposed to do, but life's too short. There seem to be umpteen mode flags and counters all doing non-obvious things. I would not be at all surprised if your different logic sections were conflicting with each other and trying to apply different outputs to the same LEDs, but it'd take more time than I can spare to figure out where.

Does it really need to be that complex? What's it supposed to do?

PeterH:
I started reviewing the code to try to figure out what it was supposed to do, but life's too short. There seem to be umpteen mode flags and counters all doing non-obvious things. I would not be at all surprised if your different logic sections were conflicting with each other and trying to apply different outputs to the same LEDs, but it'd take more time than I can spare to figure out where.

Does it really need to be that complex? What's it supposed to do?

I am positive that there are no conflicts writing to the LED's, I commented out parts to test that, VERY thoroughly.
To answer your questions:
The latter; It's a clock. 60 RGB LEDS plus an 11 LED "pendulum" I am trying to set up options: Hour/Min/Sec LED colors, and to toggle always-lit marks at 12,3,6,9 only, and marks at every hour.

to answer the former question: now that you ask, it really doesn't need to be that complex.
I could do away with the options, and pare it down to bare minimum.

thanks for the wake-up-call. it doesn't need to be that complex.

Now that you have some functionality it is time to concede that your code has become a bunch of patches rather than a nice logical progression of instructions.

it is time to follow A suggestion from Charles H Moore (creator of Forth) - throw your code away (don't try to use this as it is not quite working and doesn't need more patching) and start over. You have sen some things that work and some things that don't. You have more experience that you had when you started. A clean start with some planning (system analysis - fancy CompSci term for doing some planning) and the next iteration will work much better.

While it doesn't win points in CompSci can you define anything that is now a variable as a constant? Move as much stuff to compile time and away from execution time. A constant uses less memory fetches.

I have thrown away my code twice already. It's great advice.

I was able to build the core programming for my clock to run nice and smooth, then I started to add some optional things, and that is where it started to slow down.

I'll be cutting out some of the things I added.

And thanks for the constants tip. most of my variables could be re-defined as constants.

GoolGaul:
I am positive that there are no conflicts writing to the LED's, I commented out parts to test that, VERY thoroughly.

And yet the symptoms you describe below suggest quite strongly that is happening:

GoolGaul:
funky LED flickers and some glitchy second-advances. It's consistent flickering when the second hand is on calculated points -- :00, :15, :30, :45, -- with :00 having the most flicker, and :45 having the least