Code Along - Chapter 4

Loops & Arrays

Repeat work with for and while loops, drive an LED from a loop, store readings in an array and process them - totals, maximums and smoothing.

Estimated time 90-120 minExercises passed 0 / 9

Repeating with a for loop

A for loop has three parts in its brackets: where to start, the condition to keep going, and the step after each pass: for (int i = 1; i <= 5; i++).

A while loop only has a condition. Use it when you do not know in advance how many passes you need.

LED array, for loop, function and outputs
Loops and arrays replace repeated statements.
Worked example

Counting with for

The loop body runs once for each value of i.

void setup() {
  Serial.begin(9600);
  for (int i = 1; i <= 5; i++) {
    Serial.print("i = ");
    Serial.println(i);
  }
  Serial.println("Done");
}

void loop() {
}

Turn on JavaScript to edit, run and test this code in the browser.

Expected output
i = 1
i = 2
i = 3
i = 4
i = 5
Done
Exercise 4.1

Countdown to start

Not started

Count down from start to 1, one number per line, then print Motor start!. Use a loop - the tests change start.

Sample output
10
9
8
7
6
5
4
3
2
1
Motor start!
int start = 10;

void setup() {
  Serial.begin(9600);
  // Count down from start to 1, then print Motor start!

}

void loop() {
}

Turn on JavaScript to edit, run and test this code in the browser.

Exercise 4.3

PWM duty table

Not started

analogWrite takes a duty value from 0 to 255. Print a reference table in steps of 51, with each duty as a whole-number percentage, exactly as in the sample.

Sample output
duty 0 = 0 %
duty 51 = 20 %
duty 102 = 40 %
duty 153 = 60 %
duty 204 = 80 %
duty 255 = 100 %
void setup() {
  Serial.begin(9600);
  // duty 0, 51, 102 ... up to 255, with its percentage

}

void loop() {
}

Turn on JavaScript to edit, run and test this code in the browser.

Worked example

A while loop

This loop does not know how many passes it needs - it stops when value reaches 100 or more.

void setup() {
  Serial.begin(9600);
  int value = 1;
  while (value < 100) {
    Serial.println(value);
    value = value * 3;
  }
}

void loop() {
}

Turn on JavaScript to edit, run and test this code in the browser.

Expected output
1
3
9
27
81

Many readings in one array

An array stores several values of the same type under one name. Positions start at 0, so int readings[5] has positions 0 to 4. readings[i] reads position i.

sizeof(readings) / sizeof(readings[0]) works out how many elements an array has, so the loop keeps working if you add values. Reading outside the array is a classic bug: the Uno does not stop you, it just reads some other memory. The simulator warns you instead.

Worked example

Looping over an array

COUNT is calculated from the array itself, so the loop always visits every element.

int readings[] = {12, 7, 15, 9};
const int COUNT = sizeof(readings) / sizeof(readings[0]);

void setup() {
  Serial.begin(9600);
  Serial.print("COUNT = ");
  Serial.println(COUNT);
  int total = 0;
  for (int i = 0; i < COUNT; i++) {
    Serial.print("readings[");
    Serial.print(i);
    Serial.print("] = ");
    Serial.println(readings[i]);
    total += readings[i];
  }
  Serial.print("total = ");
  Serial.println(total);
}

void loop() {
}

Turn on JavaScript to edit, run and test this code in the browser.

Expected output
COUNT = 4
readings[0] = 12
readings[1] = 7
readings[2] = 15
readings[3] = 9
total = 43
Exercise 4.4

Total the readings

Not started

readings holds five values from a sensor. Add them all up with a loop and print the total. Keep the total in a long so large readings cannot overflow.

Sample output
Total: 2565
int readings[] = {512, 498, 530, 505, 520};

void setup() {
  Serial.begin(9600);
  long total = 0;
  // Add every reading to total with a loop


  Serial.print("Total: ");
  Serial.println(total);
}

void loop() {
}

Turn on JavaScript to edit, run and test this code in the browser.

Exercise 4.5

Average of five readings

Not started

The total is already worked out for you. Turn it into an average with two decimals and print it as in the sample.

Sample output
Average: 513.00
int readings[] = {512, 498, 530, 505, 520};

void setup() {
  Serial.begin(9600);
  long total = 0;
  for (int i = 0; i < 5; i++) {
    total += readings[i];
  }
  // Work out the average and print it

}

void loop() {
}

Turn on JavaScript to edit, run and test this code in the browser.

Exercise 4.6

Find the largest reading

Not started

Find the largest value in readings and print it. The tests include an array where every value is negative, so think about what your starting value should be.

Sample output
Max: 9
int readings[] = {3, 9, 2, 9, 1};

void setup() {
  Serial.begin(9600);
  // Find the largest value


  Serial.print("Max: ");

}

void loop() {
}

Turn on JavaScript to edit, run and test this code in the browser.

Exercise 4.7

Where was the peak?

Not started

Knowing the largest reading is useful; knowing when it happened is better. Keep track of the position as well, and print both. If the value appears twice, report the first one.

Sample output
Max: 9 at position 1
int readings[] = {3, 9, 2, 9, 1};

void setup() {
  Serial.begin(9600);
  int maxValue = readings[0];
  for (int i = 1; i < 5; i++) {
    if (readings[i] > maxValue) {
      maxValue = readings[i];
    }
  }

  Serial.print("Max: ");
  Serial.print(maxValue);
  // Add: " at position " and the position

}

void loop() {
}

Turn on JavaScript to edit, run and test this code in the browser.

Exercise 4.8

Newest reading first

Not started

Print the five values in reverse order on one line, separated by spaces, then end the line.

Sample output
5 4 3 2 1
int values[] = {1, 2, 3, 4, 5};

void setup() {
  Serial.begin(9600);
  // Print: 5 4 3 2 1

}

void loop() {
}

Turn on JavaScript to edit, run and test this code in the browser.

Exercise 4.9

Smooth out a spike

DeeperNot started

Real sensors are noisy - look at the 900 spike in samples. A moving average smooths the signal by averaging the last 4 samples. For every position end from 3 to 9, print the whole-number average of samples[end - 3] to samples[end], as in the sample.

This is how you steady analogRead values in Lessons 10 and 20.

Sample output
avg[3] = 502
avg[4] = 602
avg[5] = 598
avg[6] = 602
avg[7] = 603
avg[8] = 503
avg[9] = 500
int samples[] = {500, 520, 480, 510, 900, 505, 495, 515, 500, 490};
const int WINDOW = 4;

void setup() {
  Serial.begin(9600);
  // For end = 3 to 9: average samples[end - 3] .. samples[end]

}

void loop() {
}

Turn on JavaScript to edit, run and test this code in the browser.

Try it on a real Uno

Download Blink exactly five times and upload it. The five flashes run once at reset - press the reset button to see them again.

Then take Total the readings further on real hardware: fill the array with readings[i] = analogRead(A0); inside a loop with a short delay, and print the average of a real potentiometer instead of fixed numbers.