Skip to content

SALES INQUIRIES: 1 (888) 767-9864

Tutorial 24: Multi-Dimensional Arrays with Arduino (AKA Matrix)

Arduino Course for Absolute Beginners

Multi-Dimensional Arrays with Arduino (aka Matrix)

I don’t know if you are into Zen or not – I don’t know Zen from jack.  When I think of Zen I think of how the organization of the outside world can effect the way I think and feel – I am sure this is way off – but that’s all I have cared to ponder it thus far.

So if my shop is organized, if my computer files are organized, if my calendar is organized (then I won’t have time to build anything because I am organizing too much!) then my mind can be more organized.

So what does this have to do with Arduino or matrices?  Here is the angle I am taking – the more you can represent physical reality in how you store your data the easier it will be for you to think about and manipulate this data.  So what am I talking about?

Ok, say you are making a game for a carnival.  People shoot Bluetooth guns at these targets lined up in a row.  When a player gets a hit, your Arduino actuates a servo to drop the target and increments a counter board.  Lets say you plan to use an array to store the condition of each of these targets – how would you represent them in the array?

One way would be to have them entered in the array from left to right – the left most target is the first element in the array and the right most target ends up being the last element.  This just makes sense – unless there is some real good reason to jumble up the order of the targets, you would store them in the array as they are in the physical world.

Now lets say you want add multiple tiers of targets.  So there are four rows of targets now, and each row has 5 individual targets – how could you represent this in an Arduino data structure?

A multi-dimensional Array also know as a matrix – allows you to store data just such a way.

This lesson deviates from all the previous lessons in that the Arduino IDE does not come loaded with an example for using a multi-dimensional array.  I am not sure why this is – but in any case I have written a short sketch to demonstrate the awesomeness of matrices.  We will take 9 LEDs and position them in the form of a matrix*, which we will control with a multi-dimensional array.

*Please note that this is not an LED matrix in the traditional sense, which you may be familiar with.  LED matrices are built and operated in a different manner – though they often employ multi-dimensional arrays. See the note at the end of this tutorial for further clarification.

Using multi-dimensional arrays with Arduino doesn’t have to rocket science, so let’s get started!

You Will Need

  1. 220 Ohm Resistor (9)
  2. LEDs (9)
  3. Jumper Wires (18)
  4. Solder-less Breadboard

Step-by-Step Instruction

The trick here is to have 9 LEDs connected to pins 2 through 10.  You need a 220 Ohm resistor for each LED so it can get a little packed on the Arduino headers.

  1. From your Arduino, run a jumper wire from the ground pin to the long ground rail of your bread board.
  2. Run another jumper wire, from this ground rail to the ground rail on the opposite side of the bread board.
  3. Place an LED on your bread board.  Be sure the legs are in different rails.
  4. Connect one end of a 220-ohm resistor to the same rail as the long leg of your LED.
  5. Connect the other end of the 220-Ohm resistor to a separate rail.
  6. From pin 2, run a jumper wire to the 220-ohm resistor.  Your bread board should look like this:                                                                                                      This image made with Fritzing.
  7. Now repeat this process for the next LED, until you have three in a row, utilizing pins 2, 3 and 4.
  8. Continue the process for the next row using pins 5, 6 and 7.
  9. Complete the circuit with the last row using pins 8, 9 and 10.
  10. Plug your Arduino into your computer.
  11. Open up the Arduino IDE.
  12. Copy and paste the code from the Discuss the Sketch section below into the open IDE window.
  13. Click the Verify button on the top left side of the screen. It will turn orange and then back to blue once it has finished.
  14. Click the Upload button (next to the Verify button). It will turn orange and then back to blue once it has finished.
  15. Your LEDs should start doing cool things.

This image made with Fritzing

Discuss the Sketch

