Arduino: Loops, Conditions, and Methods

Previously, we figured out how to colour a pixel in a certain place. Today, we’ll be looking at some of the ways we can colour a whole bunch of lights by using different programming tools.

The “for” Loop

Let’s recall the code we used to colour one pixel.

strip.setPixelColor(0, strip.Color(255,255,255))

So, it’s easy then – if I want to get a bunch of these pixels off and going, I can just write them all out, right?

strip.setPixelColor(0, strip.Color(255,255,255))
strip.setPixelColor(1, strip.Color(255,255,255))
strip.setPixelColor(2, strip.Color(255,255,255))
strip.setPixelColor(3, strip.Color(255,255,255))
strip.setPixelColor(4, strip.Color(255,255,255))

Not too bad! I got 5 pixels on without doing too much! Okay, but wait a second now. What happens if I want to get each of the pixels on my strip going? Maybe that might be a little bit too much, right? Let’s try it.

 strip.setPixelColor(0, strip.Color(255,255,255))
 strip.setPixelColor(1, strip.Color(255,255,255))
 strip.setPixelColor(2, strip.Color(255,255,255))
 strip.setPixelColor(3, strip.Color(255,255,255))
 strip.setPixelColor(4, strip.Color(255,255,255))
 ...
 strip.setPixelColor(63, strip.Color(255,255,255))

Phew, okay. Wait – I didn’t want them all to be white. Damn, I have to go back and change everything by hand.

Obviously, there’s an easier way. Let’s use the following code:

void loop() {
                              // Reserve a spot in the strip of symbols and give it the name 
                              // 'i'.
                              // We could call it almost anything. Use descriptive names whenever possible.
int i;
for(
i=0;                          // start by setting that reserved spot to zero. otherwise it will                 
                              // be random.
i<64;                         // every time through the loop, check if i<64. if it is, keep going.
++i                           // just before the end of the loop and the check, remember to i=i+1.
)
{
                              // everything between the {} brackets will repeat in the loop.
strip.setPixelColor(
i,                            // the pixel address is changing!
strip.Color(255,255,255)      // the pixel color
);
}
                              // this only happens after the loop.
                              // show the new colors
strip.show();
}                             // loop end

Taking a closer look, we see that we’ve established a variable “i” as a counter of sorts – it increases by 1 per loop. We use “i” in our location set up, so while the loop is running, the address on the strip will change.

There’s a bunch of different for loops we can use. As your programming skills improve, you’ll find that you can do endless things using loops. Here’s one that will set a random colour on a random pixel every 5 seconds.

void loop() {
  for(;;) {  // always true, loops forever.
    int a = random(64);                 // a random number between 0 and 63, inclusive.
    int r = random(255);
    int g = random(255);
    int b = random(255);
    long c = strip.Color(r,g,b);
    strip.setPixelColor(a,c);
    strip.show();
    delay(200);                         // wait 200ms, so this loop will run 5 times a second
  }  // for end
}

Notice how I am carefully lining up the left side of the text so I can see where loops start and end. I’m also showing another style of placing brackets. Pick a style that works for you.

long is like int, but it’s a really big int, big enough to hold the red, green, and blue parts. int on it’s own will only hold the green and the blue parts.

It’s important to notice that in the example above we have a loop inside of a loop. That’s fine as long as we remember that the inside loop never ends. Any code between for end and loop end will never happen.

The “if … else” Statement

Dennis Hopper, Apocalypse Now
Did you know that ‘if’ is the middle word in ‘life’?

So far, all of the examples have been unmoving colours. What about some kind of animation perhaps? Let’s take a look at the following code:

// these symbols are created outside of loop() and will persist.
int clock=0;                         // number of times through the loop()
int dir=1;                           // direction
void loop() {
  int i;  // this symbol is created at the start of loop and destroyed at the end, every time.
  for(i=0;i<64;i++){
    long c = strip.Color(i*4,255-i*4,0);
    int a = (clock+i) % 64;              // the starting spot on the string changes with time!
    strip.setPixelColor(a,c);
  }
  delay(30);                           // ~33 times a second
  strip.show();
  if( dir == 1 ) {
    clock++;
    if( clock >= 63 ) {
      dir = -1;
    }
  } else {
    clock--;
    if( clock <= 0 ) {
      dir = 1;
    }
  }
}

