# pump_control.py

# Demonstrate variable-speed single-directional control of a DC motor driven via
# a MOSFET transistor driver circuit.  For a reversible motion, please see the
# DRV8833 example, but some applications (e.g. pumps and fans) only require a
# single direction of rotation at variable speed.

# Related documentation:
# https://circuitpython.readthedocs.io/en/latest/shared-bindings/pwmio/index.html#module-pwmio

# ----------------------------------------------------------------
# Import standard Python modules.
import time, math

# Load the CircuitPython hardware definition module for pin definitions.
import board

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

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

# Create a PWMOut object on GP22.  This will create a pulsing signal with
# variable duty cycle.  The switching rate of 20kHz is chosen to be
# supra-audible.
pwm = pwmio.PWMOut(board.GP22, duty_cycle=0, frequency=20000)

# Utility function to calculate and apply a new duty cycle setting.  Converts a
# unit-range (0.0 to 1.0) pwm_level to a 16-bit integer representing a fraction
# needed by the PWM driver.
def set_motor_speed(pwm_device, pwm_level):
    pwm_device.duty_cycle = min(max(int(pwm_level * 2**16), 0), 2**16-1)
    print("Applied duty cycle of %d for pwm_level %f" % (pwm_device.duty_cycle, pwm_level))
          
# ----------------------------------------------------------------
# Enter the main event loop.
while True:

    # Turn the motor on halfway.
    set_motor_speed(pwm, 0.5)
    time.sleep(1.0)

    # Turn the motor off again.
    set_motor_speed(pwm, 0.0)
    time.sleep(1.0)

    # Turn the motor on a little faster.
    set_motor_speed(pwm, 0.75)
    time.sleep(1.0)

    # Turn the motor off again.
    set_motor_speed(pwm, 0.0)
    time.sleep(1.0)
    
    # Turn the motor full.
    set_motor_speed(pwm, 1.0)
    time.sleep(1.0)

    # Turn the motor off again.
    set_motor_speed(pwm, 0.0)
    time.sleep(1.0)
