A binary value can hold one of two states: 1 or 0. Up to this point, we’ve been using those 1/0 binary values to turn lights on and off with pin14.write_digital(1) and pin14.write_digital(0).
In electronics, digital to analog conversion is used to make things seem like they are analog (varying continuously). For example, with the LED in this activity, you will use the digital values of 0 through 1023 and back to 0 to make the LED light take small steps from dim to bright and then to dim again. The steps will be so small that human eyes cannot perceive them, so it is called “digital to analog conversion”.
The pin14.write_analog() method accepts arguments from 0 to 1023 to set the LED’s brightness from off to full brightness. Here are some examples of write_analog calls that adjust how brightly the P14 LED shines.
pin14.write_analog(1023) # Max brightness
pin14.write_analog(512) # half brightness
pin14.write_analog(256) # quarter brightness
pin14.write_analog(1) # 1/1024th of full brightness
In this activity, you will experiment with write_analog and scripts that control the brightness of the P14 LED. You will also use for loops to make this brightness seem to vary continuously (analog).
For this activity, you will re-use the same setup and LED circuit from Connect and Blink a Light.
This script sets a light to ⅛, ¼, ½, and full brightnesses.
# led_brightnesses from microbit import * while True: pin14.write_analog(128) sleep(1000) pin14.write_analog(256) sleep(1000) pin14.write_analog(512) sleep(1000) pin14.write_analog(1023) sleep(1000)
Remember from the Connect and Blink a Light activity’s On-Off Signals [3] section that a blinking light has a period, frequency, and duty cycle. The period is the total on/off time for a single blink, abbreviated T and measured in s. The frequency is the blinks per second, abbreviated f and measured in Hz. The duty cycle is the percent of the period that the light is on.
The write_analog() method makes the light blink at 50 times per second (f = 50 Hz). That’s faster than the eye can see, but the eye does detect the high time of each blink as brightness. If the light is on for ½ the time, it appears to be half as bright. On for ¼ of the time -¼ as bright, and so on…
Remember that the period is 1/f. In the case of write_analog, the micro:bit sets the light's blink period to T = 1/50 Hz = 20 ms. You have 1024 options for how long the light stays on during the 20 ms period — from 0/1024ths to 1023/1024ths of the time. For 50% duty cycle (and 50% brightness), use pin14.write_analog(512). That’ll give you 512/1024ths of on time, which is 50%.
Example: Set the brightness to 25%.
Solution: For 25% brightness, we need 25% duty cycle. 0.25 x 1024 = 256, so use 256 in write_analog, like this: pin14.write_analog(256).
Here is an example that uses a for loop inside a while loop to repeatedly fade-in brightness from 0 to max (1023).
In the physical world, analog quantities like light intensity and audio volume are continuously variable. Think of “continuously variable” as having an infinite number of increments in any range. Like the blue analog line in the diagram. It’ll have values like 514.00... and 515.00..., but between those two levels, there’s an infinite number of other levels. Two examples include 514.33… and 514.66…
In electronics, analog quantities are represented by digital steps, like the orange 509 through 515 integer steps in the diagram. Many electronic devices store digital step values and use them to synthesize analog values. In addition to the light intensity example we are working with, music and video streaming use digitized audio and video data. But, the steps in the digitized values are so close together that we cannot hear/see the difference.
In the case of the micro:bit, it can set the LED to 1024 different brightnesses (including off). If it increases by one increment at a time, it looks like it varies continuously, but it’s actually stepping from one brightness to the next. Even so, it is commonly called an “analog” setting, and the process of converting a number in the 0 to 1023 range to an LED brightness is a form of “digital to analog conversion”.
Digital to analog conversion devices normally have a number of steps that is some power of two. For example, 1024 is 210. The power of 2 is actually a memory size, measured in “bits” which are memory elements that can store binary digits: 1 or 0. In the case of the micro:bit D/A converter, it’s called a 10-bit digital to analog converter. With 10 bits or memory (10 binary 1/0 digits), you can count from 0 through 1023:
Decimal Binary (10-bit)
1 0000000001
2 0000000010
3 0000000011
4 0000000100
5 0000000101
6 0000000110
7 0000000111
...
509 0111111101
510 0111111110
511 0111111111
512 1000000000
513 1000000001
514 1000000010
515 1000000011
...
1021 1111111101
1022 1111111110
1023 1111111111
Sometimes, it’s helpful to test a small loop to figure out what a larger one will really do. For example, you could use this script to quickly see what the result of a for...in range() loop with one argument will be. Since it prints 0, 1, 2, and 3, it can help verify that it counts from 0 up to, but not including, the value in the parentheses.
for n in range(4): print(n)
Another approach would be to look it up in the Python language documentation. For example, the answer is on this page too: 4. More Control Flow Tools [4]. It’s part of the Python 3 Documentation [5], which is what the MicroPython for the micro:bit is based on.
One way to make the brightness fade in and then fade back out would be to have a loop that counts up, like the one you just tried, followed by a loop that counts back down. Counting down with range needs a start, stop, and negative step value. For example, this for loop counts 5, 4, 3, 2, 1:
for n in range(5, 0, -1): print(n)
Extending that to the for brightness loop, you could use for brightness in range(1023, 0, -1). This would start at maximum brightness and count down to a brightness of 1. That loop following the fade-in loop would fade the brightness back out.
Let’s try the fade-in, fade-out effect explained in the try Did You Know section above.
Solution:
from microbit import* while True: for brightness in range(0,1023,10): sleep(500) pin14.write_analog(brightness) sleep(1000)
Links
[1] https://learn.parallax.com/tutorials/led-lights/connect-and-blink-light
[2] https://python.microbit.org/v/2
[3] https://learn.parallax.com/tutorials/language/python/led-lights/connect-and-blink-light/signals
[4] https://docs.python.org/3/tutorial/controlflow.html
[5] https://docs.python.org/3/contents.html