Tuesday, January 19, 2016

Exploring the I/O Performance of the Arduino 101

In this post I will explore the hardware input/output (I/O) performance of the recently-released Arduino 101.

The new, yet somehow familiar, Arduino 101.


Though many of my personal projects have moved beyond the Arduino eco-system, I still enjoy keeping up with the Arduino line of boards. The newly-available Arduino 101 is a very intriguing addition to the line-up. It packs an Intel Curie system-on-chip (SoC), Bluetooth Low Energy (BLE), and a six-axis accelerometer and gyroscope. Despite these new features, it only costs $30 USD and is surprisingly familiar to hold in the hand. The pinout is similar to an Arduino Uno, with power, digital I/O, and analog inputs in the usual places.

The Quark microcontroller inside the Curie SoC runs the ViperOS real-time operating system (RTOS), which Intel is promising to open-source at some point. That will present some intriguing options for advanced hobbyists and developers to extract maximum performance from the board. For now, we can program it using the Arduino IDE. As I understand it, you don't really "flash" an Arduino 101, but rather upload a new sketch for the RTOS to execute itself.

Though the Arduino IDE makes developing code for projects very easy, it also imposes performance penalties. This is especially noticeable when you are trying to stretch the limits of the I/O. I just unpacked my new Arduino 101. Before delving into the example projects for the board or attempting to port some of my previous projects over, I thought I'd have a look at the performance of the board's I/O lines.

5V Tolerant?

Here's the big question many will ask: Are the I/O pins 5V tolerant? Well, yes they are. Arduino says that the I/O lines on the 101 are 3.3V, but will not be damaged by 5V inputs. Clearly the Curie itself (a modern SoC) is not going to be a 5V device, so let's examine the schematic for the Arduino 101 and see how they accomplish this.

Level Translation on the Arduino 101. (Source: Arduino.cc)

The board uses three Texas Instruments LSF0108 level translators to accommodate all of the I/O lines (including the analog inputs). This is an interesting part. It's not really a level "shifter", and it's not a buffer. The Curie is still sourcing and sinking current to the pins, but the voltage levels are clamped at 3.3V on the Curie's side of the chip. In this regard it's kind of like a fancy analog switch. The on resistance of each signal path is in the neighborhood of 10 ohms.

The fact that the Curie sources and sinks current to the I/O pins is important to keep in mind. The original specs released for the Arduino 101 claimed a max current per pin of 4 mA. That is quite low, especially when you consider the fact that many Arduino tutorials show circuits that would easily exceed the limit. However, it seems that the maximum current per pin is actually 20 mA, based on a post in the Arduino forum and the now-updated product page. I would still like to see more information on current limits, including any limits for I/O banks and the SoC overall limit.

Digital Output Signals

Enough talk, let's look at some signals. For a first test, I programmed the board to toggle digital pin 12 as fast as possible with the standard digitalWrite() routine. The main loop was free-running with no delays. The Arduino 101 was able to produce a 114kHz square wave with this routine. I measured the rise-time at about 13ns on my scope. We aren't going to set the world on fire with the Arduino digitalWrite routine, but at least we know what we can expect as an upper limit. Knowing these performance limits might be important until we get lower-level access to the I/O.

The output transitions looked very clean with almost no ringing. It's possible the small on resistance of the level translator combined with the capacitance of my scope probe (a low-pass filter) helped in this regard. I'd like to explore the characteristics of the LSF0108 more in the future.

Toggling D12  on the Arduino 101 with a free-running main loop.

Rise time on D12 digital output on the Arduino 101.

For comparison, the free-running loop test on an Arduino Uno generated a square wave with a frequency of about 85.5 kHz. Clearly the processing speed of the Curie will be seen when doing complex mathematical operations, not when twiddling I/O pins.

Toggling D12 on an Arduino Uno with a free-running main loop.

Digital Input Logic Transitions

I applied a DC voltage to pin D7 and varied it up and down while the Arduino 101 reported the logic state in the serial monitor. This was done in order to discover the logic transition levels. Going from high to low, it returned a low state after crossing 1.26V. Going from low to high, however, the transition occurred at 1.55V.

Digital Output Voltage Level Under Load

For the next test, I set pin D7 high and connected it to a variable DC load. I checked the output voltage level at different output currents. With no load, the output voltage was 3.27V. With a 1 mA load, it was 3.18V. At 4 mA, it dropped to 3.04V. Seeing this droop, I didn't proceed to test the rated 20 mA of pin current. The on resistance of the level translator would have made a small contribution to this, but I do suspect that the Curie's output drivers are not extremely robust. I would keep pin currents as low as possible when using the Arduino 101's I/O pins.

Pulse-Width Modulation (PWM)

The Arduino 101 has four PWM outputs (digital pins 3, 5, 6, and 9). This is slightly disappointing, as we have come to expect nearly every pin to be PWM capable on modern 32-bit microcontrollers. I couldn't find documentation on the PWM frequencies used, so let's measure them.

PWM Output on Pin D6.

I found that pins D3 and D9 produced PWM signals with frequencies of 490 Hz. Pins D5 and D6 produced PWM signals with frequencies of 980 Hz. This coincidently matches the PWM frequencies used on the Arduino Uno. I suspect this was only done for compatibility, and presumably an option can be added in the future to change these frequencies. (I wouldn't even be surprised if the RTOS is just toggling these pins at the prescribed frequency and duty cycle to mimic PWM).

Analog Input Linearity

Next I tested the analog inputs. I was curious if the level translators affect the accuracy of the readings. I applied a DC voltage on pin A5, starting at 0V and increasing to 3.3V in 100 mV steps. At each step, I recorded the 10-bit analog-to-digital (ADC) readings reported by the Arduino 101. I then created a graph of the data, which is shown below. As you can see, the results are pretty linear across the entire input range. Spot-checking a few values, I found that there might have been a +20mV bias on the readings at the top end of the scale. However, I would have to tighten up my test setup to verify that. I plan to explore it more in the future.

A graph of analog input voltages versus reported ADC readings.


My initial impressions of the Arduino 101 are very positive. Besides the good test results shown above, the board is very easy to program and work with. The integration with the IDE is seamless, as you would expect from the Arduino eco-system. Uploads are very fast (a couple of seconds) and go the first time. No hitting upload two or three times like on many of the newer 32-bit boards.

There are hundreds of additional tests that could be performed, including benchmarking of real-time code execution. If you would like to see any additional tests in a follow-up post, post them below. Also, please post any comments and corrections.

Thanks for reading!

- Dan W.

No comments:

Post a Comment