From f24a1f53ea65c61894c13746b17fbc159edcf2d8 Mon Sep 17 00:00:00 2001 From: Peter Hinch Date: Tue, 6 Oct 2020 18:47:00 +0100 Subject: [PATCH] Update README files for sharp displays. --- README.md | 15 +++++++++------ drivers/sharp/README.md | 25 ++++++++++++++++++++++++- drivers/sharp/clock_batt.py | 16 ++++++---------- drivers/sharp/clocktest.py | 13 ++++++++----- 4 files changed, 47 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 3d8ec98..76890e6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ A lightweight and minimal MicroPython GUI library for display drivers based on -the `framebuf` class. With the exception of the Nokia 5110, such drivers are -currently for color and monochrome OLED displays. This is coincidental. +the `framebuf` class. Various display technologies are supported, primarily +small color OLED's. These images don't do justice to the OLED displays which are visually impressive with bright colors and extreme contrast. For some reason they are @@ -54,6 +54,9 @@ display driver is subclassed from the `framebuf` class. Examples are: * A driver for [Adafruit 1.5 inch OLED](https://www.adafruit.com/product/1431) and [Adafruit 1.27 inch OLED](https://www.adafruit.com/product/1673) may be found [here](./drivers/ssd1351/README.md). + * A driver for Sharp ultra low power consumption monochrome displays such as + [2.7 inch 400x240 pixels](https://www.adafruit.com/product/4694) + is [here](./drivers/sharp/README.md). Widgets are intended for the display of data from physical devices such as sensors. The GUI is display-only: there is no provision for user input. This @@ -462,6 +465,10 @@ For a driver to support `nanogui` it must be subclassed from the display size in pixels. This, and a `show` method, are all that is required for monochrome drivers. +Refresh must be handled by a `show` method taking no arguments; when called, +the contents of the buffer underlying the `FrameBuffer` must be copied to the +hardware. + For color drivers, to conserve RAM it is suggested that 8-bit color is used for the `framebuf`. If the hardware does not support this, conversion to the supported color space needs to be done "on the fly" as per the SSD1351 driver. @@ -476,10 +483,6 @@ form acceptable to the driver. For 8-bit rrrgggbb this can be: ``` This should be amended if the hardware uses a different 8-bit format. -Refresh must be handled by a `show` method taking no arguments; when called, -the contents of the buffer underlying the `FrameBuffer` must be copied to the -hardware. - The `Writer` (monochrome) or `CWriter` (color) classes and the `nanogui` module should then work automatically. diff --git a/drivers/sharp/README.md b/drivers/sharp/README.md index d170f29..bc499b4 100644 --- a/drivers/sharp/README.md +++ b/drivers/sharp/README.md @@ -71,7 +71,8 @@ The datasheet specifies a minimum refresh rate of 1Hz. 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. + 3. `clock_batt.py` As above but designed for low power operation. Pyboard + specific. `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. @@ -124,6 +125,28 @@ 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) diff --git a/drivers/sharp/clock_batt.py b/drivers/sharp/clock_batt.py index 32ae7a9..42537b3 100644 --- a/drivers/sharp/clock_batt.py +++ b/drivers/sharp/clock_batt.py @@ -61,26 +61,22 @@ def aclock(): lbldat = Label(wri, 100, 230, 100) hrs = Pointer(dial) mins = Pointer(dial) - secs = Pointer(dial) hstart = 0 + 0.7j # Pointer lengths and position at top mstart = 0 + 0.92j - sstart = 0 + 0.92j while True: t = rtc.datetime() # (year, month, day, weekday, hours, minutes, seconds, subseconds) - hang = -t[4]*pi/6 - t[5]*pi/360 # Angles of hour and minute hands + hang = -t[4]*pi/6 - t[5]*pi/360 # Angles of hands in radians mang = -t[5] * pi/30 - sang = -t[6] * pi/30 - if abs(hang - mang) < pi/360: # Avoid overlap of hands - hang += pi/18 + if abs(hang - mang) < pi/360: # Avoid visually confusing overlap of hands + hang += pi/30 # by making hr hand lag slightly hrs.value(hstart * uv(hang)) mins.value(mstart * uv(mang)) - secs.value(sstart * uv(sang)) - lbltim.value('{:02d}.{:02d}.{:02d}'.format(t[4], t[5], t[6])) + lbltim.value('{:02d}.{:02d}'.format(t[4], t[5])) lbldat.value('{} {} {} {}'.format(days[t[3] - 1], t[2], months[t[1] - 1], t[0])) refresh(ssd) - # Power saving: only refresh every 10s - for _ in range(10): + # Power saving: only refresh every 30s + for _ in range(30): upower.lpdelay(1000) ssd.update() # Toggle VCOM diff --git a/drivers/sharp/clocktest.py b/drivers/sharp/clocktest.py index 7ca8382..c1f9d6c 100644 --- a/drivers/sharp/clocktest.py +++ b/drivers/sharp/clocktest.py @@ -64,11 +64,14 @@ def aclock(): sstart = 0 + 0.92j while True: t = utime.localtime() - # Add 0.5min offset to hour hand. This avoids a confusing display by - # ensuring hour and minute hand never exactly overlap - hrs.value(hstart * uv(-t[3]*pi/6 - t[4]*pi/360) - pi/720) - mins.value(mstart * uv(-t[4] * pi/30)) - secs.value(sstart * uv(-t[5] * pi/30)) + hang = -t[4]*pi/6 - t[5]*pi/360 # Angles of hour and minute hands + mang = -t[5] * pi/30 + sang = -t[6] * pi/30 + if abs(hang - mang) < pi/360: # Avoid overlap of hr and min hands + hang += pi/30 # which is visually confusing. Add slight lag to hts + hrs.value(hstart * uv(hang)) + mins.value(mstart * uv(mang)) + secs.value(sstart * uv(sang)) lbltim.value('{:02d}.{:02d}.{:02d}'.format(t[3], t[4], t[5])) lbldat.value('{} {} {} {}'.format(days[t[6]], t[2], months[t[1] - 1], t[0])) refresh(ssd)