why isn't it incrementing?

So I'm driving 6 rgb LEDs using three 74HC595, and have that working. And in my main loop I have a counter that simply increments so that it changes colour every time a delay time is reached, but my problem is the line of code that increments the counter doesn't work unless there is either a delay(x); before or after the increment, where x is any number (including 0). or a Serial.print("") before and after it.

example:

delay(0);
++counter;
  if( counter > 2 ){
    counter = 0;
  }

or

Serial.print( " before " );
++counter;
Serial.print( " after " );
  if( counter > 2 ){
    counter = 0;
  }

work, but

++counter;
if( counter > 2 ){
    counter = 0;
  }

doesn't
What is happening, because otherwise the counter stays at 2, and the rest of the loop seems to execute fine...

any help would be appreciated, even if it's some stupid error on my part.

Here's all of the code (minus the bounce method).
The code in question is about halfway through.
There are a few variable lying around (specifically the once about brightness and the TIME_DELAY_TYPE) which are unused.

#define NUM_RGB_LEDS 6
#define NUM_LEDS NUM_RGB_LEDS*3

const int latchPin = 3; // RCLK  (12)
const int clockPin = 4; // SRCLK (11)
const int dataPin  = 2; // SER   (14)
int data[NUM_LEDS];

typedef struct {
  int red;
  int green;
  int blue;
  byte redBrightness;
  byte greenBrightness;
  byte blueBrightness;
} LED_TYPE;

typedef struct {
  unsigned long dt, t;
  float timePassed;
  unsigned long delayTime;
  unsigned long f;
} TIME_DELAY_TYPE;

LED_TYPE leds[NUM_RGB_LEDS];

TIME_DELAY_TYPE fadeDelay;

int counter = 0;
unsigned long t;
float dt;
float timePassed;
unsigned long delayTime;
float f;

void setup() {
 
  pinMode( clockPin, OUTPUT );
  pinMode( latchPin, OUTPUT );
  pinMode( dataPin, OUTPUT );
  
  // Turn on all blue LEDs
  /* Use data array to set leds
  for( int i = 17; i >= 0 ; i-- ){
    if( (i+1)%3  == 0 )
      data[i] = 1;
    else
      data[i] = 0;
  }
  */
  
  // Use struct array to control LEDs
  leds[0].red   = 1;
  leds[1].green = 1;
  leds[2].blue  = 1;
  leds[3].red   = 1;
  leds[4].green = 1;
  leds[5].blue  = 1;  
  
  for( int i = 0; i < NUM_RGB_LEDS; i++ ){
    leds[i].redBrightness = 255;
    leds[i].greenBrightness = 255;
    leds[i].blueBrightness = 255;
  }
  
  // delayTime in millis
  delayTime = 250;
  
  Serial.begin( 115200 );
  Serial.println( "Ready" );
  
//  delay( 2000 );
  
  bounce( 1, 0, 25 );
  bounce( 1, 1, 25 );
  bounce( 1, 2, 25 );

  
}

void loop() {
 // Serial.print( delayTime );
 // Serial.print( "\t" );
  //Serial.print( timePassed );
 // Serial.print( "\t" );
  // On board !OE is LOW, !SRCLR is HIGH
  
  // By pulsing the clock pin ( SRCLK / Shift Register CLK ), 
  // The low to high transition shifts the data from the data pin.
  // (To take input from the pin, and move data across)
  
  // By pulsing the latch pin ( RCLK / Register CLK ),
  // The low to high transition shifts the data to the outputs
  // (Turns on the LEDs based on data entered using SRCLK and SER)
  // Use once every 18 clocks for 6 rgb LEDs
  delay(0);
  ++counter;
  if( counter > 2 ){
    counter = 0;
  }
  // delay without stopping everything
  // allows other code to run when this code isn't
  if( timePassed > delayTime ){
  //  Serial.print( "\t" );
  //  Serial.print( "IN?!?!" );
  //  Serial.print( "\t" );
    
    // If counter = 0 turn on red
    //            = 1         green
    //            = 2         blue
    for( int i = 0; i < NUM_RGB_LEDS; i++ ){
      if( counter == 0 ){
        setLED( i, 1, 0, 0);
      }
      else if( counter == 1 ){
        setLED( i, 0, 1, 0 );
      }
      else if( counter == 2 ){
        setLED( i, 0, 0, 1 );
      }
    }
    Serial.print( counter );
    Serial.print( "  " );
    Serial.println( timePassed );
    timePassed = 0;
  }// end delay if
  
  writeData();
  
  printFreq();
   
}

