kopia lustrzana https://github.com/peterhinch/micropython-micro-gui
Document use with encoder.
rodzic
3a64bb5691
commit
4a1d6a86f7
147
README.md
147
README.md
|
@ -82,6 +82,8 @@ of some display drivers.
|
||||||
2.3 [Colors](./README.md#23-colors)
|
2.3 [Colors](./README.md#23-colors)
|
||||||
2.3.1 [Monochrome displays](./README.md#231-monochrome-displays)
|
2.3.1 [Monochrome displays](./README.md#231-monochrome-displays)
|
||||||
3. [The ssd and display objects](./README.md#3-the-ssd-and-display-objects)
|
3. [The ssd and display objects](./README.md#3-the-ssd-and-display-objects)
|
||||||
|
3.1 [SSD class](./README.md#31-ssd-class) Instantiation in hardware_setup.
|
||||||
|
3.2 [Display class](./README.md#32-display-class) Instantiation in hardware_setup.
|
||||||
4. [Screen class](./README.md#4-screen-class) Full screen window.
|
4. [Screen class](./README.md#4-screen-class) Full screen window.
|
||||||
4.1 [Class methods](./README.md#41-class-methods)
|
4.1 [Class methods](./README.md#41-class-methods)
|
||||||
4.2 [Constructor](./README.md#42-constructor)
|
4.2 [Constructor](./README.md#42-constructor)
|
||||||
|
@ -193,14 +195,17 @@ The GUI requires from 2 to 5 pushbuttons for control. These are:
|
||||||
4. `Increase` Move within the widget (i.e. adjust its value).
|
4. `Increase` Move within the widget (i.e. adjust its value).
|
||||||
5. `Decrease` Move within the widget.
|
5. `Decrease` Move within the widget.
|
||||||
|
|
||||||
|
An alternative is to replace buttons 4 and 5 with a quadrature encoder knob
|
||||||
|
such as [this one](https://www.adafruit.com/product/377).
|
||||||
|
|
||||||
Many widgets such as `Pushbutton` or `Checkbox` objects require only the
|
Many widgets such as `Pushbutton` or `Checkbox` objects require only the
|
||||||
`Select` button to operate: it is possible to design an interface with a subset
|
`Select` button to operate: it is possible to design an interface with a subset
|
||||||
of `micro-gui` widgets which requires only the first two buttons.
|
of `micro-gui` widgets which requires only the first two buttons.
|
||||||
|
|
||||||
Widgets such as `Listbox` objects, dropdown lists (`Dropdown`), and those for
|
Widgets such as `Listbox` objects, dropdown lists (`Dropdown`), and those for
|
||||||
floating point data entry require the `Increase` and `Decrease` buttons to
|
floating point data entry require the `Increase` and `Decrease` buttons (or an
|
||||||
select a data item or to adjust the linear value. This is discussed in
|
encoder) to select a data item or to adjust the linear value. This is discussed
|
||||||
[Floating Point Widgets](./README.md#112-floating-point-widgets).
|
in [Floating Point Widgets](./README.md#112-floating-point-widgets).
|
||||||
|
|
||||||
The currently selected `Widget` is identified by a white border: the `focus`
|
The currently selected `Widget` is identified by a white border: the `focus`
|
||||||
moves between widgets via `Next` and `Prev`. Only `active` `Widget` instances
|
moves between widgets via `Next` and `Prev`. Only `active` `Widget` instances
|
||||||
|
@ -248,9 +253,17 @@ increase = Pin(20, Pin.IN, Pin.PULL_UP) # Increase control's value
|
||||||
decrease = Pin(17, Pin.IN, Pin.PULL_UP) # Decrease control's value
|
decrease = Pin(17, Pin.IN, Pin.PULL_UP) # Decrease control's value
|
||||||
display = Display(ssd, nxt, sel, prev, increase, decrease)
|
display = Display(ssd, nxt, sel, prev, increase, decrease)
|
||||||
```
|
```
|
||||||
|
Where an encoder replaces the `increase` and `decrease` buttons the final line
|
||||||
|
only needs to be changed to read:
|
||||||
|
```python
|
||||||
|
display = Display(ssd, nxt, sel, prev, increase, decrease, 5)
|
||||||
|
```
|
||||||
|
The final arg specifies the sensitivity of the attached encoder, the higher the
|
||||||
|
value the more the knob has to be turned for a desired effect. A value of 1
|
||||||
|
provides the highest sensitivity, being the native rate of the encoder.
|
||||||
|
|
||||||
Display drivers are documented
|
Instantiation of `SSD` and `Display` classes is detailed in
|
||||||
[here](https://github.com/peterhinch/micropython-nano-gui/blob/master/DRIVERS.md).
|
[section 3](./README.md#3-the-ssd-and-display-objects).
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
|
@ -322,13 +335,13 @@ The consequence of inadequate speed is that brief button presses can be missed.
|
||||||
This is because display update blocks for tens of milliseconds, during which
|
This is because display update blocks for tens of milliseconds, during which
|
||||||
time the pushbuttons are not polled. Blocking is much reduced by item 3 above.
|
time the pushbuttons are not polled. Blocking is much reduced by item 3 above.
|
||||||
|
|
||||||
On the TTGO T-Display I found it necessary to use physical pullup resistors on
|
On the TTGO T-Display it is necessary to use physical pullup resistors on the
|
||||||
the pushbutton GPIO lines. According to the
|
pushbutton GPIO lines. According to the
|
||||||
[ESP32 gurus](https://randomnerdtutorials.com/esp32-pinout-reference-gpios/)
|
[ESP32 gurus](https://randomnerdtutorials.com/esp32-pinout-reference-gpios/)
|
||||||
pins 36-39 do not have pullup support.
|
pins 36-39 do not have pullup support.
|
||||||
|
|
||||||
On a Pyboard 1.1 with 320x240 ili9341 display it was necessary to use frozen
|
On a Pyboard 1.1 with 320x240 ili9341 display it was necessary to use frozen
|
||||||
bytecode: in this configuration running the "various" demo there was 29K of
|
bytecode: in this configuration running the `various.py` demo there was 29K of
|
||||||
free RAM. Note that, at 37.5KiB, this display is the worst-case in terms of
|
free RAM. Note that, at 37.5KiB, this display is the worst-case in terms of
|
||||||
RAM usage. A smaller display or a Pyboard D would offer more headroom.
|
RAM usage. A smaller display or a Pyboard D would offer more headroom.
|
||||||
|
|
||||||
|
@ -337,7 +350,7 @@ RAM usage. A smaller display or a Pyboard D would offer more headroom.
|
||||||
## 1.9 Firmware and dependencies
|
## 1.9 Firmware and dependencies
|
||||||
|
|
||||||
Firmware should be V1.15 or later. The source tree includes all dependencies.
|
Firmware should be V1.15 or later. The source tree includes all dependencies.
|
||||||
These are listed to enable users to check for newer versions:
|
These are listed to enable users to check for newer versions or to read docs:
|
||||||
|
|
||||||
* [writer.py](https://github.com/peterhinch/micropython-font-to-py/blob/master/writer/writer.py)
|
* [writer.py](https://github.com/peterhinch/micropython-font-to-py/blob/master/writer/writer.py)
|
||||||
Provides text rendering of Python font files.
|
Provides text rendering of Python font files.
|
||||||
|
@ -445,23 +458,24 @@ Some of these require larger screens. Required sizes are specified as
|
||||||
|
|
||||||
## 1.12 Floating Point Widgets
|
## 1.12 Floating Point Widgets
|
||||||
|
|
||||||
The challenge is to devise a way, with just two pushbuttons, of adjusting a
|
The challenge is to devise a way, with two pushbuttons or an encoder, of
|
||||||
data value which may have an extremely large dynamic range. This is the ratio
|
adjusting a data value which may have an extremely large dynamic range. This is
|
||||||
of the data value's total range to the smallest adjustment that can be made.
|
the ratio of the data value's total range to the smallest adjustment that can
|
||||||
The mechanism currently implemented enables a precision of 0.05%.
|
be made. The mechanism currently implemented enables a precision of 0.05%.
|
||||||
|
|
||||||
Floating point widgets respond to a brief press of the `increase` or `decrease`
|
Floating point widgets respond to a brief press of the `increase` or `decrease`
|
||||||
buttons by adjusting the value by a small amount. A continued press causes the
|
buttons by adjusting the value by a small amount. A continued press causes the
|
||||||
value to be repeatedly adjusted, with the amount of the adjustment increasing
|
value to be repeatedly adjusted, with the amount of the adjustment increasing
|
||||||
with time. This enables the entire range of the control to be accessed quickly,
|
with time. This enables the entire range of the control to be accessed quickly,
|
||||||
while allowing small changes of 0.5%. This works well. In many cases the level
|
while allowing small changes of 0.5%. This works well. In many cases the level
|
||||||
of precision will suffice.
|
of precision will suffice. An encoder provides similar performance.
|
||||||
|
|
||||||
Fine adjustments may be achieved by pressing the `select` button for at least
|
Fine adjustments may be achieved by pressing the `select` button for at least
|
||||||
one second. The GUI will respond by changing the border color from white
|
one second. The GUI will respond by changing the border color from white
|
||||||
(i.e. has focus) to yellow. In this mode a brief press of `increase` or
|
(i.e. has focus) to yellow. In this mode a brief press of `increase` or
|
||||||
`decrease` will have a reduced effect (0.05%). The fine mode may be cancelled
|
`decrease` or small movement of an encoder will have a reduced effect (0.05%).
|
||||||
by pressing `select` or by moving the focus to another control.
|
Fine mode may be cancelled by pressing `select` or by moving the focus to
|
||||||
|
another control.
|
||||||
|
|
||||||
In the case of slider and knob controls the precision of fine mode exceeds that
|
In the case of slider and knob controls the precision of fine mode exceeds that
|
||||||
of the visual appearance of the widget: fine changes can be too small to see.
|
of the visual appearance of the widget: fine changes can be too small to see.
|
||||||
|
@ -544,8 +558,8 @@ bound methods. Screens typically have a `CloseButton` widget. This is a special
|
||||||
physical display and closes the current screen, showing the one below. If used
|
physical display and closes the current screen, showing the one below. If used
|
||||||
on the bottom level `Screen` (as above) it closes the application.
|
on the bottom level `Screen` (as above) it closes the application.
|
||||||
|
|
||||||
The `wri` instance of `CWriter` associates a widget with a font. Constructors
|
The `CWriter` instance `wri` associates a widget with a font. Constructors for
|
||||||
for all widgets have three mandatory positional args. These are a `CWriter`
|
all widgets have three mandatory positional args. These are a `CWriter`
|
||||||
instance followed by `row` and `col`. These args are followed by a number of
|
instance followed by `row` and `col`. These args are followed by a number of
|
||||||
optional keyword args. These have (hopefully) sensible defaults enabling you to
|
optional keyword args. These have (hopefully) sensible defaults enabling you to
|
||||||
get started easily.
|
get started easily.
|
||||||
|
@ -562,7 +576,7 @@ response to user input.
|
||||||
A callback function receives positional arguments. The first is a reference to
|
A callback function receives positional arguments. The first is a reference to
|
||||||
the object raising the callback. Subsequent arguments are user defined, and are
|
the object raising the callback. Subsequent arguments are user defined, and are
|
||||||
specified as a tuple or list of items. Callbacks and their argument lists are
|
specified as a tuple or list of items. Callbacks and their argument lists are
|
||||||
optional: a default null function and empty list are provided. Callbacks may
|
optional: a default null function and empty tuple are provided. Callbacks may
|
||||||
optionally be written as bound methods. This facilitates communication between
|
optionally be written as bound methods. This facilitates communication between
|
||||||
widgets.
|
widgets.
|
||||||
|
|
||||||
|
@ -596,13 +610,16 @@ PALE_YELLOW = create_color(12, 150, 150, 0) # index, r, g, b
|
||||||
If a 4-bit driver is in use, the color `rgb(150, 150, 0)` will be assigned to
|
If a 4-bit driver is in use, the color `rgb(150, 150, 0)` will be assigned to
|
||||||
"spare" color number 12. Any color number in range `0 <= n <= 15` may be
|
"spare" color number 12. Any color number in range `0 <= n <= 15` may be
|
||||||
used, implying that predefined colors may be reassigned. It is recommended
|
used, implying that predefined colors may be reassigned. It is recommended
|
||||||
that `BLACK` (0) and `WHITE` (15) are not changed; `GREY` (6) and `YELLOW` (5)
|
that `BLACK` (0) and `WHITE` (15) are not changed. `GREY` (6) and `YELLOW` (5)
|
||||||
are also GUI defaults. If an 8-bit or larger driver is in use, the first
|
are GUI defaults for "greyed out" widgets and for "precision mode" borders, so
|
||||||
`index` arg is ignored and there is no restriction on the number of colors that
|
changing these will have obvious effects.
|
||||||
may be created.
|
|
||||||
|
|
||||||
Regardless of the display driver the `PALE_YELLOW` variable may be used to
|
If an 8-bit or larger driver is in use, the first `index` arg is ignored and
|
||||||
refer to the color. An example of custom color definition may be found in
|
there is no practical restriction on the number of colors that may be created.
|
||||||
|
|
||||||
|
In the above example, regardless of the display driver, the `PALE_YELLOW`
|
||||||
|
variable may be used to refer to the color. An example of custom color
|
||||||
|
definition may be found in
|
||||||
[this nano-gui demo](https://github.com/peterhinch/micropython-nano-gui/blob/4ef0e20da27ef7c0b5c34136dcb372200f0e5e66/gui/demos/color15.py#L92).
|
[this nano-gui demo](https://github.com/peterhinch/micropython-nano-gui/blob/4ef0e20da27ef7c0b5c34136dcb372200f0e5e66/gui/demos/color15.py#L92).
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
@ -619,8 +636,8 @@ display such as an OLED. On a Sharp display it indicates reflection.
|
||||||
|
|
||||||
There is an issue regarding ePaper displays discussed
|
There is an issue regarding ePaper displays discussed
|
||||||
[here](https://github.com/peterhinch/micropython-nano-gui/blob/master/README.md#312-monochrome-displays).
|
[here](https://github.com/peterhinch/micropython-nano-gui/blob/master/README.md#312-monochrome-displays).
|
||||||
I don't consider ePaper displays as suitable for I/O because of their slow
|
I don't consider ePaper displays suitable for I/O because of their slow refresh
|
||||||
refresh time.
|
time.
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
|
@ -630,15 +647,46 @@ The following code, issued as the first executable lines of an application,
|
||||||
initialises the display.
|
initialises the display.
|
||||||
```python
|
```python
|
||||||
import hardware_setup # Create a display instance
|
import hardware_setup # Create a display instance
|
||||||
from gui.core.ugui import Screen, ssd, display
|
from gui.core.ugui import Screen, ssd, display # display is seldom needed
|
||||||
```
|
```
|
||||||
It creates singleton instances of `SSD` and `Display` classes. Normal GUI
|
The `hardware_setup` file creates singleton instances of `SSD` and `Display`
|
||||||
applications only need to import `ssd`. This refererence to the display driver
|
classes. These instances are made available via `ugui`. Normal GUI applications
|
||||||
is used to initialise `Writer` objects. Bound variables `ssd.height` and
|
only need to import `ssd`. This refererence to the display driver is used to
|
||||||
`ssd.width` may be read to determine the dimensions of the display hardware.
|
initialise `Writer` objects. Bound variables `ssd.height` and `ssd.width` may
|
||||||
|
be read to determine the dimensions of the display hardware.
|
||||||
|
|
||||||
The `display` object is only needed in applications which use graphics
|
The `display` object is only needed in applications which use graphics
|
||||||
primitives to write directly to the screen. See Appendix 1.
|
primitives to write directly to the screen. See
|
||||||
|
[Appendix 1 Application design](./README.md#appendix-1-application-design).
|
||||||
|
|
||||||
|
## 3.1 SSD class
|
||||||
|
|
||||||
|
This is instantiated in `hardware_setup.py`. The specific class must match the
|
||||||
|
display hardware in use. Display drivers are documented
|
||||||
|
[here](https://github.com/peterhinch/micropython-nano-gui/blob/master/DRIVERS.md).
|
||||||
|
|
||||||
|
## 3.2 Display class
|
||||||
|
|
||||||
|
This is instantiated in `hardware_setup.py`. It registers the `SSD` instance
|
||||||
|
along with the `Pin` instances used for input; also whether an encoder is used.
|
||||||
|
Pins are arbitrary, but should be defined as inputs with pullups. Pushbuttons
|
||||||
|
are connected between `Gnd` and the relevant pin.
|
||||||
|
|
||||||
|
The constructor takes the following args:
|
||||||
|
1. `objssd` The `SSD` instance. A reference to the display driver.
|
||||||
|
2. `nxt` A `Pin` instance for the `next` button.
|
||||||
|
3. `sel` A `Pin` instance for the `select` button.
|
||||||
|
4. `prev=None` A `Pin` instance for the `previous` button (if used).
|
||||||
|
5. `up=None` A `Pin` instance for the `increase` button (if used).
|
||||||
|
6. `down=None` A `Pin` instance for the `decrease` button (if used).
|
||||||
|
7. `encoder=False` If an encoder is used, an integer must be passed. This
|
||||||
|
represents the division ratio. A value of 1 provides the native rate of the
|
||||||
|
encoder. I found the Adafruit encoder overly sensitive. A value of 5 slows it
|
||||||
|
down improving usability.
|
||||||
|
|
||||||
|
If an encoder is used, it should be connected to the pins assigned to
|
||||||
|
`increase` and `decrease`. If the direction of movement is wrong, these pins
|
||||||
|
should be transposed.
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
|
@ -667,14 +715,15 @@ In normal use the following methods only are required:
|
||||||
defined, screen.
|
defined, screen.
|
||||||
* `back(cls)` Restore previous screen.
|
* `back(cls)` Restore previous screen.
|
||||||
|
|
||||||
These are uncommon:__
|
These are uncommon:
|
||||||
* `shutdown(cls)` Clear the screen and shut down the GUI. Normally done by a
|
* `shutdown(cls)` Clear the screen and shut down the GUI. Normally done by a
|
||||||
`CloseButton` instance.
|
`CloseButton` instance.
|
||||||
* `show(cls, force)`. This causes the screen to be redrawn. If `force` is
|
* `show(cls, force)`. This causes the screen to be redrawn. If `force` is
|
||||||
`False` unchanged widgets are not refreshed. If `True`, all visible widgets
|
`False` unchanged widgets are not refreshed. If `True`, all visible widgets
|
||||||
are re-drawn. Explicit calls to this should never be needed.
|
are re-drawn. Explicit calls to this should never be needed.
|
||||||
|
|
||||||
See `demos/plot.py` for an example of multi-screen design.
|
See `demos/plot.py` for an example of multi-screen design, or
|
||||||
|
`screen_change.py` for a minimal example demostrating the coding technique.
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
|
||||||
|
@ -698,13 +747,13 @@ See `demos/plot.py` for examples of usage of `after_open`.
|
||||||
instance or a coroutine.
|
instance or a coroutine.
|
||||||
|
|
||||||
This is a convenience method which provides for the automatic cancellation of
|
This is a convenience method which provides for the automatic cancellation of
|
||||||
tasks. If a screen runs independent coros it can opt to register these. If the
|
tasks. If a screen runs independent tasks it can opt to register these. If the
|
||||||
screen is overlaid by another, tasks registered with `on_change` `True` are
|
screen is overlaid by another, tasks registered with `on_change` `True` are
|
||||||
cancelled. If the screen is closed, all tasks registered to it are cancelled
|
cancelled. If the screen is closed, all tasks registered to it are cancelled
|
||||||
regardless of the state of `on_change`. On shudown, any tasks registered to the
|
regardless of the state of `on_change`. On shudown, any tasks registered to the
|
||||||
base screen are cancelled.
|
base screen are cancelled.
|
||||||
|
|
||||||
For finer control applications can ignore this method and handle cancellation
|
For finer control, applications can ignore this method and handle cancellation
|
||||||
explicitly in code.
|
explicitly in code.
|
||||||
|
|
||||||
###### [Contents](./README.md#0-contents)
|
###### [Contents](./README.md#0-contents)
|
||||||
|
@ -2209,13 +2258,23 @@ variable.
|
||||||
|
|
||||||
## Encoder interface
|
## Encoder interface
|
||||||
|
|
||||||
This alternative interface comprises just two buttons `Next` and `Prev`.
|
This alternative interface comprises two buttons `Next` and `Prev` with an
|
||||||
Selection and Increase/Decrease is handled by an encoder such as
|
an encoder such as [this one](https://www.adafruit.com/product/377). Selection
|
||||||
[this one](https://www.adafruit.com/product/377). Selection occurs when the
|
occurs when the knob is pressed, and movement when it is rotated. This can be
|
||||||
knob is pressed, and movement when it is rotated. This is more intuitive,
|
more intuitive, particularly with horizontally oriented controls.
|
||||||
particularly with horizontally oriented controls.
|
|
||||||
|
|
||||||
TODO wiring details.
|
This is the pinout of the Adafruit encoder as viewed from the top, with
|
||||||
|
connections to pins passed to the `Display` constructor as `sel` (select), `up`
|
||||||
|
(increase) and `down` (decrease).
|
||||||
|
|
||||||
|
| Left | Right |
|
||||||
|
|:--------:|:------:|
|
||||||
|
| Increase | Gnd |
|
||||||
|
| Gnd | No pin |
|
||||||
|
| Decrease | Select |
|
||||||
|
|
||||||
|
If an encoder operates in the wrong direction, `Increase` and `Decrease` pins
|
||||||
|
should be transposed (physically or logically in `hardware_setup.py`).
|
||||||
|
|
||||||
## Screen layout
|
## Screen layout
|
||||||
|
|
||||||
|
@ -2243,7 +2302,7 @@ approach.
|
||||||
|
|
||||||
## Use of graphics primitives
|
## Use of graphics primitives
|
||||||
|
|
||||||
See [demo primitives.py](./gui/demos/primitives.py).
|
See demo [primitives.py](./gui/demos/primitives.py).
|
||||||
|
|
||||||
These notes are for those wishing to draw directly to the `Screen` instance.
|
These notes are for those wishing to draw directly to the `Screen` instance.
|
||||||
This is done by providing the user `Screen` class with an `after_open()` method
|
This is done by providing the user `Screen` class with an `after_open()` method
|
||||||
|
|
Ładowanie…
Reference in New Issue