kopia lustrzana https://github.com/peterhinch/micropython-nano-gui
158 wiersze
7.2 KiB
Markdown
158 wiersze
7.2 KiB
Markdown
# A MICROPYTHON DRIVER FOR SHARP DISPLAYS
|
|
|
|
These monochrome SPI displays exist in three variants from Adafruit.
|
|
1. [2.7 inch 400x240 pixels](https://www.adafruit.com/product/4694)
|
|
2. [1.3 inch 144x168](https://www.adafruit.com/product/3502)
|
|
3. [1.3 inch 96x96](https://www.adafruit.com/product/1393) - Discontinued.
|
|
|
|
I have tested on the first of these. However the
|
|
[Adfruit driver](https://github.com/adafruit/Adafruit_CircuitPython_SharpMemoryDisplay)
|
|
supports all of these and I would expect this one also to do so.
|
|
|
|
# 1. Display characteristics
|
|
|
|
These displays have extremely low current consumption: I measured ~90μA on the
|
|
2.7" board when in use. Refresh is fast, visually excellent and can run at up
|
|
to 20Hz. This contrasts with ePaper (eInk) displays where refresh is slow
|
|
(seconds) and visually intrusive; an alternative fast mode overcomes this, but
|
|
at the expense of ghosting.
|
|
|
|
On the other hand the power consumption of ePaper can be zero (you can switch
|
|
them off and the display is retained). If you power down a Sharp display the
|
|
image is retained, but only for a few seconds. In a Pyboard context 90μA is low
|
|
in comparison to stop mode and battery powered applications should be easily
|
|
realised.
|
|
|
|
The 2.7" display has excellent resolution and can display fine lines and small
|
|
fonts. In other respects the display quality is not as good as ePaper. For good
|
|
contrast best results are achieved if the viewing angle and the direction of
|
|
the light source are positioned to achieve reflection.
|
|
|
|
## 1.1 The VCOM bit
|
|
|
|
The significance of this is somewhat glossed-over in the Adafruit docs, and a
|
|
study of the datasheet is confusing in the absence of prior knowledge of LCD
|
|
technology.
|
|
|
|
The signals applied to an LCD display should have no DC component. This is
|
|
because DC can cause gradual electrolysis and deterioration of of the liquid
|
|
crystal material. Display driver hardware typically has an oscillator driving
|
|
exclusive-or gates such that antiphase signals are applied for ON pixels, and
|
|
in-phase for OFF pixels. The oscillator typically drives a D-type flip-flop to
|
|
ensure an accurate 1:1 mark space ratio and hence zero DC component.
|
|
|
|
These displays offer two ways of achieving this, in the device driver or using
|
|
an external 1:1 mark space logic signal. The bit controlling this is known as
|
|
`VCOM` and the external pins supporting it are `EXTMODE` and `EXTCOMIN`.
|
|
`EXTMODE` determines whether a hardware input is used (`Vcc`) or software
|
|
control is required (`Gnd`). It is pulled low.
|
|
|
|
The driver supports software control, in that `VCOM` is complemented each time
|
|
the display is refreshed. The Adafruit driver also does this.
|
|
|
|
Sofware control implies that, in long running applications, the display should
|
|
regularly be refreshed. The datasheet incicates that the maximum rate is 20Hz,
|
|
but a 1Hz rate is sufficient.
|
|
|
|
If hardware control is to be used, `EXTMODE` should be linked to `Vcc` and a
|
|
1:1 logic signal applied to `EXTCOMIN`. A frequency range of 0.5-10Hz is
|
|
specified, and the datasheet also specifies "`EXTCOMIN` frequency should be
|
|
made lower than frame frequency".
|
|
|
|
In my opinion the easiest way to deal with this is usually to use software
|
|
control, ensuring that the driver's `show` method is called at regular
|
|
intervals of at least 1Hz.
|
|
|
|
## 1.2 Refresh rate
|
|
|
|
The datasheet specifies a minimum refresh rate of 1Hz.
|
|
|
|
# 2. Test scripts
|
|
|
|
1. `sharptest.py` Basic functionality test.
|
|
2. `clocktest.py` Digital and analog clock display.
|
|
3. `clock_batt.py` As above but designed for low power operation. Pyboard
|
|
specific.
|
|
|
|
Tests assume that `nanogui` is installed as per the instructions. `sharptest`
|
|
should not be run for long periods as it does not regularly refresh the
|
|
display. It tests `writer.py` and some `framebuffer` graphics primitives.
|
|
`clocktest` demostrates use with `nanogui`.
|
|
|
|
The `clock_batt.py` demo needs `upower.py` from
|
|
[micropython-micropower](https://github.com/peterhinch/micropython-micropower).
|
|
|
|
Testing was done on a Pyboard D SF6W: frozen bytecode was not required. I
|
|
suspect a Pyboard 1.x would require it to prevent memory errors. Fonts in
|
|
particular benefit from freezing as their RAM usage is radically reduced.
|
|
|
|
# 3. Device driver constructor
|
|
|
|
Positional args:
|
|
1. `spi` An SPI bus instance. The constructor initialises this to the baudrate
|
|
and bit order required by the hardware.
|
|
2. `pincs` A `Pin` instance. The caller should initialise this as an output
|
|
with value 0 (unusually the hardware CS line is active high).
|
|
3. `height=240` Dimensions in pixels. Defaults are for 2.7" display.
|
|
4. `width=400`
|
|
5. `vcom=False` Accept the default unless using `pyb.standby`. See 3.2.
|
|
|
|
# 3.1 Device driver methods
|
|
|
|
1. `show` No args. Transfers the framebuffer contents to the device, updating
|
|
the display.
|
|
2. `update` Toggles the `VCOM` bit without transferring the framebuffer. This
|
|
is a power saving method for cases where the application calls `show` at a
|
|
rate of < 1Hz. In such cases `update` should be called at a 1Hz rate.
|
|
|
|
# 3.2 The vcom arg
|
|
|
|
It purpose is to support micropower applications which use `pyb.standby`.
|
|
Wakeup from standby is similar to a reboot in that program execution starts
|
|
from scratch. In the case where the board wakes up, writes to the display, and
|
|
returns to standby, the `VCOM` bit would never change. In this case the
|
|
application should store a `bool` in peristent storage, toggling it on each
|
|
restart, and pass that to the constructor.
|
|
|
|
Persistent storage exists in the RTC registers and backup RAM. See
|
|
[micopython-micropower](https://github.com/peterhinch/micropython-micropower)
|
|
for details of how to acces these resources.
|
|
|
|
# 4. Application design
|
|
|
|
In all cases the frame buffer is located on the target hardware. In the case of
|
|
the 2.7 inch display this is 400*240//8 = 12000 bytes in size. This should be
|
|
instantiated as soon as possible in the application to ensure that sufficient
|
|
contiguous RAM is available.
|
|
|
|
## 4.1 Micropower applications
|
|
|
|
These comments largely assume a Pyboard host. The application should import
|
|
`upower` from
|
|
[micropython-micropower](https://github.com/peterhinch/micropython-micropower).
|
|
This turns the USB interface off if not in use to conserve power. It also
|
|
provides an `lpdelay` function to implement a delay using `pyb.stop()` to
|
|
conserve power.
|
|
|
|
In tests the `clock_batt` demo consumed 700μA between updates. A full refresh
|
|
every 30s consumed about 48mA for 128ms. These figures correspond to a mean
|
|
current consumption of 904μA implying about 46 days operation per AH of
|
|
battery capacity. LiPo cells of 2AH capacity are widely available offering a
|
|
theoretical runtime of 92 days between charges.
|
|
|
|
Lower currents might be achieved using standby but I have major doubts. This is
|
|
because it is necessary to toggle the VCOM bit at a minimum of 1Hz. Waking from
|
|
standby uses significan amounts of power as the modules are compiled. Even if
|
|
frozen bytecode is used, there is still significant power usage importing
|
|
modules and instantiating classes; this usage is not incurred in the loop in
|
|
the demo.
|
|
|
|
# 5. Resources
|
|
|
|
[Schematic for 2.7" unit](https://learn.adafruit.com/assets/94077)
|
|
|
|
[Datasheet 2.7"](https://cdn-learn.adafruit.com/assets/assets/000/094/215/original/LS027B7DH01_Rev_Jun_2010.pdf?1597872422)
|
|
|
|
[Datasheet 1.3"](http://www.adafruit.com/datasheets/LS013B4DN04-3V_FPC-204284.pdf)
|
|
|