Files
grow-python/examples/display.py
2020-05-21 11:43:40 +01:00

184 lines
4.9 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
from grow.moisture import Moisture
from grow.pump import Pump
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
BUTTONS = [5, 6, 16, 24]
LABELS = ['A', 'B', 'X', 'Y']
channel_count = 3
channel_selected = 0
sensors = [
Moisture(channel=1),
Moisture(channel=2),
Moisture(channel=3)
]
pumps = [
Pump(channel=1),
Pump(channel=2),
Pump(channel=3)
]
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=80000000
)
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
if value == 1.0:
return r[-1]
if value == 0.0:
return r[0]
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
c1 = 1.0 - sensors[0].saturation
c2 = 1.0 - sensors[1].saturation
c3 = 1.0 - sensors[2].saturation
print(c1, c2, c3)
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 / 5)