The Structure of struct

Have fun playing the game for a while before reading this section.

In the previous section, I didn't mention any of the lines of code at the top of the sketch. Most of these are just normal global variables and constants that are fairly common. However, this section of code may be new to you.

Download: file
struct button {
  uint8_t capPad[2];
  uint8_t pixel[3];
  uint32_t color;
  uint16_t freq;
} simonButton[] = {
  { {3,2},    {0,1,2},  0x00FF00,   415 },  // GREEN
  { {0,1},    {2,3,4},  0xFFFF00,   252 },  // YELLOW
  { {12, 6},  {5,6,7},  0x0000FF,   209 },  // BLUE
  { {9, 10},  {7,8,9},  0xFF0000,   310 },  // RED 
};

This is defining, and initializing, an array (simonButton[]) of something called a struct. A struct comes from the C programming language, but is also supported in C++ and thus Arduino. What it basically does is let us create a new variable that is a collection of information associated with something, like a Simon "button". This let's us pass around and access this information from a single reference. We don't need to pass around each individual piece of information separately.

Talking about structs can get pretty complex, and they're a precursor to the more complex class of C++ and the world of OOP. But they are very useful, and we are using it in a fairly simple way in our Simple Simon code. To better understand why a struct is useful, let's look at a more simple example - a 2D point.

2D Point Example

A 2D point is represented by an x and y value. We could create these as separate variables:

Download: file
float x;
float y;

and then use them as normal:

Download: file
x = 45.3;
y = -108.6;

But what if I wanted to pass this 2D point to a function? Or what if I wanted to create another 2D point? Things start getting a little messy. This is where a struct would help out. Instead of two separate variable, we create a single struct to represent the 2D point, and put the variables in there.

Download: file
struct point {
  float x;
  float y;
}

And then to create a new point variable:

Download: file
struct point someLocation;

And assign it values:

Download: file
someLocation.x = 45.3;
someLocation.y = -108.6;

Now all one needs to do is pass the variable someLocation around. The values come along for the ride. And they don't get confused with some other values. If we need another 2D point, we just create another variable, or better yet, an array of them.

The one fancy thing being done in the Simple Simon code is to create and initialize the values of the struct in one step. For our 2D point example, this would look like:

Download: file
struct point {
  float x;
  float y;
} someLocation = {
  45.3, -108.6
}

It's just a shortcut way of creating the variable and assigning it some initial values.

The Simple Simon "button"

Getting back to our Simple Simon game, think about what each of the four "buttons" has. Most obvious is a color. But they also make a sound when they are pressed, and each has its own tone. Since we are trying to implement these on our Circuit Playground, we will use a set of NeoPixels to show off the color. Also, we plan to use capacitive touch for the buttons, with each button having a couple of pads. So, we have the following items for each "button":

  • 2 x capacitive touch pads
  • 3 x NeoPixels
  • a color
  • a tone

Hey, that should look familiar. Look again at the struct definition:

Download: file
struct button {
  uint8_t capPad[2];
  uint8_t pixel[3];
  uint32_t color;
  uint16_t freq;
}

Just like the list. For each "button" we have the indices for 2 capacitive touch pads, the indices for 3 NeoPixels, the color to use for the NeoPixels, and the frequency of the tone for the button.

We have more than one "button", so we create an array of them and initialize their values:

Download: file
  simonButton[] = {
  { {3,2},    {0,1,2},  0x00FF00,   415 },  // GREEN
  { {0,1},    {2,3,4},  0xFFFF00,   252 },  // YELLOW
  { {12, 6},  {5,6,7},  0x0000FF,   209 },  // BLUE
  { {9, 10},  {7,8,9},  0xFF0000,   310 },  // RED 
};

Each line is an entry in the array and represents one button. Each item in each line corresponds to the value of the struct and is used to define the specific buttons. For example, the first line defines the GREEN button as having the capacitive touch pads #3 and #2, the NeoPixels #0, #1, and #2, the color green (in hex), and the frequency 415Hz.

Then, if we need the frequency for the tone of the GREEN button, the syntax is:

Download: file
simonButton[0].freq

The color for the BLUE button?

Download: file
simonButton[2].color

The index of the 2nd NeoPixel for the RED button?

Download: file
simonButton[3].pixel[1]

etc. etc.

Hopefully that makes some sense and you see how it is useful. If not, meh, just have fun playing the game....for now.

So Why Didn't You Just Create a simonButton Class?

Just trying to keep it simple. But this is totally doable, since Arduino uses C++ under the hood.

This guide was first published on Jan 23, 2017. It was last updated on Jan 23, 2017. This page (The Structure of struct) was last updated on Jul 22, 2019.