The original sketch was built to use an NTC Thermistor to monitor a remote mountaintop shack's ambient temperature ... this has been in operation for over 3 years ... we recently added some batteries with a Victron BP65 over/under voltage device ... because Victron doesn't provide an API for Bluetooth to allow monitoring of the Battery Voltage on the Pi, we were thinking we would just add a simple voltage divider to monitor the voltage using one of the unused Channels on the existing ADC. HOWEVER, for some unknown reason, the moment voltage is applied to the Vbat pin (top of the 100k pot) both Channel 0 and Channel 1 read 0V even though actual voltages of 1.2V and 2.2V respectively are being applied to the inputs of these channels ... the code listed below shows that these channels are being configured for single-ended use so completely stumped as to why this simple addition not only fails to provide any readings on Channel 1 but ALSO affects Channel 0.
Can anyone explain what I might be missing here?
The only change made was to add the 100k Pot which was pre-adjusted with a 20V input so the wiper reads 3.3V to ground ... this allows for the Pi to estimate the vBat as (ADC Val) / 1024 * 20 where ADC Val would be (Vchn1 / 3.3 * 1024) ... ADC read function unchanged
Example:
ch1 ip => 2.2V -> expected ADC reading => 683 -> estimated VBat => 13.4V
Instead, both Chn0 and 1 are returning readings of 0 until the VBat voltage is removed from the 100k pot
NOTE: pg and pgl referenced in the code are defined as follows: pg is a CLI process that allows a user to manually request current status ... pgl is a continuous loop process running in the background with a watchdog used to monitor and provide instant email notifications when readings hit or exceed set limits. An unused GPIO pin on the Pi is being used as a hardware Flag to ensure a CLI request doesn't collide with a Loop Request
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
Last edited: