kopia lustrzana https://github.com/peterhinch/micropython-nano-gui
Minor changes to ePaper files and docs.
rodzic
35e1a6b1b2
commit
4108aa32a4
30
DRIVERS.md
30
DRIVERS.md
|
@ -34,7 +34,7 @@ a bare minimum of functionality required to support the above.
|
|||
6.4.1 [Micropower applications](./DRIVERS.md#641-micropower-applications)
|
||||
6.5 [Resources](./DRIVERS.md#65-resources)
|
||||
7. [ePaper displays](./DRIVERS.md#7-epaper-displays)
|
||||
7.1 [Adafruit flexible eInk Display](./DRIVERS.md#71-adafruit-flexible-eink-display)
|
||||
7.1 [Adafruit monochrome eInk Displays](./DRIVERS.md#71-adafruit-monochrome-eink-displays)
|
||||
7.1.1 [EPD constructor args](./DRIVERS.md#711-epd-constructor-args)
|
||||
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)
|
||||
|
@ -538,9 +538,9 @@ more - which may be problematic for applications which need to respond to
|
|||
external events. A specific asynchronous mode provides support for reducing
|
||||
blocking time. See [EPD Asynchronous support](./DRIVERS.md#8-epd-asynchronous-support).
|
||||
|
||||
## 7.1 Adafruit flexible eInk Display
|
||||
## 7.1 Adafruit monochrome eInk Displays
|
||||
|
||||
The driver assumes an Adafruit 2.9 inch 296*128 pixel flexible
|
||||
The driver supports two Adafruit 2.9 inch 296*128 pixel units. A flexible
|
||||
[display](https://www.adafruit.com/product/4262) interfaced via their
|
||||
[interface breakout](https://www.adafruit.com/product/4224).
|
||||
|
||||
|
@ -548,28 +548,32 @@ An alternative is the
|
|||
[Adafruit 2.9" eInk FeatherWing](https://www.adafruit.com/product/4777) with
|
||||
[wiring details](./DRIVERS.md#714-featherwing-wiring) listed below.
|
||||
|
||||
These alternatives behave identically except that the FeatherWing shows a black
|
||||
border around the display. The reason for this is
|
||||
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.
|
||||
|
||||
The breakout has an `ENA` pin which enables the display to be powered down.
|
||||
This facilitates micropower applications: the host shuts down the display
|
||||
before going into deep sleep.
|
||||
The interface breakout for the flexible display has an `ENA` pin which enables
|
||||
the display to be powered down. This facilitates micropower applications: the
|
||||
host shuts down the display before itself going into deep sleep.
|
||||
|
||||
The driver is cross platform and supports landscape or portrait mode. To keep
|
||||
the buffer size down (to 4736 bytes) there is no greyscale support. It should
|
||||
be noted that the Adafruit site cautions against refreshing these displays more
|
||||
frequently than every 180s. It is
|
||||
be noted that the Adafruit site cautions against refreshing the flexible
|
||||
displays more frequently than every 180s. This warning does not appear on the
|
||||
FeatherWing pages. No reason for the warning is given and it is
|
||||
[unclear](https://forums.adafruit.com/viewtopic.php?f=19&t=174091) if this is
|
||||
an absolute limit or an average rate.
|
||||
|
||||
##### Wiring
|
||||
|
||||
The [interface schematic is here](https://learn.adafruit.com/assets/86038). The
|
||||
drawing title is confusing but I balieve this is the correct schematic.
|
||||
drawing title is confusing but I believe this is the correct schematic.
|
||||
|
||||
The following assumes a Pyboard host. Pyboard pin numbers are based on hardware
|
||||
SPI 2 and my arbitrary choice of GPIO. All may be changed and soft SPI may be
|
||||
SPI 2 and an arbitrary choice of GPIO. All may be changed and soft SPI may be
|
||||
used.
|
||||
|
||||
| Pyb | Breakout |
|
||||
|
@ -677,7 +681,7 @@ This 2.7" 176*274 display is designed for the Raspberry Pi and is detailed
|
|||
I bought two of these units from different sources. Both have hardware issues
|
||||
discussed [here](https://forum.micropython.org/viewtopic.php?f=2&t=9564). I
|
||||
have failed to achieve consistent behaviour. Units behave perfectly one day and
|
||||
fail the next. I published this driver on the assumption that I was sold
|
||||
fail the next. I published this driver on the assumption that I was twice sold
|
||||
dubious Chinese clones and that genuine ones would be reliable.
|
||||
|
||||
The driver is cross-platform.
|
||||
|
|
4
FPLOT.md
4
FPLOT.md
|
@ -45,7 +45,7 @@ two varying vectors.
|
|||
4.2.1 [Scaling](./FPLOT.md#421-scaling) Required scaling of complex points.
|
||||
4.3 [class TSequence](./FPLOT.md#43-class-tsequence) Plot Y values on time axis.
|
||||
|
||||
###### [Main README](../README.md)
|
||||
###### [Main README](./README.md)
|
||||
|
||||
# 1. Python files
|
||||
|
||||
|
@ -170,7 +170,7 @@ The Cartesian curve constructor takes the following positional arguments:
|
|||
|
||||
Mandatory arguments:
|
||||
1. `graph` The `CartesianGraph` instance.
|
||||
2. `color`
|
||||
2. `color` If `None` is passed, the `graph` foreground color is used.
|
||||
|
||||
Optional arguments:
|
||||
3. `populate=None` A generator to populate the curve. See below.
|
||||
|
|
|
@ -33,6 +33,9 @@ floats as the notionally very long scale moves behind its small window.
|
|||
 The Textbox widget for scrolling text with word
|
||||
wrap or clipping.
|
||||
|
||||
 A mockup of a seismograph screen on an ePaper
|
||||
display.
|
||||
|
||||
Notes on [Adafruit and other OLED displays](./ADAFRUIT.md) including
|
||||
wiring details, pin names and hardware issues.
|
||||
|
||||
|
@ -258,7 +261,8 @@ Demos for larger displays.
|
|||
|
||||
Demos for ePaper displays:
|
||||
* `waveshare_test.py` For the Waveshare eInk Display HAT 2.7" 176*274 display.
|
||||
* `epd29_test.py` Demo for Adafruit 2.9" eInk 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.
|
||||
|
||||
Demos for Sharp displays:
|
||||
* `sharptest.py` Basic functionality check.
|
||||
|
@ -311,7 +315,8 @@ copied to the hardware root as `color_setup.py`. Example files:
|
|||
[Adafruit 1.44 inch TFT display](https://www.adafruit.com/product/2088).
|
||||
* `ili9341_setup.py` A 240*320 ILI9341 display on ESP32.
|
||||
* `waveshare_setup.py` 176*274 ePaper display.
|
||||
* `epd96_asyn.py` Adafruit 2.9 inch ePaper display, optimised for `uasyncio`.
|
||||
* `epd29_sync.py` Adafruit 2.9 inch ePaper display for synchronous code.
|
||||
* `epd29_async.py` Adafruit 2.9 inch ePaper display: `uasyncio` applications.
|
||||
|
||||
## 2.2 Dependencies
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# epd96_asyn.py Config for asynchronous applications on 2.9" ePaper.
|
||||
# Customise for your hardware config
|
||||
# epd29_async.py Config for asynchronous applications on 2.9" ePaper.
|
||||
# Customise for your hardware config.
|
||||
|
||||
# Released under the MIT License (MIT). See LICENSE.
|
||||
# Copyright (c) 2020 Peter Hinch
|
|
@ -1,7 +1,5 @@
|
|||
# epd96_demo.py Allow standard demos to run on ePaper.
|
||||
# Customise for your hardware config.
|
||||
# Beware of running demos for long as they refresh the display more frequently
|
||||
# than is advised by Adafruit.
|
||||
# epd29_sync.py Config for synchronous applications on 2.9" ePaper.
|
||||
# Customise for your hardware config
|
||||
|
||||
# Released under the MIT License (MIT). See LICENSE.
|
||||
# Copyright (c) 2020 Peter Hinch
|
||||
|
@ -41,4 +39,4 @@ pbusy = machine.Pin('Y4', machine.Pin.IN)
|
|||
spi = machine.SPI(2, baudrate=5_000_000)
|
||||
gc.collect() # Precaution before instantiating framebuf
|
||||
ssd = SSD(spi, pcs, pdc, prst, pbusy) # Create a display instance
|
||||
ssd.demo_mode = True
|
||||
# ssd.demo_mode = True
|
|
@ -58,7 +58,7 @@ class Curve():
|
|||
self.graph = graph
|
||||
self.origin = origin
|
||||
self.excursion = excursion
|
||||
self.color = color
|
||||
self.color = color if color is not None else graph.fgcolor
|
||||
self.lastpoint = None
|
||||
self.newpoint = None
|
||||
if populate is not None and self._valid(populate):
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
# epd29_test.py Demo program for nano_gui on an Adafruit 2.9" flexible ePaper screen
|
||||
# epd29_async.py Demo program for nano_gui on an Adafruit 2.9" flexible ePaper screen
|
||||
|
||||
# Released under the MIT License (MIT). See LICENSE.
|
||||
# Copyright (c) 2020 Peter Hinch
|
||||
|
||||
# color_setup must set landcsape True, asyn True and must not set demo_mode
|
||||
from cmath import exp, pi
|
||||
import uasyncio as asyncio
|
||||
from color_setup import ssd
|
||||
# On a monochrome display Writer is more efficient than CWriter.
|
||||
|
@ -11,11 +12,13 @@ from gui.core.writer import Writer
|
|||
from gui.core.nanogui import refresh
|
||||
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.font6 as small
|
||||
|
||||
ssd._asyn = True # HACK to make it config agnostic
|
||||
# Some ports don't support uos.urandom.
|
||||
# See https://github.com/peterhinch/micropython-samples/tree/master/random
|
||||
def xorshift64star(modulo, seed = 0xf9ac6ba4):
|
||||
|
@ -28,21 +31,20 @@ def xorshift64star(modulo, seed = 0xf9ac6ba4):
|
|||
return (x * 0x2545F4914F6CDD1D) % modulo
|
||||
return func
|
||||
|
||||
async def fields(evt):
|
||||
wri = Writer(ssd, small, verbose=False)
|
||||
async def compass(evt): # TODO why does this not get drawn on 1st pass?
|
||||
wri = Writer(ssd, arial10, verbose=False)
|
||||
wri.set_clip(False, False, False)
|
||||
textfield = Label(wri, 0, 2, wri.stringlen('longer'))
|
||||
numfield = Label(wri, 25, 2, wri.stringlen('99.990'), bdcolor=None)
|
||||
countfield = Label(wri, 0, 60, wri.stringlen('1'))
|
||||
n = 1
|
||||
random = xorshift64star(65535)
|
||||
v1 = 0 + 0.9j
|
||||
v2 = exp(0 - (pi / 6) * 1j)
|
||||
dial = Dial(wri, 5, 5, height = 75, ticks = 12, bdcolor=None,
|
||||
label='Direction', style = Dial.COMPASS)
|
||||
ptr = Pointer(dial)
|
||||
while True:
|
||||
for s in ('short', 'longer', '1', ''):
|
||||
textfield.value(s)
|
||||
numfield.value('{:5.2f}'.format(random() /1000))
|
||||
countfield.value('{:1d}'.format(n))
|
||||
n += 1
|
||||
await evt.wait()
|
||||
ptr.value(v1)
|
||||
v1 *= v2
|
||||
# await asyncio.sleep_ms(100)
|
||||
await evt.wait()
|
||||
|
||||
|
||||
async def multi_fields(evt):
|
||||
wri = Writer(ssd, small, verbose=False)
|
||||
|
@ -68,15 +70,16 @@ async def multi_fields(evt):
|
|||
|
||||
async def meter(evt):
|
||||
wri = Writer(ssd, arial10, verbose=False)
|
||||
wri.set_clip(False, False, False)
|
||||
row = 10
|
||||
col = 150
|
||||
col = 170
|
||||
args = {'height' : 80,
|
||||
'width' : 15,
|
||||
'divisions' : 4,
|
||||
'style' : Meter.BAR}
|
||||
m0 = Meter(wri, row, col, legends=('0.0', '0.5', '1.0'), **args)
|
||||
m1 = Meter(wri, row, col + 50, legends=('-1', '0', '+1'), **args)
|
||||
m2 = Meter(wri, row, col + 100, legends=('-1', '0', '+1'), **args)
|
||||
m1 = Meter(wri, row, col + 40, legends=('-1', '0', '+1'), **args)
|
||||
m2 = Meter(wri, row, col + 80, legends=('-1', '0', '+1'), **args)
|
||||
random = xorshift64star(2**24 - 1)
|
||||
while True:
|
||||
steps = 10
|
||||
|
@ -93,7 +96,7 @@ async def main():
|
|||
evt = asyncio.Event()
|
||||
asyncio.create_task(meter(evt))
|
||||
asyncio.create_task(multi_fields(evt))
|
||||
asyncio.create_task(fields(evt))
|
||||
asyncio.create_task(compass(evt))
|
||||
while True:
|
||||
# Normal procedure before refresh, but 10s sleep should mean it always returns immediately
|
||||
await ssd.wait()
|
||||
|
@ -103,7 +106,7 @@ async def main():
|
|||
# framebuffer in background
|
||||
evt.set()
|
||||
evt.clear()
|
||||
await asyncio.sleep(20) # Allow for slow refresh
|
||||
await asyncio.sleep(10) # Allow for slow refresh
|
||||
|
||||
|
||||
tstr = '''Test of asynchronous code updating the EPD. This should
|
|
@ -0,0 +1,79 @@
|
|||
# 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
|
||||
from color_setup import ssd
|
||||
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)
|
||||
|
||||
# 296*128
|
||||
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)
|
||||
|
||||
def main():
|
||||
refresh(ssd, True)
|
||||
graph()
|
||||
compass()
|
||||
meter()
|
||||
labels()
|
||||
ssd.wait_until_ready()
|
||||
refresh(ssd)
|
||||
print('Waiting for display update')
|
||||
ssd.wait_until_ready()
|
||||
|
||||
main()
|
||||
|
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 24 KiB |
Ładowanie…
Reference in New Issue