Driver/st7567 (#581)

Add ST7567/Pico GFX examples
This commit is contained in:
Gee Bartlett 2022-11-18 14:30:22 +00:00 committed by GitHub
parent 62303b6912
commit 7b127d5f19
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 567 additions and 0 deletions

View File

@ -5,11 +5,15 @@
- [Basic Examples](#basic-examples) - [Basic Examples](#basic-examples)
- [Balls Demo](#balls-demo) - [Balls Demo](#balls-demo)
- [Button Test](#button-test) - [Button Test](#button-test)
- [Calc](#calc)
- [Rainbow](#rainbow) - [Rainbow](#rainbow)
- [Snake](#snake) - [Snake](#snake)
- [Advanced Examples](#advanced-examples) - [Advanced Examples](#advanced-examples)
- [CO2](#co2) - [CO2](#co2)
- [Thermometer](#thermometer) - [Thermometer](#thermometer)
- [Wireless Examples](#wireless-examples)
- [Sunrise / Sunset](#sunrise--sunset)
- [Zoo Facts](#zoo-facts)
## About Pico GFX Pack ## About Pico GFX Pack
@ -43,6 +47,12 @@ LCD demo with a bunch of bouncy balls!
Shows how to read the buttons, display text and change the colour of the RGBW backlight. Shows how to read the buttons, display text and change the colour of the RGBW backlight.
### Calc
[calc.py](calc.py)
This example draws a nice sine wave on the display, reminiscent of the graphical calculators from the 90s.
### Rainbow ### Rainbow
[rainbow.py](rainbow.py) [rainbow.py](rainbow.py)
@ -86,3 +96,30 @@ To use the Pico's internal temperature sensor in place of the BME68x breakout, j
- :link: [BME680 breakout store page](https://shop.pimoroni.com/products/bme680-breakout) - :link: [BME680 breakout store page](https://shop.pimoroni.com/products/bme680-breakout)
- :link: [BME688 breakout store page](https://shop.pimoroni.com/products/bme688-breakout) - :link: [BME688 breakout store page](https://shop.pimoroni.com/products/bme688-breakout)
## Wireless Examples
These wireless examples need `network_manager.py` and `WIFI_CONFIG.py` from the `common` directory to be saved to your Pico W. Open up `WIFI_CONFIG.py` in Thonny to add your wifi details (and save it when you're done).
- [micropython/examples/common](../../examples/common)
### Sunrise / Sunset
[sunrise.py](sunrise.py)
This sunrise / sunset simulator displays information from the Sunrise Sunset API, and also shows how to use a 16x16 animated sprite.
Find out more about Sunrise Sunset API here: https://sunrise-sunset.org/api
### Zoo Facts
[zoo_facts.py](zoo_facts.py)
Downloads a list of five zoo animals and displays their vital statistics.
Find out more about Zoo Animal API here: https://zoo-animal-api.herokuapp.com/
- A = Next animal
- B = Last animal
- D = Show stats
- E = Fetch a different 5 animals

View File

@ -0,0 +1,54 @@
'''
calc.py
Graphical demo for the GFX Pack with Raspberry Pi Pico
This example draws a nice sine wave on the display,
reminiscent of the graphical calculators from the 90s.
'''
from math import radians, sin
from gfx_pack import GfxPack
gp = GfxPack()
display = gp.display
WIDTH, HEIGHT = display.get_bounds()
display.set_backlight(1.0) # Turns on the white component of the backlight
gp.set_backlight(0, 0, 0) # Leaves the other backlight colours off
def draw_axis():
display.line(0, 32, 128, 32)
display.line(64, 8, 64, 56)
for i in range(8):
display.line(64, (i * 12) + 8, 67, (i * 12) + 8)
display.line((i * 16), 32, (i * 16), 34)
def draw_sine(offset=0, vlines=False):
for x in range(128):
angle = 720 / 128 * x
y = int((sin(radians(angle + offset)) * 24) + 32)
display.pixel(x, y)
if vlines:
if x % 2 == 0:
display.line(x, 32, x, y)
def draw_text():
display.text("Remember A-Level Maths!", 0, 0, WIDTH, 1)
display.text("y=sin(x) x=(-360:360)", 0, 58, WIDTH, 1)
# Clear display
display.set_pen(0)
display.clear()
# Set pen to black
display.set_pen(15)
# Draw the details in the PicoGraphics frame buffer
draw_axis()
draw_sine(0, True)
draw_text()
# Update the display
display.update()

View File

@ -0,0 +1,280 @@
'''
sunrise.py
This example is for the Pico W with GFX Pack.
This displays information from the Sunrise Sunset API:
Find out more here - https://sunrise-sunset.org/api
Also shows how to use a 16x16 animated sprite.
'''
import WIFI_CONFIG
import time
from math import radians, sin, cos
from random import randint
from gfx_pack import GfxPack
from network_manager import NetworkManager
import ntptime
import urequests
import uasyncio
import machine
# Helper class so that the different formats of time can be converted into one comparable format
# Makes up for the lack of a datetime module in MicroPython
class TimeObj:
def __init__(self):
self.secs = 0
self.mins = 0
self.hours = 0
self.PM = False
# Returns time variables as a tuple (h, m, s)
def get_time(self):
pm_hrs = 0
if self.PM:
pm_hrs = 12
return (self.hours + pm_hrs, self.mins, self.secs)
# Returns time variables as a single string
def get_str(self):
h, m, s = self.get_time()
return "{0:02d}:{1:02d}:{2:02d}".format(h, m, s)
# Set time variables from the sunrise-sunset API
def parse_api(self, apiStr):
strsplit = apiStr.split()
if strsplit[1] == 'PM':
self.PM = True
timesplit = strsplit[0].split(':')
self.hours = int(timesplit[0])
self.mins = int(timesplit[1])
self.secs = int(timesplit[2])
# Set time variables form
def parse_localtime(self, localtpl):
yr, mo, dy, self.hours, self.mins, self.secs, un1, un2 = localtpl
# Returns number of seconds since midnight
def get_total_secs(self):
seconds = 0
if self.PM:
seconds += 43200 # seconds in the first 12 hours
seconds += (self.hours * 3600)
seconds += (self.mins * 60)
seconds += self.secs
return seconds
# Instances of TimeObj helper class defined above
sunrise_obj = TimeObj()
sunset_obj = TimeObj()
currenttime = TimeObj()
# Coordinates for Sheffield-on-Sea, UK
lng = -1.4659
lat = 53.3829
# Coordinates for LA, USA
# lng = -118.2437
# lat = 34.0522
URL = 'https://api.sunrise-sunset.org/json?lat={0}&lng={1}&date=today'.format(lat, lng)
rtc = machine.RTC()
gp = GfxPack()
display = gp.display
sys_status = "Starting"
WIDTH, HEIGHT = display.get_bounds()
display.set_backlight(1) # turn on the white component of the backlight
# Generate hill heights
hills1 = [randint(10, 18), randint(10, 18), randint(10, 18), randint(10, 18), randint(10, 18)]
hills2 = [randint(10, 18), randint(10, 18)]
hills3 = [randint(10, 18), randint(10, 18)]
# Sprite information for sun icon
sun = [
[
0b0000000100000000,
0b0000000000000000,
0b0010011111001000,
0b0000100000100000,
0b0001000000010000,
0b0010000000001000,
0b0010010001001000,
0b0010000100001000,
0b0010000000001000,
0b0010000000001000,
0b0001001110010000,
0b0000100000100000,
0b0010011111001000,
0b0000000000000000,
0b0000000100000000,
0b0000000000000000
],
[
0b0000000000000000,
0b0100000000000100,
0b0000011111000000,
0b0000100000100000,
0b0001000000010000,
0b0010010001001000,
0b0010010001001000,
0b1010000100001010,
0b0010000000001000,
0b0010010001001000,
0b0001001110010000,
0b0000100000100000,
0b0000011111000000,
0b0100000000000100,
0b0000000000000000,
0b0000000000000000
],
[
0b0000000100000000,
0b0100000000000100,
0b0010011111001000,
0b0000100000100000,
0b0001000000010000,
0b0010010001001000,
0b0010010001001000,
0b1010000100001010,
0b0010000000001000,
0b0010010001001000,
0b0001001110010000,
0b0000100000100000,
0b0010011111001000,
0b0100000000000100,
0b0000000100000000,
0b0000000000000000
]
]
def get_data():
# open the json file
print(f'Requesting URL: {URL}')
r = urequests.get(URL)
# open the json data
j = r.json()
print('Data obtained!')
r.close()
return j
def get_sunrise():
sun_json = get_data()
sunrise = sun_json['results']['sunrise']
sunrise_obj.parse_api(sunrise)
sunset = sun_json['results']['sunset']
sunset_obj.parse_api(sunset)
def display_status():
global sys_status
display.set_pen(0)
display.clear()
display.set_pen(15)
display.text(sys_status, 0, 0, WIDTH, 1)
display.update()
def status_handler(mode, status, ip):
# reports wifi connection status
global sys_status
print(mode, status, ip)
sys_status = 'Mode: {0} Connected: {1} IP: {2}'.format(mode, status, ip)
display_status()
display.update()
print('Connecting to wifi...')
if status is not None:
if status:
print('Wifi connection successful!')
else:
print('Wifi connection failed!')
def calc_circle_points(ori_x, ori_y, r, deg):
rads = radians(deg - 180)
x = int(cos(rads) * r) + ori_x
y = int(sin(rads) * r) + ori_y
return x, y
def to_seconds(hour, mins, secs, isPM=False):
seconds = 0
if isPM:
seconds += 43200 # Seconds in the first 12 hours
seconds += (hour * 3600)
seconds += (mins * 60)
seconds += secs
return seconds
def draw_hills():
display.set_pen(12)
for x in range(5):
display.circle(30 * x, 64, hills1[x])
display.set_pen(9)
for x in range(2):
display.circle(60 * x + 15, 64, hills2[x])
display.set_pen(3)
for x in range(2):
display.circle(60 * x + 30 + 15, 64, hills3[x])
def draw_text():
display.set_pen(15)
display.text("Sun Rise-Set API demo", 0, 0, WIDTH, 1)
display.text("Sunrise: {0}".format(sunrise_obj.get_str()), 0, 8, WIDTH, 1)
display.text("Sunset: {0}".format(sunset_obj.get_str()), 0, 16, WIDTH, 1)
display.text("{0}".format(currenttime.get_str()), 0, 24, WIDTH, 1)
def draw_sun(sunrise, sunset, time, cycle):
sunlight_range = sunset - sunrise
angle = int((180 / sunlight_range) * (time - sunrise)) % 360
pos_x, pos_y = calc_circle_points(64 - 16, 54, 50, angle)
display.set_pen(15)
if angle > 180:
gp.set_backlight(0, 0, 255)
elif angle < 90:
r = 255
g = ((angle / 100) * 90)
b = 0
gp.set_backlight(r, g, b)
elif angle > 90:
r = 255
g = 100 - (((angle - 90) / 100) * 90)
b = 0
gp.set_backlight(r, g, b)
for y in range(16):
for x in range(16):
if sun[cycle][y] & (1 << x):
display.pixel(x + pos_x, int((y + pos_y)))
try:
network_manager = NetworkManager(WIFI_CONFIG.COUNTRY, status_handler=status_handler)
uasyncio.get_event_loop().run_until_complete(network_manager.client(WIFI_CONFIG.SSID, WIFI_CONFIG.PSK))
except Exception as e:
print(f'Wifi connection failed! {e}')
get_sunrise()
ntptime.settime()
currenttime.parse_localtime(time.localtime())
count = 0 # Counter for animation
display.set_backlight(0.5) # Dim white backlight to help colours show
while True:
# Update current time class instance from RTC
currenttime.parse_localtime(time.localtime())
count += 1
display.set_pen(0)
display.clear()
# Uncomment for the animation
# draw_sun(0, 180, count % 180, count % 3)
draw_sun(sunrise_obj.get_total_secs(), sunset_obj.get_total_secs(), currenttime.get_total_secs(), count % 3)
draw_hills()
draw_text()
display.update()
time.sleep(0.2)

View File

@ -0,0 +1,196 @@
'''
zoo_facts.py
This example is for the Pico W with GFX Pack.
It uses the Zoo Animal API to download a list of 5 animals,
then displays them on the GFX Pack
A = Next animal
B = Last animal
D = Show stats
E = Fetch a different 5 animals
Find out more about Zoo Animal API here:
https://zoo-animal-api.herokuapp.com/
'''
import WIFI_CONFIG
import time
from gfx_pack import GfxPack, SWITCH_A, SWITCH_B, SWITCH_D, SWITCH_E
from network_manager import NetworkManager
import urequests
import uasyncio
URL = 'https://zoo-animal-api.herokuapp.com/animals/rand/5'
gp = GfxPack()
display = gp.display
WIDTH, HEIGHT = display.get_bounds()
display.set_backlight(0.5) # turn off the white component of the backlight
animals = []
animal_number = 0
stat_page = False
sys_status = "STATUS"
# Data class for containing the animal facts
class Animal:
def __init__(self):
self.name = ""
self.latin_name = ""
self.animal_type = ""
self.habitat = ""
self.diet = ""
self.length_max = ""
self.weight_max = ""
self.lifespan = ""
def process_json(self, json):
print(json['name'])
self.name = json['name']
self.latin_name = json['latin_name']
self.animal_type = json['animal_type']
self.habitat = json['habitat']
self.diet = json['diet']
self.length_max = json['length_max']
self.weight_max = json['weight_max']
self.lifespan = json['lifespan']
def get_data():
# open the json file
print(f'Requesting URL: {URL}')
r = urequests.get(URL)
# open the json data
j = r.json()
print('Data obtained!')
r.close()
return j
def get_animals():
global sys_status
animals = []
sys_status = 'Getting Animals'
display_status()
display.update()
json_data = get_data()
for index in range(len(json_data)):
new_animal = Animal()
new_animal.process_json(json_data[index])
animals.append(new_animal)
return animals
def display_status():
global sys_status
display.set_pen(0) # Set pen to white
display.clear()
display.set_pen(15)
display.text(sys_status, 0, 0, WIDTH, 1)
display.update()
def status_handler(mode, status, ip):
# reports wifi connection status
global sys_status
print(mode, status, ip)
sys_status = 'Mode: {0} Connected: {1} IP: {2}'.format(mode, status, ip)
display_status()
display.update()
print('Connecting to wifi...')
if status is not None:
if status:
print('Wifi connection successful!')
else:
print('Wifi connection failed!')
def display_animal(animal, stat_page):
display.set_pen(0) # Set pen to white
display.clear()
display.set_pen(15)
if stat_page is False:
display.text('Animal Info {0}'.format(animal_number), 0, 0, WIDTH, 1)
display.text('Name: {0}'.format(animal.name[:19]), 0, 10, WIDTH, 1)
display.text('Latin: {0}'.format(animal.latin_name[:19]), 0, 20, WIDTH, 1)
display.text('Type: {0}'.format(animal.animal_type[:19]), 0, 30, WIDTH, 1)
display.text('Habitat: {0}'.format(animal.habitat[:19]), 0, 40, WIDTH, 1)
display.text('Diet: {0}'.format(animal.diet[:19]), 0, 50, WIDTH, 1)
else:
display.text('Animal Stats {0}'.format(animal_number), 0, 0, WIDTH, 1)
display.text('Max Length: {0}'.format(animal.length_max), 0, 10, WIDTH, 1)
display.text('Max Weight: {0}'.format(animal.weight_max), 0, 20, WIDTH, 1)
display.text('Lifespan: {0}'.format(animal.lifespan), 0, 30, WIDTH, 1)
display.update()
try:
network_manager = NetworkManager(WIFI_CONFIG.COUNTRY, status_handler=status_handler)
uasyncio.get_event_loop().run_until_complete(network_manager.client(WIFI_CONFIG.SSID, WIFI_CONFIG.PSK))
except Exception as e:
print(f'Wifi connection failed! {e}')
# From CPython Lib/colorsys.py
def hsv_to_rgb(h, s, v):
if s == 0.0:
return v, v, v
i = int(h * 6.0)
f = (h * 6.0) - i
p = v * (1.0 - s)
q = v * (1.0 - s * f)
t = v * (1.0 - s * (1.0 - f))
i = i % 6
if i == 0:
return v, t, p
if i == 1:
return q, v, p
if i == 2:
return p, v, t
if i == 3:
return p, q, v
if i == 4:
return t, p, v
if i == 5:
return v, p, q
# some variables to keep track of rainbow background
h = 0
display.set_font("bitmap8")
animals = get_animals()
display.set_backlight(0)
while True:
h += 1
r, g, b = [int(255 * c) for c in hsv_to_rgb(h / 360.0, 1.0, 1.0)] # rainbow magic
gp.set_backlight(r, g, b) # Set backlight to a converted HSV value
display.set_pen(0) # Set pen to white
display.clear()
display.set_pen(15) # Set pen to black
# Draw text
display_animal(animals[animal_number], stat_page)
if gp.switch_pressed(SWITCH_B):
animal_number += 1
if animal_number > 4:
animal_number = 0
display_animal(animals[animal_number], stat_page)
time.sleep(0.4)
elif gp.switch_pressed(SWITCH_A):
animal_number -= 1
if animal_number < 0:
animal_number = 4
display_animal(animals[animal_number], stat_page)
time.sleep(0.4)
elif gp.switch_pressed(SWITCH_D):
stat_page = not stat_page
display_animal(animals[animal_number], stat_page)
time.sleep(0.4)
elif gp.switch_pressed(SWITCH_E):
animals = get_animals()
display_animal(animals[animal_number], stat_page)