Skip to content
steenerson edited this page Jan 27, 2020 · 5 revisions

Frequently Asked Questions

What is this shield useful for?

Measuring large numbers of nodes, especially when there's >5V at impedances that restrict common solutions like voltage dividers, which makes interfacing with microcontrollers difficult. Originally designed for complex pogo jigs and test equipment, but also useful for analog sensor arrays or anything with a lot of analog inputs.

How does the shield work?

64 input header pins are split into 4x 16-port CD4067B analog multiplexers (muxes). There are 4 digital control pins per mux that select which input is connected to each channel, and all 16 of these pins are connected to a 16-port 9555 I2C IO expander through level shifters to support 3-18V operation. The multiplexer outputs are first buffered through OP amps so the input pins are high impedance, then through resistor dividers that are separately configurable to 1:1/2:1/4:1/8:1 per channel. Next is another OP amp buffer to minimize the ADC settling time and errors, which outputs directly to 4 Arduino analog inputs.

Why are all the pins reading random results?

Unused inputs or inputs that are connected to a high impedance source such as a floating digital pins will give random results when read. Often they will read similar to adjacent inputs on the same channel because the OP amp inputs are sensitive enough to pick up the mux leakage current, which is in the nanoamp range. Connect unused ports to ground or VDD, or simply don't read them.

I need more than 64 inputs, how do I stack multiple shields?

This shield is not designed to directly stack more than one, because there's not enough room to physically fit 4 rows of headers and wires with standard stacking headers. Instead, run wires for SDA, SCL, GND, VIN and IOREF, which will be the same for up to 8 shields. Then run the 4 analog inputs E, F, G, and H to available analog pins - these cannot be shared between multiple shields.

Common boards such as Arduino Uno only have 6 analog inputs and 2 are often shared with the I2C lines, so only one shield can be used directly. Other Arduino shield compatible boards such as STM32 Nucleo boards have up to 16 analog inputs and should directly support up to 4 shields. It is also possible to chain together multiple shields but this functionality is not included in the library.

How do I set the voltage divider jumpers?

Each channel has a configurable voltage divider, set with jumpers DIVE, DIVF, DIVG, and DIVH. With no jumper, there is no attenuation (1:1). You can connect the jumpers to just one pin or vertically in any position so you don't lose them. The other 3 settings set 2:1, 4:1 and 8:1 dividers, there is an index on the board silkscreen.

The outputs of the dividers are clamped with diodes to protect against overvoltage damage to the Arduino inputs and OP amps if you select a divider with insufficient attenuation.

How do I change the I2C address?

Solder jumpers AD0, AD1 and AD2 set the lowest 3 bits of the 7-bit I2C expander address. By default they are all set to 0 which gives 0b0100000 or 0x20, and closing all 3 gives 0b0100111 or 0x27. AD0 is the 1s place, AD1 is 2 and AD2 is 4 for values in between.

How do I setup the power rails?

The shield is powered from the IOREF pin, which is directly connected to 3.3V or 5V depending on the Arduino board. JP1 can be changed so that the shield is always 5V powered, which can increase the analog circuit performance for 3.3V boards with 5V tolerant inputs such as some STM32 boards.

The multiplexers and input OP amp are powered from the Arduino VIN pin, or through a diode to IOREF/5V when powered by USB. The system can be powered by applying 6-18VDC to the VIN pin or DC jack, or by USB power. Keep in mind the max allowed voltage on any input pin is equal to the voltage on the VIN pin, and there are diode drops from the DC and USB jacks so you should measure VIN with a multimeter.

How are the inputs protected?

From the 64-pin input header, there are direct traces to the multiplexer inputs, with no resistors and no internal clamp diodes listed on the CD4067B datasheet. Input voltage must not exceed the Arduino VIN voltage or the CD4067B max input voltage, or damage to the multiplexer ICs could result!

After the multiplexers there are series resistors and clamp diodes on all channels, to protect the OP amps and Arduino inputs from overvoltage and incorrect voltage divider settings.

How fast does it switch?

The multiplexers and IO expander have propagation times in the 100s of nanoseconds range over their supply voltage ranges.

There is an OP amp buffer directly driving the Arduino analog pins, which leads to a fast settling time - approximate input capacitance of an Atmega328 analog pin is 15pF, and the OP amp output impedance is <100 ohms from DC to 100kHz. This RC constant will be in the nanosecond range for most configurations.

The I2C bus runs at 400kHz and approximately 3 bytes must be transferred to change one channel, or 4 bytes to change all 4 channels. With I2C and code overhead this leads to around 90 microseconds to set one channel, or 110 microseconds to set all channels using the 1.0.0 version of the library. This means the main bottleneck is the I2C bus.

Example sketch 'all_64_speedtest' cycles through reading all 64 pins, updating 4 at a time and then running analogRead on each. On an STM32 NUCLEO-G071RB board with stock ADC settings and version 1.0.0 of this library, this sketch measured at 1198Hz, which is around 4.8 kilosamples/second or 75 readings of each pin per second.