/*Multi-Dimensional Array AKA Matrix
 
 This sketch demonstartes the use of a multi-dimensional array
 
 to control 9 LEDs formed into a matrice.
 
 The circuit:
 
 * 9 LEDs connected from pins 2 through 10 (through 220-Ohm resistors) to ground
 
 shaped into a 3 by 3 matrix.
 
 Created 11 October 2012
 
 By Michael James
 
 
Home
This example code is in the public domain. */ //the matrix will hold the pin assignments for the led int pinMatrix[3][3] = { {2, 3, 4 }, {5, 6, 7 }, {8, 9, 10 } }; void setup() { //use a nested for loop to initialize all the pins for(int i = 0; i < 3; i++){ for(int j = 0; j < 3; j++){ pinMode(pinMatrix[i][j], OUTPUT); }//close for i }//close for j } //close setup() void loop() { //this nested for loop will turn each LED on and off in sequence for(int i = 0; i < 3; i++){ for(int j = 0; j < 3; j++){ digitalWrite(pinMatrix[i][j], HIGH); delay(100); digitalWrite(pinMatrix[i][j], LOW); }//close for i }//close for j } //close loop()  

We begin by declaring and initializing one variable – our matrix.  If you recall how to declare an array from the Lesson 9, you will notice the semblance to the matrix.

int pinMatrix[3][3] = {

{2,  3,  4},

{5,  6,  7},

{8,  9, 10}

     };

First we say what the matrix will hold – this matrix will be holding integer values, so we use the int data type.  Next we name the matrix. Since this matrix will be holding the digital pin numbers we have our LEDs attached to, I named it pinMatrix.  We follow the name by two sets of open and closing brackets.  Inside the first bracket is the number of rows the matrix will have.  The second set of brackets is the number of columns the matrix will have.

The entire matrix is enclosed in  curly brackets and each row of the matrice is also enclosed in curly brackets and separated by a comma.  Notice that I have aligned each row of the matrix in the sketch as it would appear if the LEDs were layed out.  I could have done this declaration in a single line, but it is less readable in my opinion.

int pinMatrix[3][3] = {   {2,  3,  4}, {5,  6,  7}, {8,  9, 10} };

The single line above might take less space but looses readability.  When you are setting the number of elements in the row and column you could use a variable, but it has to have the constant qualifier.  For example, we could have written:

const int rows = 3;

const int cols = 3;

int pinMatrix[ rows ][ cols ] = {

{2,  3,  4},

{5,  6,  7},

{8,  9, 10}

        };

This would have worked fine.  This way you can expand the size by adjusting the constants at the top of your program.  If you do not what to put values in the array yet, then you don’t have to.  You can just declare the array and initialize it later.  That would look like:

int pinMatrix[ rows ][ cols ];  //no need to have values from the start

You must include the size of the array when you declare it.  There are many other aspects to array declarations and initialization that I will not cover – I think you have the basics to make an array.  Look at the further reading section for some good discourse on the subject.

The setup() of the program needs to accomplish one task, and that is setting all the pins in the matrix as OUTPUTs.  We use a nested for loop to make this easily.  The nested for loop and the matrix are like tag team wrestlers – they work great together.  Before we look at how the nested for loop works, lets talk about how an matrix is indexed.

Like arrays, matrices are 0 indexed, so the first row in the matrix is 0, and the first column is 0.  So if we have initialized the matrix below:

matrix[3][3] = {

{2,  3,  4},

{5,  6,  7},

{8,  9, 10}

};

Then we we want to reference the elements in the matrix we would use the following indexing…

Matrix[0][0] would equal 2.

Matrix[0][1] would equal 3.

Matrix[1][2] would equal 7.

Matrix[2][2] would equal 10.

Get the gist?  I know it can be confusing, since the size of the array is 3 by 3, but the indexing starts at 0.  Once you get past the apparent weirdness of this, it becomes quite easy.

The following is my best attempt at explaining how we use the nested loop with this matrix – the process can be difficult to word.

