Lecture 04

E21 Computer Engineering Fundamentals

Author

Emad Masroor

Published

September 10, 2026

Announcements

  • Please complete survey available on Moodle or here.
  • Homework 1 due at midnight tonight
  • Homework 2 to be released today
  • Labs start today

Running code on your Circuit Playground Express

  • The code that’s saved in the special file code.py on your CIRCUITPY drive is automatically run whenever the board is powered on with a USB cable or battery.
  • If the board is in interactive mode, automatic execution of code.py is paused unless you click
  • Enter interactive mode using
  • The code inside code.py runs once whenever the board is reset. You can reset by:
    • pressing the physical reset button
    • unplugging and replugging the USB cable

Importing the time package

Python comes with several packages that need to be imported into programs. These packages can be:

  1. Part of the so-called standard library. Standard library packages must be imported. These include packages such as random, math, calendar and time.
  2. Available for download from the Python package index. These include packages such as numpy, for numerical computing, or matplotlib, for plotting.
  3. Local, unregistered packages
import time
while True:
  print("one iteration")
  time.sleep(2.5) # sleep for 2.5 seconds

It is good practice to insert a time.sleep() command into every while True: loop to prevent the program from getting out of hand.

Objects in Python

  • The line from adafruit_circuitplayground.express import cpx imports the class ‘Express’ which is known as cpx.
  • A class is an object associated with certain attributes and methods.
    • Methods are functions. e.g. the cpx class posssess the function cpx.play_tone(440,1)
    • Attributes are variables that are ‘part of’ the class. e.g., the cpx class possess the following attributes
      • touched — this attribute is set internally based on which pins are being touched.

        >>> cpx.touched
        [board.A2, board.A1, board.A3]
      • cpx.red_led — this attribute can be set by the user

        >>> cpx.red_led
        False

if statements

  • In Python, if statements are followed by indented blocks of code, similar to while.

    from adafruit_circuiytplayground.express import cpx
    if cpx.light < 100:
        cpx.play_tone(440,2)
    elif cpx.light < 200:
        cpx.play_tone(660,1)
    else:
        cpx.play_tone(880,0.5)
  • No end is needed.

  • elif stands for “else, if”

  • The code following an if or elif statement must be a conditional

    • Recall: Conditionals are either True or False.
    • e.g., if it’s dark in the room, cpx.light < 100 will be True.

if else and elif

The following code is equivalent:

  • Using else followed by if:

    if cpx.light < 100:
        cpx.play_tone(440,2)
    else:
        if cpx.light < 200:
            cpx.play_tone(660,1)
        else:
            cpx.play_tone(880,0.5)
  • Using elif

    if cpx.light < 100:
        cpx.play_tone(440,2)
    elif cpx.light < 200:
        cpx.play_tone(660,1)
    else:
        cpx.play_tone(880,0.5)

Multiple elifs in one block

  • Inside the same ‘block’ of code, you can have:
    • One if:
    • As many elif:s as you want
    • One else:
    if cpx.light < 100:
        cpx.play_tone(440,2)
    elif cpx.light < 200:
        cpx.play_tone(660,1)
    elif cpx.light < 400:
        cpx.play_tone(770,0.75)
    else:
        cpx.play_tone(880,0.5)

Nesting if statements

  • If statements can be nested indefinitely:

    if cpx.light < 200:
      cpx.play_tone(440,1)
      if cpx.light < 150:
          if cpx.light < 100:
              cpx.play_tone(330,1)
              if cpx.light < 50:
                  cpx.play_tone(220,1)
  • It’s up to you to check if your nested if statements make logical sense. For example, run and compare the following programs

    • Option A:

      # First, check if light < 200
      if cpx.light < 200:
          # If yes, then ...
          cpx.play_tone(440,1)
          # check if light < 150
          if cpx.light < 150:
              # if light is less than 150:
              cpx.play_tone(330,1)
          else:
              # if light is not less than 150:
              cpx.play_tone(330,2)
      else:
          # if no, light is not less than 200:
          cpx.play_tone(440,2)
    • Option B:

      # First, check if light < 200
      if cpx.light < 200:
          # If yes, then ...
          cpx.play_tone(440,1)
          # check if light > 350
          if cpx.light > 350:
              # if light is more than 150:
              cpx.play_tone(330,1)
          else:
              # if light is not less than 150:
              cpx.play_tone(330,2)
      else:
          # if no, light is not less than 200:
          cpx.play_tone(440,2)
  • In this example, lines 5-8 will never execute.

Printing Text

  • Print statements are commonly used in programs, especially for debugging purposes.

  • The print() function takes as argument a string.

  • In Python, strings are enclosed in single quotes or double quotes.

    • "This is a string"
    • 'This is also a string'
  • Try out this code and shine a flashlight:

    while True:
      if cpx.light < 200:
        print("Light is less than 200")
      else:
        print("Light is more than 200")

Strings embedded with variables

