The UNO R4 WiFi is the latest addition to Arduino’s line of classic microcontrollers. In addition to the powerful Renesas RA4M1 microcontroller, the new board features a 12 x 8 LED display matrix. Perhaps you have seen the iconic heart symbol displayed on the LED matrix. This is the default program included with every Arduino UNO R4 WiFi as shown in Figure 1.
The operation of the Arduino UNO R4 WiFi is well documented with a user-friendly API. However, we have an opportunity to explore the theory of operation behind the LED display matrix at a hardware level. This is an excellent opportunity to learn more about the nature of a microcontroller’s I/O and multiplexing techniques.
Figure 1: Heart displayed on the Arduino Uno R4 LED display matrix.
How do we control 96 LEDs with 11 control lines?
The simple answer is a technique known as Charlieplexing, supposedly named after its inventor Charles Allen. The technique depends on the tri-state nature of a microcontroller’s output pins. Each pin may be configured as:
- output: logic low
- output : logic high
- input: high impedance
This operation is suggested in Figure 2 using a series of switches. For example, a microcontroller’s tri-state switch such as TRI_0 determines if the respective pin will be an input or an output. When it is open, each microcontroller’s I/O pin floats (high impedance), allowing external circuitry to determine the voltage. When it is closed, the ROW_0 driver determines the pin’s output voltage. Follow this link for an interactive MultisimLive simulation based on Figure 2. As a challenge, try to activate LED1 to LED6 in sequence.
Figure 2: Simplified schematic for the first 6 LEDs in the Arduino UNO R4 WiFi’s LED display matrix. Follow this link for an interactive simulation.
With respect to Figure 2, we see that LED1 is activated. This occurs when ROW_0 sources current and ROW_1 sinks. We can activate LED2 by toggling both the ROW_0 and ROW_1 logic. When this is done, ROW_1 will source and ROW_0 will sink.
Note that ROW_2 is configured as an input with high impedance. This is important as it prevents multiple LEDS from activating at the same time. For example, as drawn in Figure 2, if TRI_2 was activated:
- ROW_2 high: both LED1 and LED6
- ROW_2 low: both LED1 and LED3
Tech Tip: The terms “source” and “sink” can be confusing to newcomers to electronics. This is a frame of reference problem partially attributed to the history of physics. It begins with Benjamin Franklin’s experiments in the 1750s where he proposed a current flow from the positive terminal to the negative terminal of a source. Nearly 150 years later, J.J. Thomson discovers the electron in 1897. Since then, we have thought about electricity in terms of Franklin’s conventional flow (positive to negative) and electron flow (negative to positive).
You would think this is a solved problem. However, even today, you can select textbooks with either convention. Inspection will show that every current vector is reversed, and all right-hand rules are replaced with left and vice-versa.
Once again, the terms sourcing and sinking are dependent on your frame of reference. For clarity, we will follow the conventional flow where the positive supply terminal “sources” the current and the negative terminal “sinks” the current. In Figure 2, the 5 VDC is the source, and the ground is the sink.
Arduino code example
We can use Arduino code to better understand the operation of Figure 2. For convenience assume the LED matrix is connected to pins D0, D1, and D2 corresponding to ROW_0, ROW_1, and ROW_2. As shown this code, LED1 is activated when:
pinMode(D0, OUTPUT); // Tri state configuration
pinMode(D1, OUTPUT);
pinMode(D2, INPUT);
digitalWrite(D0, HIGH); // Logic assertion when the Tri state buffer is active
digitalWrite(D1, LOW);
As another example, suppose we wish to activate LED5:
pinMode(D0, INPUT);
pinMode(D1, OUTPUT);
pinMode(D2, OUTPUT);
digitalWrite(D1, HIGH);
digitalWrite(D2, LOW);
Multiplexing
Up to this point, we have concerned ourselves with control of a single LED. In practice, it is desirable to simultaneously turn on multiple LEDs. For example, suppose we wish to simultaneously activate LED1 and LED5. This is not directly possible given the Figure 2 schematic. If LED1 is on, close inspection of Figure 2 shows that the only other possibilities are LED3 or LED6. In fact, if we walk through all 8 possibilities, we will see that only 2 LEDs can simultaneous be lit for any given switch state.
The solution is to multiplex the LEDs.
With this multiplexing technique, one and only one LED is active at any given time. We rapidly toggle between the LEDs with each LED on for a brief period. For example, to activate LED1 and LED5 we could alternate between the code snippets in the previous section. The human eye will observe both LEDs simultaneously lit, provided the round-robin sequence is completed at a rate faster that approximately 30 Hz. This persistence of vision (flicker fusion) provides an illusion that the LEDs are simultaneously activated.
One significant problem with this technique is LED brightness. Recall that multiplexing is a time division process where each LED is allotted a time slot. With our two LED problem, each LED is on for 50% of the time. For the six LED problem shown in Figure 2, each LED is on for 16% of the time. It stands to reason that an LED that is on for 50% of the time will be brighter than one that is on for 16% of the time. Refer to this article for an expanded exploration of LED multiplexing with analysis of brightness, time, and pulse current.
Charlieplexing on the Arduino UNO R4
A cursory review of the Arduino UNO R4 WiFi datasheet reveals that the LED display matrix is driven by 11 microcontroller I/O pins. It also shows a matrix of complimentary LEDs where each pair of LEDs is configured anode to cathode and cathode to anode. A small section of the schematic is included as Figure 3. Note that this is nearly identical to the Figure 2 example. The Charlieplexing principle of operation is identical to that described in the previous section.
Figure 3: This small portion of the Arduino UNO R4 WiFi schematic corresponds to Figure 2.
How can I increase the brightness of the Arduino UNO R4 WiFi display?
The short answer is to recognize that the LED brightness is constrained by the limits of the Charlieplex method which in turn are limited by the microcontroller’s current limited I/O pins. We must also consider the overhead associated with modifying the easy-to-use LED matrix library.
The display is as bright as it is going to be.
However, you can add a red lens to increase the apparent brightness. For example, the red translucent Hammond 1591STRD serves double duty as enclosure and lens. You can see the results in Video 1.
Video 1: Video of the Hammond 1591STRD enclosure serving as a red lens for the Arduino UNO R4
What are the limitations of the Charlieplex method?
To better understand the Arduino UNO R4 limitations, we need to consider the limitations of the Charlieplex method.
-
Recall that Charlieplexing is a cost-effective method used to control many LEDs. The drive power is derived directly from the microcontroller without resorting to row and column drivers. Consequently, the brightness (LED current) is a directly related to the “strength” of the microcontroller’s driving pins. This is a hard physical limit that cannot be changed without fundamentally changing the display hardware.
-
The brightness of an individual LED is determined by the on time (duty cycle). With 96 LED in the 12 x 8 display, each LED is on for approximately 1% of the time. Each LED must take its turn shining brightly, but for a moment. This is another physical limit that cannot be changed. This is especially true if we desire to keep consistent brightness across the display. For example, if only two pixels are active, we could split the time between them. However, the display would grow less bright as additional LEDs were activated.
In summary, the only way to increase the brightness it to redesign the hardware adding row and column drivers, or to lower expectations and reduce the number of LEDs in the array. Although it’s not a linear process, in general, halving the total number of LEDs will double the perceived brightness as each LED may now be activated for double the time.
Tech Tip: Individual pin current is not a single specification for a complex microcontroller such as the Renesas R7FA4M1AB3CFM#AA0. However, as a general statement, the RA4M1 can handle 8 mA per pin with limitation of 60 mA for all pins combined. Consult the datasheet as there are many additional considerations and stipulations.
How can I directly access an LED from the Arduino UNO R4 LED matrix?
Normally you would use the Arduino library to control the LED display. However, since we are already in the deep end of the pool, we can access the individual RA4M1 Special Function Registers (SFR) using the Renesas Flexible Software Package (FSP). This technique may prove useful for future experiments especially if we need the speed associated with direct port access.
Tech Tip: The Renesas Flexible Software Package (FSP) is a Hardware Abstraction Layer (HAL). In many ways it is like the Arduino language as both are designed to hide/simplify the underlying hardware improving code portability.
You will be interested to know that the Arduino implementations for the UNO R4 Minima and WiFi are built upon a Renesas FSP foundation.
Careful review of the Arduino UNO R4 WiFi schematic shows that:
- ROW_0 corresponds to P205 (port 2 pin 5)
- ROW_1 corresponds to P012 (port 0 pin 12)
- ROW_2 corresponds to P013 (port 0 pin 13)
For example, to turn on LED 1 we could use this code snippet.
R_IOPORT_PinCfg(NULL, ROW_0, IOPORT_CFG_PORT_DIRECTION_OUTPUT);
R_IOPORT_PinCfg(NULL, ROW_1, IOPORT_CFG_PORT_DIRECTION_OUTPUT);
R_IOPORT_PinCfg(NULL, ROW_2, IOPORT_CFG_PORT_DIRECTION_INPUT);
// Assume all other row drivers are inputs (high impedance)
R_IOPORT_PinWrite(&g_ioport_ctrl, ROW_0, BSP_IO_LEVEL_HIGH);
R_IOPORT_PinWrite(&g_ioport_ctrl, ROW_1, BSP_IO_LEVEL_LOW);
To turn on LED5 we could use this code snippet:
R_IOPORT_PinCfg(NULL, ROW_0, IOPORT_CFG_PORT_DIRECTION_INPUT);
R_IOPORT_PinCfg(NULL, ROW_1, IOPORT_CFG_PORT_DIRECTION_OUTPUT);
R_IOPORT_PinCfg(NULL, ROW_2, IOPORT_CFG_PORT_DIRECTION_OUTPUT);
R_IOPORT_PinWrite(&g_ioport_ctrl, ROW_1, BSP_IO_LEVEL_HIGH);
R_IOPORT_PinWrite(&g_ioport_ctrl, ROW_2, BSP_IO_LEVEL_LOW);
We can then multiplex between LED0 and LED5 using this code:
#define ROW_0 BSP_IO_PORT_02_PIN_05
#define ROW_1 BSP_IO_PORT_00_PIN_12
#define ROW_2 BSP_IO_PORT_00_PIN_13
void setup() {
;
}
void loop() {
R_IOPORT_PinCfg(NULL, ROW_0, IOPORT_CFG_PORT_DIRECTION_OUTPUT);
R_IOPORT_PinCfg(NULL, ROW_1, IOPORT_CFG_PORT_DIRECTION_OUTPUT);
R_IOPORT_PinCfg(NULL, ROW_2, IOPORT_CFG_PORT_DIRECTION_INPUT);
R_IOPORT_PinWrite(&g_ioport_ctrl, ROW_0, BSP_IO_LEVEL_HIGH);
R_IOPORT_PinWrite(&g_ioport_ctrl, ROW_1, BSP_IO_LEVEL_LOW);
delay(20);
R_IOPORT_PinCfg(NULL, ROW_0, IOPORT_CFG_PORT_DIRECTION_INPUT);
R_IOPORT_PinCfg(NULL, ROW_1, IOPORT_CFG_PORT_DIRECTION_OUTPUT);
R_IOPORT_PinCfg(NULL, ROW_2, IOPORT_CFG_PORT_DIRECTION_OUTPUT);
R_IOPORT_PinWrite(&g_ioport_ctrl, ROW_1, BSP_IO_LEVEL_HIGH);
R_IOPORT_PinWrite(&g_ioport_ctrl, ROW_2, BSP_IO_LEVEL_LOW);
delay(20);
}
When the code is run, the LEDs will appear to flicker. The flicker will be eliminated when the delay is reduced to about 10 ms.
Conclusion
The Arduino UNO R4 WiFi includes a 12 x 8 LED display matrix that is best described as fun! True to form, Arduino provides an easy-to-use library that allows you to configure and use the display in minutes.
Personally, I appreciate the UNO R4 WiFi hardware design as it provides a learning opportunity to explore the Charlieplexing technique. This hardware application provides a window into the microcontroller’s tri-state outputs, multiplexing, and tools such as the Renesas FSP. Together it leads to an increased understanding of LED current and pulsed operation.
Test your knowledge by answering the questions and critical thinking exercises located at the end of this note. Your questions and comments are welcomed in the space below.
Finally, please leave a thumbs up if you learned something.
Best wishes,
APDahlen
Helpful links
Please follow these links to related and useful information:
- Digikey’s product selection guides
- Arduino education content
- Using the Arduino UNO R4 WiFi LED Matrix
- Arduino UNO R4 WiFi Documentation
- Renesas RA4M1 documentation
- Renesas Flexible Software Package (FSP)
About this author
Aaron Dahlen, LCDR USCG (Ret.), serves as an application engineer at DigiKey. He has a unique electronics and automation foundation built over a 27-year military career as a technician and engineer which was further enhanced by 12 years of teaching (partially interwoven with military experience). With an MSEE degree from Minnesota State University, Mankato, Dahlen has taught in an ABET-accredited EE program, served as the program coordinator for an EET program, and taught component-level repair to military electronics technicians. Dahlen has returned to his Northern Minnesota home and thoroughly enjoys researching and writing educational articles about electronics and automation.
Highlighted experience
Dahlen is an active contributor to the DigiKey TechForum. At the time of this writing, he has created over 170 unique posts and provided an additional 570 forum posts. Dahlen shares his insights on a wide variety of topics including microcontrollers, FPGA programming in Verilog, and a large body of work on industrial controls.
Questions
The following questions will help reinforce the content of the article.
-
What is a tri-state buffer?
-
Describe the physical output pin circuitry for a typical microcontroller. Hint: Define and include the three states.
-
How many I/O pins are required to control the Arduino UNO R4 WiFi’s 12 x 8 LED matrix?
-
Given the number of I/O pins identified in the previous question, how many LEDs could be controlled? For example, would the control method facilitate another row or another column?
-
How is Charlieplexing dependent on the properties of a microcontroller’s output section?
-
Research flicker fusion and identify at least two considerations to maintain the illusion.
-
Describe the term duty cycle as it relates to an individual LED in the display matrix.
-
What is direct port manipulation? What is HAL? How do the techniques relate to the Arduino API?
-
Use Renesas FSP based code to sequentially Cylon scan (Battlestar Galactica - back and forth motion of a single LED) the first 12 LEDs.
-
Use Renesas FSP based code to alternate between the 12 odd and the 12 even LEDs.
-
Use the Arduino API to perform the same Cylon scan on the first 12 LEDs.
-
The term “driver” is often used to describe code to configure/control hardware. How is the term used in the Renesas environment?
Critical thinking questions
These critical thinking questions expand the article’s content allowing you to develop a big picture understanding the material and its relationship to adjacent topics. They are often open ended, require research, and are best answered in essay form.
-
What is meant by code portability? Present examples framed in the context of direct port manipulation, HAL, and in term of the Arduino API.
-
Contrast and compare the Charlieplex method with an independent LED driver such as the 74595 IC.
-
Provide two hardware recommendations to the Arduino team for improvements of the Arduino UNO R4. Make a solid business case with consideration of cost and benefits.
-
The Arduino language and the Renesas FSP are both examples of HALs. Contrast and compare the two abstractions. Hint Portability has multiple meanings. Also, identify the needs of the target programmer(s).
-
Research LED parameters for a distinction between continuous and pulsed operation. Armed with this knowledge, provide recommendations for a Charlieplex and a row/column drive configuration.