kopia lustrzana https://github.com/peterhinch/micropython-nano-gui
Add EPD micropower demo and docs.
rodzic
834e5da770
commit
bfe679d169
65
DRIVERS.md
65
DRIVERS.md
|
@ -39,6 +39,7 @@ a bare minimum of functionality required to support the above.
|
|||
7.1.2 [EPD public methods](./DRIVERS.md#712-epd-public-methods)
|
||||
7.1.3 [EPD public bound variables](./DRIVERS.md#713-epd-public-bound-variables)
|
||||
7.1.4 [FeatherWing Wiring](./DRIVERS.md#714-featherwing-wiring)
|
||||
7.1.5 [Micropower use](./DRIVERS.md#715-micropower-use)
|
||||
7.2 [Waveshare eInk Display HAT](./DRIVERS.md#72-waveshare-eink-display-hat)
|
||||
7.2.1 [EPD constructor args](./DRIVERS.md#721-epd-constructor-args)
|
||||
7.2.2 [EPD public methods](./DRIVERS.md#722-epd-public-methods)
|
||||
|
@ -46,6 +47,9 @@ a bare minimum of functionality required to support the above.
|
|||
8. [EPD Asynchronous support](./DRIVERS.md#8-epd-asynchronous-support)
|
||||
9. [Writing device drivers](./DRIVERS.md#9-writing-device-drivers)
|
||||
|
||||
The [Micropower use](./DRIVERS.md#715-micropower-use) section is applicable to
|
||||
EPD's in general but makes specific reference to the 2.9" micropower demo.
|
||||
|
||||
###### [Main README](./README.md#1-introduction)
|
||||
|
||||
# 1. Introduction
|
||||
|
@ -551,9 +555,10 @@ An alternative is the
|
|||
In my testing there are differences between these alternatives. The FeatherWing
|
||||
shows a black border around the display. The reason for this is
|
||||
[unclear](https://github.com/adafruit/Adafruit_CircuitPython_IL0373/issues/11#issuecomment-763704622).
|
||||
Secondly, while the FeatherWing behaves as expected the image on the flexible
|
||||
display gradually degrades if the display is powered down. The white background
|
||||
becomes speckled over a period of a few minutes.
|
||||
In development I encountered instances where the image on the flexible display
|
||||
gradually degraded after the system was powered down. The white background
|
||||
becomes speckled over a period of a few minutes. I'm unsure of the reason for
|
||||
this. The `epd29_lowpower` demo did not exhibit this.
|
||||
|
||||
The interface breakout for the flexible display has an `ENA` pin which enables
|
||||
the display to be powered down. This facilitates micropower applications: the
|
||||
|
@ -628,16 +633,6 @@ see below.
|
|||
seconds to enable viewing. This enables generic nanogui demos to be run on an
|
||||
EPD.
|
||||
|
||||
##### Micropower use
|
||||
|
||||
To power down the breakout the `ENA` pin must be pulled to 0v. Some
|
||||
microcontrollers can ensure that a GPIO pin is able to sink current when the
|
||||
chip goes into deep sleep. In other cases the pin becomes high impedance. The
|
||||
following ensures that a high impedance pin will cause `ENA` to be pulled low.
|
||||
The N channel MOSFET must have a low threshold voltage.
|
||||
|
||||

|
||||
|
||||
### 7.1.4 FeatherWing wiring
|
||||
|
||||
The [pinout is listed here](https://learn.adafruit.com/adafruit-eink-display-breakouts/pinouts-2).
|
||||
|
@ -671,6 +666,50 @@ The FeatherWing has a reset button which shorts the RST line to Gnd. To avoid
|
|||
risk of damage to the microcontroller pin if the button is pressed, the pin
|
||||
should be configured as open drain.
|
||||
|
||||
### 7.1.5 Micropower use
|
||||
|
||||
Developers of micropower applications will need to familiarise themselves with
|
||||
the power saving features of their board. Information may be found in
|
||||
[micropython-micropower](https://github.com/peterhinch/micropython-micropower).
|
||||
Some information is generic, but the code is Pyboard specific. Pyboard users
|
||||
should copy `upower.py` to the filesystem root. Further power savings may be
|
||||
achieved by precompiling or freezing code as this avoids the energy used by the
|
||||
compiler (on each wakeup). Users of other platforms will need to know how to
|
||||
enter and exit from deep sleep.
|
||||
|
||||
I developed this using the breakout board linked to Wbus DIP28 adaptor and a
|
||||
Pyboard D, powered from a LiPo cell. A Pyboard 1.1 could be used identically.
|
||||
The test script `epd29_lowpower.py` requires `upower.py` as described above.
|
||||
This simplifies access to the Pyboard RTC's alarms which can wake the board
|
||||
from deep sleep. Wakeup from certain pins is also possible.
|
||||
|
||||
To power down the breakout the `ENA` pin must be pulled to 0v. Some
|
||||
microcontrollers can ensure that a GPIO pin is able to sink current when the
|
||||
chip goes into deep sleep. In other cases the pin becomes high impedance. The
|
||||
following ensures that a high impedance pin will cause `ENA` to be pulled low.
|
||||
The N channel MOSFET must have a low threshold voltage.
|
||||
|
||||

|
||||
|
||||
An alternative, slightly less efficient approach, is to pull down `ENA` with
|
||||
a 2.2KΩ resistor and link it to a GPIO pin. The breakout has a 100KΩ resistor
|
||||
to Vin. The 2.2KΩ resistor causes the breakout and display to assume the power
|
||||
off state if the GPIO pin is high impedance.
|
||||
|
||||
The test script `epd29_lowpower.py` assumes pin `Y5` linked to the breakout
|
||||
enable. I used the 2.2KΩ resistor pull down. The code comments clarify the mode
|
||||
of operation. The demo wakes every 30s. Real applications would do it much less
|
||||
frequently with attendant power savings.
|
||||
|
||||
Users of other EPD's may want to develop other means of powering down the EPD.
|
||||
A p-channel MOSFET could be considered as described
|
||||
[here](https://github.com/peterhinch/micropython-micropower/blob/master/HARDWARE.md#hardware-issues).
|
||||
|
||||
In use I measured 500μA in the periods when the display is refreshing (a total
|
||||
of 10s for each wakeup) and 58μA between wakeups. The Pyboard accounts for
|
||||
about 6μA. 33μA will be used by the 100KΩ pullup on the breakout's power enable
|
||||
line. I haven't attempted to figure out where the other 19μA is going.
|
||||
|
||||
###### [Contents](./DRIVERS.md#contents)
|
||||
|
||||
## 7.2 Waveshare eInk Display HAT
|
||||
|
|
|
@ -264,6 +264,9 @@ Demos for ePaper displays:
|
|||
* `waveshare_test.py` For the Waveshare eInk Display HAT 2.7" 176*274 display.
|
||||
* `epd29_sync.py` Demo for Adafruit 2.9" eInk display: emulates a seismograph.
|
||||
* `epd29_async.py` Asynchronous demo for Adafruit 2.9" eInk display.
|
||||
* `epd29_lowpower.py` Micropower demo for Adafruit 2.9" eInk display. This doc
|
||||
[Micropower use](./DRIVERS.md#715-micropower-use) should be read before
|
||||
attempting to run this.
|
||||
|
||||
Demos for Sharp displays:
|
||||
* `sharptest.py` Basic functionality check.
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
# epd29_sync.py Demo of synchronous code on 2.9" EPD display
|
||||
|
||||
# Released under the MIT License (MIT). See LICENSE.
|
||||
# Copyright (c) 2020 Peter Hinch
|
||||
|
||||
# color_setup must set landcsape True, asyn False and must not set demo_mode
|
||||
|
||||
from math import pi, sin
|
||||
import upower
|
||||
import machine
|
||||
import pyb
|
||||
pon = machine.Pin('Y5', machine.Pin.OUT_PP, value=1) # Power on before instantiating display
|
||||
upower.lpdelay(1000) # Give the valves (tubes) time to warm up :)
|
||||
from color_setup import ssd # Instantiate
|
||||
from gui.core.writer import Writer
|
||||
from gui.core.nanogui import refresh
|
||||
from gui.core.fplot import CartesianGraph, Curve
|
||||
from gui.widgets.meter import Meter
|
||||
from gui.widgets.label import Label
|
||||
from gui.widgets.dial import Dial, Pointer
|
||||
|
||||
# Fonts
|
||||
import gui.fonts.arial10 as arial10
|
||||
import gui.fonts.freesans20 as large
|
||||
|
||||
wri = Writer(ssd, arial10, verbose=False)
|
||||
wri.set_clip(False, False, False)
|
||||
|
||||
wri_large = Writer(ssd, large, verbose=False)
|
||||
wri_large.set_clip(False, False, False)
|
||||
|
||||
def graph():
|
||||
row, col, ht, wd = 5, 140, 75, 150
|
||||
def populate():
|
||||
x = -0.998
|
||||
while x < 1.01:
|
||||
z = 6 * pi * x
|
||||
y = sin(z) / z
|
||||
yield x, y
|
||||
x += 0.05
|
||||
|
||||
g = CartesianGraph(wri, row, col, height = ht, width = wd, bdcolor=False)
|
||||
curve2 = Curve(g, None, populate())
|
||||
Label(wri, row + ht + 5, col - 10, '-2.0 t: secs')
|
||||
Label(wri, row + ht + 5, col - 8 + int(wd//2), '0.0')
|
||||
Label(wri, row + ht + 5, col - 10 + wd, '2.0')
|
||||
|
||||
def compass():
|
||||
dial = Dial(wri, 5, 5, height = 75, ticks = 12, bdcolor=None,
|
||||
label='Direction', style = Dial.COMPASS)
|
||||
ptr = Pointer(dial)
|
||||
ptr.value(1 + 1j)
|
||||
|
||||
def meter():
|
||||
m = Meter(wri, 5, 100, height = 75, divisions = 4,
|
||||
label='Peak', style=Meter.BAR, legends=('0', '50', '100'))
|
||||
m.value(0.72)
|
||||
|
||||
def labels():
|
||||
row = 100
|
||||
col = 0
|
||||
Label(wri_large, row, col, 'Seismograph')
|
||||
col = 140
|
||||
Label(wri, row, col + 0, 'Event time')
|
||||
Label(wri, row, col + 60, '01:35', bdcolor=None)
|
||||
Label(wri, row, col + 95, 'UTC')
|
||||
row = 115
|
||||
Label(wri, row, col + 0, 'Event date')
|
||||
Label(wri, row, col + 60, '6th Jan 2021', bdcolor=None)
|
||||
|
||||
|
||||
# Populate the display - GUI and Writer code goes here
|
||||
def populate():
|
||||
graph()
|
||||
compass()
|
||||
meter()
|
||||
labels()
|
||||
|
||||
# Initialise GUI clearing display. Populate frame buffer. Update diplay and
|
||||
# leave in power down state ready for phsyical loss of power
|
||||
def show():
|
||||
# Low power version of .wait_until_ready()
|
||||
def wait_ready():
|
||||
while not ssd.ready():
|
||||
upower.lpdelay(1000)
|
||||
|
||||
refresh(ssd, True) # Init and clear. busy will go True for ~5s
|
||||
populate()
|
||||
wait_ready() # wait for display ready (seconds)
|
||||
refresh(ssd)
|
||||
wait_ready()
|
||||
ssd.sleep() # Put into "off" state
|
||||
|
||||
# Handle initial power up and subsequent wakeup.
|
||||
rtc = pyb.RTC()
|
||||
# If we have a backup battery clear down any setting from a previously running program
|
||||
rtc.wakeup(None)
|
||||
reason = machine.reset_cause() # Why have we woken?
|
||||
red = pyb.LED(1)
|
||||
if reason in (machine.PWRON_RESET, machine.HARD_RESET, machine.SOFT_RESET):
|
||||
# Code to run when the application is first started
|
||||
aa = upower.Alarm('a')
|
||||
aa.timeset(second = 39)
|
||||
ab = upower.Alarm('b')
|
||||
ab.timeset(second = 9)
|
||||
elif reason == machine.DEEPSLEEP_RESET:
|
||||
# Display on. Pin is pulled down by 2K2 so hi-z turns display off.
|
||||
red.on()
|
||||
show()
|
||||
pon(0) # Physically power down display
|
||||
red.off()
|
||||
|
||||
pyb.standby()
|
Ładowanie…
Reference in New Issue