Nouveau driver ePaper Display de Waveshare supportant les Image de la librairie PIL
Beaucoup plus facile à utiliser pour de l'affichage riche
This commit is contained in:
parent
e95f6eb57a
commit
61c4296af6
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,3 +5,4 @@ raspberry/pictures/*
|
|||||||
boitier/old*
|
boitier/old*
|
||||||
.directory
|
.directory
|
||||||
*__pycache__*
|
*__pycache__*
|
||||||
|
test*
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#define MQTT_USERNAME "arofarn"
|
#define MQTT_USERNAME "arofarn"
|
||||||
#define MQTT_KEY "WaKaW9XMGUZ3rRJD"
|
#define MQTT_KEY "WaKaW9XMGUZ3rRJD"
|
||||||
#define MQTT_ID "huzzah0"
|
#define MQTT_ID "huzzah0"
|
||||||
#define MQTT_PUB_INTERVAL 10000
|
#define MQTT_PUB_INTERVAL 15000 // milliseconds
|
||||||
|
|
||||||
/************************* Time and NTP Setup *********************************/
|
/************************* Time and NTP Setup *********************************/
|
||||||
|
|
||||||
@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
#define MODE_STATION true
|
#define MODE_STATION true
|
||||||
#define DEFAULT_ALTITUDE 140.0
|
#define DEFAULT_ALTITUDE 140.0
|
||||||
#define DEFAULT_MSLP 1013.25 //Atmospheric Pressure at Sea-Level
|
#define DEFAULT_MSLP 1013.25 //Mean Atmospheric Pressure at Mean Sea-Level
|
||||||
|
|
||||||
// Create an ESP8266 WiFiClient class to connect to the MQTT server.
|
// Create an ESP8266 WiFiClient class to connect to the MQTT server.
|
||||||
WiFiClient wifi_client;
|
WiFiClient wifi_client;
|
||||||
@ -152,21 +152,11 @@ void loop() {
|
|||||||
date_str = NTP.getTimeDateString();
|
date_str = NTP.getTimeDateString();
|
||||||
date_str.toCharArray(date_val,20);
|
date_str.toCharArray(date_val,20);
|
||||||
|
|
||||||
// Now we can publish stuff!
|
|
||||||
Serial.print(F("Sending date and time "));
|
|
||||||
Serial.print(date_val);
|
|
||||||
Serial.print("...");
|
|
||||||
if (! mqtt_client.publish("huzzah0/NTP/date", date_val, true, 2)) {
|
|
||||||
Serial.println(F("Failed"));
|
|
||||||
} else {
|
|
||||||
Serial.println(F("OK!"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now we can publish stuff!
|
// Now we can publish stuff!
|
||||||
Serial.print(F("Sending pressure value "));
|
Serial.print(F("Sending pressure value "));
|
||||||
Serial.print(pressure_val);
|
Serial.print(pressure_val);
|
||||||
Serial.print("...");
|
Serial.print("...");
|
||||||
val2json(pressure_val, date_str, "hPa", "PA").toCharArray(tosend, 120);
|
val2json(pressure_val, date_str, "hPa", "AP").toCharArray(tosend, 120);
|
||||||
if (! mqtt_client.publish("huzzah0/AdaBME280_1/pressure", tosend, true, 2) ) {
|
if (! mqtt_client.publish("huzzah0/AdaBME280_1/pressure", tosend, true, 2) ) {
|
||||||
Serial.println(F("Failed"));
|
Serial.println(F("Failed"));
|
||||||
} else {
|
} else {
|
||||||
@ -182,7 +172,7 @@ void loop() {
|
|||||||
Serial.print(F("Sending sea-level pressure value "));
|
Serial.print(F("Sending sea-level pressure value "));
|
||||||
Serial.print(atm_press_sea_level);
|
Serial.print(atm_press_sea_level);
|
||||||
Serial.print("...");
|
Serial.print("...");
|
||||||
val2json(atm_press_sea_level, date_str, "hPa", "SLPA").toCharArray(tosend, 120);
|
val2json(atm_press_sea_level, date_str, "hPa", "MSLP").toCharArray(tosend, 120);
|
||||||
if (! mqtt_client.publish("huzzah0/AdaBME280_1/sea_level_pressure", tosend, true, 2) ) {
|
if (! mqtt_client.publish("huzzah0/AdaBME280_1/sea_level_pressure", tosend, true, 2) ) {
|
||||||
Serial.println(F("Failed"));
|
Serial.println(F("Failed"));
|
||||||
} else {
|
} else {
|
||||||
@ -202,7 +192,7 @@ void loop() {
|
|||||||
Serial.print(F("Sending humity value "));
|
Serial.print(F("Sending humity value "));
|
||||||
Serial.print(humidity_val);
|
Serial.print(humidity_val);
|
||||||
Serial.print("...");
|
Serial.print("...");
|
||||||
val2json(humidity_val, date_str, "%", "HR").toCharArray(tosend, 120);
|
val2json(humidity_val, date_str, "%", "RH").toCharArray(tosend, 120);
|
||||||
if (! mqtt_client.publish("huzzah0/AdaBME280_1/humidity", tosend, true, 2)) {
|
if (! mqtt_client.publish("huzzah0/AdaBME280_1/humidity", tosend, true, 2)) {
|
||||||
Serial.println(F("Failed"));
|
Serial.println(F("Failed"));
|
||||||
} else {
|
} else {
|
||||||
@ -213,12 +203,22 @@ void loop() {
|
|||||||
Serial.print(F("Sending temperature value "));
|
Serial.print(F("Sending temperature value "));
|
||||||
Serial.print(temperature_val);
|
Serial.print(temperature_val);
|
||||||
Serial.print("...");
|
Serial.print("...");
|
||||||
val2json(temperature_val, date_str, "degC", "TA").toCharArray(tosend, 120);
|
val2json(temperature_val, date_str, "degC", "AT").toCharArray(tosend, 120);
|
||||||
if (! mqtt_client.publish("huzzah0/AdaBME280_1/temperature", tosend, true, 2)) {
|
if (! mqtt_client.publish("huzzah0/AdaBME280_1/temperature", tosend, true, 2)) {
|
||||||
Serial.println(F("Failed"));
|
Serial.println(F("Failed"));
|
||||||
} else {
|
} else {
|
||||||
Serial.println(F("OK!"));
|
Serial.println(F("OK!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// __LAST__ thing to send : Date and Time
|
||||||
|
Serial.print(F("Sending date and time "));
|
||||||
|
Serial.print(date_val);
|
||||||
|
Serial.print("...");
|
||||||
|
if (! mqtt_client.publish("huzzah0/NTP/date", date_val, true, 2)) {
|
||||||
|
Serial.println(F("Failed"));
|
||||||
|
} else {
|
||||||
|
Serial.println(F("OK!"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delay(10);
|
delay(10);
|
||||||
|
@ -32,5 +32,11 @@ photo_dir=/home/pi/Cameteo/photos/
|
|||||||
photo_name=test_%%Y%%m%%d_%%H%%M%%S
|
photo_name=test_%%Y%%m%%d_%%H%%M%%S
|
||||||
photo_format=jpeg
|
photo_format=jpeg
|
||||||
|
|
||||||
|
[EPD]
|
||||||
|
epd_font_file=/usr/share/fonts/truetype/freefont/FreeMono.ttf
|
||||||
|
epd_bold_font_file=/usr/share/fonts/truetype/freefont/FreeMonoBold.ttf
|
||||||
|
epd_italic_font_file=/usr/share/fonts/truetype/freefont/FreeMonoOblique.ttf
|
||||||
|
epd_rotate = 1
|
||||||
|
|
||||||
[MISC]
|
[MISC]
|
||||||
TimeZone=2
|
TimeZone=2
|
||||||
|
@ -72,3 +72,9 @@ photo_extensions = {'jpeg': 'jpg',
|
|||||||
'yuv': 'yuv',
|
'yuv': 'yuv',
|
||||||
'rgb': 'rgb',
|
'rgb': 'rgb',
|
||||||
'rgba': 'rgba'}
|
'rgba': 'rgba'}
|
||||||
|
|
||||||
|
#epaper display
|
||||||
|
epd_font_file = parser['EPD'].get('epd_font_file' , fallback='/usr/share/fonts/truetype/freefont/FreeMono.ttf')
|
||||||
|
epd_bold_font_file = parser['EPD'].get('epd_bold_font_file' , fallback='/usr/share/fonts/truetype/freefont/FreeMonoBold.ttf')
|
||||||
|
epd_italic_font_file = parser['EPD'].get('epd_italic_font_file' , fallback='/usr/share/fonts/truetype/freefont/FreeMonoOblique.ttf')
|
||||||
|
epd_rotate = min(int(parser['EPD'].get('epd_rotate', fallback=0)), 1)
|
@ -29,7 +29,7 @@ from PIL import Image
|
|||||||
import RPi.GPIO as GPIO
|
import RPi.GPIO as GPIO
|
||||||
|
|
||||||
# Display resolution
|
# Display resolution
|
||||||
EPD_WIDTH = 122
|
EPD_WIDTH = 128
|
||||||
EPD_HEIGHT = 250
|
EPD_HEIGHT = 250
|
||||||
|
|
||||||
# EPD2IN13 commands
|
# EPD2IN13 commands
|
||||||
@ -127,7 +127,7 @@ class EPD:
|
|||||||
|
|
||||||
def wait_until_idle(self):
|
def wait_until_idle(self):
|
||||||
while(self.digital_read(self.busy_pin) == 1): # 0: idle, 1: busy
|
while(self.digital_read(self.busy_pin) == 1): # 0: idle, 1: busy
|
||||||
self.delay_ms(100)
|
self.delay_ms(20)
|
||||||
##
|
##
|
||||||
# @brief: module reset.
|
# @brief: module reset.
|
||||||
# often used to awaken the module in deep sleep,
|
# often used to awaken the module in deep sleep,
|
||||||
@ -214,7 +214,7 @@ class EPD:
|
|||||||
self.set_memory_pointer(0, 0)
|
self.set_memory_pointer(0, 0)
|
||||||
self.send_command(WRITE_RAM)
|
self.send_command(WRITE_RAM)
|
||||||
# send the color data
|
# send the color data
|
||||||
for i in range(0, self.width / 8 * self.height):
|
for i in range(0, int(self.width / 8 * self.height)):
|
||||||
self.send_data(color)
|
self.send_data(color)
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -11,13 +11,24 @@ Display data from MQTT broker on ePaper screen
|
|||||||
|
|
||||||
from cameteo_conf import *
|
from cameteo_conf import *
|
||||||
import paho.mqtt.client as mqtt
|
import paho.mqtt.client as mqtt
|
||||||
from spidev import SpiDev
|
import time
|
||||||
import EPD_driver
|
|
||||||
import json
|
import json
|
||||||
import netifaces
|
import netifaces, socket
|
||||||
|
import epd2in13
|
||||||
|
from PIL import Image
|
||||||
|
from PIL import ImageDraw
|
||||||
|
from PIL import ImageFont
|
||||||
|
|
||||||
mqtt_client_id = "epaper_display"
|
mqtt_client_id = "epaper_display"
|
||||||
|
|
||||||
|
def update_epd():
|
||||||
|
#rotation de l'image de 90° + 180° si le paramètre epd_rotate est différent de 0
|
||||||
|
# la translation permet de rattraper un petit décalage en cas de rotation de 90+180°
|
||||||
|
screen = image.rotate(90 + (epd_rotate * 180), expand=True, translate=(-6*epd_rotate, 0))
|
||||||
|
#Mis en memoire de l'image à afficher et affichage de l'image
|
||||||
|
epd.set_frame_memory(screen, 0, 0)
|
||||||
|
epd.display_frame()
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# CALLBACKS #
|
# CALLBACKS #
|
||||||
#############
|
#############
|
||||||
@ -51,35 +62,57 @@ def on_message(client, userdata, msg):
|
|||||||
val['value'] = float('nan')
|
val['value'] = float('nan')
|
||||||
|
|
||||||
#Gestion du symbole des degrés parfois difficile pour certaines sources
|
#Gestion du symbole des degrés parfois difficile pour certaines sources
|
||||||
#val['unit'] = val['unit'].replace('deg', '°')
|
val['unit'] = val['unit'].replace('deg', '°')
|
||||||
|
|
||||||
#Affichage des données
|
#Affichage des données
|
||||||
coord_type = { 'TA' : 33,
|
coord_type = { 'AT' : (2, 50),
|
||||||
'HR' : 49,
|
'RH' : (127, 50),
|
||||||
'SLPA' : 65
|
'MSLP' : (2, 66),
|
||||||
}
|
'ALTI' : (127, 66),
|
||||||
|
}
|
||||||
if val['type'] in coord_type:
|
if val['type'] in coord_type:
|
||||||
disp.Dis_String(125, coord_type[val['type']], "{} {} ".format(val['value'], val['unit']), 16)
|
#erase former text
|
||||||
|
draw.rectangle(coord_type[val['type']] + (coord_type[val['type']][0] + 122, coord_type[val['type']][1] + 14), fill=255)
|
||||||
|
#draw new values
|
||||||
|
draw.text(coord_type[val['type']], "{:8.1f} {} ".format(val['value'], val['unit']), font=font14, fill=0)
|
||||||
|
# #Update the display
|
||||||
|
# screen = image.rotate(90, expand=True)
|
||||||
|
# epd.set_frame_memory(screen, 0, 0)
|
||||||
|
# epd.display_frame()
|
||||||
|
|
||||||
#Callback managing date and time from MQTT broker
|
#Callback managing date and time from MQTT broker
|
||||||
def on_message_date(client, userdata, msg):
|
def on_message_date(client, userdata, msg):
|
||||||
payload = msg.payload.decode()
|
payload = msg.payload.decode()
|
||||||
print("Date : " + payload)
|
print("Date : " + payload)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
d = datetime.strptime(payload, "%H:%M:%S %d/%m/%Y")
|
#Mise en forme de la date et heure reçu pour fuseau horaire configuré
|
||||||
disp.Dis_String(0, 17, datetime.strftime(d + TimeZone.utcoffset(None), "%d/%m/%Y %H:%M:%S"), 16)
|
dt_texte = datetime.strftime(datetime.strptime(payload, "%H:%M:%S %d/%m/%Y") + TimeZone.utcoffset(None), "%d/%m/%Y %H:%M:%S")
|
||||||
except:
|
except:
|
||||||
disp.Dis_String(0, 17, payload, 16)
|
dt_texte = payload
|
||||||
|
|
||||||
|
#Affichage du résultat
|
||||||
|
draw.rectangle((0, 34, epd2in13.EPD_HEIGHT, 48), fill=255)
|
||||||
|
draw.text((0, 34), dt_texte, font=font14, fill=0)
|
||||||
|
update_epd()
|
||||||
|
|
||||||
#Update display with info from camera (camera shooting new photo or name of the
|
#Update display with info from camera (camera shooting new photo or name of the
|
||||||
# last photo)
|
# last photo)
|
||||||
def on_message_camera(client, userdata, msg):
|
def on_message_camera(client, userdata, msg):
|
||||||
pl = msg.payload.decode()
|
pl = msg.payload.decode()
|
||||||
print("{} : {} ({})".format(msg.topic, pl, type(pl)))
|
print("{} : {} ({})".format(msg.topic, pl, type(pl)))
|
||||||
|
|
||||||
|
# Photo en cours
|
||||||
if pl == "1" and msg.topic == camera_mqtt_topic + "/shooting" :
|
if pl == "1" and msg.topic == camera_mqtt_topic + "/shooting" :
|
||||||
disp.Dis_String(0, 105, "Shooting photo... ", 16)
|
draw.rectangle((0, 105, epd2in13.EPD_HEIGHT, 120), fill=255)
|
||||||
|
draw.text((0, 105), "Shooting photo... ", font=font14, fill=0)
|
||||||
|
update_epd()
|
||||||
|
|
||||||
|
#Dernière photo prise
|
||||||
if msg.topic == camera_mqtt_topic + "/last_photo":
|
if msg.topic == camera_mqtt_topic + "/last_photo":
|
||||||
disp.Dis_String(0, 105, "Last: " + pl, 16)
|
draw.rectangle((0, 105, epd2in13.EPD_HEIGHT, 120), fill=255)
|
||||||
|
draw.text((0, 105), "Last: " + pl, font=font14, fill=0)
|
||||||
|
update_epd()
|
||||||
|
|
||||||
#Callback de déconnexion au broker MQTT
|
#Callback de déconnexion au broker MQTT
|
||||||
def on_disconnect(client, userdata, msg):
|
def on_disconnect(client, userdata, msg):
|
||||||
@ -91,21 +124,46 @@ def on_disconnect(client, userdata, msg):
|
|||||||
# Main #
|
# Main #
|
||||||
########
|
########
|
||||||
|
|
||||||
#init and Clear full screen
|
#Screen init.
|
||||||
bus = 0
|
epd = epd2in13.EPD()
|
||||||
device = 0
|
epd.init(epd.lut_full_update)
|
||||||
disp = EPD_driver.EPD_driver(spi=SpiDev(bus, device))
|
|
||||||
|
|
||||||
print("Start display...")
|
#List of TrueType fonts
|
||||||
disp.Dis_Clear_full()
|
font12 = ImageFont.truetype(epd_font_file, 12)
|
||||||
disp.Dis_Clear_part()
|
font14 = ImageFont.truetype(epd_font_file, 14)
|
||||||
print("OK")
|
font16 = ImageFont.truetype(epd_font_file, 16)
|
||||||
|
font12_bold = ImageFont.truetype(epd_bold_font_file, 12)
|
||||||
|
font14_bold = ImageFont.truetype(epd_bold_font_file, 14)
|
||||||
|
font16_bold = ImageFont.truetype(epd_bold_font_file, 16)
|
||||||
|
#font12_obl = ImageFont.truetype(epd_italic_font_file, 12)
|
||||||
|
#font14_obl = ImageFont.truetype(epd_italic_font_file, 14)
|
||||||
|
#font16_obl = ImageFont.truetype(epd_italic_font_file, 16)
|
||||||
|
|
||||||
#disp.Dis_String(0, 0, "{} | {}".format(socket.gethostname(), netifaces.ifaddresses('wlan0')[2][0]['addr']), 12)
|
#New image buffer
|
||||||
disp.Dis_String(0, 0, "IPv4 : {}".format(netifaces.ifaddresses('wlan0')[2][0]['addr']), 16)
|
# Memo : 0=black, 255= white/blank
|
||||||
disp.Dis_String(0, 33, "Temperature : ", 16)
|
image = Image.new('1', (epd2in13.EPD_HEIGHT, epd2in13.EPD_WIDTH), 255)
|
||||||
disp.Dis_String(0, 49, "Humidity : ", 16)
|
draw = ImageDraw.Draw(image)
|
||||||
disp.Dis_String(0, 65, "Sea Pression : ", 16)
|
|
||||||
|
#Draw basic text and frame :
|
||||||
|
draw.rectangle((0, 0, epd2in13.EPD_HEIGHT, 18), fill=0)
|
||||||
|
draw.text((60, 2), "Projet Camétéo", font=font16_bold, fill=255)
|
||||||
|
draw.text((0, 20), "{} : IP= {}".format(socket.gethostname(), netifaces.ifaddresses('wlan0')[2][0]['addr']), font = font12, fill=0 )
|
||||||
|
draw.line((0,49,epd2in13.EPD_HEIGHT, 49), fill=0)
|
||||||
|
draw.line((0,65,epd2in13.EPD_HEIGHT, 65), fill=0)
|
||||||
|
draw.line((0,81,epd2in13.EPD_HEIGHT, 81), fill=0)
|
||||||
|
draw.line((125, 49, 125, 81), fill=0)
|
||||||
|
|
||||||
|
#Display on ePaper screen
|
||||||
|
epd.clear_frame_memory(0xFF)
|
||||||
|
update_epd()
|
||||||
|
|
||||||
|
#
|
||||||
|
#screen = image.rotate(90, expand=True)
|
||||||
|
#epd.set_frame_memory(screen, 0, 0)
|
||||||
|
#epd.display_frame()
|
||||||
|
|
||||||
|
#Toggle to partial refresh
|
||||||
|
epd.init(epd.lut_partial_update)
|
||||||
|
|
||||||
#Connect to MQTT broker and loop...
|
#Connect to MQTT broker and loop...
|
||||||
mqtt_client = mqtt.Client(mqtt_client_id, clean_session=True)
|
mqtt_client = mqtt.Client(mqtt_client_id, clean_session=True)
|
||||||
|
Loading…
Reference in New Issue
Block a user