Crea un conto alla rovescia con un Raspberry Pi
Inizia a contare i giorni che mancano alla tua prossima vacanza con un Raspberry Pi e un display ePaper.
Per il 2021, il Pi Day è passato, lasciando bei ricordi e tanti progetti Raspberry Pi da provare. I giorni successivi alle vacanze possono essere difficili quando si torna al lavoro dopo il buon umore e tanto divertimento, e il Pi Day non fa eccezione. Mentre guardiamo in faccia le Idi di marzo, possiamo desiderare le gioie del giorno precedente. Ma non temere più, caro celebrante del Pi Day! Per oggi iniziamo il lungo conto alla rovescia per il prossimo Pi Day!
OK, ma sul serio. Ho creato un timer per il conto alla rovescia del Pi Day e puoi farlo anche tu!
Qualche tempo fa ho acquistato un Raspberry Pi Zero W e di recente l'ho utilizzato per capire perché il mio WiFi era così pessimo. Ero anche incuriosito dall'idea di procurarmi un display ePaper per il piccolo Zero W. Non ne sapevo un buon uso, ma, dannazione, sembrava divertente! Ho acquistato un piccolo display Waveshare da 2,13", che si adatta perfettamente al Raspberry Pi Zero W. È facile da installare: basta far scorrere il display sui connettori GIPO del Raspberry Pi e sei a posto.
Ho utilizzato il sistema operativo Raspberry Pi per questo progetto e, sebbene sia sicuramente possibile farlo con altri sistemi operativi, il comando raspi-config
, utilizzato di seguito, è più facilmente disponibile sul sistema operativo Raspberry Pi.
Configura il Raspberry Pi e il display ePaper
Per configurare il Raspberry Pi per funzionare con il display ePaper è necessario abilitare la Serial Peripheral Interface (SPI) nel software Raspberry Pi, installare le librerie C BCM2835 (per accedere alle funzioni GPIO per il chip Broadcom BCM 2835 sul Raspberry Pi) e installa le librerie GPIO Python per controllare la visualizzazione di ePaper. Infine, è necessario installare le librerie Waveshare per lavorare con il display da 2,13" utilizzando Python.
Ecco una procedura dettagliata su come eseguire queste attività.
Abilita SPI
Il modo più semplice per abilitare SPI è con il comando raspi-config
Raspberry Pi. Il bus SPI consente la comunicazione dati seriale da utilizzare con i dispositivi, in questo caso il display ePaper:
$ sudo raspi-config
Dal menu visualizzato, seleziona Opzioni di interfaccia -> SPI -> Sì per abilitare l'interfaccia SPI, quindi riavvia.
Installa le librerie BCM2835
Come accennato in precedenza, le librerie BCM2835 sono software per il chip Broadcom BCM2385 sul Raspberry Pi, che consente l'accesso ai pin GPIO e la possibilità di utilizzarli per controllare i dispositivi.
Mentre scrivo questo, l'ultima versione delle librerie Broadcom BCM 2835 per Raspberry Pi è v1.68. Per installare le librerie, è necessario scaricare il tarball del software e compilare e installare il software con make
:
# Download the BCM2853 libraries and extract them
$ curl -sSL http://www.airspayce.com/mikem/bcm2835/bcm2835-1.68.tar.gz -o - | tar -xzf -
# Change directories into the extracted code
$ pushd bcm2835-1.68/
# Configure, build, check and install the BCM2853 libraries
$ sudo ./configure
$ sudo make check
$ sudo make install
# Return to the original directory
$ popd
Installa le librerie Python richieste
Sono inoltre necessarie alcune librerie Python per utilizzare Python per controllare la visualizzazione dell'ePaper, il pacchetto pip RPi.GPIO
. È inoltre necessario il pacchetto python3-pil
per disegnare forme. A quanto pare, il pacchetto PIL è quasi morto, ma esiste un’alternativa, Pillow. Non ho testato Pillow per questo progetto, ma potrebbe funzionare:
# Install the required Python libraries
$ sudo apt-get update
$ sudo apt-get install python3-pip python3-pil
$ sudo pip3 install RPi.GPIO
Nota: queste istruzioni sono per Python 3. Puoi trovare le istruzioni per Python 2 sul sito web di Waveshare
Scarica esempi Waveshare e librerie Python
Waveshare mantiene un repository Git con librerie Python e C per lavorare con i suoi display ePaper e alcuni esempi che mostrano come usarli. Per questo progetto di orologio per il conto alla rovescia, clonerai questo repository e utilizzerai le librerie per il display da 2,13":
# Clone the WaveShare e-Paper git repository
$ git clone https://github.com/waveshare/e-Paper.git
Se utilizzi un display diverso o un prodotto di un'altra azienda, dovrai utilizzare il software appropriato per il tuo display.
Waveshare fornisce istruzioni per la maggior parte di quanto sopra sul suo sito web:
- Istruzioni per la configurazione di WaveShare ePaper
- Istruzioni per l'installazione delle librerie WaveShare ePaper
Ottieni un carattere divertente (facoltativo)
Puoi visualizzare il timer come preferisci, ma perché non farlo con un po' di stile? Trova un font interessante con cui lavorare!
Ci sono tantissimi font Open Font License disponibili là fuori. Sono particolarmente affezionato a Bangers. Lo avrai notato se hai guardato YouTube: è usato ovunque. Può essere scaricato e inserito nella directory dei caratteri condivisi locali dell'utente per renderlo disponibile per qualsiasi applicazione, incluso questo progetto:
# The "Bangers" font is a Open Fonts License licensed font by Vernon Adams (https://github.com/vernnobile) from Google Fonts
$ mkdir -p ~/.local/share/fonts
$ curl -sSL https://github.com/google/fonts/raw/master/ofl/bangers/Bangers-Regular.ttf -o fonts/Bangers-Regular.ttf
Crea un timer per il conto alla rovescia del Pi Day
Ora che hai installato il software per lavorare con il display ePaper e un carattere divertente da usare, puoi creare qualcosa di interessante con esso: un timer per il conto alla rovescia fino al prossimo Pi Day!
Se lo desideri, puoi semplicemente prendere il file countdown.py Python dal repository GitHub di questo progetto e passare alla fine di questo articolo.
Per i curiosi, analizzerò il file, sezione per sezione.
Importa alcune librerie
#!/usr/bin/python3
# -*- coding:utf-8 -*-
import logging
import os
import sys
import time
from datetime import datetime
from pathlib import Path
from PIL import Image,ImageDraw,ImageFont
logging.basicConfig(level=logging.INFO)
basedir = Path(__file__).parent
waveshare_base = basedir.joinpath('e-Paper', 'RaspberryPi_JetsonNano', 'python')
libdir = waveshare_base.joinpath('lib')
All'inizio, lo script Python importa alcune librerie standard utilizzate successivamente nello script. Devi anche aggiungere Image
, ImageDraw
e ImageFont
dal pacchetto PIL, che utilizzerai per disegnare alcune forme geometriche semplici. Infine, imposta alcune variabili per la directory lib
locale che contiene le librerie Waveshare Python per lavorare con il display da 2,13" e che potrai utilizzare in seguito per caricare la libreria dalla directory locale.
Funzione di aiuto per la dimensione del carattere
La parte successiva dello script ha una funzione di supporto per impostare la dimensione del carattere per il carattere scelto: Bangers-Regular.ttf. Richiede un numero intero per la dimensione del carattere e restituisce un oggetto ImageFont che puoi utilizzare con il display:
def set_font_size(font_size):
logging.info("Loading font...")
return ImageFont.truetype(f"{basedir.joinpath('Bangers-Regular.ttf').resolve()}", font_size)
Logica del conto alla rovescia
Poi c'è una piccola funzione che calcola il nocciolo di questo progetto: quanto tempo manca al prossimo Pi Day. Se fosse, ad esempio, gennaio, sarebbe relativamente semplice contare quanti giorni mancano, ma è necessario anche considerare se il Pi Day è già passato per l'anno (faccia triste) e, in tal caso, contare quanti, moltissimi giorni mancano giorni prima che tu possa festeggiare di nuovo:
def countdown(now):
piday = datetime(now.year, 3, 14)
# Add a year if we're past PiDay
if piday < now:
piday = datetime((now.year + 1), 3, 14)
days = (piday - now).days
logging.info(f"Days till piday: {days}")
return day
La funzione principale
Infine, si arriva alla funzione principale, che inizializza il display e inizia a scrivere i dati su di esso. In questo caso, scriverai un messaggio di benvenuto e poi inizierai il conto alla rovescia per il prossimo Pi Day. Ma prima devi caricare la libreria Waveshare:
def main():
if os.path.exists(libdir):
sys.path.append(f"{libdir}")
from waveshare_epd import epd2in13_V2
else:
logging.fatal(f"not found: {libdir}")
sys.exit(1)
Lo snippet qui sopra controlla che la libreria sia stata scaricata in una directory insieme allo script del conto alla rovescia, quindi carica la libreria epd2in13_V2
. Se utilizzi un display diverso, dovrai utilizzare una libreria diversa. Puoi anche scriverne uno tuo se ne hai voglia. Ho trovato piuttosto interessante leggere il codice Python che Waveshare fornisce con il display. È molto meno complicato di quanto avrei immaginato, anche se un po' noioso.
Il successivo bit di codice crea un oggetto EPD (ePaper Display) per interagire con il display e inizializza l'hardware:
logging.info("Starting...")
try:
# Create an a display object
epd = epd2in13_V2.EPD()
# Initialize the displace, and make sure it's clear
# ePaper keeps it's state unless updated!
logging.info("Initialize and clear...")
epd.init(epd.FULL_UPDATE)
epd.Clear(0xFF)
Una nota interessante su ePaper: utilizza energia solo quando cambia un pixel da bianco a nero o viceversa. Ciò significa che quando il dispositivo viene scollegato dall'alimentazione o l'applicazione si interrompe per qualsiasi motivo, ciò che era sullo schermo rimane. È fantastico dal punto di vista del consumo energetico, ma significa anche che è necessario cancellare lo schermo all'avvio, altrimenti lo script sovrascriverà semplicemente ciò che è già sullo schermo. Pertanto, epd.Clear(0xFF)
viene utilizzato per cancellare il display all'avvio dello script.
Successivamente, crea una "tela" in cui disegnerai il resto del tuo output display:
# Create an image object
# NOTE: The "epd.heigh" is the LONG side of the screen
# NOTE: The "epd.width" is the SHORT side of the screen
# Counter-intuitive...
logging.info(f"Creating canvas - height: {epd.height}, width: {epd.width}")
image = Image.new('1', (epd.height, epd.width), 255) # 255: clear the frame
draw = ImageDraw.Draw(image)
Questo corrisponde alla larghezza e all'altezza del display, ma è in qualche modo controintuitivo, in quanto il lato corto del display è la larghezza. Penso al lato lungo come alla larghezza, quindi questo è solo qualcosa da notare. Tieni presente che epd.height
e epd.width
sono impostati dalla libreria Waveshare per corrispondere al dispositivo che stai utilizzando.
Messaggio di benvenuto
Successivamente, inizierai a disegnare qualcosa. Ciò comporta l'impostazione dei dati sull'oggetto "tela" che hai creato sopra. Questo non lo attira ancora sul display ePaper: stai solo costruendo l'immagine che desideri in questo momento. Crea un piccolo messaggio di benvenuto per celebrare il Pi Day, con l'immagine di una fetta di torta, disegnata dal sottoscritto solo per questo progetto:
(Chris Collins, CC BY-SA 4.0)
Carino, eh?
logging.info("Set text text...")
bangers64 = set_font_size(64)
draw.text((0, 30), 'PI DAY!', font = bangers64, fill = 0)
logging.info("Set BMP...")
bmp = Image.open(basedir.joinpath("img", "pie.bmp"))
image.paste(bmp, (150,2))
Alla fine, finalmente, puoi visualizzare la tela che hai disegnato, ed è un po' deludente:
logging.info("Display text and BMP")
epd.display(epd.getbuffer(image))
Quella parte sopra aggiorna il display per mostrare l'immagine che hai disegnato.
Quindi, prepara un'altra immagine per visualizzare il timer per il conto alla rovescia.
Conto alla rovescia del giorno Pi
Innanzitutto, crea un nuovo oggetto immagine che puoi utilizzare per disegnare il display. Inoltre, imposta alcune nuove dimensioni dei caratteri da utilizzare per l'immagine:
logging.info("Pi Date countdown; press CTRL-C to exit")
piday_image = Image.new('1', (epd.height, epd.width), 255)
piday_draw = ImageDraw.Draw(piday_image)
# Set some more fonts
bangers36 = set_font_size(36)
bangers64 = set_font_size(64)
Per visualizzare un ticker come un conto alla rovescia, è più efficiente aggiornare parte dell'immagine, modificando la visualizzazione solo per ciò che è cambiato nei dati che desideri disegnare. Il successivo bit di codice prepara il display a funzionare in questo modo:
# Prep for updating display
epd.displayPartBaseImage(epd.getbuffer(piday_image))
epd.init(epd.PART_UPDATE)
Infine, si arriva al bit del timer, che avvia un ciclo infinito che controlla quanto manca al prossimo Pi Day e visualizza il conto alla rovescia sul display dell'ePaper. Se effettivamente è il Pi Day, puoi gestirlo con un piccolo messaggio celebrativo:
while (True):
days = countdown(datetime.now())
unit = get_days_unit(days)
# Clear the bottom half of the screen by drawing a rectangle filld with white
piday_draw.rectangle((0, 50, 250, 122), fill = 255)
# Draw the Header
piday_draw.text((10,10), "Days till Pi-day:", font = bangers36, fill = 0)
if days == 0:
# Draw the Pi Day celebration text!
piday_draw.text((0, 50), f"It's Pi Day!", font = bangers64, fill = 0)
else:
# Draw how many days until Pi Day
piday_draw.text((70, 50), f"{str(days)} {unit}", font = bangers64, fill = 0)
# Render the screen
epd.displayPartial(epd.getbuffer(piday_image))
time.sleep(5)
L'ultima parte dello script gestisce alcuni errori, incluso del codice per rilevare le interruzioni della tastiera in modo da poter interrompere il ciclo infinito con Ctrl+C e una piccola funzione per stampare "giorno" o "giorni" a seconda che l'output debba essere singolare o meno (per quello, un solo giorno ogni anno quando appropriato):
except IOError as e:
logging.info(e)
except KeyboardInterrupt:
logging.info("Exiting...")
epd.init(epd.FULL_UPDATE)
epd.Clear(0xFF)
time.sleep(1)
epd2in13_V2.epdconfig.module_exit()
exit()
def get_days_unit(count):
if count == 1:
return "day"
return "days"
if __name__ == "__main__":
main()
E il gioco è fatto! Uno script per il conto alla rovescia e visualizzare quanti giorni mancano al Pi Day! Ecco un'azione ripresa sul mio Raspberry Pi (accelerata di 86.400; non ho abbastanza spazio su disco per salvare un video di una giornata):
(Chris Collins, CC BY-SA 4.0)
Installa il servizio systemd (facoltativo)
Se desideri che la visualizzazione del conto alla rovescia venga eseguita ogni volta che il sistema viene acceso e senza che tu debba effettuare l'accesso ed eseguire lo script, puoi installare l'unità systemd opzionale come servizio utente systemd).
Copia il file piday.service su GitHub in $ {HOME}/.config/systemd/user
, creando prima la directory se non esiste. Quindi puoi abilitare il servizio e avviarlo:
$ mkdir -p ~/.config/systemd/user
$ cp piday.service ~/.config/systemd/user
$ systemctl --user enable piday.service
$ systemctl --user start piday.service
# Enable lingering, to create a user session at boot
# and allow services to run after logout
$ loginctl enable-linger $USER
Lo script verrà inviato al journal systemd e l'output potrà essere visualizzato con il comando journalctl
.
Sta cominciando ad assomigliare molto al Pi Day!
Ed ecco il gioco! Un timer per il conto alla rovescia del Pi Day, visualizzato su un display ePaper utilizzando un Raspberry Pi Zero W e avviato all'avvio del sistema con un file unit systemd! Ora mancano solo 350 giorni e qualcosa prima che potremo riunirci ancora una volta e celebrare il fantastico dispositivo che è il Raspberry Pi. E possiamo vedere esattamente quanti giorni a colpo d'occhio con il nostro piccolo progetto.
Ma in verità, chiunque può tenere nel cuore il Pi Day tutto l'anno, quindi divertiti a creare alcuni progetti divertenti ed educativi con il tuo Raspberry Pi!