Notice if(dir ==1). The double equal sign (==) refers to a comparison, and not equate. Arduino will check when the condition is satisfied (in this particular case, when dir == 1).

So, at the start, the clock is 0 and dir is 1. Each time through, the loop clock goes up by 1. When clock >= 63, dir becomes -1. From there on, the loop clock will go down by 1 because the if() statement says the condition hasn’t been met (meaning false) and thus the “else” portion of the loop takes precedent instead. Below, I show you a sneaky way of writing the same thing:

 clock += dir;
 if( clock>=63 || clock <= 0 ) {
     dir = -dir;
 }

Methods

When we put our LEDs into the panels, the lights were arranged in an S pattern. That means when we flip the panel over, the lights are arranged like so:

00 01 02 03 04 05 06 07
15 14 13 12 11 10 09 08
16 17 18 19 20 21 22 23
31 30 29 28 27 26 25 24
32 33 34 35 36 37 38 39
47 46 45 44 43 42 41 40
48 49 50 51 52 53 54 55
63 62 61 60 59 58 57 56

Typically, we think about grids like the cartesian coordinate system. We refer to specific locations by grabbing two numbers going in two major directions – “up, down” and “left, right” – we notate this as (x, y). Okay, so we’ve got something like that going right now, but there’s a big difference – the value of x should get larger whenever we go towards the right and the y value should get larger in one particular direction, as well. We see that the y value is okay – it’s getting larger as it goes down, but because of the S pattern, the x value is kind of warped up. We want to try to get this:

00 01 02 03 04 05 06 07
08 09 10 11 12 13 14 15
16 17 18 19 20 21 22 23
24 25 26 27 28 29 30 31
32 33 34 35 36 37 38 39
40 41 42 43 44 45 46 47
48 49 50 51 52 53 54 55
56 57 58 59 60 61 62 63

There’s gotta be a method that we can use to teach the computer to switch (x, y) and get the right address for each light. Hey – maybe we can get it to set the light colour for us while we’re at it.

                                  // don't change the setup() method or the loop() method.
                                  // this is here so you can see where to write p().
void setup() { ... }
void loop() { ... }
                                  // this only works because the lights are in an 8x8 grid. if 
                                  // the grid size changes, the 8 and the 7 here would also  
                                  // have to change.
void p(int x,int y,long color) {
int a = y*8;
if( y % 2 ) { // % is modulus.
                                  // y%2 is true when y is an odd number - rows 1,3,5,7.
a += 7 - x;
} else {
                                  // y%2 is false when y is an even number - rows 0,2,4,6.
a += x;
}
strip.setPixelColor(a,color);
}

Now that we’ve got this method p() setup, we can just use it as a tool and recall it when necessary. It’s quite literally a tool – we just built something that’ll help us build more stuff in the future.

                                           // Draw a box around the board
void loop(){
                                           // saving space here by writing many on one line.
int j,c=strip.Color(255,255,255);
for( j=0; j<8; j++ ) {
p(j,0,c);                                  // loop across the top,
p(j,7,c);                                  // across the bottom,
p(0,j,c);                                  // down the left side,
p(7,j,c);                                  // and down the right side
}
strip.show();
}

We get to use p() a bunch of times here.

Questions

  • Take another look at our code. How much work is strip.Color() and strip.show() doing? Can you imagine writing out the code without them?

Definitions

int xCreates a variable x that is an integer.
int x = yCreates a variable x that has the integral value y.
random(x)Generates a random number between 0 and x, inclusive.
for(x=0, x<y, ++x)Creates a for loop with a starting counter x of 0. Each loop, it will check if x<y; if it is, keep looping and also increase the counter by 1.
long x = (a,b,c…)Creates a large int value.
if(x == y)

a else b

If a condition is met (x==y), task “a” will happen once.
If the condition is not met, task “b” will happen once.
||

&&

Or

And

%Modulus