I want to use the MAX1032 ADC (datasheet) to measure a voltage (Vin) through a voltage divider (30K/3K) with a PIC microcontroller over SPI. I have written a simple library for Single-Ended Unipolar measurements which works.. However the voltage doesn't correspondent with the theoretical value it should be. To clarify the problem:
- Voltage divider disconnected from adc: Vin=45.8V, Vadc=4.16V (as it should be theoretically).
- Voltage divider connected to ADC: Vin=45.8V, Vadc=3.95V (0,21V error)
- ADC inputs floating: I measure around 2.35V at the inputs
It looks like the 2.35V conflicts with Vadc resulting in erratic voltages (which are being read correctly, checked with multimeter..). Could this be due to a wrong configuration or am I processing the input wrong?
Additional info:
Configuration
VREF is configured to internal 4.096V by bypassing REFCAP pin with 0.1μF to AGND1 and REF pin with 1.0μF to AGND1).
At startup a Analog Input Configuration Byte is written for each channel (see datasheet Table 2 and Table 6) . This byte configures each channel to be Single-Ended Unipolar 0 to (+3 x VREF)/2. FSR = (3 x VREF)/2).
#define START 1 << 7 /* defines the beginning of the analog input configuration byte */
#define DIF_SGL 0 << 3 /* Single ended: input voltages are measured between the selected input channel and AGND1 */
#define RANGE_SELECT_BITS 0b011 /* Table 6. Range-Select Bits: R2, R1, R0 (Single-Ended Unipolar 0 to (+3 x VREF)/2. FSR = (3 x VREF)/2) */
void max1032_inputConfigSingleEndedUnipolar(max1032_channel_t ch){
CS_MAX1032_SetLow();
spiWrite((uint8_t)(START | (ch << 4)| DIF_SGL | RANGE_SELECT_BITS));
CS_MAX1032_SetHigh();
}
Reading
The function below is used for reading raw adc values. Vadc is acquired by multiplying the adc value with 6.144/16384 according to ((3 x VREF)/2)/14bit. Then Vin is acquired by multiplying Vadc with (30K + 3K) / 3K
#define CONVERSION_START_BYTE 0b10000000 /* D7 start bit high, edit with [6...4]:Channel-Select */
uint16_t max1032_readRaw(max1032_channel_t ch){
uint8_t dataRawHi;
uint8_t dataRawLo;
CS_MAX1032_SetLow();
spiWrite((uint8_t)(CONVERSION_START_BYTE | (ch << 4)));
spiWrite(0x00);
dataRawHi = spiRead();
dataRawLo = spiRead();
CS_MAX1032_SetHigh();
return (uint16_t)((dataRawHi << 6) | (dataRawLo >> 2)); /* response: B13-B0 */
}