Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TM1621 Display] Plugin 148: Sonoff POWR3xxD and THR3xxD display (#4448) #4452

Merged
merged 12 commits into from
Jan 10, 2023
228 changes: 228 additions & 0 deletions docs/source/Plugin/P148.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
.. include:: ../Plugin/_plugin_substitutions_p14x.repl
.. _P148_page:

|P148_typename|
==================================================

|P148_shortinfo|

Plugin details
--------------

Type: |P148_type|

Name: |P148_name|

Status: |P148_status|

GitHub: |P148_github|_

Maintainer: |P148_maintainer|

Used libraries: |P148_usedlibraries|

Description
-----------

The latest revision of the Sonoff POW and TH modules are now available in an "Elite" version.

These are equipped with a LCD with 2 rows of 4x 7-segment display.


Hardware
--------

A short summary of the improvements compared to the previous models:

* Looks a lot better.
* ESP32 with 4MB flash (Older ESP8266 version of the POW and POW2 also had 4M flash, but the TH series did not)
* Greatly improved WiFi antenna, connected via IPEX connector.
* Improved power terminals.
* DIN rail mount clamp included.
* LCD
* 2 individually addressable LEDs (3 on the THR3xxD).

Specific to the THR3xxD Elite:

* 2x relais
* 1 relais with "dry" contacts, thus not connected to anything else.
* RJ9 connector for external sensors, like Dallas DS18b20.


See for more information about the new design and hardware features the Sonoff site:

* `Sonoff TH Elite series <https://sonoff.tech/product/diy-smart-switches/th-elite/>`_
* `Sonoff POW Elite series <https://sonoff.tech/product/diy-smart-switches/pow-elite/>`_

List of GPIO pinout:

* `templates.blakadder.com/sonoff_THR316D <https://templates.blakadder.com/sonoff_THR316D.html>`_
* `templates.blakadder.com/sonoff_POWR316D <https://templates.blakadder.com/sonoff_POWR316D.html>`_



Configuration
-------------

.. image:: P148_DeviceConfiguration.png
:alt: Device configuration

* **Name**: Required by ESPEasy, must be unique among the list of available devices/tasks.

* **Enabled**: The device can be disabled or enabled. When not enabled the device should not use any resources.


Device Settings
^^^^^^^^^^^^^^^

.. image:: P148_DeviceSettingsScreenshot.png
:alt: Device configuration

The TM1621 LCD controller chip needs 4 pins to allow communication:

* ``DAT`` Data line, used to read and write data and send commands to the TM1621.
* ``WR`` Pulled low to start a write sequence. On the rising edge of the /WR signal, the data on the DATA line is written to the TM1621.
* ``RD`` Usually pulled low, but only after a read or read/write command it should be pulled up to indicate the need to read a bit.
* ``CS`` Chip-Select. Must be pulled low to address a chip. While this pin is high, all other signals will be ignored by the TM1621.

Since this chip and this display is only used in 2 devices made by Sonoff, the used pins of both devices is made available via the "Device Template" selection.
When this is set to any value other than "Custom", the set GPIO selection will be ignored and overwritten by the GPIOs used on those Sonoff devices.

Default pins on Sonoff devices
``````````````````````````````

.. code-block:: none

Sonoff THR3xxD POWR3xxD
TM1621 DAT GPIO05 GPIO14
TM1621 WR GPIO18 GPIO27
TM1621 RD GPIO23 GPIO26
TM1621 CS GPIO17 GPIO25

Sources:

* `templates.blakadder.com/sonoff_THR316D <https://templates.blakadder.com/sonoff_THR316D.html>`_
* `templates.blakadder.com/sonoff_POWR316D <https://templates.blakadder.com/sonoff_POWR316D.html>`_

Display Layout
^^^^^^^^^^^^^^

Most LCDs used in devices, not using a dot-matrix layout, only have a limited number of segments which can be switched between black and transparent.

The LCD used on these Sonoff Elite devices does only have 64 "pixels" or "segments".
There are 2 rows with each 4x 7-segment digits and only between the 3rd and 4th digit is a decimal dot.

The symbols on the right are:

* Degree Celsius
* Degree Fahrenheit
* ``V`` and ``A`` combined
* ``kWh`` and ``W`` combined
* ``%RH``

The 'combined' symbols can not be addressed separately.
This limits the flexibility of the display as it will be confusing to show 2 rows with readings of a voltage.
Also showing current (Ampere) and power (Watt) at the same time is confusing since both symbols are on the same row.

.. image:: P148_Sonoff_THR316D_display_all_pixels.jpg
:width: 800
:alt: Sonoff THR316D display with all pixels lit


Display Values
^^^^^^^^^^^^^^

There are 2 options to display some values on the LCD:

* The plugin can 'loop' over upto 3 sets of taskvalues periodically.
* Using commands via for example the rules.

Due to the limited number of digits on the display, the range of numerical values is rather limited:

* -999 ... 9999 without decimal point.
* -99.9 ... 999.9 with decimal point.
* Numericals will be right aligned due to the fixed position of the decimal point.

Most letters of the alphabet are also present and can be used.

* Some letters are not included, like the ``K``, ``M``, ``W``, ``X`` and ``Z``.
* Upper and lower case letters are somewhat mixed. For example ``D`` and ``O`` would be indistinguishable from the number ``0`` on a 7-segment display. Therefore those look more like their lower case parts.
* As special characters, the ``-`` and ``?`` are also included. All not included characters will look like a space.

At least the most important letters can be clearly shown on a 7-segment display:

.. image:: P148_TM1621_Display_ESP_Easy.jpg
:width: 500
:alt: Sonoff THR316D display showing "ESPEasy"

Display Page Temp/Hum
`````````````````````

An example showing the configuration displaying temperature and humidity from a BME280 sensor.

.. image:: P148_Page_BME280.png
:alt: Page definition showing temperature and humidity fields

Display Page Clear Line
```````````````````````

An example showing the configuration displaying temperature on the first row and clearing the second row.

.. image:: P148_temp_empty_row.png
:alt: Page definition showing temperature and an empty row

When switching pages and a row is not defined, then the content of the previous page may still be visible.
By selecting "Clear Line", the row will be cleared.



Display Page With Text Label
````````````````````````````

An example showing the configuration displaying temperature on the first row and some text label on the second row.

.. image:: P148_Page_temp_label.png
:alt: Page definition showing temperature and a text label on the second row

One can give task values a descriptive name, which can be displayed on the 'other' row.
As long as the used characters are available in the limited font.

For example, one can write "Co2" or "in" or "out".
These labels are taken from the selected task value names.


Switching Pages
^^^^^^^^^^^^^^^

A "task run", which happens every set ``Interval`` period, will try to draw the "next page" which causes an update to the display.

.. image:: P148_IntervalSetting.png

If this interval is set to "0", there will be no automatic page updates.
A user may trigger a "page update" by calling a ``taskrun`` for this task.
Each taskrun, the next page will be displayed.
When only a single "page" is defined, the same page will be refreshed.

When updates to the display are only sent via commands, the ``Interval`` should be set to ``0``.



Commands available
^^^^^^^^^^^^^^^^^^

.. include:: P148_commands.repl


Change log
----------

.. versionchanged:: 2.0
...

|added|
2023-01-10 Initial release version.





Binary file added docs/source/Plugin/P148_DeviceConfiguration.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/source/Plugin/P148_IntervalSetting.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/source/Plugin/P148_Page_BME280.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/source/Plugin/P148_Page_temp_label.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
79 changes: 79 additions & 0 deletions docs/source/Plugin/P148_commands.repl
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
.. csv-table::
:header: "Command Syntax", "Extra information"
:widths: 20, 30

"
| ``tm1621,write,<str1>,[<str2>]``

| ``<str1>``: Upto 4 characters
| ``<str2>``: Upto 4 characters
","
| Writes ``str1`` value on first row and ``str2`` value on second row (if given). Any symbol on the right will be cleared.

| The implemented font is limited since not all characters can be displayed on a 7-segment display.

| Only numericals can have a decimal dot and only between the 3rd and 4th position.

| If a numerical string does not have a dot, the value will not be shown with a dot.

| When a numerical > 999.9 or < 99.9 is displayed, no decimal dot will be shown.
"
"
| ``tm1621,writerow,<rownr>,<str>``

| ``<rownr>``: Use <= 1 for first row, otherwise second row.
| ``<str>``: Upto 4 characters.
","
| Writes ``str1`` value on the given row. Any symbol on the right will be cleared.

| See remarks with ``tm1621,write`` command.
"
"
| ``tm1621,voltamp,<volt>,<amps>``

| ``<volt>``: Range -999 ... 9999.
| ``<amps>``: Range -999 ... 9999.
","
| Writes ``volt`` value on first row and ``amps`` value on second row. The ``V`` and ``A`` symbols on the LCD are also enabled.

| NB: The ``V`` and ``A`` symbols are connected to each other and thus they cannot be independently switched.
"
"
| ``tm1621,energy,<kWh>,<Watt>``

| ``<kWh>``: Range -999 ... 9999.
| ``<Watt>``: Range -999 ... 9999.
","
| Writes ``kWh`` value on first row and ``Watt`` value on second row. The ``kWh`` and ``W`` symbols on the LCD are also enabled.

| NB: The ``kWh`` and ``W`` symbols are connected to each other and thus they cannot be independently switched.
"
"
| ``tm1621,celcius,<temperature>``
| ``tm1621,fahrenheit,<temperature>``

| ``<temperature>``: Range -999 ... 9999.
","
| Writes ``temperature`` value on first row. The degree ``C`` or ``F`` symbol on the LCD is also enabled.

| NB: The temperature symbols are only present on the first row on the display.
| N.B.2: The value is not checked, thus it is possible to display below -273.15C.
"
"
| ``tm1621,humidity,<rel humidity>``

| ``<rel humidity>``: Range -999 ... 9999.
","
| Writes ``rel humidity`` value on second row. The ``%RH`` symbol on the LCD is also enabled.

| NB: The ``%RH`` symbol is only present on the second row on the display.
| N.B.2: The value is not checked, thus it is possible to display negative or above 100% relative humidity.
"
"
| ``tm1621,raw,<64 bit HEX value>``
","
| Writes HEX values directly to the frame buffer of the display.

| For example: ``tm1621,raw,0x2f6b3700f2e7d357`` will create the characters showing ``ESP`` on the first row and ``EASY`` on the second row.
| ``tm1621,raw,0xffffffffffffffff`` will turn all 'pixels' on the LCD on.
"
Binary file added docs/source/Plugin/P148_temp_empty_row.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/source/Plugin/_Plugin.rst
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ There are different released versions of ESP Easy:
":ref:`P135_page`","|P135_status|","P135"
":ref:`P141_page`","|P141_status|","P141"
":ref:`P143_page`","|P143_status|","P143"
":ref:`P148_page`","|P148_status|","P148"


Internal GPIO handling
Expand Down
2 changes: 1 addition & 1 deletion docs/source/Plugin/_plugin_categories.repl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.. |Plugin_Analog_input| replace:: :ref:`P002_page`, :ref:`P007_page`, :ref:`P025_page`, :ref:`P060_page`, :ref:`P097_page`
.. |Plugin_Acceleration| replace:: :ref:`P120_page`, :ref:`P125_page`
.. |Plugin_Communication| replace:: :ref:`P016_page`, :ref:`P020_page`, :ref:`P035_page`, :ref:`P044_page`, :ref:`P054_page`, :ref:`P071_page`, :ref:`P087_page`, :ref:`P089_page`, :ref:`P094_page`, :ref:`P101_page`, :ref:`P118_page`
.. |Plugin_Display| replace:: :ref:`P012_page`, :ref:`P023_page`, :ref:`P036_page`, :ref:`P057_page`, :ref:`P073_page`, :ref:`P075_page`, :ref:`P095_page`, :ref:`P104_page`, :ref:`P116_page`, :ref:`P131_page`
.. |Plugin_Display| replace:: :ref:`P012_page`, :ref:`P023_page`, :ref:`P036_page`, :ref:`P057_page`, :ref:`P073_page`, :ref:`P075_page`, :ref:`P095_page`, :ref:`P104_page`, :ref:`P116_page`, :ref:`P131_page`, :ref:`P148_page`
.. |Plugin_Distance| replace:: :ref:`P110_page`, :ref:`P113_page`
.. |Plugin_Dust| replace:: :ref:`P018_page`, :ref:`P053_page`, :ref:`P056_page`
.. |Plugin_Energy_AC| replace:: :ref:`P076_page`, :ref:`P077_page`, :ref:`P078_page`, :ref:`P102_page`, :ref:`P108_page`
Expand Down
13 changes: 13 additions & 0 deletions docs/source/Plugin/_plugin_substitutions_p14x.repl
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,16 @@
.. |P143_maintainer| replace:: `tonhuisman`
.. |P143_compileinfo| replace:: `.`
.. |P143_usedlibraries| replace:: `https://github.com/adafruit/Adafruit_Seesaw`

.. |P148_name| replace:: :cyan:`POWR3xxD/THR3xxD`
.. |P148_type| replace:: :cyan:`Display`
.. |P148_typename| replace:: :cyan:`Display - POWR3xxD/THR3xxD`
.. |P148_porttype| replace:: `.`
.. |P148_status| replace:: :yellow:`ENERGY` :yellow:`DISPLAY`
.. |P148_github| replace:: P148_POWRxxD_THR3xxD.ino
.. _P148_github: https://github.com/letscontrolit/ESPEasy/blob/mega/src/_P148_POWRxxD_THR3xxD.ino
.. |P148_usedby| replace:: `.`
.. |P148_shortinfo| replace:: `Display for Sonoff Elite POWR3xxD/THR3xxD`
.. |P148_maintainer| replace:: `TD-er`
.. |P148_compileinfo| replace:: `.`
.. |P148_usedlibraries| replace:: `.`
5 changes: 5 additions & 0 deletions docs/source/Reference/Command.rst
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,11 @@ P143 :ref:`P143_page`

.. include:: ../Plugin/P143_commands.repl

P148 :ref:`P148_page`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. include:: ../Plugin/P148_commands.repl

.. .. *** Insert regular plugin commands above this remark! ***

.. _AdafruitGFX Helper commands:
Expand Down
4 changes: 2 additions & 2 deletions src/_P003_Pulse.ino
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ boolean Plugin_003(uint8_t function, struct EventStruct *event, String& string)
{
Internal_GPIO_pulseHelper::pulseCounterConfig config;
config.setDebounceTime(PCONFIG(P003_IDX_DEBOUNCETIME));
config.gpio = Settings.TaskDevicePin1[event->TaskIndex];
config.gpio = CONFIG_PIN1;
config.taskIndex = event->TaskIndex;
config.interruptPinMode = static_cast<Internal_GPIO_pulseHelper::GPIOtriggerMode>(PCONFIG(P003_IDX_MODETYPE));
config.pullupPinMode = Settings.TaskDevicePin1PullUp[event->TaskIndex] ? INPUT_PULLUP : INPUT;
Expand Down Expand Up @@ -186,7 +186,7 @@ boolean Plugin_003(uint8_t function, struct EventStruct *event, String& string)
String log;
if (log.reserve(20)) {
log += F("INIT : PulsePin: ");
log += Settings.TaskDevicePin1[event->TaskIndex];
log += CONFIG_PIN1;
addLogMove(LOG_LEVEL_INFO, log);
}
}
Expand Down
12 changes: 8 additions & 4 deletions src/_P021_Level.ino
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,11 @@ boolean Plugin_021(uint8_t function, struct EventStruct *event, String& string)
{
addRowLabel(F("Check Task"));
addTaskSelect(F("ptask"), P021_CHECK_TASK);

LoadTaskSettings(P021_CHECK_TASK); // we need to load the values from another task for selection!
addRowLabel(F("Check Value"));
addTaskValueSelect(F("pvalue"), P021_CHECK_VALUE, P021_CHECK_TASK);
if (validTaskIndex(P021_CHECK_TASK)) {
LoadTaskSettings(P021_CHECK_TASK); // we need to load the values from another task for selection!
addRowLabel(F("Check Value"));
addTaskValueSelect(F("pvalue"), P021_CHECK_VALUE, P021_CHECK_TASK);
}

addFormTextBox(F("Set Level"), F("psetvalue"), toString(P021_TRIGGER_LEVEL), 8);

Expand Down Expand Up @@ -178,6 +179,9 @@ boolean Plugin_021(uint8_t function, struct EventStruct *event, String& string)
{
// we're checking a var from another task, so calculate that basevar
taskIndex_t TaskIndex = P021_CHECK_TASK;
if (!validTaskIndex(TaskIndex)) {
break;
}
uint8_t BaseVarIndex = TaskIndex * VARS_PER_TASK + P021_CHECK_VALUE;
float value = UserVar[BaseVarIndex];
uint8_t state = switchstate[event->TaskIndex];
Expand Down