Implemented a generic Pi/MCP3004 sketch to read a Thermistor with Channel 0 ... this has been working great for well over 3 years in an unattended mountaintop radio shack (providing remote monitoring of the shack temperature) ... today we added a 100k Pot ... Input Voltage (VBat) on one end of the pot the other end is Ground with the wiper attached to Channel 1 input (pin 2) ... the wiper was pre-adjusted to 3.3 V with a 20V input voltage (approx 16k to Gnd) ... the MCP3004 Vref is 3.3V ... the expectation was any reading from Channel 1 would provide VBat as (chn1 reading)/1024*20 to provide the actual voltage ... the Battery Voltage is expected in the range of 12.4V to 16V (Victron lower/upper cutoffs) ... the issue: as soon as I attach the battery to VBat (top of pot) both the Thermistor (chn0) and (chn1) read 0 ... Physical Channel Voltage readings are 1.2V and 2.2V respectively (2.2 V on Chn 1 should correspond to Vbat of 13.6V) ... the Python function that reads the chip hasn't changed ... it only requires a Port # as a parameter (code attached below) ... removal of the + Vbat from pot connected to chn1 restores readings on chn0
The MCP3004 documentation indicates there is a distinct AGnd for the channel inputs ... looking at the implemented schematic it appears AGnd and DGnd were tied together ... the expectation is separating grounds is typically done for Noisy environments ... there are other details regarding Single-ended vs Differential ... this failure suggests the chip may be in Differential mode ... The code below indicates the channels should be in single-ended mode ... SO ... the big question is: how/why is Vbat wiping out Channel 0 and not providing a reading for Channel 1 ... has anyone experienced a failure like this?
Python Code
#----------------- readADC( Channel# ) ---------------------------------------
# Microchip ADC MCP300X family has 3 variations; 2, 4 or 8 Channel 10bit A/D
# all 3 use a Serial Data Pin to Clock in Commands & Clock out Digital Data
# representing the Analog values
#
def readAdc(iChn): # MCP3004 has 4 Channels: 0 to 3
# ensure both pgl and pg don't attempt to read adc at the same time
bArf = GPIO.input(ARF[_PIN]) # is there a Read in Progress
while bArf == 1:
bArf = GPIO.input(ARF[_PIN])
# wend
GPIO.output(ARF[_PIN], GPIO.HIGH) # set Read in Progress
# Datasheet says chip select must be pulled high between conversions
GPIO.output(CS[_PIN], GPIO.HIGH)
# Start the read with clock high and chip select low
GPIO.output(CS[_PIN], GPIO.LOW)
GPIO.output(CLK[_PIN], GPIO.HIGH)
# ADC commands are 5 bits long:
# start bit = 1
# single-ended comparison = 1 (vs. pseudo-differential = 0)
# channel num bit 2 (MSB) (for MCP3004 this is always 0)
# channel num bit 1
# channel num bit 0 (LSB)
# ie for single-ended channel 0 this command should be 1 1 0 0 0 or 0x18
iAdcCmd = 0x18 # base command for Channel 0
iAdcCmd |= iChn # add Channel to command
for iBit in range(5):
# output MSB bit: HI or LO
if iAdcCmd & 0x10: # is MSB HI?
GPIO.output(MOSI[_PIN], GPIO.HIGH)
else:
GPIO.output(MOSI[_PIN], GPIO.LOW)
# endif
# Shift next bit to MSB
iAdcCmd <<= 1
# Send a clock pulse HI then immediately LO
GPIO.output(CLK[_PIN], GPIO.HIGH)
GPIO.output(CLK[_PIN], GPIO.LOW)
# next
iAdcVal = 0
for iBit in range(12):
# Pulse clock pin
GPIO.output(CLK[_PIN], GPIO.HIGH)
GPIO.output(CLK[_PIN], GPIO.LOW)
# Read 1 data bit in
if GPIO.input(MISO[_PIN]):
iAdcVal |= 0x1
# endif
# Shift in next bit
iAdcVal <<= 1
# next
# Divide by two to drop the stop bit
iAdcVal = (iAdcVal/2)
iAdcVal &= 0x3FF
# Set chip select high to end the read
GPIO.output(CS[_PIN], GPIO.HIGH)
GPIO.output(CS[_PIN], GPIO.LOW)
GPIO.output(ARF[_PIN], GPIO.LOW) # clear Read in Progress
return iAdcVal
# end readACD