grade my first sketch

I am making a flasher for a sign. this is just test code the final unit will use a mega and control 60 lights.

it is functioning and the only glitch is that it once in a while misses the button press .
I am guessing this is because of the way i tried to use noInterrupts() to debounce the button

the pattern functions followTheLeader() and centerBloom() could be done better and I plan to fix them
but some of the patterns he wants will have to be written this way.

I'd like to get input on any mistakes made or suggestions to improve it.

 /* 
 Greg's Flasher
       flasher unit for greg's antique sign
  Les Hawkins     May 2015
 */
 

 int ledPins[] = {3,4,5,6,7};                 // Array to assign led pins
 int pot = A0;                                // analog pin for speed adjustment
 int potValue = 0;                            // variable for analog pin reading
 int button = 0;                              // button on interrupt 0 (digital pin 2)
 volatile int pattern = 0;                    // variable that is used during interrupt

 void setup(){
  
   for(int index = 0; index <= 4; index++){   // count ledPins
   pinMode(ledPins[index],OUTPUT);            // initiailize ledPins
  }
  attachInterrupt (button ,patChange , RISING); // interrupt
 }

 void patChange(){                            // interrupt handler
  
   noInterrupts();                               // my attempt to debounce button
   pattern = pattern+1;                       // change to next pattern
   if (pattern >= 2) pattern = 0;             // restart the cycle when complete
      
 }

 void loop(){
  
  switch (pattern) {                          // state machine to change patterns
   case 0:
     followTheLeader();
     break;
   case 1:
     centerBloom();
     break;
   case 2:
    
     break;
   case 3:
    
     break;
   case 4:
    
     break;
   case 5:
    
     break;
  } 
   interrupts();                                     // my attempt to debounce button
   delay(400);
   
 }
 
 void potRead(){
  
  potValue = analogRead(pot);                 // read potentiometer
  potValue = map(potValue, 0, 1023, 50, 750); // map acceptable range
 }
 
 void followTheLeader(){                      // Light up all the LEDs in turn then shut them off in turn
  
   potRead();
   digitalWrite(ledPins[0], HIGH);            // Turns on LED #0 (pin 3)
   delay(potValue);                           // wait delayTime milliseconds
   digitalWrite(ledPins[1], HIGH);            // Turns on LED #1 (pin 4)
   delay(potValue);                           // wait delayTime milliseconds
   digitalWrite(ledPins[2], HIGH);            // Turns on LED #2 (pin 5)
   delay(potValue);                           // wait delayTime milliseconds
   digitalWrite(ledPins[3], HIGH);            // Turns on LED #3 (pin 6)
   delay(potValue);                           // wait delayTime milliseconds
   digitalWrite(ledPins[4], HIGH);            // Turns on LED #4 (pin 7)
   // delay(potValue);                        // wait delayTime milliseconds
  
   potRead();
   digitalWrite(ledPins[0], LOW);             // Turn off LED #0 (pin 3)
   delay(potValue);                           // wait delayTime milliseconds
   digitalWrite(ledPins[1], LOW);             // Turn off LED #1 (pin 4)
   delay(potValue);                           // wait delayTime milliseconds
   digitalWrite(ledPins[2], LOW);             // Turn off LED #2 (pin 5)
   delay(potValue);                           // wait delayTime milliseconds
   digitalWrite(ledPins[3], LOW);             // Turn off LED #3 (pin 6)
   delay(potValue);                           // wait delayTime milliseconds
   digitalWrite(ledPins[4], LOW);             // Turn off LED #4 (pin 7)
   delay(potValue);                           // wait delayTime milliseconds
  }
 
 void centerBloom(){                          // start in center expand then contract
 
   potRead();
   digitalWrite(ledPins[2], HIGH);            // Turns on LED #2 (pin 5)
   delay(potValue);                           // wait delayTime milliseconds
   digitalWrite(ledPins[1], HIGH);            // Turns on LED #1 (pin 4)
   digitalWrite(ledPins[3], HIGH);            // Turns on LED #3 (pin 6)
   delay(potValue);                           // wait delayTime milliseconds
   digitalWrite(ledPins[0], HIGH);            // Turns on LED #0 (pin 3)
   digitalWrite(ledPins[4], HIGH);            // Turns on LED #4 (pin 7)
   potRead();
   delay(potValue*2);                         // wait delayTime milliseconds *3
   
   potRead();
   digitalWrite(ledPins[0], LOW);             // Turn off LED #0 (pin 3)
   digitalWrite(ledPins[4], LOW);             // Turn off LED #4 (pin 7)
   delay(potValue);                           // wait delayTime milliseconds
   digitalWrite(ledPins[1], LOW);             // Turn off LED #1 (pin 4)
   digitalWrite(ledPins[3], LOW);             // Turn off LED #3 (pin 6)
   delay(potValue);                           // wait delayTime milliseconds
   digitalWrite(ledPins[2], LOW);             // Turn off LED #2 (pin 5)
   potRead();
   delay(potValue*3);                         // wait delayTime milliseconds *3
 }
 void patChange(){                            // interrupt handler
 
   noInterrupts();                               // my attempt to debounce button

Interrupts are off in an ISR anyway, so this won't do anything useful.

You need a better debounce.

I'm becoming convinced that the best way to debounce a switch is to put a capacitor across it. Software be bounce is way more trouble than its worth, and never fails to fail the "Uh. Didn't think of that." test.

Thanks guys
popped a cap in it haha
seems to work better
anything else?

int ledPins[] = {3,4,5,6,7};

Do you ever expect to see the day when you've got an Arduino with 32767 pins?
Or pins with negative numbers?
Do you plan on changing these values whilst the sketch is running?

ok I saved 214 bytes program storage space and 11 bytes memory by changing 4 variable types
Thanks AWOL

updated code

 /* 
 Greg's Flasher
       flasher unit for greg's antique sign
  Les Hawkins     May 2015
 */
 

 const byte ledPins[] = {3,4,5,6,7};                 // Array to assign led pins
 const byte pot = A0;                                // analog pin for speed adjustment
 int potValue = 0;                            // variable for analog pin reading
 const byte button = 0;                              // button on interrupt 0 (digital pin 2)
 volatile byte pattern = 0;                    // variable that is used during interrupt

 void setup(){
  
   for(int index = 0; index <= 4; index++){   // count ledPins
   pinMode(ledPins[index],OUTPUT);            // initiailize ledPins
  }
  attachInterrupt (button ,patChange , RISING); // interrupt
 }

 void patChange(){                            // interrupt handler
   pattern = pattern+1;                       // change to next pattern
   if (pattern >= 2) pattern = 0;             // restart the cycle when complete
      
 }

 void loop(){
  
  switch (pattern) {                          // state machine to change patterns
   case 0:
     followTheLeader();
     break;
   case 1:
     centerBloom();
     break;
   case 2:
    
     break;
   case 3:
    
     break;
   case 4:
    
     break;
   case 5:
    
     break;
  } 

   delay(400);
   
 }
 
 void potRead(){
  
  potValue = analogRead(pot);                 // read potentiometer
  potValue = map(potValue, 0, 1023, 50, 750); // map acceptable range
 }
 
 void followTheLeader(){                      // Light up all the LEDs in turn then shut them off in turn
  
   potRead();
   digitalWrite(ledPins[0], HIGH);            // Turns on LED #0 (pin 3)
   delay(potValue);                           // wait delayTime milliseconds
   digitalWrite(ledPins[1], HIGH);            // Turns on LED #1 (pin 4)
   delay(potValue);                           // wait delayTime milliseconds
   digitalWrite(ledPins[2], HIGH);            // Turns on LED #2 (pin 5)
   delay(potValue);                           // wait delayTime milliseconds
   digitalWrite(ledPins[3], HIGH);            // Turns on LED #3 (pin 6)
   delay(potValue);                           // wait delayTime milliseconds
   digitalWrite(ledPins[4], HIGH);            // Turns on LED #4 (pin 7)
   // delay(potValue);                        // wait delayTime milliseconds
  
   potRead();
   digitalWrite(ledPins[0], LOW);             // Turn off LED #0 (pin 3)
   delay(potValue);                           // wait delayTime milliseconds
   digitalWrite(ledPins[1], LOW);             // Turn off LED #1 (pin 4)
   delay(potValue);                           // wait delayTime milliseconds
   digitalWrite(ledPins[2], LOW);             // Turn off LED #2 (pin 5)
   delay(potValue);                           // wait delayTime milliseconds
   digitalWrite(ledPins[3], LOW);             // Turn off LED #3 (pin 6)
   delay(potValue);                           // wait delayTime milliseconds
   digitalWrite(ledPins[4], LOW);             // Turn off LED #4 (pin 7)
   delay(potValue);                           // wait delayTime milliseconds
  }
 
 void centerBloom(){                          // start in center expand then contract
 
   potRead();
   digitalWrite(ledPins[2], HIGH);            // Turns on LED #2 (pin 5)
   delay(potValue);                           // wait delayTime milliseconds
   digitalWrite(ledPins[1], HIGH);            // Turns on LED #1 (pin 4)
   digitalWrite(ledPins[3], HIGH);            // Turns on LED #3 (pin 6)
   delay(potValue);                           // wait delayTime milliseconds
   digitalWrite(ledPins[0], HIGH);            // Turns on LED #0 (pin 3)
   digitalWrite(ledPins[4], HIGH);            // Turns on LED #4 (pin 7)
   potRead();
   delay(potValue*2);                         // wait delayTime milliseconds *3
   
   potRead();
   digitalWrite(ledPins[0], LOW);             // Turn off LED #0 (pin 3)
   digitalWrite(ledPins[4], LOW);             // Turn off LED #4 (pin 7)
   delay(potValue);                           // wait delayTime milliseconds
   digitalWrite(ledPins[1], LOW);             // Turn off LED #1 (pin 4)
   digitalWrite(ledPins[3], LOW);             // Turn off LED #3 (pin 6)
   delay(potValue);                           // wait delayTime milliseconds
   digitalWrite(ledPins[2], LOW);             // Turn off LED #2 (pin 5)
   potRead();
   delay(potValue*3);                         // wait delayTime milliseconds *3
 }

There is an item, Auto Format, on the Tools menu. You REALLY should become familiar with it.

The ONLY argument that has ever been remotely convincing for

 void setup(){

over the more readable

void setup()
{

was that it used one fewer lines. Following the "one fewer lines" style with a blank line renders that feeble argument moot.

   pattern = pattern+1;                       // change to next pattern

Have you ever wondered why the language used to program the Arduino was called C++, instead of C=C+1?

  switch (pattern) {                          // state machine to change patterns

Since pattern is limited to 0 or 1, supplying 6 cases seems redundant.
Since pattern is limited to 0 or 1, supplying 6 cases seems redundant.
Since pattern is limited to 0 or 1, supplying 6 cases seems redundant.
Since pattern is limited to 0 or 1, supplying 6 cases seems redundant.

 void potRead(){

If you ever need to add another potentiometer, what are you going to call that function? This function should take arguments - for the pin number and for the range to map the reading to. It should return a value, NOT modify a global variable.

It seems silly to allow adjusting the speed partway through followTheLeader() and centerBloom().

Oh, and using an interrupt to detect attempts to change the pattern in code riddled with delays is lazy.

You should EASILY be able to detect a desire to change patterns by polling to switch. Of course, that means dumping that code, and starting over with a state machine.

But, trying to expand to 60 lights is going to require fundamental changes in the code anyway. So, dumping the delay-riddled code now, and doing it right seems like a good idea, anyway.

Now this is what I was looking for

void setup(){

vs

void setup()
{

actually i changed from one to the other just so I wouldn't get called out on it. ahh well.

PaulS:

   pattern = pattern+1;                       // change to next pattern

Have you ever wondered why the language used to program the Arduino was called C++, instead of C=C+1?

now this gave me fits.
made the mistake of doing this at the same time I added the interrupt so it took me awhile to figure this out when it didn't work.
but I originally had at as pattern++ but it didn't work until I changed it to pattern+1. I just tried again and it still doesn't work.

PaulS:

  switch (pattern) {                          // state machine to change patterns

Since pattern is limited to 0 or 1, supplying 6 cases seems redundant.

placeholders for future patterns

PaulS:

 void potRead(){

If you ever need to add another potentiometer, what are you going to call that function? This function should take arguments - for the pin number and for the range to map the reading to. It should return a value, NOT modify a global variable.

now this is interesting info I hadn't considered.

PaulS:
Oh, and using an interrupt to detect attempts to change the pattern in code riddled with delays is lazy.

You should EASILY be able to detect a desire to change patterns by polling to switch. Of course, that means dumping that code, and starting over with a state machine.

But, trying to expand to 60 lights is going to require fundamental changes in the code anyway. So, dumping the delay-riddled code now, and doing it right seems like a good idea, anyway.

You nailed me with that first line. although I did say I planned to fix those 2 functions and learning to use an interrupt was worth it

My friend has requested a specific pattern. a sort of line that snakes back and forth making it's way around the circle. I haven't a clue how to do this any other way so unless I find one I will have to do it this way. any suggestions?

My intention WAS to simply scale this up to 60 lights so I would certainly like to hear what changes will have to be made to do so. please expand on this.

Have you ever wondered why the language used to program the Arduino was called C++, instead of C=C+1?

Good 8)

PaulS:
Have you ever wondered why the language used to program the Arduino was called C++, instead of C=C+1?

But you can do var++ in straight C (I am referring here to (C++)-- ).

but I originally had at as pattern++ but it didn't work until I changed it to pattern+1. I just tried again and it still doesn't work.

If you mean that you originally had:

pattern = pattern++;

then it is not too surprising that "it didn't work". Whatever that means.

pattern++ increments the value in pattern and returns a value. But, which does it do first?

The correct bit of code is:

pattern++;

Both things happen, but the return value is discarded, so the order doesn't matter. When the result is NOT discarded, but is instead stored in the variable being modified, the order DOES matter. The order that the operations is performed is not defined in the standard.

The correct bit of code is:

pattern++;

Thanks agian

PaulMurrayCbr:
I'm becoming convinced that the best way to debounce a switch is to put a capacitor across it. Software be bounce is way more trouble than its worth, and never fails to fail the "Uh. Didn't think of that." test.

Well, I don't think it's always the best way. But I will admit that sometimes it might be. However, there are really only three things that you need to do for software debounce reliability. I have never heard of any instance where there was any problem that was not a failure to do one of the three things.

  1. Keep a state variable to represent the current state of the switch
  2. Use the state variable to control whether you are testing for a press or a release
  3. After detecting either a press or release and reporting a press or release event, initiate an adequate delay before changing the state variable.

I have phrased (3) for the lowest latency, but for humanly pressed keys, the delay is so short that you can safely reverse the sequence and report the state after the delay. That makes for very straightforward coding.

There's nothing else to think of. That I can think of. :slight_smile: I have written many debounce routines, including one with n-key rollover for a matrix.

After detecting either a press or release and reporting a press or release event, initiate an adequate delay before changing the state variable.

To put it another way, ignore state changes if a certain interval has not elapsed. You don't literally need a delay.

Yes, that is more accurate.

I really appreciate all the help everyone.

I am working on incorporating what I have learned here and looking to figure out code for the patterns that doesn't rely on delays.

The mega should be here in a couple days and I have already loaded up a breadboard with 30 LEDs for the next phase of testing.

The only concern I have left at the moment is in regards to PaulS comment about needing "fundamental changes To the code" to scale up to 60 lights.
Could someone enlighten me on what changes would be needed.

The only concern I have left at the moment is in regards to PaulS comment about needing "fundamental changes To the code" to scale up to 60 lights.

Which Arduino are you using? Which Arduino has 60 output pins?

Since the answer to the last question is none of them, you'll need additional hardware to control that many lights. Whatever the hardware, each Arduino pin is going to control more than one light.

THAT is going to require fundamental changes in your code.

Now, if you had said 48 lights, you could get away with minimal changes to the code.

I see
I was under the impression that That the mega had 54 digital pins and 16 analog.
And that the analog pins could be used as digital pins giving 70 total

Is this wrong?

If so then yes it looks like I will have to look at shift registers correct?

Thanks again for putting up with this noob

60 LEDs @ how much current each?
How many do you expect to be on at any one time?