# cpb_soft_analog.py

# Demonstrate measurement of an analog soft sensor input.  This is intended to attach
# to an external soft touch sensor hand-fabricated using conductive fabric and
# Velostat.  The electrical resistance of the sensor varies with pressure.

# This example uses three pads on the board: A3, A2, and GND.  The A3 pad is
# used as a electrical current source by placing it in a digital-input mode with
# the internal pullup resistor enabled.  The pad then emits a small sensing
# voltage which we use to probe the resistive sensor.  As mechanical pressure is
# applied, the sensor resistance drops along with the voltage across the sensor.
# This voltage is measured by the A2 pad, used in the analog-input mode.  Please
# note that the sensor voltage follows an inverse logic: when not pressed, the
# input value will be midrange, and when pressed, it will drop (possibly to
# zero).

# The wiring for this is as follows:
#  1. One half of sensor connected to GND (either half).
#  2. Other half of sensor connected to A2.
#  3. Jumper wire connects A3 to A2.

# Note on A3: the corresponding digital input is D10.  Empirically the internal
# pullup resistor appears to be about 13.5K connected to 3.3V, e.g. it will
# drive a 10K external resistance to 1.4 Volts.

# ----------------------------------------------------------------
# Import the standard Python time functions.
import time

# Import the low-level hardware libraries.
import board
import digitalio
import analogio

# ----------------------------------------------------------------
# Initialize hardware.

# Configure the digital input pin used for its pullup resistor bias voltage.
bias = digitalio.DigitalInOut(board.D10)
bias.switch_to_input(pull=digitalio.Pull.UP)

# Configure the analog input pin used to measure the sensor voltage.
sensor = analogio.AnalogIn(board.A2)
scaling = sensor.reference_voltage / (2**16)

# ----------------------------------------------------------------
# Begin the main processing loop.
while True:

    # Read the integer sensor value and scale it to a value in Volts.
    volts = sensor.value * scaling
    
    # Every handmade sensor will have different properties, so the
    # interpretation of the voltage value will usually need to be individually
    # calibrated.  One way to accomplish this is by measuring the voltage
    # response under different conditions, then applying additional scaling and
    # offset to produce a normalized signal (possibly inverted).  For example,
    # if the observed voltage ranges between 1.4 and 0.1 Volts, the input signal
    # could be normalized to a [0,1] range as follows:
    pressure = (1.4 - volts) / (1.4 - 0.1)

    # Print the voltage reading and normalized value on the console.
    print(f"({volts}, {pressure})")
    
    # Limit the rate of the main loop.
    time.sleep(0.1)
