Summary: I looked at the voltage and current supplied to the BBC micro:bit for different numbers of active LEDs. The voltage to the LEDs is pulsed at about 55Hz, with each LED on about 1/3 of the time at maximum intensity. The frequency is high enough that the LED appears continuously lit. The current draw from a single pin is in spec for the microcontroller. The current supplied to each LED decreases as the total number of LEDs being sourced from the same microcontroller pin increases. If the LED ntensity is decreased in code, then the LED is active for a smaller fraction of each voltage cycle.
An interesting question at stackexchange asked how the pins to the microcontroller on the microbit could handle the current to and from all 25 of the LEDs on the board. At first glance, it looks like there are too many LEDs being supplied by too few pins to stay within the 5mA current limit for a single pin on the Nordic nRF51822 microcontroller.
There is a schematic for the microbit board on github. A screenshot showing how the microcontroller pins are connected to the LEDs, taken from sheet 1 and 5 of the github site is shown below.
There are three pins called ROW1-ROW3 that supply current to the anodes (the left of the LED symbol) of all 25 LEDs. Pin PO.13 on the microcontroller is connected to ROW1 and supplies 9 LEDs. Pin PO.14 connects to ROW2 and supplies 7 LEDs. Pin PO.15 connects to ROW3 and supplies 9 LEDs. According to the datasheet for the microcontroller, up to 3 pins can supply or sink up to 5mA in 'high-drive' mode. The rest can source or sink 1.5mA each.
The cathode (the bit of the LED connected to the resistor) of each LED is connected to one of nine 220 Ohm resistors. Upto 3 LED cathodes are connected to each resistor. Each of the nine resistors is then connected to a single microcontroller pin, to sink the LED current.
A limit of 5mA from a single pin to source current to 9 LEDs is not a lot. So what is happening? Are the pins being overloaded?
I pulled the C++ microbit compiler code from the lancaster university github. It looks like one row of the microbit display is illuminated at a time and the display constantly scans through the rows.
Anything that turns on and off at a frequency greater than about 15Hz appears as if it is constantly on.
Using a power supply, I measured the current draw with different numbers of LEDs active. The voltage applied was 3.00V from a TTi EX345RD power supply.
The results surprised me:
LEDS current in mA
So about 14.01-4.74 = 9.27mA extra current is being used to supply 25 LEDs.
I used an Analog Discovery 2 with its Wavefroms software to both power the board and as a 'scope. A Fluke multimeter measured the current and was used to verify that the supply voltage stayed constant.
The Analog Discover 2 supply pins were connected to the ground and 3V pin on the edge connector for the microbit. With a supply voltage of 3V from the Analog Discovery 2, I measured 3.001V across the ground and 3V edge connector pins for 1 LED on and 2.994V with all 25 LEDs on, so the voltage drop across the supply pins is 0.2% while increasing the number of active LEDs. Not much of a voltage drop.
With the 'scope, I can see that the voltage to each LED is indeed pulsed. The screen shot taken from the Waveform software below shows what I saw 'scoping the anode of an LED. The red vertical lines show where I measured time intervals. I am fairly sure that I am 'scoping the LED's anthode as I could count 9 of the pins connected to this side of the LED and 3 at the other end. Which agrees with the schematic. Plus I used my Fluke to verify the LED polarity. Matty likes to double check what he is measuring after having made so many, many mistakes over the years.
Clearly the current draw I measured from the power supply was showing the average current. The current through the LEDs will vary with the voltage. The resistor is 220 Ohm. The current will be V^2/R, where V is the voltage across the resistor.
The LED voltage at the anode is high for 5.8824ms out of 17.914ms = 32.83% duty cycle. So the pin is high for about 1/3 of the time. This makes sense - one pin out of the three that supply current to the LEDs is active at a time. The pulse frequency is 55.821Hz. So the pulsing is invisible to the eye.
The frequency and pulse widths do not change with the number of LEDs that are on. What does change is the anode and cathode amplitude. This drops as the number of LEDs on increases. The supply voltage to the microbit stayed almost constant though.
The image below shows the anode voltage on two separate supply pins, showing that they are indeed turned on at different times. Should I have three probes, the gap would be filled in by 'scoping the pin supplying the third row of LEDs.
With no LEDs on, the voltage rail was 3.0200 on the 'scope. Fair enough. That's pretty much the supply rail. With all LEDs on, I measured two voltages, 2.0896V and 2.1640V. If you've been paying attention, it won't be a suprise that the higher voltage occurs on 7 LEDs (ROW2 on the schematic) and the lower on the remaining 18 (ROW1 and ROW3 on the schematic).
Let's look at the cathode of one of the LEDs. A screen grab is shown below. With a single lit LED, the cathode is at 3V for 2/3 of the time as the sink pin goes high to prevent current, from, well, being sinked. When it goes low, current can flow from through the LED and the resistor and back to ground through the microcontroller pin. Thus completing the circuit and allowing the LED to light up. When the current is flowing, the voltage drops at the cathode. In this screen grab, with only 3 LEDs active, I measured 912.34mV at the cathode of the lit LED. Which makes for a current of 0.91234^2/220 = 3.78mA through the single LED and resistor. Note: I had the LEDs set on maximum intensity.
What is interesting, is that the low value of the cathode voltage decreases with an increasing number of lit LEDs. So the current flowing through the LED must similarly decrease. So the voltage and thus current decreases with increasing lit LEDs, which means that the brightness also decreases. Similarly, the fraction of time that the cathode is high also decreases as the number of active LEDs increases, which makes sense, as for a greater fraction of the time the multiplexed cathode will be sinking current.
With all LEDs on, I measure 356.81mV for 1/3 of the time and 292.46mV for 2/3 of the time. Can you guess why the voltage is stepped between the two values? I suspect it as the voltage switches between supplying 9 and 7 LEDs. Please see the two 'scope grabs below.
The human eye is not so good at discerning different light intensities. I think that having a bunch of LEDs not so brightly lit as a single one also helps fool the eye in judging their individual brightness.
With all LEDs on, the maximum current flow through the 220 Ohm resistor for the pin supplying 7 LEDs is 0.35681^2/220 = 0.5787mA. So for 7 LEDs, the total draw is 4.05mA.
For the 9 LED pins, the current per LED is 0.29246^2/220 = 0.3888mA. So for 9 LEDs, this is 3.499mA, again inside the 5mA spec for a single 'high-drive' pin to supply. However, the pin is only active for about 1/3 of the time. So the average current flow per LED will be 1/3 of the above values.
The current sinking into the pins that sink current is within the 1.5mA spec for a non 'high-drive' pin.
Lets look at all 25 LEDs active. About (7 x 0.5787 x 1/3)+ (9 x 0.3888 x 2/3) is being drawn at any instant. Which is 4.125mA. I measured an increase of around 9mA with all LEDs active. Hmmm, where does the extra current go? I'm open to suggestions. I've gone down the rabbit-hole with this. Time to move onto something else.
An obvious question is: How do the traces look when the intensity changes? I edited the code shown at the end of the article to have the minimum LED intensity. Prior to this, I'd had everything set at maximum intensity.
Looking at the 'scope, the anode voltage stayed the same as for when we have maximum intensity - it is high for about 1/3 of the time for any given LED. Below see the cathode voltage for minimum intensity, all LEDs lit and a repeat of the image for when the LED intensity is maximum. We can see that the cathode voltage goes low, which allows current to flow, for much less of the cycle when the intensity is at a minimum. Which makes sense. At maximum intensity, current flows for almost all of the time that the anode voltage is high (about 1/3 of the time). I measured the cathode coming low for only 32.637us at minimum intensity, which is only about 0.18% of the illumination cycle, compared with the roughly 32% of the time when at maximum intensity.
I work at sea for half of the year, on a six week on, six week off rota. I first looked at this while I was on a survey ship, with limited test equipment and time as I am paid to do 12 hour shifts, that usually over run. Obviously, the ship would stop operating if Little Matty was not at his station when he is supposed to be.
I found a voltage supply on the ship, lashed this up to the microbit with a set voltage of 3.00V and measured the current draw through a Fluke multimeter for different numbers of LEDs. What I did not have access to was a 'scope. So I finished off my investigations when I was back home.
Looking at the display through a digital camera - I could see that the LED brightness is not constant. The frame rate of the digital camera is not synced with the refresh rate of the display, so as the rows are switched on and off, this is picked up as a variation in intensity in the camera display.
So even without a 'scope, I was pretty sure that the rows were being pulsed on and off. Actually, there is a 'scope on the ship, but as it is connected to the recording equipment to monitor all is well, I figured I should leave it in place.
Here's my micropython script to turn on/off one LED at a time using the A/B buttons:
# ''' Light LEDs using A and B buttons. ''' from microbit import * # intensity of LED BRIGHT = '9' # how many LEDs to turn on at a time INCREMENT = 1 # maximum number of LEDs allowed on at once MAX_BRIGHT = 25 # how many LEDs on at boot START_BRIGHT = 3 def decrease(num_bright, inc): num_bright = limit(num_bright-inc, MAX_BRIGHT) return num_bright def increase(num_bright, inc): num_bright = limit(num_bright+inc, MAX_BRIGHT) return num_bright def leds_string2(bright): ''' return led string ''' bright = limit(bright, MAX_BRIGHT) leds_string = BRIGHT*bright + '0' * (MAX_BRIGHT-bright) leds_string = ":".join(leds_string[i:i+5] for i in range(0, len(leds_string), 5)) leds_image = Image(leds_string + ':') return leds_image def limit(val, limit): ''' limit <val> between 0 and <limit>''' if val > limit: val = 0 if val < 0: val = MAX_BRIGHT return int(val) num_bright = START_BRIGHT while True: if button_a.was_pressed(): num_bright = (decrease(num_bright, INCREMENT)) if button_b.was_pressed(): num_bright = (increase(num_bright, INCREMENT)) display.show(leds_string2(num_bright)) sleep(0.1)