kopia lustrzana https://github.com/pimoroni/pimoroni-pico
116 wiersze
4.3 KiB
Python
116 wiersze
4.3 KiB
Python
# Automatic brightness example.
|
|
|
|
import time
|
|
from machine import ADC, Pin
|
|
from pimoroni import Button
|
|
from picographics import PicoGraphics, DISPLAY_TUFTY_2040
|
|
import micropython
|
|
|
|
# Constants for automatic brightness adjustment.
|
|
# Below about 3/8ths, the backlight is entirely off. The top of the range is OK.
|
|
BACKLIGHT_LOW = micropython.const(0.375)
|
|
BACKLIGHT_HIGH = micropython.const(1.0)
|
|
|
|
# The luminance sensor seems to cover the whole 16-bit range pretty well from
|
|
# buried in shadow to bright phone torch in its face, but setting a lower high
|
|
# point will make it generally bias brighter in calm room lighting, and a higher
|
|
# low will use the darkest backlight without needing to completely hard-mask the
|
|
# sensor in complete darkness.
|
|
LUMINANCE_LOW = micropython.const(384)
|
|
LUMINANCE_HIGH = micropython.const(2048) # 65535 to use the full range.
|
|
|
|
# If on battery, and the supply voltage drops below this, force minimum
|
|
# backlight brightness.
|
|
# The bottom of the Tufty2040 input range is 3.0v, so values below that likely
|
|
# will not trigger before it cuts out.
|
|
LOW_BATTERY_VOLTAGE = micropython.const(3.1)
|
|
|
|
# Hold button A to pretend the LUX sensor is seeing maximally bright light.
|
|
# (To test darkness, put your finger over the sensor! :D )
|
|
button_a = Button(7, invert=False)
|
|
# Hold button B to pretend the system is on battery, and the battery is low.
|
|
button_b = Button(8, invert=False)
|
|
# Pins and analogue-digital converters we need to set up to measure sensors.
|
|
lux_vref_pwr = Pin(27, Pin.OUT)
|
|
lux = ADC(Pin(26))
|
|
vbat_adc = ADC(Pin(29))
|
|
vref_adc = ADC(Pin(28))
|
|
usb_power = Pin(24, Pin.IN)
|
|
|
|
display = PicoGraphics(display=DISPLAY_TUFTY_2040)
|
|
display.set_backlight(1.0)
|
|
display.set_font("bitmap8")
|
|
WHITE = display.create_pen(255, 255, 255)
|
|
BLACK = display.create_pen(0, 0, 0)
|
|
WIDTH, HEIGHT = display.get_bounds()
|
|
|
|
|
|
# Returns a tuple of the raw luminance value, and the brightness to now use.
|
|
def auto_brightness(previous: float) -> (float, float):
|
|
luminance = lux.read_u16()
|
|
if button_a.is_pressed: # Debug key.
|
|
luminance = 65535
|
|
luminance_frac = max(0.0, float(luminance - LUMINANCE_LOW))
|
|
luminance_frac = min(1.0, luminance_frac / (LUMINANCE_HIGH - LUMINANCE_LOW))
|
|
backlight = BACKLIGHT_LOW + (luminance_frac * (BACKLIGHT_HIGH - BACKLIGHT_LOW))
|
|
# Use the previous value to smooth out changes to reduce flickering.
|
|
# The "32" value here controls how quickly it reacts (larger = slower).
|
|
# The rate at which the main loop calls us also affects that!
|
|
backlight_diff = backlight - previous
|
|
backlight = previous + (backlight_diff * (1.0 / 32.0))
|
|
return (luminance, backlight)
|
|
|
|
|
|
# Returns a tuple of voltage (fake value if on USB), "is on USB", and "is low".
|
|
def measure_battery() -> (float, bool, bool):
|
|
if button_b.is_pressed: # Debug key.
|
|
return (3.0, False, True)
|
|
|
|
if usb_power.value():
|
|
return (5.0, True, False)
|
|
|
|
# See the battery.py example for how this works.
|
|
vdd = 1.24 * (65535 / vref_adc.read_u16())
|
|
vbat = ((vbat_adc.read_u16() / 65535) * 3 * vdd)
|
|
|
|
low_battery = False
|
|
if vbat < LOW_BATTERY_VOLTAGE:
|
|
low_battery = True
|
|
return (vbat, False, low_battery)
|
|
|
|
|
|
backlight = BACKLIGHT_LOW
|
|
while True:
|
|
# Turn on VREF and LUX only while we measure things.
|
|
lux_vref_pwr.value(1)
|
|
(vbat, on_usb, low_battery) = measure_battery()
|
|
if low_battery:
|
|
backlight = BACKLIGHT_LOW
|
|
else:
|
|
(luminance, backlight) = auto_brightness(backlight)
|
|
lux_vref_pwr.value(0)
|
|
|
|
# Set the new backlight value.
|
|
display.set_backlight(backlight)
|
|
|
|
# Show our measurements.
|
|
display.set_pen(WHITE)
|
|
display.clear()
|
|
display.set_pen(BLACK)
|
|
display.text(f"Backlight: {backlight * 100:03.0f}%", 8, 8, WIDTH - 8, 4)
|
|
|
|
if low_battery:
|
|
display.text("Luminance: Ignored, low battery!", 8, 48 + (20 * 1), WIDTH - 8, 2)
|
|
else:
|
|
display.text(f"Luminance: {luminance:05.0f} (of 65535)", 8, 48 + (20 * 1), WIDTH - 8, 2)
|
|
if on_usb:
|
|
display.text("Battery: Ignored, on USB.", 8, 48 + (20 * 2), WIDTH - 8, 2)
|
|
else:
|
|
display.text(f"Battery: {vbat:.2f}v", 8, 48 + (20 * 2), WIDTH - 8, 2)
|
|
|
|
display.text("Hold A to pretend the room is bright.", 8, HEIGHT - (20 * 4), WIDTH - 8, 2)
|
|
display.text("Hold B to pretend the battery is low.", 8, HEIGHT - (20 * 2), WIDTH - 8, 2)
|
|
display.update()
|
|
|
|
time.sleep(0.1)
|