We often want to embed variables into a Python string, before printing it.

  • Variables can be directly printed

    print("the light sensor reads ",cpx.light," in some unknown units")
  • Variables can be embedded into a string by enclosing in {} and preceding the string with the letter f like so:

    print(f"the light sensor reads {cpx.light} in some unknown units")
  • When using f-strings, the precision of numerical variables can be specified using the notation :.nf where n is the number of significant figures after the decimal point.

    print(f"the light sensor reads {cpx.light:.1f} in some unknown units")
  • Write a program that prints the temperature to 2 decimal places at 1 second intervals

Loops and counter variables

Counter variables are used inside a loop to increment each time the loop is run.

  • A simple counter variable

    k = 0
    while True:
        print(f"The value of k is {k}")
        k = k + 1
  • In this example, k is a counter variable.

  • Counter variables can be conditional:

    k = 0
    while True:
      if cpx.light > 200:
        k = k + 1
      print(f"The value of k is {k}")

The break keyword terminates a loop

  • The break keyword terminates the lowest-level loop in which it is found, immediately.

  • Compare the following

    • Option A

      k = 0
      while True:
          k += 1
          print(f"iteration {k}")
          if k == 9:
              break
              print("breaking")
    • Option B

      k = 0
      while True:
          k += 1
          print(f"iteration {k}")
          if k == 9:
              print("breaking")
              break
  • When using nested loops, break terminates the innermost loop only.

    from adafruit_circuitplayground.express import cpx
    import time
    k = 0
    while True:
        time.sleep(1)
        k += 1
        print(f"Outer iteration {k}")
        if k % 3 == 0: # k ÷ 3 has remainder 0
            m = 0
            while True:
                time.sleep(1)
                m += 1
                print(f"Outer iteration {k}, inner iteration {m} ")
                if cpx.touch_A2:
                    print("terminating")
                    break

    Modify this so that if pin A5 is touched, the outer loop terminates

The continue keyword

The continue keyword immediately exits the current iteration of a loop and moves on to the next one.

  • Run and compare the following code

  • Option A

    from adafruit_circuitplayground.express import cpx
    import time
    k = 0
    while True:
        time.sleep(1)
        k += 1
        print(f"Outer iteration {k}")
        if k % 3 == 0: # k ÷ 3 has remainder 0
            m = 0
            while True:
                time.sleep(1)
                if cpx.touch_A2:
                    print("skip this iteration")
                    continue
                m += 1
                print(f"Outer iteration {k}, inner iteration {m} ")
  • Option B

    from adafruit_circuitplayground.express import cpx
    import time
    k = 0
    while True:
        time.sleep(1)
        k += 1
        print(f"Outer iteration {k}")
        if k % 3 == 0: # k ÷ 3 has remainder 0
            m = 0
            while True:
                time.sleep(1)
                m += 1
                print(f"Outer iteration {k}, inner iteration {m} ")
                if cpx.touch_A2:
                    print("skip this iteration")
                    continue
  • In Option A, the inner loop is terminated upon touching A2 before the print statement, so line 16 is not executed if A2 is touched.

  • In Option B, the inner loop is terminated upon touching A2 after the print statement, so line 13 is executed even if A2 is touched.

The pass keyword

pass is used inside a loop (if, while, for, etc.) as a placeholder that doesn’t do anything.

while True:
  pass

The for loop

  • A for loop runs a specified number of times.

    for i in range(5):
        print("Run once")
  • The iterating variable in a for loop has a different value each time the loop is run — like a built-in counter variable that you don’t need to increment.

    for i in range(5):
        print(f"Run once. This time, the value of i is {i}")
  • A for loop iterates over an iterable object. These include:

    • List

      for i in [2,99,3.5,"hello"]:
          print(i)
    • Tuple

      for i in (2,99,3.5,"hello"):
          print(i)
    • Range

      for i in range(2,15,3):
          print(i)
    • String

      for i in "hello":
          print(i)
  • Like any other block of code, you can nest a for loop inside another for loop.

    • A common use of nested loops in engineering is a ‘grid’ of variables

        for i in range(3):
            for j in range(5):
                print(f"i = {i} and j = {j}")

More features of the Circuit Playground Express

  • Switches and buttons:
    • Button A cpx.button_a
    • Button B cpx.button_b
    • Sliding switch cpx.switch
  • Start and stop tone:
    • cpx.start_tone(440) starts playing the tone 440 Hz.
    • cpx.stop_tone() terminates whichever tone is being played.
  • The function cpx.pixels.fill() takes as argument a 3-element tuple and fills all pixels with that color.
    • You can use this with cpx.pixels.fill((0,0,0)) to switch off all neopixels.
  • See the documentation for the Adafruit CircuitPlayground Library to see examples of how to use all of its features.

Conditional LEDs program

Write a program and save to code.py. Your program should:

  • Light up a blue pixel for as long as button A is pressed.
  • Light up a yellow pixel for as long as button B is pressed.
  • If a button is not being pressed, the corresponding light should be off
  • Print a statement about which button is currently pressed every x seconds, where x is a small number less than one.