Back

Activity 2.8: Analog Input

The Messy Real World — Day 1 of 4

divider

Activity 2.8

Analog Input

Key Concepts

Analog Input

Scaling a Range

Position in a List

Activity 2.3 Told You a Half-Truth

"A digital pin has exactly two states. No in-between."

True — of digital pins. Today you meet the other kind, which reports a whole range.

Two Kinds of Answer

button.value() # 0 or 1. Nothing else.
pot.read_u16() # 0, 1, 2, ... all the way to 65535

A button is a yes-or-no question. A knob is a how much question, and the board answers with a number from 0 to 65535.

Reading an Analog Pin

pot = ADC(Pin(40))
reading = pot.read_u16()

ADC stands for analog-to-digital converter— the circuit inside the board that turns a voltage into a number your code can use.

What the Knob Actually Does

A potentiometer is a strip of resistive material with a slider on it. One end sits at 3.3V, the other at 0V, and the middle leg picks off whatever voltage is at the slider's position.

Turn the knob, move the slider, change the voltage. The ADC turns that voltage into your number.

Too Big a Number

65,536 possible readings. Five LEDs. Those do not line up, so the reading has to be scaled down before it can mean anything to the array.

# 65536 possible readings, 5 LEDs.
height = reading * (5 + 1) // 65536

Six buckets, because "no LEDs" is a valid answer too. Integer division from Activity 1.4 does the whole job.

Now You Need Positions

Every animation in 2.6 treated all five LEDs the same way. A bar graph does not — it lights the first three and leaves the rest dark.

for led in leds: # every LED, same treatment
led.value(1)
leds[i].value(1) # this one, by position

for led in leds: cannot express "the first three." Asking for leds[i] by position can.

Today's Objectives

  • Reading a potentiometer with ADC and read_u16()
  • Explaining how an analog pin differs from a digital one
  • Scaling a 0–65535 reading down onto a smaller range
  • Lighting the first N LEDs to show a value as a bar

Key Terms

Analog Input
A pin that reports a range of values rather than just on or off.
ADC
Analog-to-digital converter — the circuit that turns a voltage into a number.
Potentiometer
A knob that divides a voltage; its middle leg reports the slider's position.
Scaling
Converting a value from one range into another, here 0–65535 down to 0–5.

'F' → Fullscreen

divider

Build

Leave Activity 2.6's five-LED array exactly as it is. Create a new MicroPython program named 2-8-analog-input.


Task 1: Read the Knob

  • Wire the potentiometer: its two outer legs to 3V3 and GND, its middle leg to A0.
  • Create it as an ADC and print the reading in a loop.
  • Turn the knob slowly and watch the numbers move.

The analog pins are the six on the bottom header, labeled A0 through A5. A0 is at the far right:

The SparkFun IoT RedBoard RP2350 with the pin labeled A0 outlined on the bottom header

It does not matter which outer leg goes to 3V3 and which to GND — swapping them just reverses which way you turn the knob to get a bigger number.

Circuit diagram of a potentiometer with its outer legs on 3V3 and GND and its wiper connected to analog pin A0
[PHOTO PLACEHOLDER — Task 1: Potentiometer Wired Beside the Five-LED Array]
Analog Input
from machine import Pin, ADC
import time
pot = ADC(Pin(40))
while True:
print(pot.read_u16())
time.sleep(0.2)

Task 2: Find Its Real Range

  • Track the lowest and highest readings you have seen, the same way you tracked your best reaction time in 2.7.
  • Turn the knob all the way in both directions.
  • Write down the two numbers you actually get. You will need them next session.

Do not assume the answer. A knob turned fully one way may not read 0, and fully the other way may not read 65535. Find out what your knob does.

Analog Input
from machine import Pin, ADC
import time
pot = ADC(Pin(40))
lowest = 65535
highest = 0
while True:
reading = pot.read_u16()
if reading < lowest:
lowest = reading
if reading > highest:
highest = reading
print("now:", reading, " lowest:", lowest, " highest:", highest)
time.sleep(0.2)

Task 3: Scale the Reading

  • Bring the five-LED array into this script.
  • Write bar_height(reading, led_count) that converts a reading into a whole number of LEDs.
  • Print the reading and the height side by side, and check the height climbs 0, 1, 2, 3, 4, 5 as you turn.
Analog Input
from machine import Pin, ADC
import time
leds = [
Pin(28, Pin.OUT),
Pin(29, Pin.OUT),
Pin(30, Pin.OUT),
Pin(31, Pin.OUT),
Pin(32, Pin.OUT),
]
pot = ADC(Pin(40))
def bar_height(reading, led_count):
return reading * (led_count + 1) // 65536
while True:
reading = pot.read_u16()
print("reading:", reading, " bar:", bar_height(reading, len(leds)))
time.sleep(0.2)

Task 4: Light the Bar

  • Write show_bar(leds, count) that lights the first count LEDs and turns the rest off.
  • Call it every time round the loop, so the bar follows the knob live.

This is the function that needs leds[i]. Work out for yourself why for led in leds: cannot do it before you read the code below.

Analog Input
from machine import Pin, ADC
import time
leds = [
Pin(28, Pin.OUT),
Pin(29, Pin.OUT),
Pin(30, Pin.OUT),
Pin(31, Pin.OUT),
Pin(32, Pin.OUT),
]
pot = ADC(Pin(40))
def bar_height(reading, led_count):
return reading * (led_count + 1) // 65536
def show_bar(leds, count):
for i in range(len(leds)):
if i < count:
leds[i].value(1)
else:
leds[i].value(0)
while True:
reading = pot.read_u16()
height = bar_height(reading, len(leds))
show_bar(leds, height)
print("reading:", reading, " bar:", height)
time.sleep(0.1)
[PHOTO PLACEHOLDER — Task 4: Bar Graph at Mid-Range, Three LEDs Lit]

Challenge (Optional): The Knob Sets the Speed

  • Bring your chase() function over from Activity 2.6.
  • Use the knob to set the pause length instead of the bar height, so turning it speeds the animation up and slows it down.
  • A pause between about 0.02 and 0.5 seconds works well — scale the reading into that range.
divider

Checkpoint

Turning the knob from one end to the other should print something like this, and move the bar with it:

Terminal window
reading: 148 bar: 0
reading: 11302 bar: 1
reading: 24907 bar: 2
reading: 38455 bar: 3
reading: 51100 bar: 4
reading: 65216 bar: 5
  • The bar follows the knob smoothly, with no jumps of more than one LED
  • Fully one way gives no LEDs lit; fully the other gives all five
  • The printed height never goes below 0 or above 5
  • Holding the knob still leaves the reading roughly — but perhaps not exactly — steady
divider

Reflection

Answer the following questions before submitting your work.

  1. Activity 2.3 said a digital pin has exactly two states. How is an analog pin different, and why did the reading have to be scaled before the LED array could show it?
  2. Every animation in 2.6 used for led in leds:, but show_bar() needs leds[i]. Explain what the bar graph asks for that a plain traversal cannot give.
  3. In Task 2 you recorded your knob's real lowest and highest readings. Were they exactly 0 and 65535? What would go wrong in a program that simply assumed they were?
divider

Submit

Submit the required files to the appropriate dropbox.

Activity Complete