-
Notifications
You must be signed in to change notification settings - Fork 1
Home
- What is this shield useful for?
- How does the shield work?
- Why are all the pins reading random results?
- I need more than 64 inputs, how do I stack multiple shields?
- How do I set the voltage divider jumpers?
- How do I change the I2C address?
- How do I setup the power rails?
- How are the inputs protected?
- How fast does it switch?
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.
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.
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.
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.
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.
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.
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.
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.
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.