For part of a project I am working on, I would like to measure the time it takes for a capacitor to discharge to some arbitrary voltage (effectively simulate analog using digital pins). To do this, I made a simple RC circuit shown below and set the GPIO pins to one of two states:
State 1 - Pin 8 charges the capacitor, pin 6 is the ground
State 2 - Pin 8 changes to an input, pin 6 is the ground
Once the circuit is in state 2, the value of pin 8 is checked at a specified sampling interval until the value returned is a 0 instead of a 1. I naively assumed that the time until the pin went from a value of 1 to 0 should be relatively consistent since it should be tied to the time constant of the circuit. In actuality, this value varies wildly (39[ms] lowest and 90[ms] highest recorded). Sometimes the pin value will even go from 1 to 0 nearly immediately then switch back to 1 for more than 10 milliseconds before going back to 0, etc. As a result, my code compares the running average of the last 5 values to a threshold in order to help reduce the impact of the low input "outliers". If anyone has any ideas as to why this simple proof-of-concept isn't returning consistent values, I would greatly appreciate your help. Thanks! References below:

Here is the code:
Code: Select all
import numpy as np
import RPi.GPIO as GPIO
import time
# Initial Setup
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
# Settings
pin_A = 8
charge_time = 2
sample_interval = 0.001 # Time interval between samples
# Main Loop
# A High - Charging
GPIO.setup(pin_A, GPIO.OUT, initial=GPIO.HIGH)
print('Charging')
time.sleep(charge_time)
# A Low - Discharging
GPIO.setup(pin_A, GPIO.IN)
# Measure time until Pin A is low
pin_A_high = True
time_pin_A_high = 0
last_pin_values = np.array([]) # Used to find running average of last 5 values of pin A
while pin_A_high:
pin_value = GPIO.input(pin_A)
print(pin_value)
if last_pin_values.size == 5: # Removes first element in vector containing last 5 pin A values
last_pin_values = np.delete(last_pin_values, 0)
if pin_value == 1:
last_pin_values = np.append(last_pin_values, 1)
time_pin_A_high += sample_interval
time.sleep(sample_interval)
elif pin_value == 0:
last_pin_values = np.append(last_pin_values, 0)
pin_value_sum = sum(last_pin_values)
if (pin_value_sum < 3) & (last_pin_values.size == 5): # If 2 of last 5 values of pin A are LOW and at least 5 samples taken
pin_A_high = False
else:
time_pin_A_high += sample_interval
time.sleep(sample_interval)
print('High to Low Time: %f' % time_pin_A_high)


