Files
grow-python/examples/display.py
2020-05-15 17:42:26 +01:00

160 lines
4.4 KiB
Python

import time
import ST7735
import random
import math
from PIL import Image, ImageDraw, ImageFont
from fonts.ttf import RobotoMedium as UserFont
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
BUTTONS = [5, 6, 16, 24]
LABELS = ['A', 'B', 'X', 'Y']
channel_count = 3
channel_selected = 0
GPIO.setup(BUTTONS, GPIO.IN, pull_up_down=GPIO.PUD_UP)
font = ImageFont.truetype(UserFont, 14)
def handle_button(pin):
global channel_selected
index = BUTTONS.index(pin)
label = LABELS[index]
if label == 'A':
channel_selected += 1
channel_selected %= channel_count
print("Button {} pressed! Channel: {}".format(label, channel_selected))
for pin in BUTTONS:
GPIO.add_event_detect(pin, GPIO.FALLING, handle_button, bouncetime=150)
display = ST7735.ST7735(
port=0,
cs=1,
dc=9,
backlight=12,
rotation=270,
spi_speed_hz=10000000
)
ramp = [
(192, 225, 254), # Blue
(196, 255, 209), # Green
(255, 243, 192), # Yellow
(254, 192, 192) # Red
]
ramp_sat = [
(32, 137, 251), # Blue
(100, 255, 124), # Green
(254, 219, 82), # Yellow
(254, 82, 82), # Red
]
def indicator_color(value, r=None):
if r is None:
r = ramp
value *= len(r) - 1
a = int(math.floor(value))
b = a + 1
blend = float(value - a)
r, g, b = [int(((r[b][i] - r[a][i]) * blend) + r[a][i]) for i in range(3)]
return (r, g, b)
display.begin()
WIDTH, HEIGHT = display.width, display.height
# Only the ALPHA channel is used from these images
icon_drop = Image.open("icons/icon-drop.png")
icon_nodrop = Image.open("icons/icon-nodrop.png")
icon_rightarrow = Image.open("icons/icon-rightarrow.png")
icon_snooze = Image.open("icons/icon-snooze.png")
plants = []
for x in range(1, 15):
plants.append(Image.open("icons/flat-{}.png".format(x)))
CHANNEL_W = 40
CHANNEL_M = 2
print(WIDTH, HEIGHT)
image = Image.new("RGBA", (WIDTH, HEIGHT), color=(255, 255, 255))
draw = ImageDraw.Draw(image)
draw.rectangle((0, 0, 19, 19), (32, 138, 251))
draw.rectangle((0, HEIGHT - 19, 19, HEIGHT), (255, 255, 255))
draw.rectangle((WIDTH - 20, 0, WIDTH, 19), (75, 166, 252))
draw.rectangle((WIDTH - 20, HEIGHT - 19, WIDTH, HEIGHT), (254, 218, 80))
def icon(image, icon, position, color):
col = Image.new("RGBA", (20, 20), color=color)
image.paste(col, position, mask=icon)
icon(image, icon_rightarrow, (0, 0), (255, 255, 255))
icon(image, icon_snooze, (0, HEIGHT - 20), (129, 129, 129))
icon(image, icon_drop, (WIDTH - 20, 0), (255, 255, 255))
icon(image, icon_nodrop, (WIDTH - 20, HEIGHT - 20), (255, 255, 255))
def plant(image, plant, channel):
x = [18, 58, 98][channel]
y = HEIGHT - plant.height
image.paste(plant, (x, y), mask=plant)
picked = random.sample(plants, 3)
# image.save("test.png")
while True:
t = time.time() / 10.0
c1 = (math.sin(math.pi + t * math.pi) + 1.0) / 2.0
c2 = (math.sin(t * math.pi) + 1.0) / 2.0
c3 = (math.sin(math.pi + t * math.pi) + 1.0) / 2.0
draw.rectangle((21, 0, 138, HEIGHT), (255, 255, 255)) # Erase channel area
# Draw background bars
draw.rectangle((21, int(c1 * HEIGHT), 58, HEIGHT), indicator_color(c1))
draw.rectangle((61, int(c2 * HEIGHT), 98, HEIGHT), indicator_color(c2))
draw.rectangle((101, int(c3 * HEIGHT), 138, HEIGHT), indicator_color(c3))
# Draw plant images
for p in range(3):
plant(image, picked[p], p)
# Channel selection icons
draw.rectangle((33, 2, 48, 17), indicator_color(c1, ramp_sat))
draw.rectangle((33 + 40, 2, 48 + 40, 17), indicator_color(c2, ramp_sat))
draw.rectangle((33 + 80, 2, 48 + 80, 17), indicator_color(c3, ramp_sat))
selected_x = 21 + (40 * channel_selected) + 10
draw.rectangle((selected_x, 0, selected_x + 19, 20), indicator_color([c1, c2, c3][channel_selected], ramp_sat))
draw.polygon([
(selected_x, 20),
(selected_x + 9, 25),
(selected_x + 19, 20)
],
fill=indicator_color([c1, c2, c3][channel_selected], ramp_sat))
draw.text((33 + 3, 2), "1", font=font, fill=(255, 255, 255))
draw.text((33 + 40 + 4, 2), "2", font=font, fill=(255, 255, 255))
draw.text((33 + 80 + 4, 2), "3", font=font, fill=(255, 255, 255))
# Erase snooze icon
draw.rectangle((0, HEIGHT - 19, 19, HEIGHT), (255, 255, 255))
r = int(((math.sin(time.time() * 3 * math.pi) + 1.0) / 2.0) * 255)
icon(image, icon_snooze, (0, HEIGHT - 20), (r, 129, 129))
display.display(image.convert("RGB"))
time.sleep(1.0 / 30)