Last active
July 9, 2023 12:59
-
-
Save mu88/30672b24909995ade76ceda10cbde80b to your computer and use it in GitHub Desktop.
Display screenshot on Waveshare ePaper display
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import framebuf | |
import gc | |
from machine import Pin, SPI, I2C | |
import network | |
import time | |
import urequests | |
import utime | |
class INA219: | |
def __init__(self, i2c_bus=1, addr=0x40): | |
self.i2c = I2C(i2c_bus); | |
self.addr = addr | |
# Set chip to known config values to start | |
self._cal_value = 0 | |
self._current_lsb = 0 | |
self._power_lsb = 0 | |
self.set_calibration_32V_2A() | |
def read(self,address): | |
data = self.i2c.readfrom_mem(self.addr, address, 2) | |
return ((data[0] * 256 ) + data[1]) | |
def write(self,address,data): | |
temp = [0,0] | |
temp[1] = data & 0xFF | |
temp[0] =(data & 0xFF00) >> 8 | |
self.i2c.writeto_mem(self.addr,address,bytes(temp)) | |
def set_calibration_32V_2A(self): | |
self._current_lsb = 1 # Current LSB = 100uA per bit | |
self._cal_value = 4096 | |
self._power_lsb = .002 # Power LSB = 2mW per bit | |
self.write(0x05,self._cal_value) | |
# Set Config register to take into account the settings above | |
self.bus_voltage_range = 0x01 | |
self.gain = 0x03 | |
self.bus_adc_resolution = 0x0D | |
self.shunt_adc_resolution = 0x0D | |
self.mode = 0x07 | |
self.config = self.bus_voltage_range << 13 | \ | |
self.gain << 11 | \ | |
self.bus_adc_resolution << 7 | \ | |
self.shunt_adc_resolution << 3 | \ | |
self.mode | |
self.write(0x00,self.config) | |
def getBusVoltage(self): | |
self.read(0x02) | |
bus_voltage = (self.read(0x02) >> 3) * 0.004 | |
percentage = (bus_voltage -3)/1.2*100 | |
if(percentage<0):percentage=0 | |
elif(percentage>100):percentage=100 | |
return percentage | |
# Display resolution | |
EPD_WIDTH = 800 | |
EPD_HEIGHT = 480 | |
RST_PIN = 12 | |
DC_PIN = 8 | |
CS_PIN = 9 | |
BUSY_PIN = 13 | |
class EPD_7in5_B: | |
def __init__(self): | |
self.reset_pin = Pin(RST_PIN, Pin.OUT) | |
self.busy_pin = Pin(BUSY_PIN, Pin.IN, Pin.PULL_UP) | |
self.cs_pin = Pin(CS_PIN, Pin.OUT) | |
self.width = EPD_WIDTH | |
self.height = EPD_HEIGHT | |
self.spi = SPI(1) | |
self.spi.init(baudrate=4000_000) | |
self.dc_pin = Pin(DC_PIN, Pin.OUT) | |
self.buffer_black = bytearray(self.height * self.width // 8) | |
self.buffer_red = bytearray(self.height * self.width // 8) | |
self.imageblack = framebuf.FrameBuffer(self.buffer_black, self.width, self.height, framebuf.MONO_HLSB) | |
self.imagered = framebuf.FrameBuffer(self.buffer_red, self.width, self.height, framebuf.MONO_HLSB) | |
self.init() | |
def digital_write(self, pin, value): | |
pin.value(value) | |
def digital_read(self, pin): | |
return pin.value() | |
def delay_ms(self, delaytime): | |
utime.sleep(delaytime / 1000.0) | |
def spi_writebyte(self, data): | |
self.spi.write(bytearray(data)) | |
def module_exit(self): | |
self.digital_write(self.reset_pin, 0) | |
# Hardware reset | |
def reset(self): | |
self.digital_write(self.reset_pin, 1) | |
self.delay_ms(200) | |
self.digital_write(self.reset_pin, 0) | |
self.delay_ms(2) | |
self.digital_write(self.reset_pin, 1) | |
self.delay_ms(200) | |
def send_command(self, command): | |
self.digital_write(self.dc_pin, 0) | |
self.digital_write(self.cs_pin, 0) | |
self.spi_writebyte([command]) | |
self.digital_write(self.cs_pin, 1) | |
def send_data(self, data): | |
self.digital_write(self.dc_pin, 1) | |
self.digital_write(self.cs_pin, 0) | |
self.spi_writebyte([data]) | |
self.digital_write(self.cs_pin, 1) | |
def send_data1(self, buf): | |
self.digital_write(self.dc_pin, 1) | |
self.digital_write(self.cs_pin, 0) | |
self.spi.write(bytearray(buf)) | |
self.digital_write(self.cs_pin, 1) | |
def WaitUntilIdle(self): | |
print("e-Paper busy") | |
while(self.digital_read(self.busy_pin) == 0): # Wait until the busy_pin goes LOW | |
self.delay_ms(20) | |
self.delay_ms(20) | |
print("e-Paper busy release") | |
def TurnOnDisplay(self): | |
self.send_command(0x12) # DISPLAY REFRESH | |
self.delay_ms(100) #!!!The delay here is necessary, 200uS at least!!! | |
self.WaitUntilIdle() | |
def init(self): | |
# EPD hardware init start | |
self.reset() | |
self.send_command(0x06) # btst | |
self.send_data(0x17) | |
self.send_data(0x17) | |
self.send_data(0x28) # If an exception is displayed, try using 0x38 | |
self.send_data(0x17) | |
self.send_command(0x04) # POWER ON | |
self.delay_ms(100) | |
self.WaitUntilIdle() | |
self.send_command(0X00) # PANNEL SETTING | |
self.send_data(0x0F) # KW-3f KWR-2F BWROTP 0f BWOTP 1f | |
self.send_command(0x61) # tres | |
self.send_data(0x03) # source 800 | |
self.send_data(0x20) | |
self.send_data(0x01) # gate 480 | |
self.send_data(0xE0) | |
self.send_command(0X15) | |
self.send_data(0x00) | |
self.send_command(0X50) # VCOM AND DATA INTERVAL SETTING | |
self.send_data(0x11) | |
self.send_data(0x07) | |
self.send_command(0X60) # TCON SETTING | |
self.send_data(0x22) | |
self.send_command(0x65) # Resolution setting | |
self.send_data(0x00) | |
self.send_data(0x00) # 800*480 | |
self.send_data(0x00) | |
self.send_data(0x00) | |
return 0; | |
def Clear(self): | |
high = self.height | |
if( self.width % 8 == 0) : | |
wide = self.width // 8 | |
else : | |
wide = self.width // 8 + 1 | |
self.send_command(0x10) | |
for i in range(0, wide): | |
self.send_data1([0xff] * high) | |
self.send_command(0x13) | |
for i in range(0, wide): | |
self.send_data1([0x00] * high) | |
self.TurnOnDisplay() | |
def display(self): | |
high = self.height | |
if( self.width % 8 == 0) : | |
wide = self.width // 8 | |
else : | |
wide = self.width // 8 + 1 | |
# send black data | |
self.send_command(0x10) | |
for i in range(0, wide): | |
self.send_data1(self.buffer_black[(i * high) : ((i+1) * high)]) | |
# send red data | |
self.send_command(0x13) | |
for i in range(0, wide): | |
self.send_data1(self.buffer_red[(i * high) : ((i+1) * high)]) | |
self.TurnOnDisplay() | |
def sleep(self): | |
self.send_command(0x02) # power off | |
self.WaitUntilIdle() | |
self.send_command(0x07) # deep sleep | |
self.send_data(0xa5) | |
def connect_wifi(): | |
pin = Pin("LED", Pin.OUT) | |
pin.off() | |
# waiting some time between connecting and checking the status is crucial for a reliable WiFi connection | |
wifi = network.WLAN(network.STA_IF) | |
wifi.active(True) | |
time.sleep(2) | |
wifi.connect('<<SSID>>', '<<Password>>') | |
time.sleep(2) | |
max_wait = 10 | |
while max_wait > 0: | |
if wifi.status() < 0 or wifi.status() >= 3: | |
break | |
max_wait -= 1 | |
time.sleep(1) | |
if wifi.status() != 3: | |
raise RuntimeError('network connection failed') | |
wifi = None | |
if __name__=='__main__': | |
gc.enable() | |
pin = Pin("LED", Pin.OUT) | |
pin.off() | |
epd = EPD_7in5_B() | |
epd.Clear() | |
sleep_in_seconds = 90 | |
empty_buffer = bytearray(0) | |
ina219 = INA219(addr=0x43) | |
try: | |
connect_wifi() | |
while(True): | |
gc.collect() | |
response = urequests.get('http://<<Server>>/screenshotCreator/latestImage?blackAndWhite=true&asWaveshareBytes=true&addWaveshareInstructions=true') | |
if response.status_code == 200: | |
update_screen = response.headers.get('waveshare-update-screen', 'True') == 'True' | |
sleep_in_seconds = int(response.headers.get('waveshare-sleep-between-updates', '90')) | |
if update_screen: | |
last_modified = response.headers.get('waveshare-last-modified-local-time', 'xx:xx') | |
voltage_percentage = ina219.getBusVoltage() | |
epd.init() # explicitly wake up display from deep sleep | |
# assign black and red portion | |
gc.collect() | |
time.sleep(1) | |
epd.buffer_black = response.content | |
epd.imagered.fill(0x00) | |
epd.imagered.text(last_modified, 750, 460, 0xff) | |
epd.imagered.text(str(voltage_percentage), 20, 460, 0xff) | |
# display and go to deep sleep | |
epd.display() | |
epd.sleep() | |
# do not leak memory | |
epd.buffer_black = empty_buffer | |
update_screen = None | |
last_modified = None | |
response = None | |
time.sleep(sleep_in_seconds) | |
except Exception as e: | |
print(e) | |
f = open('error.txt', 'w') | |
f.write(str(e)) | |
f.close() | |
pin = Pin("LED", Pin.OUT) | |
pin.on() | |
raise e |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import framebuf | |
import gc | |
from machine import Pin, SPI | |
import network | |
import time | |
import urequests | |
import utime | |
# Display resolution | |
EPD_WIDTH = 800 | |
EPD_HEIGHT = 480 | |
RST_PIN = 12 | |
DC_PIN = 8 | |
CS_PIN = 9 | |
BUSY_PIN = 13 | |
class EPD_7in5_B: | |
def __init__(self): | |
self.reset_pin = Pin(RST_PIN, Pin.OUT) | |
self.busy_pin = Pin(BUSY_PIN, Pin.IN, Pin.PULL_UP) | |
self.cs_pin = Pin(CS_PIN, Pin.OUT) | |
self.width = EPD_WIDTH | |
self.height = EPD_HEIGHT | |
self.spi = SPI(1) | |
self.spi.init(baudrate=4000_000) | |
self.dc_pin = Pin(DC_PIN, Pin.OUT) | |
self.buffer_black = bytearray(self.height * self.width // 8) | |
self.buffer_red = bytearray(self.height * self.width // 8) | |
self.imageblack = framebuf.FrameBuffer(self.buffer_black, self.width, self.height, framebuf.MONO_HLSB) | |
self.imagered = framebuf.FrameBuffer(self.buffer_red, self.width, self.height, framebuf.MONO_HLSB) | |
self.init() | |
def digital_write(self, pin, value): | |
pin.value(value) | |
def digital_read(self, pin): | |
return pin.value() | |
def delay_ms(self, delaytime): | |
utime.sleep(delaytime / 1000.0) | |
def spi_writebyte(self, data): | |
self.spi.write(bytearray(data)) | |
def module_exit(self): | |
self.digital_write(self.reset_pin, 0) | |
# Hardware reset | |
def reset(self): | |
self.digital_write(self.reset_pin, 1) | |
self.delay_ms(200) | |
self.digital_write(self.reset_pin, 0) | |
self.delay_ms(2) | |
self.digital_write(self.reset_pin, 1) | |
self.delay_ms(200) | |
def send_command(self, command): | |
self.digital_write(self.dc_pin, 0) | |
self.digital_write(self.cs_pin, 0) | |
self.spi_writebyte([command]) | |
self.digital_write(self.cs_pin, 1) | |
def send_data(self, data): | |
self.digital_write(self.dc_pin, 1) | |
self.digital_write(self.cs_pin, 0) | |
self.spi_writebyte([data]) | |
self.digital_write(self.cs_pin, 1) | |
def send_data1(self, buf): | |
self.digital_write(self.dc_pin, 1) | |
self.digital_write(self.cs_pin, 0) | |
self.spi.write(bytearray(buf)) | |
self.digital_write(self.cs_pin, 1) | |
def WaitUntilIdle(self): | |
print("e-Paper busy") | |
while(self.digital_read(self.busy_pin) == 0): # Wait until the busy_pin goes LOW | |
self.delay_ms(20) | |
self.delay_ms(20) | |
print("e-Paper busy release") | |
def TurnOnDisplay(self): | |
self.send_command(0x12) # DISPLAY REFRESH | |
self.delay_ms(100) #!!!The delay here is necessary, 200uS at least!!! | |
self.WaitUntilIdle() | |
def init(self): | |
# EPD hardware init start | |
self.reset() | |
self.send_command(0x06) # btst | |
self.send_data(0x17) | |
self.send_data(0x17) | |
self.send_data(0x28) # If an exception is displayed, try using 0x38 | |
self.send_data(0x17) | |
self.send_command(0x04) # POWER ON | |
self.delay_ms(100) | |
self.WaitUntilIdle() | |
self.send_command(0X00) # PANNEL SETTING | |
self.send_data(0x0F) # KW-3f KWR-2F BWROTP 0f BWOTP 1f | |
self.send_command(0x61) # tres | |
self.send_data(0x03) # source 800 | |
self.send_data(0x20) | |
self.send_data(0x01) # gate 480 | |
self.send_data(0xE0) | |
self.send_command(0X15) | |
self.send_data(0x00) | |
self.send_command(0X50) # VCOM AND DATA INTERVAL SETTING | |
self.send_data(0x11) | |
self.send_data(0x07) | |
self.send_command(0X60) # TCON SETTING | |
self.send_data(0x22) | |
self.send_command(0x65) # Resolution setting | |
self.send_data(0x00) | |
self.send_data(0x00) # 800*480 | |
self.send_data(0x00) | |
self.send_data(0x00) | |
return 0; | |
def Clear(self): | |
high = self.height | |
if( self.width % 8 == 0) : | |
wide = self.width // 8 | |
else : | |
wide = self.width // 8 + 1 | |
self.send_command(0x10) | |
for i in range(0, wide): | |
self.send_data1([0xff] * high) | |
self.send_command(0x13) | |
for i in range(0, wide): | |
self.send_data1([0x00] * high) | |
self.TurnOnDisplay() | |
def display(self): | |
high = self.height | |
if( self.width % 8 == 0) : | |
wide = self.width // 8 | |
else : | |
wide = self.width // 8 + 1 | |
# send black data | |
self.send_command(0x10) | |
for i in range(0, wide): | |
self.send_data1(self.buffer_black[(i * high) : ((i+1) * high)]) | |
# send red data | |
self.send_command(0x13) | |
for i in range(0, wide): | |
self.send_data1(self.buffer_red[(i * high) : ((i+1) * high)]) | |
self.TurnOnDisplay() | |
def sleep(self): | |
self.send_command(0x02) # power off | |
self.WaitUntilIdle() | |
self.send_command(0x07) # deep sleep | |
self.send_data(0xa5) | |
def connect_wifi(): | |
pin = Pin("LED", Pin.OUT) | |
pin.off() | |
# waiting some time between connecting and checking the status is crucial for a reliable WiFi connection | |
wifi = network.WLAN(network.STA_IF) | |
wifi.active(True) | |
time.sleep(2) | |
wifi.connect('<<SSID>>', '<<Password>>') | |
time.sleep(2) | |
max_wait = 10 | |
while max_wait > 0: | |
if wifi.status() < 0 or wifi.status() >= 3: | |
break | |
max_wait -= 1 | |
time.sleep(1) | |
if wifi.status() != 3: | |
raise RuntimeError('network connection failed') | |
wifi = None | |
if __name__=='__main__': | |
gc.enable() | |
pin = Pin("LED", Pin.OUT) | |
pin.off() | |
epd = EPD_7in5_B() | |
epd.Clear() | |
sleep_in_seconds = 90 | |
empty_buffer = bytearray(0) | |
try: | |
connect_wifi() | |
while(True): | |
gc.collect() | |
response = urequests.get('http://<<Server>>/screenshotCreator/latestImage?blackAndWhite=true&asWaveshareBytes=true&addWaveshareInstructions=true') | |
if response.status_code == 200: | |
update_screen = response.headers.get('waveshare-update-screen', 'True') == 'True' | |
sleep_in_seconds = int(response.headers.get('waveshare-sleep-between-updates', '90')) | |
if update_screen: | |
last_modified = response.headers.get('waveshare-last-modified-local-time', 'xx:xx') | |
epd.init() # explicitly wake up display from deep sleep | |
# assign black and red portion | |
gc.collect() | |
time.sleep(1) | |
epd.buffer_black = response.content | |
epd.imagered.fill(0x00) | |
epd.imagered.text(last_modified, 750, 460, 0xff) | |
# display and go to deep sleep | |
epd.display() | |
epd.sleep() | |
# do not leak memory | |
epd.buffer_black = empty_buffer | |
update_screen = None | |
last_modified = None | |
response = None | |
time.sleep(sleep_in_seconds) | |
except Exception as e: | |
print(e) | |
f = open('error.txt', 'w') | |
f.write(str(e)) | |
f.close() | |
pin = Pin("LED", Pin.OUT) | |
pin.on() | |
raise e |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment