Home‎ > ‎CS 11M‎ > ‎

Counting Loops


Questions, Answers and Review

  • Questions from last class?
  • Questions about homework?

Counting Loops

  • Counting is a way to solve many programming problems
  • As an example, assume we want a program to write a list of numbers
  • We want to start at the number 1 and let the user choose the ending number
  • Thus the program output will look something like:
    This program writes lists of numbers.
    Enter the maximum number:
    1
    2
    3
    4
    5
    
  • We cannot simply write five numbers with cout because the user chooses the maximum number
  • To help us understand how to approach the problem we try out some counting examples

Looping Statements

  • It turns out that counting is a very common use of loops
  • Loops that are controlled by a counter variable are called counter-controlled loops
  • We can visualize a counter-controlled loop as a series of steps to reach a goal
  • We use a counting variable to keep track of the number of times the loop has repeated
  • We have looked at two looping statements previously: for and while
  • Both statements can be used to solve counting problems, but the for loop is the one designed for counting
  • To finish designing our counting application, we will review our previous use of the for statement

Check Yourself

  1. For a computer to remember a count, we write code to declare a ________.
  2. Loops that are controlled by a counter variable are know as ________ loops.
  3. True or false: counter-controlled loops end after a certain number of steps.

Understanding for Statements

  • We have used for loops previously to repeat commands a certain number of times
  • For example, we wrote a sketch that:
    1. Blinks 20 times
    2. Pauses for 3 seconds
    3. Starts again
  • We could have written the blink code 20 time, like:
    digitalWrite(ledPin, HIGH);
    delay(delayPeriod);
    digitalWrite(ledPin, LOW);
    delay(delayPeriod);
    // repeat above 4 lines 20x
    delay(3000);
    
  • Such code requires lots of typing and is error prone

Looping with for

  • To repeat code a specific number of times we use a for-loop:
    for (int i = start; i < end; i = i + 1) {
        // code to repeat
    }
    
  • Where:
    • i: the name of a counter variable
    • start: the initial starting count
    • end: the final ending count
  • The commands to repeat are placed inside the curly braces
  • The looping code is shorter and easier to maintain than repeated code

Example for-loop Code

for (int i = 0; i < 20; i = i + 1) {
  digitalWrite(ledPin, HIGH);
  delay(delayPeriod);
  digitalWrite(ledPin, LOW);
  delay(delayPeriod);
}
delay(3000);

Diagram of for Loop Operation

for loop flow chart

Execution Steps

  1. When for loop is reached, execute the initialize statement (example: int i = 0)
  2. Check if condition is true (example: i < 20)
    1. if true then continue with Step 3
    2. Otherwise it is false so continue with Step 6
  3. Execute the block containing the statements to repeat (body)
  4. When end of loop body is reached, execute the update statement (example: i = i + 1)
  5. Return to Step 2
  6. Loop is finished: continue with statements after the loop

Check Yourself

for (int i = 0; i < max; i++) {
  cout << i << endl;
}
  1. In the loop above, the initialization statement is ________.
    1. int i = 0
    2. i < max
    3. i++
    4. cout << 1 << endl;
  2. In the same loop, the test condition is ________.
    1. int i = 0
    2. i < max
    3. i++
    4. cout << 1 << endl;
  3. In the same loop, the update statement is ________.
    1. int i = 0
    2. i < max
    3. i++
    4. cout << 1 << endl;
  4. In the same loop, if max is 3 the loop prints ________.
    1. 0, 1, 2, 3
    2. 1, 2, 3
    3. 0, 1, 2
    4. 1, 2, 3, 4

More Information

Exercise 1: Counting Numbers 

  1. Start the Arduino IDE with a new sketch and save the program as counting.
  2. In the setup() function add the following code:
    void setup() {
      Serial.begin(9600);
    cout << "This sketch writes lists of numbers." << endl; cout << "Enter the maximum number:" << endl; }
  3. In the loop() function, add the following code to get the maximum number from the user:
    void loop() {
      int max;
      cin >> max;
      // Add code from the next step here...
    }
    
  4. After getting the input, add a for-loop 
    cout << "for loop:" << endl;
    for (int i = 0; i < max; i++) {
      cout << i << endl;
    }
    
  5. Compile and run your code to verify it works.
    1. Does it start and stop with the correct numbers?
    2. If not, what needs to change?
  6. Save your counting.ino file to submit to Canvas with the next homework.

When finished, please help those around you.

Summary

  • The for statement is used to repeat a block of statements enclosed inside its curly braces
  • A for statement is used whenever we have a certain number of commands to repeat
  • We use a counter variable to keep count of the number of iterations
  • Also, we use a test condition to decide when to keep looping and when to stop
  • The following is an illustration of the syntax of a for loop
For loop illustrate

Source: www.arduino.cc

Counting Loop Applications

#include <ArduinoSTL.h>

using namespace std; 

const int LightSensor = A0; 

void setup() {
  Serial.begin(9600);
}

void loop() {
  int sum;
  int samples; 

  cout << "How many samples do you wish to take?" << endl;
  cin >> samples;
  
  for (int i=0; i<samples; i++) {
    int reading = analogRead(LightSensor);
    cout << "Current reading: " << reading << endl;
    sum += reading;
    delay(1000);
  }
  int average = sum / samples;

  cout << "The average is: " << average << endl << endl;
}

Averaging a Sensor Reading

  • Sensor readings fluctuate 
  • Sometimes you want to slow down how quickly a program reacts to changes
    • The automatic brightness setting on your phone or tablet.
    • Uses a light sensor like the one on your breadboard. 
    • But... brightness should change slowly or it's annoying.

Smoothing Readings

  • Sometimes a sensor reading fluctuates and gives "jumpy" readings
  • One way to solve the problem is to take multiple readings and average them
  • Continuously averaging a series of numbers is a form of data smoothing
  • To find an average, we sum a series of numbers and then divide by the count of numbers
  • If we wanted to average 5 readings, we would add a for-loop as shown below

Averaging Sensor Readings

  for (int i=0; i<samples; i++) {
    int reading = analogRead(LightSensor);
    cout << "Current reading: " << reading << endl;
    sum += reading;
    delay(1000);
  }
  int average = sum / samples;

Check Yourself

  1. When sensor numbers are "jumpy", it is because the sensor readings ________.
  2. True or false: one technique to smooth jumpy readings is to average the numbers.
  3. In the following loop, if the analogRead() function returns the numbers 1, 2, 3, 4, 5 the value of sum after the loop finishes executing the sum is ________.
    double sum = 0.0;
    for (int i = 0; i < 5; i++) {
      int reading = analogRead(A0);
      sum += reading;
      delay(1);
    }
    
  4. After the above loop completes, the correct statement to average the readings is ________.
    1. int average = sum * 5;
    2. double average = sum / 5;
    3. int average = sum / 5;
    4. double average = sum * sum / 5;

Iterating Over Strings

#include <ArduinoSTL.h>

using namespace std; 

void setup() {
  Serial.begin(9600);
}

void loop() {
  string str;
  cout << "Enter a word or phrase." << endl;
  getline(cin, str); 

  for (int i=0; i<str.length(); i++) {
    cout << str[i];
  }
  cout << endl;

  for (int i=str.length()-1; i>=0; i--) {
    cout << str[i];
  }
  cout << endl;  
}
  • Strings are an array of chars.
  • We'll talk about arrays soon... 
  • You can access a single char in a string using square brackets [ and ].
  • The above example takes a phrase and prints the phrase forward and backwards.  

Summing Numbers 

  • Whenever we need to sum a list of numbers, coding a loop is a good approach
  • Notice that we have a separate variable to store the sum
    double sum = 0.0;
    
  • We need two variables in a summing loop
    • i: the counter variable to store the current count
    • sum: the variable to store the sum of the numbers
  • One we have a sum, we can divide by the number of numbers to find the average
    double average = sum / 5;
    

Variations

  • Sometimes we only want to sum part of the numbers we get
  • We can adjust the summing loop to read a different quantity of readings by changing the starting or ending value
  • For example, if we wanted to read six values we would change the for-loop like:
    for (int i = 0; i < 6; i++)
    
  • We could change the summing loop to read every other value by changing the update statement like:
    for (int i = 0; i < 5; i += 2)
    
  • What numbers does the above loop tally?
  • Another option is to change the starting or ending value
    for (int i = 1; i < 5; i += 2)
    
  • What numbers does the above loop tally?
Be the computer

Tracing a Loop

  • To understand what is happening with these loops it is important to trace iterations
  • In essence, we must "be the computer" and follow it execution path
  • The counting variable is used by the computer to track the number of iterations
  • Thus a good technique is to keep track of the counting variable to understand the loop
  • In addition, we want to keep track of any other variable processed inside the loop
  • For example, with the following loop we would want to track the variables: sum, i, and reading:
    int sum = 0;
    for (int i = 0; i < 5cout << endl;
     
  • ; i++) {
      int reading = analogRead(0);
      sum += reading;
      delay(1);
    }
    
  • Thus we would write out headings for each value and update the variables for each pass of the loop
    sum   i   reading
    ---   -   -------
    0     0   1
    1     1   2
    3     2   3
    ...

Check Yourself

double sum = 0.0;
for (int i = 0; i < 5; i++) {
  int reading = analogRead(A0);
  sum += reading;
  delay(1);
}
  1. True or false: summing numbers in a loop requires a dedicated variable to store the sum.
  2. For the above loop, if the input numbers are 1, 2, 3, 4, 5 the value of sum after the loop finishes executing is ________.
    1. 3
    2. 5
    3. 10
    4. 15
  3. In the above loop, to sum even numbers only we would change the update statement to ________.
  4. To sum odd numbers only, we would additionally change the initialization statement to start at ________.
  5. To compute the product of the numbers, we would change the update statement to use the operator ________.

Graphing Bar Charts

  • We can use a counting loop to graph a horizontal bar
  • To make the chart, we display a series of '*' characters for the "bar", like:
    cout << '*';
    
  • At the end of the bar, after the loop, we print a newline using:
    cout << endl;
    
  • The following example prints a single bar for every number entered

Example Arduino Application That Displays a Bar Chart

#include <ArduinoSTL.h>

using namespace std;

void setup() {
  Serial.begin(9600);
}

void loop() {
  int num; 
  cout << "Enter a number" << endl;
  cin >> num;
  for (int i=0; i<num; i++) {
    cout << "*";
  }
  cout << endl;
}

Variations

What if we wanted the program to display nicer bars? Here are some variations:
  • The program uses the | (pipes) character to show "caps" on the ends of the bars. 
  for (int i=0; i<num; i++) {
    if (i == 0) {
      cout << "|";
    }
    else if (i == num - 1) {
      cout << "|";
    }
    else {
      cout << "*";
    }
  }
  cout << endl;
  • Here's a addition to the last block that puts a plus sign every five steps to make it easier to read:
  for (int i=0; i<num; i++) {
    if (i == 0) {
      cout << "|";
    }
    else if (i == num - 1) {
      cout << "|";
    }
    else if ((i % 5) == 0) {
      cout << "+";
    }
    else {
      cout << "*";
    }
  }
  cout << endl;

Smooth Fading of an LED

  • As an example looping application, we use a for-loop to smoothly fade in and out an LED

Example Sketch for Pulsing an LED

#include <ArduinoSTL.h> using namespace std; const int greenLED = 10; void setup() { Serial.begin(9600); } void loop() { // Fade out for (int i=0; i<255; i++) { analogWrite(greenLED, i); delay(10); } }

Pulse-Width Modulation

  • Recall that the analogWrite() function is controlling the duty cycle of power supplied to an output pin
  • This technique is called Pulse Width Modulation (PWM)
  • PWM is a technique for getting analog results with digital controls
  • By changing the amount of time that power is supplied to a pin, the amount of power changes proportionally
  • The function analogWrite() controls the pulse width on a scale of 0 to 255 as shown in the following diagram
  • In the image below, the green lines represent a regular time period of around 2 milliseconds

Exercise 2: Fading LED

In this exercise we'll complete the fade in code above.

Specifications

  1. Start the Arduino IDE, copy the example code above and paste it into the main IDE window.
  2. Save the project using the name fader (File > Save As...) to a convenient location like the Desktop or the Arduino projects folder.
  3. Copy and paste the code from the previous section as your starter code. 
  4. Compile the sketch to verify you copied the starter code correctly.

    When compiling is successful, you will see a message at the bottom of the source code window saying, "Done compiling."

  5. Upload the sketch and observe the LED fading.
  6. Add another for loop that causes the LED to fade in. 
    1. To fade in the index variable must start at 255 and decrease to 0. 
  7. Verify that your LED fades in, then out, then in, then out, etc...
  8. Save your fader.ino file to submit to Canvas with the next homework.

When finished, please help those around you.

Nested Loops

  • Some looping applications have loops nested within other loops
  • For example, we may use a nested loop to print a table of values or draw shapes
  • The following example shows a simple table created with nested loops
  • Let's follow the execution sequence before running the code

Example of Nested Loops

#include <ArduinoSTL.h>

using namespace std;

void setup() {
  Serial.begin(9600);
  cout << "Outer   Inner" << endl;
  for (int outer=0; outer < 4; outer++) {
    for (int inner=0; inner < 4; inner++) {
      cout << outer << "\t" << inner << endl;
    }
  }
}

void loop() {
}

Tracing the Variables

  • To understand a looping application, we need to trace the loop by hand
  • To trace the loop, write the variables used in the loop as headings across a page
  • On the first line under the headings, write the initial values
  • Execute the loop 3-5 times and record the values of the variables each time through the loop
  • Pay especial attention when entering the loop the first time and when ending the loop
  • We can slightly modify the computations if it helps to test the loop
  • Below is an annotated trace of the variables for the inner and outer loops
  • Note that the outer loop changes only after the inner loop is finished
Memory  Screen 
 outer   inner   
  1   1 1 1
    2 1 2
    3 1 3
    4 (end of loop)    
  2   1 2 1
    2 2 2
    3 2 3
    4 (end of loop)    
  3   1 3 1
    2 3 2
    3 3 3
    4 (end of loop)    
  4 (end of loop)       

Nested Loop Example: Graphing PWM

  • As an example of nested loops, let us add a bar chart to the PWM project
  • In the loop() section, we had coded a for-loop to pulse the LED

Loops Inside of Loops

  • Notice that we already have a loop inside of another loop
  • The loop() section of an Arduino sketch is a built-in loop that every sketch must have
  • Inside of the loop() function we have a for-loop to pulse the LED
  • However, we want to add yet another for-loop inside the existing for-loop
  • This will give us a loop structure that is three loops deep!

Adding a PWM Bar Chart

  • Combine the "Bar Chart" code example with the previous exercise.
  • The loop we want to add is to display a bar chart of the current PWM level
  • Since the counter variable i has the current PWM level, we can use it for the ending value of the loop
      for (int j=0; j<num; j++) {
        cout << "*";
      }
    
  • Notice that the new loop has a new counter variable "j"
  • Use of i, j and k are common in for-loops

Scaling the Bar Chart

  • PWM values range from 0 to 255
  • Thus adding the above loop displays a bar chart that is up to 255 characters wide
  • We can reduce the range of values to make a more displayable chart
  • A convenient value is to reduce the width of the chart by a factor of 8
  • Thus, we would print a single '*' character for every 8 values
  • Why is a factor of 8 a convenient value?
  • The following code displays a the bar chart scaled by a factor of 8

Code for a Scaled Bar Chart

for (int j=0; j<num; j+=8) {
    cout << "*";
}

Exercise 3: Graphing the PWM Value

In this exercise we add bar graphs to the starter code of the PWM project from the last exercise.

Specifications

  1. Start with the code from the last exercise.
  2. Save As a new sketch called graph-fader
  3. Compile the sketch to verify the starter code is correct.
  4. When compiling is successful, you will see a message at the bottom of the source code window saying, "Done compiling."
  5. Add the following code inside the current for-loop 

    for (int j=0; j<num; j+=8) {

        cout << "*";
    }
    cout << endl;

  6. Compile and upload your code to verify it works correctly.
  7. If you have problems, ask a classmate or the instructor for help.
  8. Verify your code with the example shown below. Your code does not need to be the same but comparing helps understand other ways of coding.
  9. Save your graph-fader.ino file to submit to Canvas with the next homework.

When finished, please help those around you.

Summary

  • We looked at how to graph a bar chart using a for-loop
  • Inside the basic loop, we can add variations using if-else statements
  • Some looping applications have loops nested within other loops
  • The structure of nested loops looks like:
    for (int outer = 1; outer < 4; outer++) {
      for (int inner = 1; inner < 4; inner++) {
        
      }
    }
    
  • We added a bar chart to the PWM project with a nested for-loop

Wrap Up and Reminders

  • When class is over, please shutdown your computer.
  • Complete any unfinished exercises from today 
Comments