Intermediate 9: Arrays
In this lesson, we learn about the array data structure and how to use it.

controller-full

Summary

Arrays are a type of data structure that can store a collection of elements.  The variables are neatly stored and labelled, so specific values are easy to recall.

 

What Are Arrays?

An array is a tool for data storage, much like a variable.  Unlike a variable, an array can hold multiple values.  Think of an array like a row of empty boxes:

emptyarray8

Array with 8 elements

This image represents an array named myArray with 8 boxes.  Each of these boxes is called an element.

Each element can store a number, just like a variable.   Instead of naming each box, though, we just group them under the array “myArray” and number them from 0 – 7 (we start at 0).   For example, if we wanted to store 8 integers: 1, 7, 15, -23, -92, 0, 5, and 57

storedarray8

myArray storing 8 integers

Instead of creating 8 different variables, we can now store the 8 numbers in a single array.   To recall a specific value, we can point to a specific element in the array.

If I wanted to recall the number -92, I would use the code

This points to the 5th element in the array.  It’s important to realize that the array starts at the 0th element.

 

 

Using Arrays

Just like a variable, an array must be initialized before it is used

data type  myArray[]

data type ArrayName[Array Size];

data type – The data type indicates what type of data you are choosing to store in the array.  All elements in the array must be the specified data type.

Array Name – You can name the array anything you want.

Array Size – The size of an array must be declared before using the array.  This means you need to know how many elements you expect to use.

 

Some important things to keep in mind:

  1. Indexes always start at 0.  This means the first element in an array is always element 0 (myArray[0]).
  2. If you store or read past an array’s initialized size, you won’t receive an error. It will just ruin your program without warning.
  3. Elements within an array act just like variables. They can be overwritten and called whenever you want.
  4. An initialized element will begin with a value of 0.
  5. INDEXES ALWAYS START AT ZERO.  DON’T FORGET.

 

Let’s start with an example

Example 1: Basic 5 Element Array

arrayprint1

Output

We begin this example by initializing an integer array named newArray  with 5 elements.   We then set the first element to newArray[0] = 10 , and the fourth element to newArray[3] = 9 .

Notice that the output shows the 2nd, 3rd and 5th element to all equal 0.

 

Example 1: Another Basic 5 Element Array

arrayprint

Output

 

Here we start by initializing an integer array named newArray  with 5 elements.  Using brackets, we can set the starting value of each element:

We then print each element of the array to the serial monitor using a for-loop.  The variable i  loops through the values 0 to 4, allowing us to print the array values newArray[0]  to newArray[4] .

 

 

Using Arrays

The uses for arrays are limited only by your creativity.  To best understand arrays, the rest of this lesson will walk through the development of an advanced CoDrone program utilizing arrays.

The goal of this program is to create a ‘planned flight path’ mode for the controller.

 

Planned Flight Path Mode

  1. While the right IR sensor (18) is covered, ‘planned flight path’ mode is engaged
  2. During ‘planned flight path’ mode, all joystick inputs will be stored, but not executed
  3. Once the right IR sensor is released, all stored inputs will be sequentially executed
  4. At the end of the stored flight path, the CoDrone will land

An example of using ‘planned flight path’ mode would look like this,

Cover IR Sensor 18,
Move Left Joystick Upwards for 1 second (THROTTLE = 100),

Move Right Joystick  Upwards for 1 second (PITCH = 100),
Move Right Joystick Right for 1 second (ROLL = 100),
Release Sensor 18
CoDrone then throttles for 1 second (THROTTLE = 100),
Then pitches for 1 second (PITCH = 100),
Then rolls for 1 second (ROLL = 100),
Then lands

The maneuvers don’t execute until the sensor is released.  Then they all execute in chronological order.

 

Storing Joystick Inputs

The code for reading our joystick inputs is as follows.

 

To keep things simple, we’ll focus on THROTTLE

 

if we used a variable to store THROTTLE, then our value for the variable throttle  would get overwritten every time this line ran.  We would lose all of the previous THROTTLE values.

 

 

throttle-variable

The solution is to store each value in a new element in the throttle[] array.   To do this, we use an incrementing variable j

We also need to use a loop.

At this point, we know of two different looping methods: the for-loop and the while-loop.

For-Loop

  • Loops for a predetermined number of times

While-Loop

  • Loops as long as a certain condition is met

Since we don’t know for sure how many times we want to loop, we will be using a while loop.

For as long as we hold down the digital IR sensor 18, our throttle values will be saved in the throttle array.  With the incrementing variable j , we are saving each new value as a new element.

throttle-arr

Now we have to decide on how often we want to save store our input.  Let’s say we want to save our throttle input every 250 milliseconds

throttle-array

We now have an array with the throttle input stored into it.  Every element represent 250 milliseconds apart.  Every 4 elements represent 1 second of stored data.

If we choose a shorter delay, we will get more data points per second.  The delay here represents what we call a sampling rate.  A higher sampling rate means we have a higher resolution.

 

Choosing the Correct Resolution

In the code shown above, the delay()  represents our ‘resolution’.

A higher resolution (shorter delay()) means that our stored array more accurately represents what our actual joystick movements were.

 

For example, let’s say you slowly move your throttle joystick up and down over one second.  If we had a sampling rate of 1 sample/second,

reso-1

our two save points would be at 0ms and 1000ms.  At both of these times, our throttle happens to be 0.  Our saved array data is missing all of our joystick inputs that happened between our samples.

If we were to use a higher sampling rate at a delay of 250 milliseconds,

reso-2

we now get 4 samples per second.  Our data now captures the high and low points of our throttle input.

A sampling rate that is too high will cost a lot of memory space, so keep your delay above 100 milliseconds (10 samples per second).

 

Replaying Saved Data

Now that we have our joystick inputs saved in our array throttle[j]

we need a way to replay the maneuver.

We will again need to use an array and a loop.  This time we’ll use a for-loop, since we know that we have j  saved array elements.

It’s important that we use the same delay()  length for both writing and reading our array.

 

Putting this all together, we get the program

We use a delay of 100 ms and an array size of 50, which would give us 5 seconds of data storage  (100 ms per sample * 50 samples = 5000 ms ).   This means we can save our throttle 10 times per second for 5 seconds.

 

 

Data Overflow

What happens if we accidentally hold the IR sensor 18 for more than 5 seconds?  Our while loop   while (digitalRead(18)) { will continue to run and our variable j  will continue to increment.   Soon, we’ll be writing to throttle[51] , then throttle[52] , even though we only initialized throttle  to have 50 elements.

This is called data overflow.  The C language does not handle data overflow well, so writing to throttle[51] will cause your program to malfunction.  To prevent this, we will use an extra operator in our while loop.

 

Final Code

To make things easier for the user, we will add buzzers as indicators for where the code is.  We will also include a landing command and a kill-switch. Our final code:

 

Activity:  Planning Ahead

Complete the planned flight mode for all joystick inputs.  Add an array that stores the input of your IR sensor and performs an action accordingly when replayed.