Basically the nested for loop says “Lets look at the first row of the matric and work from left to right across the columns setting each pin as an OUTPUT.  Once we get to the last column, lets move on to the next row, and start back from left to right.  Keep repeating this until we are out of rows.” There is no better way to understand matrix reference and operations than trying some on your own!

So now lets take a look at the first nested for loop.

for(int i = 0; i < 3; i++){                                    //first loop

for(int j = 0; j < 3; j++){                           //second loop

pinMode(pinMatrix[i][j], OUTPUT);          //set current pin as OUTPUT

}//close for i

}//close for j

Consider just the first for loop.

for(int i = 0; i < 3; i++)

We start the variable i = 0 as the counter variable, we set the condition for the loop to continue as i being less than 3, and then we increment i by one every time through the loop.  This first loop is in control of the rows of the matrix.  The first time through the loop, i is equal to zero, and we will use this to reference the first row in the matrix.  What code do we execute when we start the first for loop?  Why it’s another for loop!

The next for loop looks exactly like the first, except that now we use the variable j as the counter variable.   We will use j to reference the columns of the matrix.  So now that the inner for loop is active, it will continue until its condition is met, and that is j < 3.  Since j start equal to 0, this loop will run three times.  What code does this loop execute?

It sets the modes of the pins, using pinMode().  Simple enough.  SO the first time through the both of these

pinMode(pinMatrix[i][j], OUTPUT);

Do you see how pinMatrix[][] is referenced?  Using i and j?  The first time through the outer loop, i equals 0, and j equals zero.

Thus pinMatrix[0][0] is equal to 2

       i    j

So pin 2 is set as an OUTPUT by pinMode().  Now the inner j loop will run again – because it has not met its condition yet.  So now j will equal 1 but i still equals zero.  So now the pin mode will be set by pinMatrix[0][1] which references pin 3.

                                    i     j

Once again the inner loop will run and j will equal 2 =>pinMatrix[0][2] which means pin 4 has been set as an OUTPUT.  Now the condition of the inner for loop has been met, j cannot be incremented any further – so it exists the inner loop.

Now we start back at the outer loop.  The i  counter gets incremented from 0 to 1.  What is the first code that gets executed in the outer for loop?  It’s just the inner for loop again.  The inner for loop starts again from scratch, j equals 0.  Now we will be looking at the first element in the second row:

pinMatrix[1][0]

                           i    j

The inner loop will continue through until its condition is met and then exit and the outer loop will start one more time, allowing us to reference the third row of the matrix.

Once these two for loops have run their course, all the pins in array will be set as OUTPUTs.  This accomplishes the setup().

No we want to turn the LEDs on and off in sequence.  Start at the top left of the matrix and running down the first row, and then starting on the second row form left right and finally the third row.

Again we employ a nested for loop along with the code to turn an LED on and off.

//this nested for loop will turn each LED on and off in sequence

for(int i = 0; i < 3;i++){

for(int j = 0; j < 3; j++){

digitalWrite(pinMatrix[i][j], HIGH);

delay(100);

digitalWrite(pinMatrix[i][j], LOW);

}//close for i

}//close for j

There is no difference between this nested for loop and the one used in the setup().  The only thing that has changed is what code gets executed in the inner loop.  Instead of setting pinMode() we are using digitalWrtite() and delay() to blink our LED on and then off, in sequence.

And that is all this for loop wrote.  Once the nested loops complete, the loop() starts again – thus giving us a continuous LED light show.

NOTE: These 9 LEDs in the form of a matrix that we have made and controlled are set up and operated differently than typical LED matrices you might be familiar with.  Most LED matrices turn on and off the LEDs at a rapid pace to make it “look” like a constant image, when in fact all the LEDs are blinking very rapidly.

This allows you to control more LEDs with fewer output pins – to be perfectly honest – it is very cool!  Here we use 9 pins to control 9 LEDs, but you could use 6 Pins to control 9 LEDs if you wired them accordingly and wrote a sketch that blinked them rapidly.