/*
 * The data array is sent in reverse order, as the data 
 * is pushed along as data is entered 
 *  R  G  B  R  G  B  R  G  B  R  G  B  R  G  B  R  G  B
 *  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
 */

// Pass an array NUM_LEDS bits long, then display based on the array
// The array is a global variable, along with leds, defined at the start
void writeData(){
  // Get values from LED_TYPE and enter into array to send
  for(int i = 0; i < NUM_RGB_LEDS; i++ ){
    data[ i*3 ]     = leds[i].red;
    data[ i*3 + 1 ] = leds[i].green;
    data[ i*3 + 2 ] = leds[i].blue;
  }
  
  // set latch pin low
  digitalWrite( latchPin, LOW );

  for( int i = NUM_LEDS - 1; i >= 0 ; i-- ){  // start loop
  // check value in data
  // if 1 then set data high
    if( data[i] == 1 )
      digitalWrite( dataPin, HIGH );
    else  // if 0 then set data low
      digitalWrite( dataPin, LOW );

  // clock
    digitalWrite( clockPin, HIGH );
    digitalWrite( clockPin, LOW );
    digitalWrite( dataPin, LOW );
  } // end loop
  // latch data (set latch pin high) 
  digitalWrite( latchPin, HIGH );
}


void setLED( int ledNum, int r, int g, int b ){
  leds[ ledNum ].red   = r;
  leds[ ledNum ].green = g;
  leds[ ledNum ].blue  = b;
}

/*
  NOTE: It seems that the Serial.print() functions takes a while to execute
        causing the whole code to take longer, also leave Serial to last in code
        as (especially when reading the time, micros() ) a discrepency made by waiting 
        until after Serial to check can cause timing errors.
        This was found as "t = micros();" in the following code was previously after 
        the Serial calls, causing timing errors.
 */
void printFreq(){
  dt = micros() - t;
  t = micros();
  f = 1/(dt/1000000);
//  Serial.print( "freq: " );
//  Serial.print( f );
//  Serial.print( "Hz\tdt: " );
//  Serial.print( dt );
//  Serial.println( "us" );
  
  timePassed += (dt/1000);
}

Just a shot in the dark but you might try turning down the baud rate from 115200 to 9600. No clue if it will do anything but I don't really see a need for it to be so high and it might be causing problems.

  delay(0);

Why? TakeYouTimeDoingNothing() until 0 milliseconds have elapsed. How can this possibly make sense?

The Serial.print() statements cause a short, intermittent, delay. If that is when your code actually works, then, clearly some delay is needed.

Your use of timePassed looks highly dodgy to me.

You're calculating it in a function who's name gives no clue that it does that, and you are updating the blink state regardless of whether it is time to update the display. It's quite likely this makes the state transition sequence depend on the precise timing of your loop - when it works, it only works by coincidence.

If you want your code to run at regular intervals, use the approach demonstrated in blink without delay to make that happen. What you're doing here looks like a very small change to the example sketch; instead of toggling an LED on and off, you need update a blink state and update the display. I'd suggest giving 'counter' a more meaningful name, use increment and modulo to update it and a switch statement to carry out the action associated with each state.

ookid - I changed the baud rate to 9600 and it doesn't change anything, the reason I have it so high was that I was playing around with it at one point and haven't changed it back. Also shouldn't it mean sending data at a higher rate taking less time?

