# photomotor.py
#
# Raspberry Pi Pico - photointerrupter and DC motordemo
#
# Demonstrates operating a DC motors driven by a DRV8833 based
# on a photointerrupter signal.
#
# This assumes a photointerrupter circuit is wired to analog input 0.
#
# This assumes a Pololu DRV8833 dual motor driver has been wired up to the Pico as follows:
#   Pico pin 24, GPIO18   -> AIN1
#   Pico pin 25, GPIO19   -> AIN2
#   Pico pin 26, GPIO20   -> BIN2
#   Pico pin 27, GPIO21   -> BIN1
#   any Pico GND          -> GND
# DRV8833 carrier board: https://www.pololu.com/product/2130

################################################################
# CircuitPython module documentation:
# time    https://circuitpython.readthedocs.io/en/latest/shared-bindings/time/index.html
# math    https://circuitpython.readthedocs.io/en/latest/shared-bindings/math/index.html
# board   https://circuitpython.readthedocs.io/en/latest/shared-bindings/board/index.html
# pwmio   https://circuitpython.readthedocs.io/en/latest/shared-bindings/pwmio/index.html

################################################################################
# print a banner as reminder of what code is loaded
print("Starting photomotor script.")

# load standard Python modules
import math, time

# load the CircuitPython hardware definition module for pin definitions
import board

# load the CircuitPython interface to the analog-to-digital converter
import analogio

# load the CircuitPython pulse-width-modulation module for driving hardware
import pwmio

# load the drv8833.py module, which should be copied to the top-level of CIRCUITPY
from drv8833 import DRV8833

#--------------------------------------------------------------------------------
# Create an object to represent a dual motor driver.
print("Creating driver object.")
driver = DRV8833()

# Create an object to represent the ADC0 input, which is physically pin 31.
# E.g., this may be attached to photocell or photointerrupter with associated pullup resistor.
sensor = analogio.AnalogIn(board.A0)

#--------------------------------------------------------------------------------
# Begin the main processing loop.  This is structured as a looping script, since
# each movement primitive 'blocks', i.e. doesn't return until the action is
# finished.

print("Starting main script.")
while True:

    # Read the sensor once per cycle.
    sensor_level = sensor.value

    # Map to a motor activation level between -1.0 and 1.0.  The Pico has 12-bit
    # analog-to-digital conversion so the actual conversion has 4096 possible
    # values, but the results are scaled to a 16-bit unsigned integer with range
    # from 0 to 65535.
    pwm = 2 * (2**16 - sensor_level) * (1.0 / 2**16)

    print("PWM:", pwm)

    # Set the motor speed.
    driver.write(0, pwm)

    # Slow the printing rate.
    time.sleep(0.1)

