123 lines
4.2 KiB
Python
123 lines
4.2 KiB
Python
# TinyPICO MicroPython Helper Library
|
|
# 2019 Seon Rozenblum, Matt Trentini
|
|
#
|
|
# Project home:
|
|
# https://github.com/TinyPICO
|
|
#
|
|
# 2019-Mar-12 - v0.1 - Initial implementation
|
|
# 2019-May-20 - v1.0 - Initial Release
|
|
# 2019-Oct-23 - v1.1 - Removed temp sensor code, prep for frozen modules
|
|
|
|
# Import required libraries
|
|
from micropython import const
|
|
from machine import Pin, SPI, ADC
|
|
import machine, time, esp32
|
|
|
|
# TinyPICO Hardware Pin Assignments
|
|
|
|
# Battery
|
|
BAT_VOLTAGE = const(35)
|
|
BAT_CHARGE = const(34)
|
|
|
|
# APA102 Dotstar pins for production boards
|
|
DOTSTAR_CLK = const(12)
|
|
DOTSTAR_DATA = const(2)
|
|
DOTSTAR_PWR = const(13)
|
|
|
|
# SPI
|
|
SPI_MOSI = const(23)
|
|
SPI_CLK = const(18)
|
|
SPI_MISO = const(19)
|
|
|
|
# I2C
|
|
I2C_SDA = const(21)
|
|
I2C_SCL = const(22)
|
|
|
|
# DAC
|
|
DAC1 = const(25)
|
|
DAC2 = const(26)
|
|
|
|
# Helper functions
|
|
|
|
# Get a *rough* estimate of the current battery voltage
|
|
# If the battery is not present, the charge IC will still report it's trying to charge at X voltage
|
|
# so it will still show a voltage.
|
|
def get_battery_voltage():
|
|
"""
|
|
Returns the current battery voltage. If no battery is connected, returns 3.7V
|
|
This is an approximation only, but useful to detect of the charge state of the battery is getting low.
|
|
"""
|
|
adc = ADC(Pin(BAT_VOLTAGE)) # Assign the ADC pin to read
|
|
measuredvbat = adc.read() # Read the value
|
|
measuredvbat /= 4095 # divide by 4095 as we are using the default ADC voltage range of 0-1V
|
|
measuredvbat *= 3.7 # Multiply by 3.7V, our reference voltage
|
|
return measuredvbat
|
|
|
|
|
|
# Return the current charge state of the battery - we need to read the value multiple times
|
|
# to eliminate false negatives due to the charge IC not knowing the difference between no battery
|
|
# and a full battery not charging - This is why the charge LED flashes
|
|
def get_battery_charging():
|
|
"""
|
|
Returns the current battery charging state.
|
|
This can trigger false positives as the charge IC can't tell the difference between a full battery or no battery connected.
|
|
"""
|
|
measuredVal = 0 # start our reading at 0
|
|
io = Pin(BAT_CHARGE, Pin.IN) # Assign the pin to read
|
|
|
|
for y in range(
|
|
0, 10
|
|
): # loop through 10 times adding the read values together to ensure no false positives
|
|
measuredVal += io.value()
|
|
|
|
return measuredVal == 0 # return True if the value is 0
|
|
|
|
|
|
# Power to the on-board Dotstar is controlled by a PNP transistor, so low is ON and high is OFF
|
|
# We also need to set the Dotstar clock and data pins to be inputs to prevent power leakage when power is off
|
|
# This might be improved at a future date
|
|
# The reason we have power control for the Dotstar is that it has a quiescent current of around 1mA, so we
|
|
# need to be able to cut power to it to minimise power consumption during deep sleep or with general battery powered use
|
|
# to minimise unneeded battery drain
|
|
def set_dotstar_power(state):
|
|
"""Set the power for the on-board Dostar to allow no current draw when not needed."""
|
|
# Set the power pin to the inverse of state
|
|
if state:
|
|
Pin(DOTSTAR_PWR, Pin.OUT, None) # Break the PULL_HOLD on the pin
|
|
Pin(DOTSTAR_PWR).value(False) # Set the pin to LOW to enable the Transistor
|
|
else:
|
|
Pin(13, Pin.IN, Pin.PULL_HOLD) # Set PULL_HOLD on the pin to allow the 3V3 pull-up to work
|
|
|
|
Pin(
|
|
DOTSTAR_CLK, Pin.OUT if state else Pin.IN
|
|
) # If power is on, set CLK to be output, otherwise input
|
|
Pin(
|
|
DOTSTAR_DATA, Pin.OUT if state else Pin.IN
|
|
) # If power is on, set DATA to be output, otherwise input
|
|
|
|
# A small delay to let the IO change state
|
|
time.sleep(0.035)
|
|
|
|
|
|
# Dotstar rainbow colour wheel
|
|
def dotstar_color_wheel(wheel_pos):
|
|
"""Color wheel to allow for cycling through the rainbow of RGB colors."""
|
|
wheel_pos = wheel_pos % 255
|
|
|
|
if wheel_pos < 85:
|
|
return 255 - wheel_pos * 3, 0, wheel_pos * 3
|
|
elif wheel_pos < 170:
|
|
wheel_pos -= 85
|
|
return 0, wheel_pos * 3, 255 - wheel_pos * 3
|
|
else:
|
|
wheel_pos -= 170
|
|
return wheel_pos * 3, 255 - wheel_pos * 3, 0
|
|
|
|
|
|
# Go into deep sleep but shut down the APA first to save power
|
|
# Use this if you want lowest deep sleep current
|
|
def go_deepsleep(t):
|
|
"""Deep sleep helper that also powers down the on-board Dotstar."""
|
|
set_dotstar_power(False)
|
|
machine.deepsleep(t)
|