PaulS - That's the thing, why doesn't it work without that there? it works when the delay(0) is there, or any other delay is there, but why? it's not really an issue now that I've found it but it seems to be a bit of an oddity.

PeterH - Really? timePassed is simply a variable that is (roughly) equivalent to currentMillis - previousMillis used in the blink without delay example, it times it correctly. And I do realise that the function name is no longer relevant, at one point it was, I just haven't been bothered to update the function name of it yet. However it doesn't just work "by coincidence", it took me a few tries to get it right, (mostly because of variable types, there's always infinite solutions to every problem with some better than others, I just picked one I came up with).

This is just a rough sketch, later on I might go through and fix names and such.

I tried moving the call to writeData() in the if, so that it is only called when the LED is changed, but again removing the delay(0) causes it to be erratic, but it does change. To show this here is some of the output. where the first number is the value of counter and the second value is the time passed since it was last checked (should roughly be the same as delayTime in this case is 250) in milliseconds.

0  250.05
2  250.01
1  250.02
0  250.08
0  250.09
2  250.07
1  250.04
0  250.06
2  250.03
2  250.12
0  250.02

and when the code is working as it should the output is as follows

0  250.13
2  250.06
1  250.07
0  250.13
2  250.09
1  250.11
0  250.16
2  250.11
1  250.11
0  250.12
2  250.13

The only difference between the two bit of code used to produce each output is when it is to get it working correctly is a delay(0) before counter is incremented and to get the erratic (first) the delay is commented out and writeData() is moved into the if.
working:

void loop() {
  delay(0);
  ++counter;
  if( counter > 2 ){
    counter = 0;
  }
  // delay without stopping everything
  // allows other code to run when this code isn't
  if( timePassed > delayTime ){
  //  Serial.print( "\t" );
  //  Serial.print( "IN?!?!" );
  //  Serial.print( "\t" );
    
    // If counter = 0 turn on red
    //            = 1         green
    //            = 2         blue
    for( int i = 0; i < NUM_RGB_LEDS; i++ ){
      if( counter == 0 ){
        setLED( i, 1, 0, 0);
      }
      else if( counter == 1 ){
        setLED( i, 0, 1, 0 );
      }
      else if( counter == 2 ){
        setLED( i, 0, 0, 1 );
      }
    }
    Serial.print( counter );
    Serial.print( "  " );
    Serial.println( timePassed );
    timePassed = 0;
//     writeData();
  }// end delay if
  
  writeData();
  
  printFreq();
   
}

erratic:

void loop() {

//  delay(0);
  ++counter;
  if( counter > 2 ){
    counter = 0;
  }
  // delay without stopping everything
  // allows other code to run when this code isn't
  if( timePassed > delayTime ){
  //  Serial.print( "\t" );
  //  Serial.print( "IN?!?!" );
  //  Serial.print( "\t" );
    
    // If counter = 0 turn on red
    //            = 1         green
    //            = 2         blue
    for( int i = 0; i < NUM_RGB_LEDS; i++ ){
      if( counter == 0 ){
        setLED( i, 1, 0, 0);
      }
      else if( counter == 1 ){
        setLED( i, 0, 1, 0 );
      }
      else if( counter == 2 ){
        setLED( i, 0, 0, 1 );
      }
    }
    Serial.print( counter );
    Serial.print( "  " );
    Serial.println( timePassed );
    timePassed = 0;
     writeData();
  }// end delay if
  
  printFreq(); //updates timePassed
   
}

I guess it's not really an issue now that I've found it and can work around it, but it's something that would be nice to know why it happens.
It should be reproducable without making the circuit as it doesn't rely on anything.

sketch_apr10a.cpp: In function 'void setup()':
sketch_apr10a:73: error: 'bounce' was not declared in this scope

the line of code that increments the counter doesn't work ...

How do you know? Incrementing counters always works.

However it doesn't just work "by coincidence", it took me a few tries to get it right, (mostly because of variable types

Yes it does.
A delay(0) is still a delay itis just indeterminate.
Your variable types are all wrong. They will compile but they are wrong.