If this is what you want to try, don’t worry – they still use multi-dimensional arrays to control these and the timing code is amazingly simple to do once you get the gist.

Try On Your Own

  • Instead of the LEDs blinking down the rows from left to right, could you have the blink down the columns from top to bottom?
  • Can you reverse the direction of the blinking so that the lights go from right to left?
  • Can you make an entire row blink at once? In sequence down the rows from top to bottom?

Further Reading

14 Comments

  1. Avatar Chris on October 16, 2012 at 10:16 am

    This is the clearest explanation of nested looping functions and multi-dimensional arrays that I have seen yet. I’m working on a similar set of functions to control servos and up until now I have been a little lost.

    Thanks!

    • Avatar oshj on October 16, 2012 at 5:15 pm

      Great, I am glad you liked it – sometimes I get worried my explanations are too bogged down. Let me know if there is anything specific I can help you with. P.S. Great website, really enjoyed the macroscopic images!

  2. Avatar Peter Newman on November 3, 2012 at 2:38 am

    I am just starting out using Arduino and am finding the coding aspect to be the most difficult to grasp. Your tutorials are very well constructed with clear concise explanations and diagrams to illustrate the lesson. Keep up the good work, your effort is appreciated, Pedro.

    • Avatar Michael - OSHJ on November 3, 2012 at 9:06 am

      Great to hear these have been helpful. Let me know if you would like to see any specific tutorials or want anything fleshed out more clearly.

  3. Avatar agrippaa on August 20, 2014 at 2:27 pm

    This tutorial has been very helpful and is very well written! I am dealing with a similar project and the concepts here are very helpful. Thanks!

    • Avatar MICHAEL JAMES on August 20, 2014 at 11:10 pm

      Thanks a ton! I am glad it could help.

  4. Avatar pepe on May 30, 2017 at 8:43 pm

    gracias <3

  5. Avatar Gilberto Gozzi on May 19, 2019 at 11:37 pm

    int cube_matrix[3][3][3] = {

    {{0,1,2},// row 0
    {3,4,5},
    {6,7,8}},

    { {9,10,11},
    {12,13,14},
    {15,16,17}},

    {{18,19,20},
    {21,22,23},
    {24,25,26}}

    };

    void setup() {
    // put your setup code here, to run once:
    Serial.begin(9600);
    }

    void loop() {
    // put your main code here, to run repeatedly:
    for (int i=0;i<3;i++){
    for (int j=0;j<3;j++){
    for(int k=0;k<3;k++){

    Serial.println(cube_matrix[i][j][k]);
    delay(1000);
    }
    }
    }
    }

  6. Avatar jeff on July 3, 2019 at 10:53 am

    Love this tutorial, however I’d like to draw attention to this section:

    const int rows = 3;

    const int cols = 3;

    int pinMatrix = {

    {2, 3, 4},

    {5, 6, 7},

    {8, 9, 10}

    };

    Shouldn’t the

    int pinMatrix = { //values

    part really be

    int pinMatrix[rows][cols] = { //Values

    • Avatar Michael James on July 3, 2019 at 4:36 pm

      Thanks for bringing that up Jeff! I didn’t realize it, but the HTML editor for the site, was consider the brackets with a word, as shortcode, and was hiding them. I added some spaces, and it seems to be working now.

  7. Avatar Jim on October 5, 2019 at 7:18 am

    This tutorial would have been _miles_ better imo if you had had a different number of rows and columns, say 3×4 or 4×3. Then i and j in the for’s would have been different, and it would be more obvious which is the row and which is the column. Those i and j variables could also benefit from real world names, for the same reason.

    • Avatar Michael James on October 5, 2019 at 8:58 pm

      Great point Jim – Thanks for this feedback!

  8. Avatar Rene West on October 13, 2019 at 11:48 am

    Thank you a lot for this, however using a 3×3 is super confusing for a newbie like me. A 4×3 or a 2×4 makes it a bit more clear on how to read all this.

Leave a Comment