Network Module Manual - Code Rev 20231009 1022
Network Module Manual - Code Rev 20231009 1022
Introduction
Did you buy one (or more) of these Network Modules and then find disappointment in
the software on the board?
- All of the modules have the same MAC address. That's a problem if you want
more than one on your network. And the supplier does not give you a way to
change the MAC.
- If you change the IP Address the device returns to its default IP Address when it
power cycles. That makes it pretty much useless even if you only put one on your
network - unless you're OK with it always having IP Address 192.168.1.4.
I decided to write my own firmware for the device to provide a web server interface that
let's you change the IP Address, Gateway (Default Router) Address, Netmask, Port
number (a REAL port number), and MAC Address. I also added the ability for the device
to remember all these settings through a power cycle. Any Output settings you make are
also optionally saved through a power cycle (Outputs typically being Relay controls).
1
NOTE 1: The software provided in this project only works with the “Web_Relays_Con
V2.0 HW-584” which is based on the STM8S-005 or STM8S-105 processor and
ENC28J60 ethernet controller. I haven't tried it with any other version of the hardware. I
think the V.1 FC-160 is based on a Nuvoton processor and this code and the tools are
incompatible.
NOTE 2: I am not in any way associated with the manufacturer of this device. I only
wrote code to run on it for my own hobby purposes, and I am making it available for
other hobbyists.
NOTE 3: Buying update: As of April 2023 the only place I’m finding these modules is on
AliExpress. They are available from several stores on AliExpress. Keywords for
searching are “8 16 Channel ENC28J60 28J60 W5100 RJ45 Network web Relay Control
Switch Internet Management P2P WIFI Router Control relay Module”. Be careful to only
buy modules marked with “HW-584”.
2
Thank You!
Many thanks to contributors:
Carlos Ladeira for his help with user interface ideas, many hours of testing, and his
patience during development of the MQTT version of this code.
Jevgeni Kiski for his guidance and code contributions in developing the Home Assistant
interface, new Configuration interface, and JavaScript.
“peoyli” (github.com ID) for code contributions related to alternative pin out mapping.
We’ve ended up with a much better project as a result of these collaborations.
And of course a thank you to prior github code project creators that provided underlying
code and concepts in the following areas:
Simon Kueppers: ENC28J60, SPI, and HTTP interfaces.
Adam Dunkels: UIP
Liam Bindle: MQTT
Document License
Copyright (C) 2020, 2021, 2022, 2023 Michael Nielson.
Permission is granted to copy, distribute and/or modify this document under the terms of
the GNU Free Documentation License, Version 1.3 or any later version published by the
Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no
Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free
Documentation License".
3
Table of Contents
Introduction..........................................................................................................................1
Thank You!..........................................................................................................................3
Document License...............................................................................................................3
Table of Contents.................................................................................................................4
Quick Start Guide................................................................................................................7
MQTT Firmware vs Browser Only Firmware.....................................................................8
Build Type Feature Comparisons....................................................................................9
Screen Shots and Usage - MQTT Home Assistant Build..................................................10
Screen Shots and Usage - MQTT Domoticz Build...........................................................14
Screen Shots and Usage - Browser Only Build.................................................................17
Screen Shots and Usage - All Builds.................................................................................22
Notes on Feature Settings..................................................................................................23
PCF8574 Function.............................................................................................................26
Individual IO Settings – MQTT Home Assistant build.....................................................27
Individual IO Settings – MQTT Domoticz build..............................................................29
Individual IO Settings – Browser Only build....................................................................31
Timers: A Description of Accuracy and Precision........................................................34
Additional IO Name and Timer Notes...........................................................................36
Linked Inputs and Outputs.................................................................................................38
MAC Address....................................................................................................................41
Reset Button.......................................................................................................................42
LED....................................................................................................................................42
Default Firmware Settings.................................................................................................43
REST Commands..............................................................................................................44
MQTT Home Assistant......................................................................................................52
Home Assistant Auto Discovery...................................................................................58
MQTT Domoticz...............................................................................................................63
Network Statistics – Browser Only...................................................................................67
Link Error Statistics...........................................................................................................68
Functional Limitations.......................................................................................................74
Programming the Module..................................................................................................76
Setting up to Program the Module.................................................................................76
Setting up the Hardware to Allow Programming..........................................................83
Programming the Module the FIRST TIME.................................................................84
Programming the Module the NEXT TIME..................................................................91
IMPORTANT: Re-Installing Non-UPG Versions via SWIM.......................................93
IMPORTANT: Re-Installing UPG Versions via SWIM...............................................94
Upgradeable Firmware......................................................................................................95
What hardware is needed?.............................................................................................95
Connecting the I2C EEPROM module to the Network Module...................................97
How does it work?.........................................................................................................97
4
Future upgrades.............................................................................................................98
Alternative Way to Force Defaults or Downgrade Firmware...........................................99
Alternative Way to Set Initial IP Address.......................................................................102
Display Values vs Pin Logic Levels................................................................................105
Network Module Schematic............................................................................................107
Pinouts.............................................................................................................................109
Selecting Alternative Pinouts..........................................................................................110
Interfacing to Relay Modules..........................................................................................113
16 Channel Relay Modules..............................................................................................119
A Better Fix #1............................................................................................................122
A Better Fix #2............................................................................................................129
How I Modified a Board..............................................................................................131
A Possible “Directly Compatible” 16 Channel Relay Board......................................138
Input Pin Considerations..................................................................................................140
PCF8574 Inputs...............................................................................................................140
PCF8574 Outputs.............................................................................................................141
Hardware Design to Maintain Relay States Through a Power Loss or Reboot...............142
Adding DS18B20 Temperature Sensors..........................................................................148
Adding a BME280 Sensor...............................................................................................151
Browser Issues.................................................................................................................154
Chrome Auto-Complete and Pre-Fetch.......................................................................154
Developers: Setting Up a Development Environment.....................................................157
Developers: CXSTM8 Compiler Issues..........................................................................159
Developers: Location of EEPROM Variables.................................................................161
Developers: Debug Bytes................................................................................................163
Developers: Configuration Debug and pin_control Bytes...............................................167
Developers: Proto-Sockets...............................................................................................169
Developers: #pragma, Sections, Segments and the .lkf File............................................171
Editing the .lkf file.......................................................................................................171
Stack Overflow Detection............................................................................................171
Flash Update and Copy-RAM-to-Flash Code.............................................................172
_fctcpy.........................................................................................................................175
#pragma Sections.........................................................................................................176
Content of the .lkf File.................................................................................................177
Developers: STM8 Address Map....................................................................................179
Developers: Flash Memory Map.....................................................................................180
STM8 Flash Map for Non-Upgradeable builds...........................................................180
STM8 Flash Map for Upgradeable builds...................................................................181
Developers: I2C EEPROM Memory Map.......................................................................182
I2C EEPROM Regions for Upgradeable Builds.........................................................182
Addressing the I2C EEPROM Regions.......................................................................184
Developers: Upgradeable Firmware – How File Upload Works.....................................185
Developers: Strings File Generation for Ethernet Upgradeable Firmware.....................189
Developers: Using the UART..........................................................................................190
Developers: Analysis of MQTT sendbuf sizing..............................................................193
Developers: Storing Variables in Flash via the Application...........................................197
5
Developers: Flash and EEPROM Wear Notes................................................................202
Developers: How Connections Open and Close And Relationship to the
“current_webpage” Variable...........................................................................................204
Developers: How Proto-Sockets are Implemented and Connections Established...........206
Developers: Timer Internal Operation.............................................................................210
Developers: URL Command Map...................................................................................212
Developers: MQTT Local Port Numbers........................................................................217
Change Log......................................................................................................................218
Code Credits....................................................................................................................229
Documentation License Note..........................................................................................232
6
Quick Start Guide
If this is your first time to re-program your first module I recommend the following:
Follow the steps in section “Programming the Module” using the non-upgradeable
Browser Only firmware (NetworkModule-Browser.sx).
If you see a message “I2C EEPROM Missing” then you most likely tried to
program a UPG (upgradeable) code version.
Once programmed look around in the GUI and try turning a few outputs on and
off.
The above will get you going the very first time. Once you are comfortable with the
above you can explore the many other options like MQTT, upgradeable firmware, and all
the various option settings in the various firmware types.
7
MQTT Firmware vs Browser Only Firmware
Two basic firmware types are available for the Network Module: “MQTT” and “Browser
Only”.
The intent of having “MQTT” and “Browser Only” firmware builds is to address two
different communities of users.
The MQTT firmware is directed at users that have the network infrastructure to support a
MQTT Broker and device management tools like Home Assistant, NodeRed, and similar
tools. Those added network tools provide a very diverse set of device management
capabilities including user friendly interfaces and timing control. The MQTT firmware
CAN also be used by someone that only wants a Browser GUI.
The Browser Only firmware is directed at users that want simpler, self-contained
functionality without the need for an MQTT broker and other “always on” network tools.
The Browser Only firmware eliminates the MQTT code and provides a GUI that includes
a few extra user interface features like “IO Naming” and “IO Timers”. Of course
“Browser Only” significantly limits automation relative to what you can do with MQTT
and the device management tools associated with MQTT.
8
Build Type Feature Comparisons
9
Screen Shots and Usage - MQTT Home Assistant
Build
10
Screen Shots and Usage
MQTT Home Assistant Build
11
Screen Shots and Usage
MQTT Home Assistant Build
12
Screen Shots and Usage
MQTT Home Assistant Build
13
Screen Shots and Usage - MQTT Domoticz Build
14
Screen Shots and Usage
MQTT Domoticz Build
15
16
Screen Shots and Usage - Browser Only Build
17
Screen Shots and Usage
Browser Only Build
18
Screen Shots and Usage
Browser Only Build
19
Screen Shots and Usage
Browser Only Build
20
Screen Shots and Usage
Browser Only Build
To access the Network Statistics Page enter the http command “http://IP:Port/68”.
21
Screen Shots and Usage - All Builds
22
Notes on Feature Settings
The Features checkboxes on the Configuration page let you modify operation of the code
as follows:
During test it was found that Cisco business level switches exhibited Half Duplex
timing that the ENC28J60 cannot handle, the symptom being a device disconnect
(and automatic recovery) every few hours. This isn’t the fault of the Cisco switch,
rather it appears to be the fault of errata in the ENC28J60. During test it was
determined that we could get around this issue when connected to the Cisco
23
switch by enabling Full Duplex mode in the ENC28J60. While there was concern
that this would not work (due to chip spec notes and online discussion over the
years), it seemed to run error free. There may be other switches which show the
same issue. Again, the reason Full Duplex works may be the very low messaging
rate used with the Network Module which eliminates the need for flow control.
Note 1: The spec for the chip indicates that Full/Half Duplex auto-negotiation
DOES NOT work. However, experimentation showed that both Full and Half
Duplex worked with some unmanaged switches, but not with others. Problems
were always running Half Duplex only with the Cisco 1G managed switch. No
problem was seen running Half Duplex with a Cisco 10/100 managed switch.
Note 2: If you choose to use the Full Duplex setting note that the spec says the
Switch port the device is connected to MUST be manually configured for Full
Duplex operation … even though our testing did not always show that to be the
case. Of course we had a limited number of switches and this might be an issue on
some other switch.
Note3: Feel free to experiment with this setting at your own risk to see what
works best in your network configuration. I recommend you use Half Duplex and
only try Full Duplex if you have issues.
HA Auto:
The Home Assistant Auto Discovery setting enables the Network Module to send
MQTT Auto Discovery Publish messages to your Home Assistant server.
Checking this setting will automatically enable MQTT (and the MQTT checkbox
will automatically be set). Do not enable this setting unless you are operating in
an MQTT environment with Home Assistant.
MQTT:
Checking this box will enable the MQTT interface. HA Auto DOES NOT need to
be enabled with MQTT. This will allow you to operate with MQTT servers
without using Home Assistant, OR it will enable you to use Home Assistant
without Auto Discovery.
DS18B20:
Checking this box will cause IO 16 (Pin 16) to be disabled for use as an Input /
Output pin and will enable operation of the DS18B20 Temperature Sensor
interface on IO 16 (Pin 16). You can attach up to 5 DS18B20 temperature sensors
to pin 16, and the temperatures sensed by those devices will be displayed on the
IOControl page. See the section “Adding DS18B20 Temperature Sensors”. The
DS18B20 cannot be set at the same time as the BME280.
24
BME280:
Checking this box will enable operation of the BME280 Sensor on the I2C
interface. Only 1 BME280 sensor can be attached. The Temperature, Pressure,
and Humidity values measured by the BME280 will be displayed on the
IOControl page. Note that the Linked Pins functionality is disabled in the
BME280 code load. See the section “Adding a BME280 Sensor”.
25
PCF8574 Function
The PCF8574 is an 8 bit IO expander. It can be added to the Network Module on the I2C
bus (IO pins 14 and 15) under the following conditions:
Either the Upgradeable Browser or Upgradeable MQTT code is installed.
An I2C EEPROM has been added.
Since the I2C bus and I2C EEPROM are required the PCF8574 expansion cannot be
added to the non-upgradeable builds. See section “Upgradeable Firmware”.
There is no “Feature Setting” for the PCF8574. The code will recognize the presence of
the PCF8574 and will enable PCF8574 functionality including the PCF8574
Configuration and IOControl pages. If the PCF8574 device is missing the PCF8574
Configuration and IOControl buttons will be disabled.
If enabled the PCF8574 IO pins have the same functionality as the original STM8 IO
pins. IO numbering on the PCF8574 is pin 17 to 24.
26
Individual IO Settings – MQTT Home
Assistant build
The Individual IO Settings drop down and check boxes on the Configuration page lets
you modify functionality of each IO as follows:
27
IMPORTANT: Set the Input/Output/Disabled/Linked setting, THEN Save,
THEN make other setting changes.
VERY IMPORTANT: Be sure you understand your hardware design. You must
avoid setting an IO as an Output if the associated pin is tied to VCC or Ground, as
that is likely to damage the output driver on the processor. If your hardware
design can provide high levels of input current on a pin make sure that pin is
defined as an Input.
BME280: “Linked” does not apply to BME280 builds. If a pin is set to “Linked”
it will be changed to “Disabled” on Save if a BME280 build is installed.
Invert Settings:
Each IO has an “Invert” checkbox.
Effect on Inputs:
If not checked, a low voltage on the Input pin will display as OFF in the
IOControl page and will be reported as OFF to MQTT clients.
If checked, a low voltage in the Input pin will display as ON in the
IOControl page and will be reported as ON to MQTT clients.
Effect on Outputs:
If not checked, an OFF indication in the IOControl page or MQTT Client
will result in a low voltage on the Output pin.
If checked, an OFF indication in the IOControl page or MQTT Client will
result in a high voltage on the Output pin.
Since some devices connected to Output pins may be in an ON state with a low
voltage, and others may be in an OFF state with a low voltage you will need to
figure out what the Invert setting should be for your specific design. It is really a
simple matter of connecting your peripheral device, setting ON or OFF in the
Browser, then checking the Invert box as needed so that an ON state in the
Browser matches an ON condition in your peripheral.
28
Individual IO Settings – MQTT Domoticz
build
The Individual IO Settings drop down and check boxes on the Configuration page lets
you modify functionality of each IO as follows:
Invert Settings:
These settings operate identically to the Type Drop Down Settings described in
the “Individual IO Settings – MQTT Home Assistant Build” section.
29
Boot State Settings:
These settings operate identically to the Type Drop Down Settings described in
the “Individual IO Settings – MQTT Home Assistant Build” section.
IDX Settings:
The IDX value established when configuring devices in Domoticz is to be placed
in these fields. See the documentation for the Domoticz Home Automation
System to understand IDX values.
30
Individual IO Settings – Browser Only build
The Individual IO Settings drop down and check boxes on the Configuration page lets
you modify functionality of each IO as follows:
31
IMPORTANT: Set the Input/Output/Disabled/Linked setting, THEN Save,
THEN make other setting changes.
VERY IMPORTANT: Be sure you understand your hardware design. You must
avoid setting an IO as an Output if the associated pin is tied to VCC or Ground, as
that is likely to damage the output driver on the processor. If your hardware
design can provide high levels of input current on a pin make sure that pin is
defined as an Input.
Invert Settings:
Each IO has an “Invert” checkbox.
Effect on Inputs:
If not checked, a low voltage on the Input pin will display as OFF in the
IOControl page and will be reported as OFF to MQTT clients.
If checked, a low voltage in the Input pin will display as ON in the
IOControl page and will be reported as ON to MQTT clients.
Effect on Outputs:
If not checked, an OFF indication in the IOControl page or MQTT Client
will result in a low voltage on the Output pin.
If checked, an OFF indication in the IOControl page or MQTT Client will
result in a high voltage on the Output pin.
Since some devices connected to Output pins may be in an ON state with a low
voltage, and others may be in an OFF state with a low voltage you will need to
figure out what the Invert setting should be for your specific design. It is really a
simple matter of connecting your peripheral device, setting ON or OFF in the
Browser, then checking the Invert box as needed so that an ON state in the
Browser matches an ON condition in your peripheral.
Name Settings:
Enter a name for the IO pin. This name will appear on the IOControl page for the
pin. Use any alphanumeric character plus -*_ and . (no spaces).
32
Timer Settings:
Two fields are provided:
“Value” field:
0 disables the Timer.
1 to 16383 can be entered for the number of “ticks” to operate the Timer.
For example, ticks at 0.1 second or 1 second or 1 minute or 1 hour.
The Network Module does not have a precise clock, so very long timers
can have significant error. Additionally significant error can be present
when very small values are entered. See the “Precision” description below.
“Units” field:
Select the time unit to use: 0.1 second, seconds, minutes, or hours.
If you enter “0” in the Value field the Timer will not affect the Output pin.
The Timer assumes that the “Boot State” is the idle state of the output, ie,
the “normal” state the output is in. If you then change the output to its
non-idle state the Timer will start and will return the output to the idle
state when the Timer expires. Example:
Output #1 is named “Porch Light”. The Boot State is “off”. So,
normally this output is “off”. I have the Timer value and units set
to 15 seconds. If I change the output to “on” the Timer will turn
the output off after 15 seconds.
“Boot State” must be “on” or “off”. “retain” will disable the Timer.
If a Reboot or power cycle occurs while a Timer is running the Output will
be set to its “Boot State”.
33
Timers: A Description of Accuracy and Precision
As I start this description I must remind you that “precision” and “accuracy” are not the
same thing.
Accuracy refers to how close a value is to the true value – for instance, if the Network
Module reports 1 second, how close is that to an actual 1 second passage of time? The
answer is “close, but not really very accurate”. The reason is because all timers are
running from the STM8 internal 16MHz clock, which is NOT a calibrated clock. But it is
close enough for this application.
Accuracy
Here is some basic information on accuracy of the 16MHz clock.
34
As shown in the Datasheet the accuracy of the 16MHz oscillator could be off by as much
as 5% from the factory. Also as mentioned the device can be user-trimmed to bring it
closer to 1%, but that is about as close as can be achieved.
The Application Note describes setting up special hardware and special code to find the
best trim values to match your power mains frequency. That’s a real pain to do.
An alternative: If truly essential URL commands could be developed to allow the user to
set trim values on a per device basis. A potential process would be to compare a fairly
long pin Timer to a known source (a pulse generator, or even a stopwatch), and
experiment with settings until the best match is found. However, I suspect that if this
device is being used in a situation where more accurate pin timers are needed it is the
wrong device for the application.
If someone wanted to use this approach I’d suggest using Timer units of 0.1s and a Timer
value of 3000 (5 minutes). Just by visual comparison to a good stopwatch the user should
be able to see timing differences of 1 second (0.33%) which far exceeds the accuracy that
can be set. So getting as close to the 5 minute time as possible would obtain the best trim
that can be achieved. Of course it may take several passes of the test so this could easily
take 30 minutes to an hour to trim a single board.
35
Precision
You’ll find the precision of timers is fairly predictable, and can be described as “the timer
will trigger at any point from (time – 1 tick) to (the time selected)”. Why is this the case?
Because when a time is entered we don’t know if a “tick” clock edge is just about to
occur, or if it occurred just before the timer setting was entered. How can precision be
improved? By not using the smallest values for a given units setting. This illustration
should clarify:
The basic take-away from the above is “For best precision always use a value of 100 or
above for any given unit setting”. It is okay to use a value of 1 to 100 with any given unit,
but precision is reduced. For an extreme example:
Units = 0.1 second.
Value = 2.
Result will be a time from 0.1 to 0.2 seconds.
NOTE: “Name” and “IO Timer” features are not available in the MQTT builds due to
lack of Flash space. Typically this type of feature isn’t needed in MQTT environments as
MQTT management tools provide similar functionality.
36
IMPORTANT: Don’t change the IO Names and IO Timers settings frequently.
These values are stored in the Flash (not in the EEPROM). Flash has a much more
limited number of write cycles than EEPROM, so try to keep the number of times you
change IO Name or IO Timer settings to a few hundred per pin. This should be more than
adequate for typical usage.
37
Linked Inputs and Outputs
In addition to setting a pin Type as Disabled, Input, or Output the user has the option to
set a pair of pins to “Linked”. This will Link an Input pin to an Output pin. When Linked
and the Input pin changes state (either 0 to 1, or 1 to 0) the Output pin will flip its current
state.
For this function the only pins that can be used as Linked Inputs are pins 1 to 8.
The corresponding Linked Outputs are pins 9 to 16.
Pin 1 can only be Linked to Pin 9
Pin 2 can only be Linked to Pin 10
Pin 3 can only be Linked to Pin 11
Pin 4 can only be Linked to Pin 12
Pin 5 can only be Linked to Pin 13
Pin 6 can only be Linked to Pin 14
Pin 7 can only be Linked to Pin 15
Pin 8 can only be Linked to Pin 16
For pins 1 to 8 (and 17 to 20 with a PCF8574): When the pin Type is changed in the GUI
to “Linked” the pin will show in the Configuration GUI as Linked, but it will function as
an Input, and will appear in the IOControl page and MQTT traffic as an Input.
For pin 9 to 16 (and 21 to 24 with a PCF8574): When the pin Type is changed in the GUI
to “Linked” the pin will show in the Configuration GUI as Linked, but it will function as
an Output, and will appear in the IOControl page and MQTT traffic as an Output.
When pins are set to Linked in the GUI and Save is clicked the firmware will validate
that setting against other higher priority settings and will reject the Linked setting if
necessary. For example if pin 16 is being used for DS18B20 temperature sensors then
pins 8 and 16 cannot be Linked. If a Linked setting is rejected the pins will retain their
previous pin Type setting.
If the user wants to link two pins they must set both pins to Linked at the same time,
followed by Save. This helps assure that the user doesn’t inadvertently select the wrong
pins. If the user fails to set both pins to Linked at the same time the pins will retain their
previous Type when the Save occurs.
38
To “Un-Link” pins both of the pins must be set to a Type other than “Linked” at the same
time. The user can select Disabled, Input, or Output as the new pin Type provided BOTH
pins are no longer set to Linked. If the user leaves either pin as Linked then the new pin
Types are discarded and both pins will remain Linked.
When pins are linked the IOControl page can still be used to set the ON/OFF state of the
Output pin, and the next edge on the Linked Input pin will then simply flip the Output
state. Likewise MQTT or the REST functions can set the ON/OFF state of the Output
pin, and the next edge on the Linked Input pin will then simply flip the Output state.
If using a Browser version the Output Timers will continue to function on the Linked
Output pin in the same way the Timers work on a regular Output pin.
39
BME280 Build: The Linked Pins function does not apply to the special BME280 build.
Any pins set to “Linked” will be changed to “Disabled” on Save if a BME280 build is
installed.
40
MAC Address
When delivered from the factory the Network Modules all have the same MAC address.
This obviously doesn’t work when you try to put more than one on a network.
A MAC address is only used within your network. Your router(s) and switch(es) use the
MAC address as the means of uniquely addressing all the hardware in your network. The
MAC address does not appear outside your network so it only needs to be unique to
YOUR network, not to the entire world. This being the case, you only need to make sure
that any MAC address you put in the Network Module does not conflict with any other
hardware in your local network.
Despite this being a LAA MAC address there is still some very remote possibility the
MAC you pick will conflict with some other hardware you have on your network. You
can search on Google to find methods of finding all MAC addresses on your network –
the method you choose will depend on your level of expertise. Generally this is not
required, and if you suspect a conflict you may just find it easier to try a different MAC
address on the Network Module. Maybe make the middle fours octets something you
fancy.
If you are installing multiple devices on your network I suggest that you just change the
values in the least significant octet and leave the others as-is. I advise you add a label to
your Network Module with the MAC you programmed into it.
41
42
Reset Button
There is a single “reset” button on the board. The button provides two functions:
1) If pressed for at least 1 second but less than 5 seconds the module will restart.
2) If pressed for more than 5 seconds the module will return to the hard-coded
default settings of the firmware.
If the button is briefly pressed (less than one second) there is no effect.
LED
There is a red LED next to the Reset Button. The original factory firmware left this LED
off after boot, but the firmware provided with this project leaves the LED ON after boot.
In part this was done so that it is easier to tell if initial re-programming of the Network
Module HW-584 was successful.
You may notice that the LED “flickers” at various times during boot or when
upgradeable firmware is downloaded and installed. This is primarily for development
purposes to determine progress through the automated programming and boot steps. This
is generally the same over releases, but may change at any time.
43
Default Firmware Settings
When a device is first programmed (a point at which the EEPROM does not yet contain
the “magic number”), or if the Reset button is pressed for more than 5 seconds to force a
return to defaults, following are the settings that will be used in the device:
IO Pins
Pin state = OFF
Boot state = OFF
Retain = OFF
Invert = OFF
Pin Type = Disabled
44
REST Commands
45
68 = Show Network Statistics page (Browser Only builds)
69 = Clear Network Statistics and refresh page (Browser Only builds)
70 = Clear the "Reset Status Register" counters (Only in Developer Debug builds)
71 = Display the Temperature Sensor Serial Numbers (Only in special debug builds)
72 = Load Code Uploader (Only in Upgradeable builds)
73 = Reload firmware existing image (Only in the Code Uploader)
74 = Erase entire I2C EEPROM (Only in the Code Uploader)
75 = Show RF Attenuator Settings page (Only in special build) (see notes)
76 = Show INA226 Measurements page (Only in special build) (see notes)
77 = Show the Latching/Keep Relay status page and turn on Latching/Keep Relay mode
(Only in special build). (see notes)
78 = Turn off Keep Relay mode, aka Latching Relay mode (Only in special build). (see
notes)
79 = Set INA226 Shunt Resistance Option (Only in special build). (see notes)
91 = Reboot
98 = Show Short Form IO States (without HTML formatting) (see notes)
99 = Same as /98 (see notes)
Note1: Output control commands (/00 to /47) only work for IO defined as an Output. If
the IO referenced in the command is an Input no action is taken.
Note 2: Commands /98 and /99 provide a “Short Form” output page with displays the
IO states as 16 alphanumeric characters WITHOUT any HTML formatting. Both
commands produce the same result for backward compatibility. This command may be
useful to some external applications that automate interaction with the Network Module
using URL style commands. When a PCF8574 IO Expander is present the IO states are
shown as 24 alphanumeric characters.
If the “Show Disabled Pins as –“ option is enabled (see command /84 “Short Form
Option”) then any Disabled pins will appear in the Short Form display as a ‘-‘.
46
Note 3: When the /00 to /47, /55, /56, or /50 commands are executed they will return a
blank webpage. This is done to reduce Browser traffic helping to prevent interference
with other Browsers that may be accessing the Network Module.
Note 5: The /50 and /51 commands allow the user to set and clear all output pins in a
user defined pattern. A “mask” and “pins” value is used to control Output pins in “batch
mode”. The command is structured as /50mmmmpppp or /51mmmmpppp where:
mmmm is a mask consisting of four hex characters representing a 16 bit value.
The mask will allow the user to specify which pins will be changed so that pins
not involved in the operation will be left as-is. A zero in a bit location indicates no
change is to be made to that pin.
pppp is the desired state of the pins, consisting of four hex characters representing
a 16 bit value. The pppp value sets the state of the output pins subject to the mask.
The above only affects Output pins. All other pins are ignored regardless of the
mmmm and pppp values.
The /50 command returns no webpage. The /51 command returns the Short Form
IO State page.
Examples:
URL Command “192.168.1.183/50ffff0007” will turn off all outputs except the
three least significant outputs which will be turned on.
47
URL Command “192.168.1.183/5000ffffff” will turn on the 8 least significant
outputs (because the upper 8 are masked).
Note 6: The /81 command allows the user to enter the altitude of the device. This is used
by the BME280 Temperature / Pressure / Humidity Sensor to compensate barometric
pressure at altitude. The data only needs to be entered once at a given altitude, and can be
re-entered if the device is relocated to a different altitude. Altitude can be entered in feet
or meters. Examples:
Note 7: The /82 command allows the user to select an alternative physical pinout on the
IO connector. Examples:
Note 8: The /84 command allows the user to change the way that the Short Form IO
State page shows Disabled pins. Examples:
48
URL Command “192.168.1.183/84+” will cause the Short Form to display
Disabled pins with a ‘0’ or ‘1’. Whether ‘0’ or ‘1’ are displayed in indeterminate,
but is usually the last known state of the pin.
The “+” command is provided so that the user can revert the setting to the default if they
had previously used the ‘-‘ command.
The /84 command returns the Short Form IO State page. This allows the user to
immediately see the changes generated by the /84 command, and is of some use to URL
script programmers that switch between the various Short Form IO State modes.
Note 9: The /85 command is used after removal of a PCF8574 device to inform the
firmware that the device removal was intentional, and that the PCF8574 pin definitions
are to be removed in Home Assistant. A reboot is generated as part of this command so
that the Home Assistant Auto Discovery process will run to generate the appropriate
delete messages over MQTT to Home Assistant. This is an aid to the user to reduce the
amount of work needed in updating Home Assistant when the PCF8574 device is
removed.
Note 10: The /a0 command controls the “Response Lockout” feature. Response Lockout
allows you to lock the Ethernet response process so that any attempt to access the device
results in no response. This can be useful if you have exposed your device to the Internet
but want to prevent internet bots from discovering the device using port probing.
IMPORTANT: Not all builds include this feature due to Flash size limitations. See the
Features Comparison in the “MQTT Firmware vs Browser Only Firmware” section.
49
Note 11: The /75 command displays the “RF
Attenuator Settings” webpage. This command only
functions in a special build developed to support a
Software Defined Radio project. The basic function
of the webpage is to interpret IO2 to IO6 as a binary
decibel setting. The webpage displays the bits as a
decimal decibel value (to show the current setting)
and the webpage includes buttons labeled from 1 to
31 to set the decibel value. The IO pins of the
Network Module HW-584 are connected to the
control pins on an RF attenuator.
50
Note 12: The /76 command displays the “INA226
Measurements” webpage. This command only functions
in a special build developed to support a Software
Defined Radio project. The basic function of the
webpage is to display the values read from an INA226
voltage / current / power measurements device.
51
Note 14: The /78 command turns off “Latching Relay Mode”, aka “Keep Relay Mode”.
This command only functions in a special build developed to support a Software Defined
Radio project.
Note 15: The /79 command allows the user to set the Shunt Resistance option of the
INA226 current/voltage/power measurement devices. This command is only available in
special builds for the Software Defined Radio project. The command only needs to be run
once to set the option. The default option is “0”. Examples:
Typical INA226 modules will have either a 0.1 ohm or 0.002 ohm shunt resistor
implemented on the module. Use the /79 command to identify the shunt resistor value.
All INA226 devices connected to a given Network Module must have the same shunt
resistance value.
52
MQTT Home Assistant
This is not a tutorial on MQTT as there are a lot of great resources online to bring you up
to speed if you are just getting started with this protocol. Here I am only including notes
on the tools and methods used in test of the MQTT functionality on the Network Module.
Configuration Settings:
At this date the MQTT Broker Server must be specified in the form of an IP
Address (as opposed to a URL). In future versions I may be able to allow use of a
URL for the Broker Server.
The MQTT Port is self explanatory. The MQTT default value of 1883
automatically appears, but you can enter any port number you have assigned to
MQTT on your Broker Server.
Security:
The MQTT Username and MQTT Password are optional and only required if
you’ve set up your Broker to require them.
If security is really important due to the need to access MQTT on the device from
the internet I suggest setting up access to your internal MQTT Broker Server in a
secure way, then letting the Broker Server pass all messages on your internal
network. You don’t have to do it this way, but this is a suggestion for improving
security rather than just exposing the device to the internet.
53
Tools and test methods:
You aren’t restricted to the above. Any tools and interfaces that are MQTT compliant
should work just as well. But if you are just getting started I can recommend the
above as a good place to start.
The MQTT Status indicators show connection progress with the MQTT Server
and Broker:
Box 1 - Indicates that the MQTT Connection process has started.
Box 2 - Indicates a successful ARP reply from the Server.
Box 3 - Indicates a successful TCP connection with the Server.
Box 4 - Indicates the MQTT Broker has responded (Connect phase)
Box 5 - Indicates initial communication with the Broker has completed
successfully (initial subscribe and publish messages completed).
Once all 5 boxes are green the Network Module is connected to the Broker and
normal MQTT communications can proceed.
A reminder regarding the Output Boot State setting for the Outputs on the
Configuration page: If you select ‘Retain’ the Output states are written to the
EEPROM every time an Output changes state. If you anticipate a lot of Output
state changes you may wear out the EEPROM with too many changes to the
Output states. I suggest that Retain only be used when Outputs are expected to
change only a few times per day.
54
Client Publish and Subscribe messaging:
The Network Module Publishes the following when an IO state change occurs:
NetworkModule/<devicename>/input/xx Payload: "ON" or "OFF"
55
NetworkModule/<devicename>/output/xx Payload: "ON" or "OFF"
Where “xx” is the IO number of the Input or Output
The Network Module Publishes the following every 30 seconds if DS18B20 mode is
enabled and Temperature Sensors are attached to the Network Module::
NetworkModule/<devicename>/temp/xxxxxxxxxxxx Payload: Temperature
in degrees Celsius in the format " 000.0" or “-000.0”
Where “xxxxxxxxxxxx” is the Temperature Sensor ID in 12 hex encoded
characters.
The Network Module Publishes the following every 300 seconds (5 min) if BME280
mode is enabled and a BME280 Sensor is attached to the Network Module::
NetworkModule/<devicename>/temp/BME280-0xxxx Payload: Temperature
in degrees Celsius in the format " 000.00" or “-000.00”
Where “xxxx” is the lower 4 characters of the module IP address in hex. For
example 192.168.1.182 is c0.a8.01.b6 in hex, so the “xxxx” is “01b6”.
56
Bit 2 = IO 3 state
Bit 1 = IO 2 state
Bit 0 = IO 1 state
Note that Disabled IO will still have either an ON or OFF state. The state is
indeterminate but is generally dependent on the last state seen for that IO. The
user application is responsible for knowing which IO are Enabled and Disabled
when using the above response.
Note that Disabled IO will still have either an ON or OFF state. The state is
indeterminate but is generally dependent on the last state seen for that IO. The
user application is responsible for knowing which IO are Enabled and Disabled
when using the above response.
57
The Network Module Subscribes to the following topics when it connects to the Broker:
NetworkModule/<devicename>/output/+/set
This Subscribe enables the Network Module to receive output Publish
commands from Clients. The + as used above causes the broker to send
the module the "set" commands, but won't reflect the modules own IO
state messages back to the module (reduces traffic).
NetworkModule/<devicename>/state-req
This Subscribe enables the Network Module to receive the state-req
Publish command from Clients.
NetworkModule/<devicename>/state-req24
This Subscribe enables the Network Module to receive the state-req
Publish command from Clients. This only applies to hardware
configuration that include the PCF8574 IO Expander.
When the Network Module connects to the Broker it will establish a "last will" message
of "offline" with the will topic “NetworkModule/<devicename>/availability”
When the Network Module connects to the Broker it will Publish to the following topics:
NetworkModule/<devicename>/availability Payload: online
NetworkModule/<devicename>/input/xx Payload: "ON" or "OFF"
NetworkModule/<devicename>/output/xx Payload: "ON" or "OFF"
Where “xx” is the IO number for the Input or Output.
No Publish occurs for a Disabled IO.
Where “xxxx” is the lower 4 characters of the module IP address in hex. For
example 192.168.1.182 is c0.a8.01.b6 in hex, so the “xxxx” is “01b6”.
58
Home Assistant Auto Discovery
If the HA Auto checkbox is set to enable the Network Module Publishes the following
messages at boot time:
59
For the BME280 Pressure Sensor:
homeassistant/sensor/<macaddress>/BME280-1xxxx/config Payload: see below
This only occurs if BME280 mode is Enabled.
“xxxx” is the lower 4 characters of the module IP address in hex.
NOTE: The Network Module never issues an empty payload message for Sensors
that are removed (or fail) or if the DS18B20 or BME280 function is disabled after
sensors have been configured. The implication is that HA may show sensor
entities that are “Unavailable”, and in that case they can only be removed in HA
using HA functionality. As of this writing (9/21/2022) I found that I could not
directly Delete these entities in Home Assistant. Instead I had to “Disable” them
in HA, then reboot the HA host, then give HA a couple of minutes to actually
make the sensors “disappear”. I also found that HA didn’t really delete them, it
only made them invisible. I found that when a “Disabled” sensor was reinstalled
HA still have the information on the sensor. So, as a user you may have some
sorting out to do in HA.
Payload Information:
Where a Home Assistant Auto Discovery Payload is not empty it takes this form for the
“switch” topics:
{
"uniq_id":"<macaddress>_output_01",
"name":"output 01",
"~":"NetworkModule/<devicename>",
"avty_t":"~/availability",
"stat_t":"~/output/01",
"cmd_t":"~/output/01/set",
"dev":{
"ids":["NetworkModule_<macaddress>"],
"mdl":"HW-584",
"mf":"NetworkModule",
60
"name":"<devicename>",
"sw":"<code_revision>"
}
}
The above example is for an Output on IO 01.
<macaddress> is replaced with the MAC address of the Network Module as entered on
the Configuration page..
<devicename> is replaced with the Name of the Network Module as entered on the
Configuration page.
<code_revision> is replaced with the code revision for the firmware programmed into the
Network Module.
Where a Home Assistant Auto Discovery Payload is not empty it takes this form for the
“binary-sensor” topics:
{
"uniq_id":"<macaddress>_input_01",
"name":"input 01",
"~":"NetworkModule/<devicename>",
"avty_t":"~/availability",
"stat_t":"~/input/01",
"dev":{
"ids":["NetworkModule_<macaddress>"],
"mdl":"HW-584",
"mf":"NetworkModule",
"name":"<devicename>",
"sw":"<code_revision>"
}
}
The above example is for Input on IO 01.
<macaddress> is replaced with the MAC address of the Network Module as entered on
the Configuration page..
<devicename> is replaced with the Name of the Network Module as entered on the
Configuration page.
<code_revision> is replaced with the code revision for the firmware programmed into the
Network Module.
A Home Assistant Auto Discovery Payload takes this form for the “temp” topics:
{
"uniq_id":"<macaddress>_temp_012356abcdef",
"name":"temp 012356abcdef ",
"~":"NetworkModule/<devicename>",
"avty_t":"~/availability",
"stat_t":”~/temp/012356abcdef ",
"unit_of_meas":"\xc2\xb0\x43",
61
"dev":{
"ids":["NetworkModule_<macaddress>"],
"mdl":"HW-584",
"mf":"NetworkModule",
"name":"<devicename>",
"sw":"<code_revision>"
}
}
The above example is for Temperature Sensor ID “012356abcdef”. For the DS18B20 the
ID is a 12 character hex encoded field representing the 6 digits (48 bits) of the
Temperature Sensor serial number (which also happens to be a MAC).
For the BME280 Temperature Sensor the ID would appears as “BME280-0xxxx” where
the “xxxx” is the least significant four hex digits of the Network Module IP Address
(example: 192.168.1.182 is c0.a8.01.b6 in hex, so the “xxxx” is “01b6”.
.
<macaddress> is replaced with the MAC address of the Network Module as entered on
the Configuration page..
<devicename> is replaced with the Name of the Network Module as entered on the
Configuration page.
<code_revision> is replaced with the code revision for the firmware programmed into the
Network Module.
A Home Assistant Auto Discovery Payload takes this form for the “pres” topics:
{
"uniq_id":"<macaddress>_pres_BME280-201b6",
"name":"pres BME280-201b6",
"~":"NetworkModule/<devicename>",
"avty_t":"~/availability",
"stat_t":”~/pres/ BME280-201b6",
"unit_of_meas":"hPa",
"dev":{
"ids":["NetworkModule_<macaddress>"],
"mdl":"HW-584",
"mf":"NetworkModule",
"name":"<devicename>",
"sw":"<code_revision>"
}
}
The above example is for Pressure Sensor ID “BME280-201b6”.
<macaddress> is replaced with the MAC address of the Network Module as entered on
the Configuration page..
<devicename> is replaced with the Name of the Network Module as entered on the
Configuration page.
<code_revision> is replaced with the code revision for the firmware programmed into the
Network Module.
62
A Home Assistant Auto Discovery Payload takes this form for the “hum” topics:
{
"uniq_id":"<macaddress>_hum_BME280-301b6",
"name":"hum BME280-301b6",
"~":"NetworkModule/<devicename>",
"avty_t":"~/availability",
"stat_t":”~/hum/ BME280-301b6",
"unit_of_meas":"%",
"dev":{
"ids":["NetworkModule_<macaddress>"],
"mdl":"HW-584",
"mf":"NetworkModule",
"name":"<devicename>",
"sw":"<code_revision>"
}
}
The above example is for Humidity Sensor ID “BME280-301b6”.
<macaddress> is replaced with the MAC address of the Network Module as entered on
the Configuration page..
<devicename> is replaced with the Name of the Network Module as entered on the
Configuration page.
<code_revision> is replaced with the code revision for the firmware programmed into the
Network Module.
63
MQTT Domoticz
This is not a tutorial on the MQTT Domoticz Home Automation System. If you are just
getting started with Domoticz you’ll have to spend some time reading the documentation
on that product. Here I will describe how the “under the covers” interface between the
Network Module and Domoticz works.
While the Domoticz product has many GUI similarities to Home Assistant the
communication protocol is very different. Home Assistant typically has complicated
“topics” and very simple “payloads”. Domoticz is just the opposite: very simple “topics”
and very complicated “payloads”.
First a quick discussion of setting up communication between the Network Module and
the MQTT Broker. Within the Network Module Configuration menu you need to set up
the MQTT server settings as follows.
Configuration Settings:
At this date the MQTT Broker Server must be specified in the form of an IP
Address (as opposed to a URL). In future versions I may be able to allow use of a
URL for the Broker Server.
The MQTT Port is self explanatory. The MQTT default value of 1883
automatically appears, but you can enter any port number you have assigned to
MQTT on your Broker Server.
Security:
The MQTT Username and MQTT Password are optional and only required if
you’ve set up your Broker to require them.
64
IMPORTANT: SSL/TSL are NOT implemented due to memory restrictions. I
haven’t found any implementations that are small enough to fit in the flash space
available on the Network Module, so I don’t expect this to ever be possible.
If security is really important due to the need to access MQTT on the device from
the internet I suggest setting up access to your internal MQTT Broker Server in a
secure way, then letting the Broker Server pass all messages on your internal
network. You don’t have to do it this way, but this is a suggestion for improving
security rather than just exposing the device to the internet.
The MQTT Status indicators show connection progress with the MQTT Server
and Broker:
Box 1 - Indicates that the MQTT Connection process has started.
Box 2 - Indicates a successful ARP reply from the Server.
Box 3 - Indicates a successful TCP connection with the Server.
Box 4 - Indicates the MQTT Broker has responded (Connect phase)
Box 5 - Indicates initial communication with the Broker has completed
successfully (initial subscribe and publish messages completed).
Once all 5 boxes are green the Network Module is connected to the Broker and
normal MQTT communications can proceed.
A reminder regarding the Output Boot State setting for the Outputs on the
Configuration page: If you select ‘Retain’ the Output states are written to the
EEPROM every time an Output changes state. If you anticipate a lot of Output
state changes you may wear out the EEPROM with too many changes to the
Output states. I suggest that Retain only be used when Outputs are expected to
change only a few times per day.
65
Domoticz Topics:
The Network Module is designed to operate utilizing “Flat” topic structures. See the
Domoticz documentation at https://www.domoticz.com/wiki/MQTT#Publish_Topic for
an explanation of what this means, and for information on how you can operate other
products on your network that utilize other topic structures.
The Network Module Publishes the following when an IO state change occurs:
Topic: domoticz/in
Payload:
{“command”:”switchlight”, “idx”: xxxxxx, “switchcmd”:”on”}
or
{“command”:”switchlight”, “idx”: xxxxxx, “switchcmd”:”off”}
The Network Module Publishes the following every 30 seconds if DS18B20 mode is
enabled and Temperature Sensors are attached to the Network Module::
Topic: domoticz/in
Payload:
{"command": "udevice", "idx": xxxxxx, "nvalue": x, "svalue": "xxxx.x", "parse":
true}
The “idx” value can be up to 6 text digits in this application.
The “svalue” is the temperature measured by the DS18B20 in degrees C. The first
character of the “svalue” can be a “-“ sign.
66
The Network Module Publishes the following every 300 seconds (5 min) if BME280
mode is enabled and a BME280 Sensor is attached to the Network Module::
Topic: domoticz/in
Payload:
{"command":"udevice","idx":xxxxxx,"svalue":"8.8;91;3;1029;0"}
The “idx” value can be up to 6 text digits in this application.
The “svalue” shown is just an example explained here:
8.8 – An example temperature value in degrees C
91 - An example relative humidity value in %
3 – An example “humidity” interpretation. Allowed values are:
HUM_NORMAL value 0
HUM_COMFORTABLE value 1
HUM_DRY value 2
HUM_WET value 3
1029 – An example barometric pressure ih hPa
0 - An example “weather prediction”. This is not implemented.
The Network Module Subscribes to the following topic when it connects to the Broker:
Topic: domoticz/out
When the Network Module connects to the Broker it will establish a "last will" message
of "offline" with the will topic “NetworkModule/<devicename>/availability”
When the Network Module connects to the Broker it will Publish to the following topics:
NetworkModule/<devicename>/availability Payload: online
For every IO Pin that is enabled:
domoticz/in Payload: Pin state as described above
domoticz/in Payload: DS18B20 values as described above
domoticz/in Payload: BME280 values as described above
No Publish occurs for a Disabled IO or absent sensors.
67
Network Statistics – Browser Only
Network Statistics are accessible only via the http command “http://IP:Port/68”. This
page is available in the Browser Only build (there is not enough memory in the MQTT
build to include it). To be honest I was reluctant to add this page as it has only been
minimally useful – but it is kind of cool so here it is. The information may be useful if
you are debugging your network or developing applications to interface to the Network
Module.
Note: Seeing large numbers of “Dropped packets at the IP layer” is not unusual. At least
not unusual in my network. I traced this to Smart Home devices that seem to attempt
some form of connection maintenance with everything on the network many times per
hour. And I have lots of Smart Home devices on my network … so … lots of connection
attempts. The Network Module drops these requests. The difference between “Dropped”
and “Received” is the number of packets actually destined for the Network Module.
68
Link Error Statistics
Link Error Statistics are accessible only via the http command “http://IP:Port/66”. The
statistics may be useful to you for determining if Full Duplex works better than Half
Duplex in your particular network configuration.
As noted in other parts of the manual the normal mode of operation is “Half Duplex”, and
you should not need to change that. However, during development it was noticed that the
Network Module works better with some Cisco 1 Gbit business class switches if the
Network Module and the Cisco switch are manually set to Full Duplex. So, this statistics
page can let you compare error statistics over several hours or days to help you decide
which configuration works better for you.
IMPORTANT: If you use “Full Duplex” the ENC28J60 specifications state that you must
manually set your switch to “Full Duplex”. This is because the ENC28J60 cannot auto-
negotiate Full/Half Duplex. If your switch does not allow you to manually set Full
Duplex you should probably just leave the Network Module at Half Duplex. Having said
that, experimentation suggests that some switches will work just fine regardless of the
Full/Half duplex setting in the Network Module. So … do your own experiments and use
the “/66” command to observe results. But in general I suggest you just leave the module
at its default “Half Duplex” mode.
If you enter the “/66” command you’ll get a display similar to this:
69
70
The Link Error Statistics page is “semi-hidden” and enabled only by the “/66” command
because it can be very confusing to the typical user. Most counters and registers are reset
by the “/67” command. If you are investigating a problem it is recommended that you
71
reset the counters and registers when you start your investigation so that you will have a
relative time point from which to judge the repetition rate of detected events.
The content of the Link Error Statistics page is likely to change as the code matures.
Seconds counter: Shows the number of seconds since boot. The Seconds counter is
approximate. The Network Module does not have a highly accurate clock, and there will
be an accumulating deviation from real time particularly if the counter is run for a long
period. But, it is close enough for this application.
Transmit counter: Shows the number of transmits from the ENC28J60. Mostly useful to
determine that the module is transmitting as expected when running tests.
Stack error: Not a counter, “1” will indicate detection of a stack overflow. That’s bad …
drop me a note if you see that happen. The URL /67 command will clear this indicator.
ENC28J60 revision: Chip revision. This should indicate “06”, which indicates chip B7.
See ENC28J60 documentation if you are curious.
EMCF Reset Counter: This counter should always be zero except in cases where an
unexpected power outage occurred. This is NOT a reliable power-loss detector – but a
power loss COULD cause an increment in the count. I haven’t really found it to be
useful. See STM8S documentation RM0016 STM8 Reference Manual.
SWIMF Reset Counter: This counter will increment each time the device is
programmed via the SWIM interface. This does not indicate an error. See STM8S
documentation RM0016 STM8 Reference Manual.
ILLOPF Reset Counter: This counter should always be zero. A count value indicates
that an illegal op code was encountered which is typically caused by an errant pointer.
This counter is useful in debug reports. See STM8S documentation RM0016 STM8
Reference Manual.
IWDGF Reset Counter: This counter should always be zero. A count value indicates
that an unexpected reset occurred, typically because of a hung processor. This could
indicate an errant pointer. This counter is useful in debug reports. See STM8S
documentation RM0016 STM8 Reference Manual.
72
WWDGF Reset Counter: This counter increments when the code commands a
hardware reboot. This does not indicate an error in this application as the Window
Watchdog is used by firmware to force a hardware reset. See STM8S documentation
RM0016 STM8 Reference Manual.
MQTT Response Timeout count: Count of response timeouts in the MQTT code. This
does not indicate an error if the count increments only once or twice a day in a very
active MQTT environment.
MQTT Not OK: Count of MQTT Not OK events in the MQTT code. This count may
indicate a firmware problem, but more typically indicates network problems. It should
never increment in a stable network environment.
The RXERIF and TXERIF counters were added to assist with development testing of
MQTT performance using a variety of switches. One critical finding is that the statistics
are not completely consistent, likely due to the number of variables affecting the values.
Still, they can be useful for relative measurements when determining if you might have
unusually high error rates on your network, and/or if you might need to experiment with
the Half / Full Duplex setting.
The RXERIF error indicates that the ENC28J60 experienced a receive buffer overflow
condition. This likely indicates extremely high network traffic. The impact is that packets
received at the Network Module may be dropped. It is not unusual to have a few of these
errors over a long period of time.
The TXERIF error indicates that a transmit abort has occurred. This error can occur as a
result of the following;
1) Excessive Ethernet packet collisions
2) Late collisions
3) Transmission was unable to occur because the medium was occupied for too long.
It is normal to see transmit or receive errors, just not "too many", which is somewhat
arbitrary. On a LAN with well behaving clients and good cabling you may only see one
error every few months. Communication over WiFi, WAN, or Internet will see much
higher error rates. And the error rate depends on how much traffic is occurring. Some
users may never see an error indication, which is great. Others may see lots of errors,
which may be 'normal' or may indicate a problem depending on their specific
environment.
73
These counters are included because they were useful during development to help
determine that Full Duplex worked much better than Half Duplex on the Cisco 1Gb
“business level” managed switches. With Half Duplex a TXERIF error was occurring
several times per day, accompanied by an MQTT disconnect (and automatic reconnect).
Once Full Duplex was enabled zero errors were seen for several weeks in the Cisco 1Gb
configuration.
On the other hand, TXERIF errors were seen when Full Duplex was used with some
unmanaged switches, and no errors when those same switches were used with Half
Duplex.
Your specific configuration and conditions may require some experimentation to get the
best result.
74
Functional Limitations
The code space and RAM in the processor on the Network Module is extremely limited,
so there are many functional limitations that you would not expect on a device without
these constraints. Some of the limitations to be aware of:
MQTT SSL/TSL:
MQTT does not support SSL/TSL. There is insufficient code space to implement this
functionality.
75
Overall Command rate:
Processing speed is very limited given the functions implemented, so I imagine it will
be easy to over-run the Network Module with state change requests. The code is
single threaded, so whatever function has been requested must be completed before
the next can be addressed. More testing needs to be done to determine if packets are
simply dropped (if too many received) or if there are cases where the module may
stop functioning. So far I haven’t seen a “stopped functioning” scenario. If that were
to occur a power cycle may be the only recovery option.
Configuration Errors:
There are very few “warnings” in the code to keep the user from creating bad
configurations. The most concerning is that if you enable “Retain” for the power
cycle output states AND you subject the device to rapid output state changes you run
the risk of wearing out the EEPROM. Other situations likely only cause the device to
lose contact with browsers or MQTT brokers (like mis-configuring IP addresses or
Port numbers).
76
77
Programming the Module
Assuming you have the Web_Relays_Con V2.0 HW-584 and all you want to do is apply
this firmware the following describes the process.
IMPORTANT NOTE: In the steps below you’ll turn off the Read Out
Protection bit on the Network Module. This will ERASE the program
currently in the device. It will only work again after you successfully
reprogram it. DO THIS AT YOUR OWN RISK.
Note that as of January 2021 I’ve gone to one release of the firmware that covers the
functionality of the four previous parallel releases.
Unfortunately there are a lot of steps the very first time you program your module. It is
much simpler on subsequent re-programs.
1) Prepare your Network Module: Install a 4 pin header on the board (see photo)
78
79
2) Buy the Programmer: Purchase a ST-Link V2 (see photo). If you are patient you can
get one from China in about a month for about $3.50. Or in less than a week from within
the US for about $6.00 (assuming you are in North America). Price estimates are as of
June 2020. Search on Google, Amazon, eBay, etc.
The ST-Link V2 modules come in several colors so pick the color you like.
80
Note: From user reports it appears there are two pinouts. It doesn’t matter which one you
buy as long as you attach it to the Network Module correctly. I’ll get back to that later but
here are photos of the two module types. Note the way the SWIM and GND pins are
swapped.
81
3) Obtain and Install Free Software: All of my development work was on the Windows
10 OS. If you are using Linux you will have a little more homework to do on your own,
but I don’t think there is much difference. For Windows you’ll need to download and
install the following files:
en.stsw-link009.zip
You'll find the above at https://www.st.com/en/development-tools/stsw-
link009.html
en.stvp-stm8.zip
You'll find the above at https://www.st.com/en/development-tools/stvp-stm8.html
You'll need to create an account at st.com to get the above software. It's free but
they want an email address to contact you. When you try to download the
software you’ll be asked for your account credentials and given the option to
create an account. By providing my email address I've gotten some invitations to
online programming seminars but otherwise no spam. Not much hassle.
1) ST Visual Develop
2) ST Visual Programmer (STVP)
I only used STVP even when developing the code. And if you are only
reprogramming your devices STVP is the only tool you’ll need.
82
4) Copy the Program: Now that you’ve installed the necessary software you need to
copy the STVP Project file and the Binary file from GitHub that will be programmed into
the Network Module.
NOTE: Beginning with the February 20, 2021 release you should obtain source code
and executable files from the “Releases” part of the GitHub web page (along the
right margin of the page).
C:/Users/Mike/Documents/COSMIC/FSE_Compilers/CXSTM8/NetworkModule
If you locate your copy of the project files in a similar Documents file location this
should minimize the tinkering you have to do. And should you decide to modify the
program you’ll already have an appropriate directory set up.
The STVP programmer only needs the “.sx” file to program the Network Module.
Depending on the functionality you want you’ll need to copy one or more of the
following files into the Documents directory you created above:
For the Ethernet Upgradeable MQTT Home Assistant plus limited Browser
Version:
NetworkModule-MQTT-Home-UPG.sx - Firmware binary file
NetworkModule-CodeUploader.sx - Uploader binary file
NetworkModule-Strings.sx - Strings file
83
For the Ethernet Upgradeable MQTT Domoticz w/ BME280 Version:
NetworkModule-Domo-BME280-UPG.sx - Firmware Binary file
NetworkModule-CodeUploader.sx - Uploader binary file
NetworkModule-Strings.sx - Strings file
You will find these files in the “Releases” section of the GitHub web page (along the
right margin of the page). The above are the only files you need to copy from the GitHub
project account if you only want to program your module and you are not jumping right
into code modifications.
The project file contains various settings that enable the ST-Link V2 to communicate
with your target board. They should already be set for you, but just in case the following
is how I had them set:
Under “Edit/Preferences”:
(Continued)
84
Under “Configure/Configure ST Visual Programmer”
NOTE: Some boards come with the STM8S105 device. If that is what you have (look at
the markings on the chip) be sure to select it in the “Device” column rather that the
STM8S005.
85
Setting up the Hardware to Allow Programming
First, attach the ST-Link V2 to your Network Module. Depending on which ST-Link V2
pinout you bought choose one of the following wiring diagrams:
86
Programming the Module the FIRST TIME
These steps apply to the Non-Upgradeable Firmware. If this is your first time
programming a module I recommend you follow these steps.
If you already have experience programming a module and want to use the upgradeable-
over-Ethernet firmware see the “Upgradeable Firmware” section for information on
installing and using the UPG firmware versions. Some of the following programming
steps will be used with the first installation of Non-Upgradeable firmware, so it is still
useful to understand how this is done.
Steps
1) Apply power to your Network Module. You should be using a 5V power supply
connected to the power pins on the Network Module.
4) Click on “File/Open” and select the .sx file you want to program into the Network
Module.
The .sx file will now load into the STVP programmer.
If you see “out of range” messages like the following this is NOT an error. It
would have been nice if the messages were more informative, but they are just
87
telling you that the indicated addresses are in non-programmable areas of the chip
during program load. The addresses shown are typically in EEPROM and RAM.
Once the program is successfully loaded into the STVP programmer you will see
a message like this (although the checksum will likely be different than what you
see here).
If you didn’t see the above and instead got some other error message indicating
failure:
a) Make sure the RST connection is in place between the ST-Link V2 and the
Network Module.
b) Make sure the power supply connected to the Network Module is providing
5V.
c) Make sure you have good connections from the ST-Link V2 to the Network
Module.
d) You might have to unplug the ST-Link V2 from the USB port on your PC and
plug it back in again.
e) You might have to stop the STVP program, unplug and replug the ST-Link
V2, then restart the STVP program.
f) If you have 16 relays connected to your Network Module I suggest
disconnecting them while reprogramming. If you have a very robust power
supply it may be possible to leave them connected. The Network Module will
be reset a couple of times during programming, and this may cause the relays
to simultaneously turn on and off. Whether this interferes with programming
depends on whether your power supply can handle the surge caused by the
relay coils.
Generally I haven’t had to do any of the above as I seldom saw an error. But
on occasion I saw an error message that the link was not working, and the
above tinkering got it working again.
88
5) Clear the ROP Bit:
If this is the first time you are programming your Network Module you will need
to clear the Read Out Protection (ROP) bit. If you don’t clear the ROP any
attempt to program the Network Module will give you a “This device is
protected” message. Once the ROP is cleared in a device you do not need to do it
again.
(Continued)
89
Make sure “Read Out Protection OFF” is selected in this drop down.
This will clear the ROP bit and allow you to reprogram the device.
90
6) Programming Firmware into the Module:
7) If programming an MQTT version of the firmware use this step, else go to Step 8.
Successfully programming the STM8S will result in a message that looks like
this:
91
8) If programming a Browser version of the firmware:
Successfully programming the STM8S will result in a message that looks like
this:
92
9) Connect to the Network
If you see the “File successfully loaded” message you are ready to attempt to
connect to the Network Module via the Ethernet connector.
a) Disconnect the RST wire between the ST-Link V2 and the Network
Module. You can also disconnect the other wires, or leave them connected
for the time being.
b) Connect the Ethernet cable. I suggest you do this the first time without
using your network. Make a direct Ethernet cable connection from the
Network Module to your PC and attempt to access it at 192.168.1.4:8080.
If the connection does not work check your IPV4 Ethernet settings on the
PC and set it to use IP address 192.168.1.100 (not DHCP). If you don’t
know how to do this Google it. Here’s a helpful link:
https://stevessmarthomeguide.com/setting-up-static-ip-address-windows-
10/
While the device is directly connected to your PC you can use your browser to
make address setting changes on the Network Module that are appropriate to your
network. Then you can connect the device to your network, return your PC to its
original Ethernet settings, and attempt to access the device.
93
Programming the Module the NEXT TIME
Once you’ve gone through all the steps above to program your module the first time it
becomes much easier the next time you need to re-program it. You do not need to
disconnect the module from your network.
(Note: If you are using “upgradeable” firmware see section “Upgradeable Firmware”
following this section).
.
1) Copy the Program: Download the .sx file you need from Github.
2) Connect the ST-Link V2 to the module and PC USB port. Start the STVP
program.
3) Click on “File/Open” and select the .sx file you want to program into the Network
Module.
94
6) If programming an MQTT-Domo version of the firmware use this step, else go to
Step 7.
Select “Program / Address Range” and use range 8000-FE7F
95
IMPORTANT: Re-Installing Non-UPG Versions via
SWIM
This is described in the programming steps above, but I’m repeating it here for emphasis.
MQTT-Home:
Select “Program / Current Tab”. MQTT-Home doesn’t store any data in the
upper address range of Flash. But be aware that if you previously used another
version of firmware (say Browser Only or MQTT-Domo) and now install MQTT-
Home, the GUI entered data stored in Flash will be over-written, and if you go
back to one of those other versions you will have to manually re-enter your
settings in the GUI.
MQTT-Domo:
Select “Program / Address Range” and use range 8000-FE7F. This will
preserve data you previously entered via the GUI.
Browser Only:
Select “Program / Address Range” and use range 8000-FEBF. This will
preserve data you previously entered via the GUI.
96
IMPORTANT: Re-Installing UPG Versions via
SWIM
You should never have to use the SWIM interface to install a UPG version of the code.
Instead you should use the Code Uploader method (see section “Upgradeable
Firmware”). However, should you have some special circumstance where you want to
use the SWIM interface I will provide some pointers here.
First of all, you need to be sure the correct Strings file has been installed in I2C Flash. I’ll
assume you know this was done via previous use of the Code Uploader method.
Next, you need to be aware that IDX, IO_NAME, and IO_TIMER values are stored in
upper Flash. For this reason if you use SWIM you must use the “Program/Address
Range” method to install most UPG versions of code. Using the Code Uploader method
automatically takes care of preventing any over-write of data stored in upper Flash.
97
Upgradeable Firmware
By adding an external I2C EEPROM you can take advantage of “Upgradeable” firmware
that enables you to update the firmware on the Network Module via Ethernet. You still
must program the Network Module at least one time via the SWIM interface, but
thereafter you can do all code upgrades via Ethernet. Both the MQTT and Browser Only
versions of the firmware are available in Upgradeable form.
Advantages:
- No need to physically access the Network Module to update the firmware.
Reprogramming is fairly fast, taking only about 1 minute.
- You can switch between upgradeable MQTT and Browser Only versions as
needed.
- More Flash space is made available for future features.
- An I2C interface is implemented to support the feature, enabling addition of other
I2C devices.
Disadvantages:
- IO pins 14 and 15 are required for use as an I2C interface
- You must add an external 1MBit (128Kbyte) I2C EEPROM.
98
The EEPROM needed is a 24AA1025 or 24LC1025 or
24FC1025 in DIP form.
You can also consider searching eBay or other sites for SO to 8 pin DIP converter boards.
I found these under the heading “SO/SOP/SOIC 8 to DIP8 Adapter Converter”.
99
Connecting the I2C EEPROM module to the
Network Module
The “VCC” pin on the EEPROM board must be attached to 3.3V on the Network
Module. 3.3V is accessible on the SWIM connector, or you can add a wire.
The “SCL” pin on the EEPROM board must be attached to IO 14 on the Network
Module.
The “SDA” pin on the EEPROM board must be attached to IO 15 on the Network
Module.
The “GND” pin on the EEPROM board must be attached to GND on the Network
Module.
IMPORTANT: The A2 jumper on the EEPROM board needs to be moved to the outer
position (tied to 3.3V) . The WP, A0, and A1 jumpers remain as shown in the photo
above (all tied to GND).
Due to the small amount of code space on the Network Module the “upgradeable
firmware process” works as follows:
a) A “Code Uploader” is copied from the added “I2C EEPROM” into the STM8
Flash, replacing the program that was in the Flash.
b) The Code Uploader is then used to install and start new firmware.
I left out some details in the above for simplification. So let me expand on the process.
The first question you may ask is “How did the Code Uploader get into the I2C
EEPROM”? Well, whenever the Code Uploader runs the first thing it does is copy itself
to a special region in the I2C EEPROM. So, the first time this process is ever used the
user must use the SWIM interface to install the Code Uploader in the Network Module
Flash, and then boot the Network Module. The Code Uploader copies itself to the I2C
EEPROM, and it is then available for future use.
Another detail: The “upgradeable” versions of the MQTT and Browser Only firmware
needed more space for runtime code, so the “strings” used to define the IOControl and
Configuration pages are also stored in the I2C EEPROM. The Code Uploader is used to
copy those strings to the I2C EEPROM.
100
So, knowing all this, here is the procedure the FIRST time you install the upgradeable
firmware:
a) Use the SWIM interface to install the Code Uploader in the Network Module.
b) Boot the Network Module to start the Code Uploader and access the Network
Module with your Browser
c) Use the Code Uploader GUI to select the “Strings” file and upload it.
d) Use the Code Uploader GUI to select the upgradeable version of the MQTT or
Browser Only runtime code and install it.
You are up and running.
Future upgrades
After initial install as described above here’s how you upgrade firmware in the future:
a) A release will always contain these files:
- Code Uploader (example name: NetworkModule-CodeUploader.sx)
- Strings file (example name: NetworkModule-Strings.sx)
- Runtime files: (example names: NetworkModule-MQTT-HA-UPG.sx and
NetworkModule-Browser-UPG.sx)
When using “upgradeable” code it is important to ONLY load the MQTT and
Browser Only >>upgradeable<< versions or you will break the upgrade loop and
have to go back to the “first time” steps.
b) Since you are upgrading you already have a “runtime” version installed. Enter the
URL command /72. This will install the Code Uploader from the I2C EEPROM.
c) Use the Code Uploader to install the new Code Uploader. Why do this? Often
there won’t be any change to the Code Uploader, but just to keep the process
“familiar” I will always release all files at the same time.
d) Use the Code Uploader to install the new Strings file. Again this file usually
doesn’t change, but installing it every time prevents procedural mistakes.
e) Use the Code Uploader to install the new Runtime file of your choice.
Note: If you are certain you already installed the new Code Uploader and String files
you can use the Code Uploader (via the /72 URL command) to install the upgradeable
MQTT and Browser versions as needed. This lets you move back and forth between
the code types for development work.
That’s pretty much it. The Code Upload process includes some pop-up screens to help
you with progress and timing of the steps. But if you are new to the Network Module it
may be best to just use the non-upgradeable code and the ST-Link V2 / SWIM interface
programming process until you get familiar.
101
Alternative Way to Force Defaults or
Downgrade Firmware
Normally all you have to do to return to “factory defaults” is press the Reset button on
the Network Module board for 5 seconds. However, during development there were a
couple of times where pressing the Reset button did not revive the Network Module to a
point that it would operate. Admittedly this was due to “in development” code errors and
may not be needed, but I’m providing it just in case.
This information is only useful if you are going to do your own development from this
code. I DO NOT RECOMMEND THIS METHOD UNLESS ALL ELSE HAS FAILED
TO REVIVE THE DEVICE.
1) When the Network Module is connected to the STLink (including the Reset wire) you
can access the EEPROM content with the “Data Memory” tab.
102
2a) After clicking on the Data Memory tab click on Read / Current tab to read the
EEPROM contents.
2b) You can change any value in the Data Memory one character at a time, then you can
write the result to the EEPROM with the Program / Current tab selection.
103
2c) To force the EEPROM to a state where firmware must start over again set the bytes
circled in blue to 0.
After committing to EEPROM reboot the device (power cycle or reconnect the reset
wire, wait 2 seconds, and disconnect the reset wire).
2) You can now disconnect the STLink and connect the Network Module to your
network. Once connected you should be able to use a browser to connect to the
Network Module via the factory default address 192.168.1.4:8080.
FIRMWARE DOWNGRADE
Once you’ve cleared the EEPROM content as shown above you should be able to load a
prior release of the firmware should you need to do so. If your intention is to downgrade
the firmware DO NOT reboot the device until you complete programming of the down
level firmware.
104
Alternative Way to Set Initial IP Address
A user commented that it was cumbersome to have to set up a laptop with a fixed IP
Address to program the Network Module with its first “network compatible address”.
Here’s an alternative that may be useful to you.
Let’s say your network already uses 192.168.1.4, so you can’t attach the device directly
to your network. Or perhaps your network uses some other variant of the
192.168.xxx.xxx address range, or even the 10.0.0.x address range. A way to work
around this without needing to set up a laptop or PC for the initial Ethernet connection to
the Network module as follows;
1) Assumption is that you successfully programmed the flash with the Network
Module code. Reboot the Network Module (usually just be releasing the reset
wire). Then reconnect the reset wire.
2) Using the STLink change the IP address in the EEPROM. Reboot the Network
Module.
3) Attach the Network Module to your network, access the Network Module with a
browser, and finish changing any settings via the Configuration menu.
105
2a) After clicking on the Data Memory tab click on Read / Current tab to read the
EEPROM contents.
2b) You can change any value in the Data Memory one character at a time, then you can
write the result to the EEPROM with the Program / Current tab selection.
106
2c) SO …. Which value do you want to change? You can change any of the values, but
typically you only need to change the IP Address of the module to get it to appear on
your network. Looking at the EEPROM map the below shows where the IP Address
is located.
After committing to EEPROM reboot the device (power cycle or reconnect the reset
wire, wait 2 seconds, and disconnect the reset wire).
5) You can now disconnect the STLink and connect the Network Module to your
network. Once connected you should be able to use a browser to connect to the
Network Module and make any further changes you need in the Configuration page.
107
IMPORTANT NOTES:
a) You should not use the “direct access to the EEPROM” method for anything other
than the minimum needed to gain access via a browser. Usually you only need to
change the Network Module IP Address (hostaddr). It’s too easy to make a
mistake … so don’t forget about the reset button if you mess it up.
b) If you press the reset button on the Network Module for at least 5 seconds it will
return to the hard-coded defaults over-writing the EEPROM content. You’ll have
to go through this process again to get back to a network compatible IP address.
c) If you change the “Magic Number” it will cause a return to factory defaults on
reboot.
108
Display Values vs Pin Logic Levels
This information may be useful to you for understanding how the values displayed in the
browser or contained in the MQTT fields correspond to output and input pin voltage
levels. The IO Name vs Pin Number as marked on board are for the default pin map.
109
110
Network Module Schematic
I traced out the parts of the Network Module that are pertinent to developing the new
software. I did not trace ALL connections as my intention was not to reverse engineer the
hardware design. My intention was only to fix the inadequate function of the software.
The schematic may be useful should you decide to improve on the software I’ve
provided. Some notes:
- There are a number of capacitors connecting power and ground. These are left out
of the schematic.
- Unused pins or pins that did not appear to be a necessary part of the functionality
were programmed to be inputs with pull-ups. These are shown as disconnected on
the schematic even if there was a component attached.
o There are some components connected to the Port B pins. I suspect the
original code used these to identify if the board was “8 port” or “16 port”.
- I didn’t trace out most of the pins on the ENC28J60, as I knew the design worked
and did not need to do any modifications. Some notes:
o The SPI interface on the ENC28J60 is not connected to the SPI interface
on the STM8S005. Ordinary port pins on the STM8S005 are used to “bit
bang” the SPI interface. Not very fast, but this is not an Ethernet
performance design so it works just fine.
o The –WOL pin does not appear to be connected.
o The CLKOUT pin is not connected.
- If you dig into the STM8S005 specification you’ll find that most pins that I show
simply as “port pins” can be defined for other uses. I didn’t include all that
information in the component drawing as it just creates confusion in this context.
The Network Module uses all the pins as “port pins”, so that is all I show.
- The STM8S005 operates on its internal 16MHz clock. It does not have an external
crystal or clock source.
111
112
Pinouts
Following are the pin definitions for the default IO Name vs connector pinout.
113
Selecting Alternative Pinouts
URL command /82 can be used to change the mapping of IO Pins as they appear in the
GUI to the physical connector pins. The following applies:
URL command /82 will have no effect if there is a syntax error.
The IOControl page is always displayed after command /82.
Alternative pinouts are ONLY available for the non-upgradeable builds. This is
because the alternative pinouts can interfere with proper operation of the I2C bus.
The DS18B20 functionality cannot be used with alternative pinouts. If DS18B20
is already enabled and you then select a Pinout Option other than Option 1,
DS18B20 will be disabled.
Developer note: UART functionality can only be used with Pinout Option 1. If
UART functionality is enabled then the Pinout will automatically be set to Option
1.
The primary purpose for an alternative pinout is for cases where the Network
Module HW-584 is used ONLY as a relay driver (no external sensors, no Ethernet
upgrade, no PCF8574 IO expansion, etc). The intent is to provide:
o Pinout Option 2 to drive 16 channel relay boards
o Pinout Option 3 to provide flexibility in driving 8 channel boards.
114
URL command /822 selects Pinout Option 2.
This map matches most common 16 Relay
boards.
115
URL command /824 selects Pinout Option 4.
This map shifts the pin rows of Pinout Option 2
to opposite sides of the connector. This is
useful when attaching 16 channel boards with
the Network Module flipped “upside down” vs
the orientation in Option 2.
116
Interfacing to Relay Modules
There are two things to be cautious of when attaching relay modules to the Network
Module: Power Distribution and Type of Relay Module.
Power Distribution
The first thing to consider is supplying power to the relay modules. The basic design of
the Network Module is intended to provide +5V power to the relay modules via the pin
header that also provides the relay control signals. This works well for just a few relays
(up to 3 or 4). This connection method is illustrated here:
If you attach more relays you need to make sure that there is sufficient current supplied
by your +5V power supply attached to the Network Module AND you need to make sure
the method used to send power to the relay modules is adequate. This is particularly
important if you are transferring power via a ribbon cable.
If you don’t think you can provide adequate power to the relay modules via the Network
Module relay header you can consider a couple of options:
1) Connect +5V power only at the Relays, and let the power/signal header send +5V
back to the Network module.
117
2) Use separate +5V power supplies on the Network Module and Relay Modules. If
you do this you’ll need to disconnect the +5V power connection between the
headers.
118
Type of Relay Module
The second consideration is the type of relay modules you attach. The SM8S processor
on the Network Module operates at 3V and its outputs are connected directly to the relay
control header. So, you need to avoid inadvertently causing +5V feedback from the relay
modules to the 3V output pins of the processor that exceed the processor specifications
(check the spec, but the short version is: Max 3.3V and/or limit to 4mA per pin, AND
limit to 20mA across all pins). The reason this is a concern is because the SM8S output
pins have overvoltage protection diodes that can provide a current path if a voltage higher
than 3.3V appears on the pin when it is not in an active pull-down state. To visualize this
here is a drawing illustrating the output pin:
Focus on the Protection Diode. There is also a protection diode to ground, but it is not a
concern in this discussion so I left it out. If any of the relay modules can provide a current
path from a higher voltage through the chip pin (when the pin is not pulling down) then
there is the potential for damage. Knowing this let’s look at typical relay module designs.
119
a) Opto-isolated relay boards: If you use opto-isolated relay boards there should
not be a concern as long as the relay boards are designed to operate at a voltage
no higher than 5V. The typical design of these relay modules looks like this:
Note that in fact this relay module can provide a current path from +5V, through
the photo emitter diode of the opto-isolator, through the visible LED, through the
1K resistor, then to the SM8S output pin via the “IN1” connection. But this will
still work and here is why:
- The difference in voltage from the 5V supply to the SM8S output pin is 5V –
3V. But about 0.7V is dropped across the photo emitter diode. Then another
0.7V is dropped across the LED. And about 0.3V is dropped across the
protection diode in the SM8S. The result is that there is only 5 – 3 – 0.7 - 0.7 -
0.3 = 0.3V potential across the 1K resistor. This will result in about 300 uA of
current flowing through the path. This is not enough current to damage the
SM8S and not enough current to cause the relay module to operate. So while
not ideal it works.
- If your relay module does not have the LED in the trigger signal path as
shown in the drawing above it might still work, but you’ll have to test it to
verify. The difference is that the 0.7 volt drop across the LED is missing from
the equation so about 1mA will flow into the output pin of the SM8S. That
won’t hurt the SM8S, but it might cause the opto-isolator to operate in turn
preventing the relay from releasing or causing the relay to release
intermittently.
120
b) Non-isolated relay module, Active HIGH trigger signal: Some relay modules
do not have opto-isolators. If they are of a design that has an active high trigger
signal then the typical design has a 1K ohm resistor feeding the base of a NPN
transistor. This type of relay module should operate just fine when connected
directly to the Network Module, although you’ll find that the logic seems reversed
and you may have to set or clear the “Invert” function in the Relay Control page
of the GUI.
The reason this module works with the Network Module is because it has no path
from +5V back to the SM8S output pin..
121
c) Non-isolated relay module, Active LOW trigger signal: This is another relay
module design that does not have opto-isolators. This design typically has an
active low trigger signal, and the typical design has a 1K ohm resistor feeding the
base of a PNP transistor. A typical relay module design looks like this:
This design is problematic in that the PNP transistor is connected to 5V, and when
the Network Module control signal goes to a high state a reverse current flow
(also known as an injected current flow) will travel from +5V through the PNP
transistor, through the 1K resistor, and into the SM8S output pin. Analyzing this
path:
- If the relay module you have places the LED in series with the PNP
transistor the module may work better due to the voltage drop across
the LED. However, there may still be enough current to cause the PNP
transistor and the relay to operate intermittently. All you can do is give
it a try.
122
16 Channel Relay Modules
123
With some circuit tracing the circuit design on each channel appears to be as follows:
While the particular board this user had utilized 24V relays it appears that the board also
comes in 5V and 12V relay versions. But the important thing to note is that the opto-
isolator input circuit does not include an LED like the boards discussed in the previous
section. So, less voltage is dropped between 5V and the STM8 output pin, and the current
path through the output pin of the STM8 (via its internal protection diode) continues to
conduct enough current to operate the opto-isolator even when the ouput pin is set to a
logic 1 condition. This is a major problem in that the opto-isolator will remain activated
regardless of the state of the output pin on the Network Module.
A possible solution to this problem is to add some additional resistance in series with the
input pin, or better is to add a diode in series with the input pin as shown here:
The diode replaces the voltage drop that the series LED provides on most other relay
module designs and prevents the current path through the STM8S pin protection diode
124
from keeping the PC817 in its active region (re-read (a) in the section above for more
information). I am not sure if all 16 channel relays boards are designed this way, but all
the ones found in a search on April 9 2021 appear to be as discussed here.
125
A Better Fix #1
Adding a diode in series with every input looks fine in theory but is very messy in
practice because you may need to add up to 16 diodes. Here’s a better idea: Put a single
diode in series with the +5V path from the relay module +5V to the resistors that power
all the opto-isolator devices. This requires a trace cut and insertion of the diode.
The relay board with 12V and 24V relays will have a down-converter power supply on
the board. This converts 12V or 24V to 5V for use by the PC817 devices and to
optionally provide power to an off-board controller that requires 5V. The circuit
components on boards with 12V and 24V relays (and some with 5V relays) look like this:
126
The circuit traces and component orientation on each board is a little different, but they
all appear to be based on this circuit schematic:
Note that the actual component values for Cin, L1, and Cout may be different from your
board. The way to tell the difference between Cin and Cout is that Cin will have a higher
voltage rating marked on the part, and Cin will be physically larger than Cout.
Some 16 Channel circuit boards with 5V relays do not have the down-converter
components.
Looking at online photos from various vendors I can see that there are differences in
component orientation and trace layout.
127
Before beginning modifications it is important to locate the 5V output side of L1 and
C2.
In the above photo the 5V connection to L1 is on the component pin closest to the
PC817 devices. But I’ve noticed 5V is on the component pin furthest from the
PC817 in at least one layout, and in another case L1 and C1 are in a completely
different location.
Do your best to look at the circuit traces to find which side of L1 is connected to
the positive side of C1. For reference, the negative side of C1 is marked like this:
So, find C1, find the positive side of C1, look at the board traces to find the
positive side of L1 (connected to the positive side of C1). Put a very small mark
on the bottom side of the board marking the positive side of both L1 and C1
(you’ll need this marking later).
128
Now for the modifications:
1) Cut the 5V trace that runs under the row of PC817 devices at the location in this
photo. In some layouts the trace runs under the other row of PC817 devices. If in
doubt scrape some of the coating off the trace and measure the ohms from the
trace to the 5V pins you identified on L1 or C2.
129
2) Cut the 5V trace to the 5V pins on the header as shown here. I haven’t identified
where the trace is because it is in a different place in each of several layouts I
looked at. The 5V trace will be wider than the signal traces. In some layouts the
trace runs up from the pins toward the PC817 devices, in another layout I see it
running out to the left of the pins, and in one layout it is on the bottom of the
board.
130
3) On the top side of the board attach a 4 inch small gauge wire to the 5V side of one
of the resistor packs or resistor groups that provide pull ups to pin 1 of the PC817
devices. The wire will carry a max of 60ma so 30 gauge wire is adequate. Some
boards have 4 surface mount resistors, some have a resistor pack. For example:
The wire can be attached to any one of the groups of resistors. Be careful not to
heat up the resistor(s) to the point that it falls off the board.
131
4) On the bottom of the board solder the anode end of a 1N914 (or similar) diode to
the side of L1 that you identified as the 5V output side. Keep the cathode lead
fairly short (between 1/4 and 1/2 inch).
5) Solder the loose end of the wire that you installed in step 3 to the cathode end of
the diode. Shorten the anode lead of the diode to about 1/4 inch. Shorten the wire
to minimize excess. Once soldered use glue to secure the wire and diode to the
board surface. Do not use RTV as it may be conductive. Find a non-conductive
glue like airplane cement or similar. Make sure the bare connections on the diode
are not able to make contact with any conductor on the board.
6) On the bottom of the board attach a wire from one of the 5V pins on the header to
the C1 pin that you previously determined to be the 5V output. 30 gauge wire is
adequate if you are only powering a Network Module. If you are powering greater
loads consider a slightly larger wire. If you are not using the 5V pin on the header
you do not need to add this wire. Here is the current rating of various gauge wire:
AWG #30 0.5A
AWG #28 0.7A
AWT #26 1.0A
A smaller wire will be easier for you to attach to the board.
132
A Better Fix #2
Another user took the approach of replacing the LM2576 5V regulator with a 3.3 volt
version. This requires some careful surface mount soldering, but the leads are relatively
large so it is doable if you are careful.
This appears to work because the DC- (which is GND) and DC+ are fed directly to the
relays. If you look at the LM2596 spec that input voltage needs to be at least 7V. While
the relays are “5V relays” operating them at 7V will work OK. The LM2596 is then just
used to provide 5V to the front end interface parts, so replacing it with a 3.3V regulator
works fine.
VERY IMPORTANT: This method will put 3.3V on the “5V” pins of the Relay Module
header.
133
You need to make sure the 3.3V pins (marked 5V) on this header DO NOT get connected
to the 5V pins on the Network Module header.
a) If you are using ribbon cable connections do not connect these pins on the
headers.
b) If you are directly connecting the Network Module to the Relay Module with
the headers you will need to:
i. Cut the trace on the Relay Module that goes to the pins marked 5V on
the header
ii. OR cut the pins marked 5V off of the header on the Relay Module
iii. OR use some other method to make sure you don’t connect these pins
between the Relay Module and the Network Module.
134
How I Modified a Board
I bought a 16 channel relay board with 5V relays. Here is what this one looked like on
arrival:
Notice that even though most 5V boards arrive without the 5V power circuit components
this one had them:
135
On tracing out the circuit I found:
1) The DC- is connected to GND.
2) DC+ provides power directly to the relays and is also connected to the ULN2803
“common” pins (pin 11 on each of the two ULN2803 devices).
3) DC+ is also the input power to the 5V regulator. The output of the 5V regulator
provides power to to pin 4 of each of the PC317 devices, the pull-up resistor
packs connected to pin1 of each of the PC317 devices, and the 5V pins on the
dual-row edge connector.
136
2) On removal of the parts in step the 5V connections to the front end logic were
separated from the DC+ input power, and the ULN2903 and Relay power connections
remained connected to DC+. So, no wires needed to be added to power the relays, and no
traces needed to be cut to isolate the PC317 devices.
3) Added a diode to feed power from the DC+ power to the PC317 devices. I was able to
use the + side of the input capacitor lead holes (since the capacitor was removed) for the
anode end of the diode, and was able to connect to the PC317 power inputs by utilizing
the lead hole made vacant by removal of the inductor.
The diode provides a current path from DC+ to the PC317 pull-up resistors and output
logic. The diode adds a 0.7V drop to prevent the protection diodes within the STM8
processor from causing the relays to be active when the trigger signal is high.
137
4) Clipped the 5V pins on the dual-row edge connector so that the 5V pins on the
Network Module HW-584 do not connect with the diode-dropped voltage on the relay
board.
Now the Network Module HW-584 can be directly connected to the 16 Channel relay
board. You must make sure the Network Module HW-584 is oriented so that the Ground
pins match up, then you can select the appropriate “Pinout Option” in firmware to make
IO1 match relay 1, IO2 match relay 2, and so on (see section “Selecting Alternative
Pinouts”). Unfortunately if you install a female header on the Network Module and try to
connect it to a 16 Relay board you’ll find that the power connector on the Network
138
Module HW-584 and the power connector on the Relay Board interfere with each other.
Options:
a) You can remove the power connector on one of the boards and reinstall it
on the other side of the board.
b) Or you can remove the IO connector on the Relay Board and reinstall it on
the other side of the board. Removing the IO connector is difficult and I
don’t recommend that solution.
c) Or you can use a ribbon connector to attach the Network Module HW-584
board to the Relay board.
I decided to use the “ribbon connector” method and it looks like this when the Network
Module has had male pins exiting the bottom of the board:
139
A shorter ribbon with both IDC connectors on the same side of the ribbon:
Same short ribbon but this Network Module has the male pins on the top.
140
To make the IO numbering in the Network Module HW-584 GUI match the relay
numbering on this particular 16 Channel board I used Pinout Option 4.
141
A Possible “Directly Compatible” 16 Channel Relay
Board
Contributor P-O Yiniemi (peoyli) reports that he found a 16 Channel Relay board that has
IO Control pins that match the voltage requirements of the Network Module HW-548
board. This is documented in Issue #202 “Documentation: about 16 channel relay
modules”. The information is repeated here:
The 16 channel relay module that works directly is called HW-523 (-A for 12V,
and -B for 5V relays). Also printed as identification on some of the boards I found
online is "HP20014116A". Another identification string is between the relay rows
which says "16 Relay Module Low Level Trigger". There are probably more
variants of these, but the important thing to look for is the power LED near +5V
on the 20p header. If it's there, there is a high probability that the board works
directly with the HW-584 controller.
One of the many sellers of this board design (cheap board, but shipping costs adds
up quick for each board added)
https://www.aliexpress.com/item/1005004962029461.html
After my own searches for the HW-523B I was concerned that I would not get the right
board when ordered. The paragraph above from @peoyli seems to be the best search
information, but some vendors are showing a very different board design using the same
"HW-523B" name.
The primary advantage of this board is that the control pin voltages and current paths are
compatible with the 3.3V logic of the Network Module HW-548 board. I haven't bought
one so I haven't reverse engineered the circuit design - but @peoyli reports that it works.
142
A couple of photos of a Network Module attached to the board.
143
Input Pin Considerations
If you configure the Network Module to include digital inputs you’ll need to be careful
about the voltage you put on the input pin. The pins are directly connected to the SM8S
processor. The processor operates at 3V, so you’ll need to limit the high level voltage
applied to the pin to 3V, or limit the current to no more than 1 mA.
Each input pin has a weak pull-up applied internal to the SM8S processor. The pull-up
has a typical resistance equivalent of 60Kohm, but can range from 30Kohm to 80Kohm.
Some recommendations:
1) If you are using 3V logic to drive the input pin you should be able to directly
connect it.
2) If your driver circuitry might place more than 3V on the input pin you can do one
of the following:
a) Use open collector devices or level translators to prevent putting more than
3V on the input pin.
b) Use relay contacts to ground the input pin, relying on the SM8S pull-up to
take the pin high. This might not be adequate if the wiring to the input pin is
long or is subject to electrical interference.
c) Put a 1Kohm resistor between the driver logic and the input pin, but be sure
the driver cannot exceed 5V. This isn’t ideal, but should limit any current
driven into the SM8S to an acceptable level and still achieve adequate logic
levels at the SM8S input.
PCF8574 Inputs
If a PCF8574 IO Expander is being used any pin that is to be used as an Input should
have a series resistor added to the pin. This is to protect the PCF8574 (and perhaps the
external driver logic) from momentary periods when the PCF8574 input pin may be
driven as an output.
144
PCF8574 Outputs
At power on the PCF8574 has all pins set to a weak pullup for about 5 seconds until the
device is initialized by firmware over the I2C bus.
This can be a problem in applications that need the outputs to be low at power on. Simply
applying a pull-down resistor does not help as the PCF8574 only uses a weak pullup
internally for a logic 1 output and therefore cannot overdrive a pull-down resistor. A
potential solution is to add inverting drivers to those pins that will be used as outputs on
the PCF8574.
The PCF8574 specification describes this behavior as "by design", so there is not much
that can be done about it without external logic.
145
Hardware Design to Maintain Relay States
Through a Power Loss or Reboot
A user wanted to know how to prevent relays from changing state during a power loss on
the Network Module. This question is very dependent on the whether the relays remain
powered up during the power loss on the Network Module, AND it is dependent on
whether the control input to the relay is active low or active high. So let’s explore why
things happen and what you can do about it.
First of all, be aware that when the Network Module loses power its outputs go to a low
level signal. I’m sure this makes sense to you: no power, no signal output. But there is the
additional consideration that the overvoltage protection on the device pins (effectively a
diode to VCC) will look like a pull-down when VCC on the STM8S processor goes to
zero. Also be aware that when the SM8S processor powers up it defaults all IO pins to a
“floating input” state. This is a function of the chip design, so it can’t be changed.
Regardless of what you define as ON or OFF, this discussion here is purely from the
perspective of the output signal levels on the Network Module and the input type of the
relay being driven.
Scenario 1:
a) Assume relays remain powered up while the Network Module is powered down.
b) Relays are active high inputs (a high level signal activates the relay).
Scenario 2:
b) Assume relays remain powered up while the Network Module is powered down.
c) Relays are active low inputs (a low level signal activates the relay).
146
- When the Network Module loses power and then reboots any relay that is inactive
will go to an active state because the Network Module outputs go to a low state
during power loss, then the relay will return to an inactive state if Retain was
enabled in Configuration.
- When the Network Module loses power and then reboots any relay that is active
will remain in an active state if Retain was enabled in Configuration.
- Note: If the relays also lose power they will of course go inactive during power
loss.
So let’s say you don’t like the above scenarios and you want the relays to stay just the
way you set them through a power loss, regardless of whether they were active or not.
Well, this can only be done with hardware external to the Network Module. Here are
some suggested solutions:
Option A:
- Assume the relays remain powered up while only the Network Module loses
power.
- The relays can be either active low or active high inputs.
Since we know the Network Module outputs will go low during power loss we need to
build hardware that will maintain the state of the relay control input during the outage.
An example circuit is shown here for 16 Relays:
147
In the above circuit the Power Supervision device will detect when power is falling on
the Network Module and will cause the D-latch devices to capture the output states of the
Network Module. As long as power is maintained on the Relays and the D-latches the
relays will maintain their state.
Once power returns on the Network Module the Power Supervision device will continue
to keep the D-latch devices in a hold state until the STM8 processor is operating. If
additional time is needed a capacitor can be added to the MR- input.
The latching circuit described above is placed between the Network Module and the
Relay Module as shown here:
148
The downside to the above: The devices in the Latching Circuit may not all be available
in DIP form – some may be surface mount. This implies that you may have to design a
circuit board for this solution. That is not as onerous as you might think. There are cheap
manufacturing sources in China that will make up to 10 circuit boards for almost nothing
(less than $10 USD). But you must design the board and generate gerber files.
Option B:
- Use “Latching Relays”
This option almost sounds like nirvana until you look at the details.
First let me caution you about “bi-stable self latching” relays that you may find on eBay.
Those are meant to be provided with a pulse and they will switch and hold their state.
BUT, you can’t tell what state they are in remotely, so not very useful for remote
applications. It might be possible to tap into their circuitry and find a sense point that
could be fed back to one of the Network Module sense inputs. But remember these bi-
stable relays are not actual latching relays as they require that power be maintained to the
relay for it to retain it’s state (just like Option A above)..
So, what about REAL latching relays? They will maintain their state even if ALL power
is lost to the Network Module and the Relay Module. These relays are sometimes called
“Impulse” relays because they require a pulse on a Set pin to put them in one state, and a
pulse on a Reset pin to go to the other state. An example of this type of relay is the
G5RL-K1-E-DC5 for low current applications (Google it).
Since the Network module only has a single state output a circuit is required to convert
that signal to the pulses needed by the latching relays. And a driver is needed to supply
149
the necessary pulse current to the relays. AND the circuit still needs to detect power loss
to prevent inadvertent pulse generation when power is lost and restored.
150
The pulse circuit looks like this:
The above needs to be repeated for each relay (except the Power Supervision can be
common).
As in Option A a capacitor can be applied to the MR- input of the Power Supervision if a
longer delay time is needed for the STM8 to stabilize.
Suggested part number for the Schmitt NAND gate is the SN74HC7001 and for the
Inverter is the SN74LVC1G04.
After considering the Pulse Circuit, Power Supervision, and Current Drivers once again
the circuit is complicated enough to require a circuit board.
151
Option C:
You may want to consider using a UPS to prevent power loss. That will solve most of the
problems discussed here. If power loss is nearly non-existent, then the only concern is
brief relay chatter in event of a reboot, which should also be nearly non-existent once the
Network Module is set up.
IMPORTANT: I have not implemented any of the above power loss circuits, so
there may be errors in what I’ve described. If you plan to go this route analyze the
design carefully.
Summary:
In the end you need to consider carefully if fully retaining the relay states all the way
through a power loss is really necessary. You can use the Retain setting in the Network
Module to be sure the relays return to their pre-power loss state, but they may still
“chatter” once or twice during reboot or power loss and recovery.
152
Adding DS18B20 Temperature Sensors
Code was added to allow you to use IO 16 (pin 16) for DS18B20 Temperature Sensors.
You can attach up to 5 DS18B20 sensors to this pin.
In the Features section of the Configuration page you’ll see a checkbox for DS18B20.
If you check this box IO 16 will show as “Disabled”, and in fact the pin IS disabled for
use as an Input/Output pin. But you can now attach up to 5 DS18B20 temperature sensors
to the pin and have the temperature seen at these sensors displayed in the IOControl page.
If you also check MQTT the temperature is Published on MQTT. And, if you also check
HA Auto the temperature sensor will be Auto Discovered in Home Assistant.
153
Diagram for attaching multiple sensors:
On power up the temperature display may show a “filler” value of ------°C degrees for
each sensor. Likewise, if one of the 5 sensors is missing it will show the filler value. As
soon as communication with the sensor is established the value will be as reported by the
sensor. If the sensor fails or becomes disconnected after initial communication is
established the reported temperature will be -000.1°C until the Network Module is
rebooted, at which time the sensor will no longer appear in the IOControl page. Once the
sensor is re-connected the temperature reported will require 1 to 2 minutes for the
DS18B20 to begin reporting correct values. In the meantime the reported values may be
indeterminate. If the sensor is replaced with a new sensor the Network must be rebooted
to find the new sensor.
The sensors appear in the display in the order of the unique 48-bit Serial Number
contained within each DS18B20. All 48 bits are displayed as the Temperature sensor ID
(6 bytes shown as 12 hex encoded characters). But there is a little bit of a catch: The
serial numbers are read from the devices LSbit first, so the device discovery and sorting
algorithm is based on LSbit to MSbit, one bit at a time. However, the display of the
values is shown MSByte on the left to LSByte on the right. So, they might not appear to
be in some sort of ascending order, but in fact they are.
Since the serial numbers are sorted as described above they will always maintain their
order in the Browser display. Thus if a sensor fails and is replaced the new sensor might
be inserted in the list at any point (again, based on the LSbit to MSbit sorting). But a
given sensor’s ID will always remain the same.
154
Note that Home Assistant sorts the sensors in ascending order based on the MSByte to
LSByte order. So, Home Assistant will display the sensor ID’s in a different order than
the Browser.
155
Adding a BME280 Sensor
Code was added to allow you to attach a single BME280 Temperature / Pressure /
Humidity Sensor. The sensor is accessed via the I2C connections on pins 14 (SCL) and
15 (SDA), and can only be used with a special BME280 build along with an I2C
EEPROM. Sensor measurements are reported every 300 seconds (5 min) since this sensor
is best suited for weather monitoring and a shorter interval should not be required.
In the Features section of the Configuration page you’ll see a checkbox for BME280.
If you check the BME280 box AND you have installed the special BME280 build you
can attach a single BME280 to the I2C bus (pins 14 and 15) along with an I2C EEPROM
(see section “Upgradeable Firmware), and the sensor Temperature, Pressure, and
Humidity values will be displayed in the IOControl page. If you also check the MQTT
checkbox the sensor values are Published on MQTT. And, if you also check the HA Auto
checkbox the sensors will be Auto Discovered in Home Assistant.
Altitude: The sensor needs to know your Altitude to properly adjust barometric pressure.
This is done using URL command 81 (see section “REST Commands”).
Restriction: The DS18B20 sensor and BME280 sensor cannot be enabled at the same
time. If you are running the BME280 build and check the DS18B20 box it will be
changed back to unchecked on Save. In any build if you check both the DS18B20 and
BME280 boxes BOTH will be changed to unchecked on Save. You should ONLY check
the BME280 box when the BME280 build is used.
156
How do you tell the difference between a BME280 and and BMP280?
This is a BMP280 module. Notice the sensor (in the metal can) is rectangular in shape
with the vent hole near a corner.
This is a BME280 module (the one you want!). Notice the sensor is square in shape with
the vent hole near the center of one edge.
157
This is a closeup of the sensor types:
The boards that the sensors are mounted on may have 4-pin or 6-pin edge connectors.
Typically the two additional pins add SPI interface capability. In the Network Module
application only the I2C interface is used, so only the VCC (or VIN), GND, SCL and
SDA pins are needed. So either the 6 pin or 4 pin board will work.
The modules have on-board pull-up resistors for the SCL and SDA pins, so no external
pullups are required.
Notes on barometric pressure: The barometric pressure display is in hPa, which is the
same as mbar. If you are used to seeing pressure in inHg there are online converters you
can use.
158
Browser Issues
This section addresses browser issues as they relate to functionality of the Network
Module code.
Remember that many Network Module URL commands automatically cause actions to
occur in the Network Module. For instance, using the /55 or /56 command turns on or
turns off all of the IO pins. So if you ever used those commands, and you start entering
command /50, as soon as you type /5 Chrome may pre-fetch /55 and/or /56, causing
relays outputs to switch state. This is a bad problem.
The only workaround appears to be to prevent Chrome from performing pre-fetch. Here
is the way to disable this function in Chrome as of July 2023:
159
160
161
Developers: Setting Up a Development
Environment
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code. You don’t need to do this if you are going to
use the binaries (.stp and .sx files) already provided.
If you want to change the code for your own use I assume you have some experience
with coding and the tools typically involved. I used the tools described in the previous
sections for actual programming of the device, and used the Cosmic tools for the
development environment. To duplicate this you'll want the following:
1) Download and install the Cosmic Compiler: Use the one that is specifically for
the STM8 devices. Start at this website
https://www.st.com/en/development-tools/cxstm8.html#product-details
Click on Product Details and follow the link to the "partner website". From there
you can download the compiler. The compiler is free. They will send you a 1-year
license, but I think you can renew over and over. Note that the license is specific
to the machine you install it on.
As an FYI, even though my PC is x64, the tools installed in this directory:
C:/Program Files (x86)/COSMIC/FSE_Compilers/
3) Copy the Program: With the above installed the next step is to copy the entire
project from GitHub into your Documents directory. On my Windows 10 machine
the project was located in the following directory:
C:/Users/Mike/Documents/COSMIC/FSE_Compilers/CXSTM8/NetworkModule
Of course you will likely have a different user ID.
Start the Cosmic tools by double clicking on the NetworkModule.prjsm8 file. You should
be on your way.
162
A note about my coding style: My coding is not particularly esoteric or convoluted. I try
to keep it simple to read and understand even if that is less efficient. And I put a lot of
comments in, particularly if I had to do things to make the code work that didn’t fully
make sense to me. Sometimes that stuff happens and my intention is to come back and
look at it again later. So, feel free to modify and “do it your way”. I’m not proud as long
as it works.
163
Developers: CXSTM8 Compiler Issues
For the STM8S device the compiler used within the IdeaSTM8 development environment
is the CXSTM8 compiler. In general it has worked very well for this application, but
there are a few problems.
a) Memory leak: There must be a memory leak within the IdeaSTM8 application.
I’ve noticed that when making a lot of edits over numerous project files two
problems occur:
- When a “Build / Rebuild All” is performed and several files are open in
the editor tabs it is common for the editor to be displaying one file, but any
keyboard inputs are being applied to another file. The only workaround
seems to be to click on several of the tabs and then find your way back to
the tab for the file you want to edit.
- If you keep IdeaSTM8 open a very long time eventually menus will start
appearing with no content. Even the “File” menu is blank so you can’t
save your work. Workarounds: a) Press Ctrl-S to save your work, then
click the “X” in the upper right to close IdeaSTM8, then reopen
IdeaSTM8, OR b) Sometimes you can close some of the file tabs and the
File menu will start working, then you can Save, but you’ll still need to
Exit and restart IdeaSTM8.
b) Silent Compile Fail: Care needs to be taken in writing EEPROM on the processor
chip. The compiler can fail without producing an error message … it just doesn’t
complete the compile, and you might think it did.
Example:
stored_config is located in EEPROM.
pending_config and config are RAM variables.
The write to EEPROM needs to be in a simple “=” code line. If the first case is
used the compiler will stop without producing an error, so it becomes very hard to
find the errant code.
164
c) Watch out for recast problems.
Example:
int32_t a;
uint16_t b;
int16_t c;
The following statement fails with varous messages about missing files, but
nothing to indicate which c code line is at fault. The fail occurs even if it is known
that the value in "b" does not set the msb of the variable (ie, even if the unsigned
value is 10):
a = (int32_t)b;
The problem in the above seems to be directly recasting a 16 bit unsigned to a 32
bit signed.
165
Developers: Location of EEPROM Variables
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code.
You can view the contents of the EEPROM with the STVP programmer by selecting the
“Data Memory” tab and using the “Read / Current Tab” function. The displayed
information has the following definitions.
Note that the data in some fields is “left to right”, a more human readable direction. For
instance the device_name field. Some fields are “right to left”, for instance the hostaddr
field.
See the Comments in the main.c file where @eeprom declarations are described.
166
167
Developers: Debug Bytes
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code.
The code contains compile options for implementing various debug modes. This section
describes the debug modes and how debug information is captured in EEPROM.
When code is compiled with any DEBUG_SUPPORT option debug data is stored
in RAM locations named debug[].
The data in the debug[] RAM locations is copied to EEPROM when the function
update_debug_storage1() is called, or when a function requires specific debug[]
bytes to be stored in EEPROM. In some functions any change in a specific
debug[] byte will cause it to be stored in EEPROM.
Note that ANY time a debug[] byte is stored in EEPROM it is first compared to the byte
already stored in EEPROM, and the EEPROM write only occurs if the bytes do not
compare. This is to prevent excessive writes to EEPROM. Example code:
for (i = 0; i < NUM_DEBUG_BYTES; i++) {
if (stored_debug[i] != debug[i]) stored_debug[i] = debug[i];
}
IMPORTANT: This “compare before write to EEPROM” concept should be used any
time a write to EEPROM of any kind is to occur. This will help prevent excessive wear
on the EEPROM, particularly when a coding error is made that might cause a frequent
write to EEPROM.
ALSO IMPORTANT: The EEPROM must be unlocked prior to any write (see function
unlock_eeprom() ). After the write the EEPROM should be locked again (see function
lock_eeprom() ). This helps prevent coding errors from inadverently writing EEPROM.
168
Historical comment: A larger set of routines existed at one point to enable the capture of
numerous “debug bytes” and copy them to the EEPROM as needed. At the time this was
the only method for capturing internal operating information and making it available to
the developer. Since then the UART mechanism was implemented and provided a much
more useful display capability for debug. As such some debris has been left behind
associated with “debug bytes”. Now that the UART is available as a tool there are only
10 useful debug bytes left behind, and their capture is always enabled.
!!!!! Leave DEBUG_SUPPORT 11 enabled for Production Code. While this seems
inconsistent with the normal use of “debug”, DEBUG_SUPPORT 11 enables the
“Link Error Stats” web page. The Link Error Stats web page can be very useful to
regular users that may need to diagnose whether Full Duplex is needed with their
network switch(es).
169
DEBUG_SUPPORT table
Bits
7 6 5 4 3 2 1 0 Dec Function
170
171
Developers: Configuration Debug and
pin_control Bytes
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code.
Some of the Configuration pages contain a debug feature useful for development. If you
go to the Configuration page, add #d to the URL, then click Refresh a column of numbers
will appear to the right of the settings as illustrated here:
These values are the decimal equivalents of the content of the pin_control bytes in the
code. The pin_control bytes are defined as shown here:
172
173
Developers: Proto-Sockets
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code.
Most developers that build web server code are familiar with Windows or Linux systems
which provide a “socket” interface. The “socket” basically maintains all pointers and
parameters associated with a given network connection.
In a “bare metal” application like the Network Module there is no operating system
providing the socket interface, so a bare-bones implementation is used and is typically
called a “proto-socket” interface. The interface maintains only the very basic and
essential pointers and parameters associated with network connections in order to
minimize memory associated with the connections.
I didn’t write the original code used for proto sockets in this application, but I did modify
it as needed. Here are some notes I took along the way in case they are useful to other
developers and for future debug efforts.
struct uip_conn is a single structure identifying all the paramters of a single connection,
and each uip_conn is connected by a union to a struct tHttpD, thus defining a "Proto-
Socket". A Proto-Socket is really just the set of parameters that define the variables,
pointers, and status of a given connection.
uip_conns[] is an array of the uip_conn structures, and the number of elements in the
uip_conns[] array is defined by UIP_CONNS in the uipopt.h file. The uip_conns[] array
of structures is statically allocated in the uip.c file with this statement:
struct uip_conn uip_conns[UIP_CONNS];
So, the structures are "pre-existing" and remain in RAM at all times. Note that anything
added to the structure will occupy memory on a per uip_conn basis, so if I add say 10
bytes to the structure is will be multiplied by the UIP_CONNS value. UIP_CONNS is
defined as 4 in this application, so adding 10 bytes to the structure would add 40 bytes of
memory consumption.
Where is the content of the structure initialized? In uip.c, where the only real
initialization is to set each connection to UIP_CLOSED as follows:
void uip_init(void)
{
for (c = 0; c < UIP_LISTENPORTS; ++c) uip_listenports[c] = 0;
for (c = 0; c < UIP_CONNS; ++c) uip_conns[c].tcpstateflags = UIP_CLOSED;
/* IPv4 initialization. */
}
174
A connection is set up when a packet arrives over ethernet with the appropriate MAC, IP,
and Port. If the Port matches one of the "listening ports" then the uip_process() code finds
its way to the "found_listen:" code, an unused connection is located in the connection
table, and the necessary connection parameters are initialized in one of the uip_conn
structures contained in the uip_conns[] array.
For each connection I maintain all necessary parameters in the uip_conn structures with
the exception of variables used in parsing POSTs. Of these variables the parse_tail[] array
is the largest. parse_tail[] is used when parsing POST data from a Browser. parse_tail[] is
very large and must be maintained across packet fragments in a POST. parse_tail[] is too
large have a separate one for each connection ... so it is a usage requirement that the user
must never POST from more than one Browser at a time. If they do the parse_tail[] will
be corrupted and results will be indeterminate.
The other variables used in POST parsing are the “Pending_” variables. These provide
temporary storage of user entered data POST parsing completes. There are many of these
and there is not enough memory for them to be maintained in the uip_conn structures, so
again it is a usage requirement that the user never POST from more than one Browser at a
time.
In similar fashion the Code Uploader must only be run from one Browser as it is a
"POST" mechanism.
175
Developers: #pragma, Sections, Segments
and the .lkf File
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code.
I’ve included this section mostly so I don’t forget how all this works.
There are several places where I’ve had to define additional “segments” where code is
segregated for specific purposes. Those areas are:
a) Stack Overflow detection
b) Flash Update code
c) Copy RAM to Flash code
In general the reason that these segments must be defined in this application is to 1)
enable the linker to provide warnings if segment sizes interfere with each other, 2)
specify the location of specific code so that Flash updates will work without overwriting
code that is being used, 3) enable special functionality to copy RAM content to Flash.
Defining and using code segments requires that you be able to edit the .lkf file. To enable
editing the Linker .lkf file in IdeaSTM8 you must first edit the .prjsm8 file. Make sure the
following line is in the .prjsm8 file:
LinkFileAutomatic=NO
When you first install IdeaSTM8 the default is for the program to auto generate the .lkf
file each time a build is done. This is useful because it creates all the linker commands
you typically need. However, when you reach the point that you need to make your own
changes to the .lkf file (such as described below) edit access is disabled until the
LinkFileAutomatic line is modified to “NO”.
Stack Overflow Detection is a part of the released code. In the main.c file the following
code is used to declare two constants at the top of the RAM area. Regular variable
176
assignments start at memory address 0x0000 and grow upwards to 0x5ff. Stack starts at
0x7ff and grows downward to 0x0600. Two constants are placed at 0x5fe and 0x5ff and
are monitored to make sure they never change. If they do change it implies that the Stack
has grown into the variable storage RAM, or that a "wild pointer" may have caused
writes to RAM to exceed the space allocated to RAM.
One way to locate RAM variables in a specific location is to simply use Absolute
Addressing. For example:
uint8_t stack_limit1 @0x05fe;
uint8_t stack_limit2 @0x05ff;
Those two declarations would place the variables at addresses 0x05fe and 0x05ff.
However, using that method does not let the compiler/linker validate whether its own
variable placements also utilize those two memory addresses. So, using the #pragma and
linker directives is the safer method to use.
The pragma code creates the two variables in a special section named ".iconst". In the
main.c file a pragma section is created that looks like this:
#pragma section @near [iconst]
uint8_t stack_limit1;
uint8_t stack_limit2;
#pragma section @near []
The linker needs to be told where to place this section in memory. The following
directive needs to be placed in the .lkf file. This directive will place the two stack limit
variables at 0x5fe and 0x5ff. In the .lkf file specify the location of the pragma section like
this:
+seg .iconst -b 0x5fe -n .iconst
Now the linker will be able to warn you if allocation of variables in RAM has enough
space.
The “upgradeable” versions of the code provide the ability to upload new firmware to the
Network Module and write it to the Flash on the STM8 device. This requires adding
hardware in the form of an I2C EEPROM. Assuming that is done, the following process
is followed by the firmware:
c) New firmware is received from the Browser and written to the I2C EEPROM.
d) The new firmware in the I2C EEPROM is copied to Flash.
In order for a) and b) to work the I2C driver must remain functional throughout the write
to Flash. This requires that the I2C driver be located in a part of Flash that will remain
untouched until the final parts of the Flash update.
177
Further, because the I2C driver itself might be updated there needs to be a means of over-
writing that driver with code running from some location other than Flash. In this
application that code (the copy_ram_to_flash() function) will run from RAM.
And one last requirement: To make the Flash writes occur as fast as possible they must
occur as 128 byte block writes. This is accomplished in the Flash update code by copying
four 128 byte blocks from I2C EEPROM to RAM, then calling the copy_ram_to_flash()
function to copy those blocks from RAM to Flash.
To keep the I2C driver segment separate from the rest of the Flash code it is located in
upper Flash as follows:
In the I2C.c file a #pragma flash_update code segment is defined containing the
I2C driver and functions which call the copy_ram_to_flash() code.
In the linker .lkf file the following directive is added to specify the location of the
pragma section:
+seg .flash_update -b 0xfc80
The copy_ram_to_flash() code also requires special handling as the STM8 hardware will
only allow copies from RAM to Flash if the code performing the copy is running in
RAM. Since RAM is very limited the copy_ram_to_flash code is designed to have a
minimal code space footprint. The steps to implement this part of the code are as follows:
In the linker .lkf file the following directives are added to specify the location of
the pragma section:
+seg .memcpy_update -a .data -n memcpy_update –ic
+seg .bss -a memcpy_update -n .bss
178
In the main.c file the following code causes the copy_ram_to_flash() function to
be relocated to RAM. Once relocated, the function can be called like any other
function.
_fctcpy ('m');
Given the above: To complete a copy of new firmware from I2C EEPROM to Flash the
process is as follows:
a) The _fctcpy ('m') function is called from main.c
b) The eeprom_copy_to_flash() function is called from main.c. This function will
copy all of the I2C EEPROM content to Flash except for the segment containing
the I2C driver and copy_ram_to_flash() code. As mentioned this is done by
copying 512 bytes to RAM then copying the 512 bytes to Flash and repeating as
needed.
c) The last step in the eeprom_copy_to_flash() code is to copy the I2C Driver and
copy_ram_to_flash() function to RAM. These functions fit within 512 bytes. Next
the code initiates a copy of those functions from RAM to Flash. Remember, at
this point the actual copy function is being run from the existing
copy_ram_to_flash() function in RAM, so it doesn’t matter that the functions are
being over-written in Flash. Once the copy completes, the code waits for a device
reset using the Window watchdog function. At boot the new firmware is run from
Flash.
179
_fctcpy
180
#pragma Sections
https://cosmic-software.com/faq/faq18.php
181
Content of the .lkf File
For reference the +seg part of the .lkf file for this project looks like this:
182
Paraphrased from the CXSTM8_Userguide.pdf
-b* set the physical start address of the segment to *. Option –e or -a cannot be specified
if -b has been specified.
-m* set the maximum size of the segment to * bytes. If not specified, there is no checking
on any segment size. If a segment is declared with the -a option as following a segment
which is marked with the -m option, then set the maximum available space for all the
possible consecutive segments. If a -m is specified on a -a segment, the actual maximum
size checked is equal to the given value minus the size of all the segments already
allocated from the first segment of the –a list. So the new maximum size is computed
from the start address of the list and not from the start address of that segment.
-n* set the output name of the segment to *. Segment output names have at most 15
characters; longer names are truncated. If no name is given with a -n option, the segment
inherits a default name equal to its assembler section name.
183
Developers: STM8 Address Map
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code.
184
Developers: Flash Memory Map
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code.
185
STM8 Flash Map for Upgradeable builds
0xfeb0 – 0xfebf
16 bytes empty
0xfec0 – 0xfedf
32 bytes IO_TIMER
fields
254 0xff00 – 0xff7f 0xff00 – 0xff7f
128 bytes IO_NAMEs
255 0xff80 – 0xffff 0xff80 – 0xffff
128 bytes IO_NAMEs
186
Developers: I2C EEPROM Memory Map
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code.
The I2C EEPROM used with Upgradeable Builds is divided into four 32KB regions as
follows:
Map:
0x0000 - 0x003f NOT DEFINED
0x0040 - 0x007f Pointers to the start of webpages stored in Region 2.
0x0080 - 0x009f Sizes of webpages stored in Region 2.
0x0100 Start of the first webpage stored in Region 2. Other
webpages are stored sequentially with pointers and sizes
stored in 0x0040 to 0x009f.
0x7ec0 - 0x7edf PCF8574 IO_TIMERS. Each pin requires 2 bytes for the
IO_TIMER value. There are 8 pins so this is 16 bytes. A 32
byte block is allocated in anticipation of adding more pins.
0x7ee0 - 0x7eef PCF8574 PIN_CONTROL. Each pin requires 1 byte. There
are 8 pins, thus 8 bytes are required. 16 bytes are allocated
in anticipation of adding more pins in the future.
187
0x7ef0 - 0x7eff NOT DEFINED
0x7f00 - 0x7fff PCF8574 IO_NAMES. Each pin requires 16 bytes for the
IO_NAME string. There are 8 pins so this is 128 bytes. A
256 byte block is allocated in anticipation of adding more
pins.
188
Addressing the I2C EEPROM Regions
The 24xx1025 is addressed as if it were a pair of 64KB devices. So even though it is used
as four 32KB regions, the addressing of the device requires some translation.
When Region 0 or Region 1 are addressed the “I2C Command Byte” used on the I2C bus
to perform a Read is 0xa1, and to perform a Write is 0xa0. Then Region 0 is addressed as
bytes 0x0000 to 0x7fff, and Region 1 is addressed as bytes 0x8000 to 0xffff.
When Region 2 or Region 3 are addressed the “I2C Command Byte” used on the I2C bus
to perform a Read is 0xa9, and to perform a Write is 0xa8. Then Region 2 is addressed as
bytes 0x0000 to 0x7fff, and Region 3 is addressed as bytes 0x8000 to 0xffff.
The following defines are used to help translate this into something more “readable” in
code:
189
Developers: Upgradeable Firmware – How
File Upload Works
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code.
This is a general description of how file upload works, including shortfalls and
descriptions of potential future improvements.
When a file upload is started the file is copied to I2C EEPROM Region 0. The files are
always in a Motorola SREC format. The first line of any file uploaded (the S0 SREC)
should have a string that looks like one of these two examples:
I won’t explain the entire format of an SREC line. A good reference is here:
https://www.systutorials.com/docs/linux/man/5-srec/
In the above examples I’ve decoded the text part of the S0 SREC so that you can see
what the content looks like.
The first example is what the S0 SREC line looks like for a Firmware file. Because this
file is generated by the Cosmic Compiler the text will contain the name of the .sx file.
Now, having said that it is a little confusing as to why the file extension is “.sm8” rather
than “.sx” in the SREC. The actual file has a “.sx” file extension. This is an artifact of the
way the Cosmic Compiler builds its output files. While an oddity it doesn’t matter in
installation of the firmware.
Note that in the first example the Cosmic Compiler was told to generate the file
“NetworkModule.sx”. It has become my general practice to generate .sx files with that
name, then rename the file to the firmware type I actually built (as an example
“NetworkModule-Browser-UPG.sx”). But if I do that the SREC file will still contain the
text “NetworkModule.sm8”.
In the second example above the text contains the string “String File”. That text was
placed in the S0 SREC line by the “prepsx” program that generates the NetworkModule-
strings.sx” file.
190
The content of the S0 SREC is important because the Uploader firmware looks for the
“N” or “S” in the first character of the S0 SREC text to determine if the file being
uploaded is Firmware or if it is the String file. So, it is critical that firmware files always
have a file name that starts with “N” (as in the name NetworkModule.sx) and that the
“prepsx” program always generates the String file with the S0 SREC text containing “S”
as the first character of the text in the S0 SREC.
In the above note the SREC with address 0000D79E. The last byte in that record
is at 0000D7A7. Near the bottom of the sample you’ll see the data continued at
the SREC with address 0000D7A8. Between those two SRECs there is data at
various other starting addresses. These issues are handled in firmware in Uploader
191
state machine states labeled PARSE_FILE_SEQUENTIAL and
PARSE_FILE_NONSEQ.
3) The I2C EEPROM can be written 1 byte at a time, however this is very
inefficient. The best block size to write the I2C EEPROM is 128 byte blocks (the
I2C EEPROM page size). However memory limitations don’t allow a
reconstruction buffer that large, so the firmware writes 64 byte blocks at a time
always starting at an I2C EEPROM page boundary or the boundary + 64 bytes.
But note that the incoming SREC data does not necessarily start on even 64 byte
addresses, so this must be accounted for as the datagram is read and sent to the
I2C EEPROM.
4) Only the data within the SREC is written to the I2C EEPROM, as that is what we
want in the execution Flash space.
Comment: Note that on the Uploader webpage the user is given the opportunity to abort
the Uploader and “Restore” the firmware image that was running before the Uploader
was started. If “Restore” is selected the firmware in I2C EEPROM Region 0 is copied to
Flash. Note this only works if the user selects “Restore” BEFORE submitting any
filename for upload, as once an Upload starts I2C EEPROM Region 0 will be
overwritten.
Now that you have the “overview” you can work your way through the source code to
figure out further detail.
192
See section “Developers: #pragma, Sections, Segments and the .lkf File” for details on
how I2C EEPROM content is copied to Flash. In particular look at the notes on the
_fctcpy function.
193
Developers: Strings File Generation for
Ethernet Upgradeable Firmware
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code.
When using Upgradeable Builds a “Strings File” must be generated and stored in the off-
board I2C EEPROM. The “Strings File” contains the HTML and Javascript that defines
the IO Control and Configuration web pages. That HTML and Javascript resides in the
httpd.c file, but it must be extracted and placed in a separate .sx file for upload to the I2C
EEPROM attached to the Network Module.
I’ve written a program that runs in the Windows environment that parses the httpd.c file,
locates the webpage HTML of interest, and generates the required .sx file. Along with the
HTML text the .sx file also includes pointers to the start of the HTML in the .sx file and
the size of the HTML text. The resulting .sx file can be directly uploaded to the Network
Module using the Code Uploader.
The parsing program is named “prepsx.exe”. The syntax for running the program is
“prepsx inputfile outputfile”, for example “prepsx httpd.c NetworkModule-strings.sx”.
I recommend creating a temporary directory, copying the prepsx.exe and httpd.c files to
that directory, then running the program to create the output file. Open an Administrator
Command Prompt window and find your way to the temporary directory. Follow the
instructions in the “Upgradeable Firmware” section to make use of the strings file.
Comment: The prepsx.exe program was created using Visual Studio. The project file is
named “prepsx.sln”, and the source code is in a main.c file.
194
Developers: Using the UART
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code.
The STM8S processor includes a UART. The code can be compiled with the UART
enabled so that you can add debug statements to the code. The compile option is available
in the uipopt.h file (see #define DEBUG_SUPPORT).
When the UART is enabled it will take over IO Pin 11 and use that as the UART transmit
pin. No UART receive pin is implemented. The Configuration page will show the pin 11
as an Output, and you will not be able to change that pin configuration when the UART
option is compiled. Likewise, the IOControl page will show the pin as an Output, and any
attempt to change the pin state will not be successful. But the pin will continue to
function as the UART output until the code is recompiled with the Debug UART option
turned off.
To connect the Network Module UART Tx pin (IO 11) to a terminal on your PC you’ll
need a TTL-RS232 or TTL-USB converter. There are several ways to do this, but I will
describe the method I used:
a) Use a TTL-USB converter to connect the Tx pin to the USB port on a laptop.
Here’s the device I used:
195
Keep in mind that the Network Module operates at 3V, so the adapter needs to be
set to 3V IO with the jumper located near the connection pins.
Pin 11 on the Network Module is the “TX” output from the Network Module. It
must be connected to the “RX” pin on the Serial Adapter shown above. The only
other connections to the Network Module are +3.3V and GND.
b) My laptop was a Windows 10 OS, so I had to download the drivers for the TTL-
USB interface here:
https://ftdichip.com/drivers/
196
d) If everything is set up correctly you should see something like this in the PuTTY
display when the Network Module boots:
Note: Use the http command “http://IP:Port/70” to clear the “Reset Status Register"
counters (the counts for EMCF, SWIMF, ILLOPF, IWDGF, WWDGF). See the STM8S
documentation for definitions of the Reset Status Register content.
197
Developers: Analysis of MQTT sendbuf
sizing
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code.
During MQTT startup we do not queue any MQTT messages. They are sent one at a
time, and in the case of CONNECT or SUBSCRIBE messages the code will wait for an
ACK from the broker.
After startup there can be queuing of messages, but that queue will only grow to a
maximum of 2 messages. This occurs when a PINGREQ is issued, and that request
immediately precedes or immediately follows some other PUBLISH message. The reason
the queue is needed is because we need to watch for a PINGRESP (an ACK) to the
PINGREQ. Thus, the PINGREQ is retained in the queue until the PINGRESP is received.
PUBLISH does not wait for an ACK since we are operating as QOS0.
Why is all the above mentioned? Because we want the mqtt_sendbuf to be as small as
possible. The way the MQTT code works is that it places a message in the mqtt_sendbuf,
and that message is always accompanied by a queue management structure of about 11
bytes. So to determine the mimimum size required for mqtt_sendbuf we need to know
that maximum size MQTT message that will go in the buffer.
198
It turns out the largest message is the CONNECT message, which is only sent during
MQTT startup. At that time no PINGREQ messages can be issued, so the CONNECT
message will occupy the mqtt_sendbuf by itself. An analysis of the size of the
CONNECT message:
CONNECT message
Payload:
The payload of the CONNECT Packet contains one or more length-prefixed fields,
whose presence is determined by the flags in the variable header. These fields, if present,
MUST appear in the order Client Identifier, Will Topic, Will Message, User Name,
Password [MQTT-3.1.3-1].
199
Username 10 bytes
Passwoard Length 2 bytes
Password 10 bytes
Queued Message Header 11 bytes
Total 131 bytes
Thus the CONNECT message can be up to up to 131 bytes in length. Add the Message
Queue (12 bytes) and the mqtt_sendbuf needs to be a minimum of 143 bytes. Note that
no PINGREQ can occur during the MQTT Startup process, so the CONNECT message
will occupy the mqtt_sendbuf alone. This sets the required size of the mqtt_sendbuf at
143 bytes ... will make it 150 to provide a little buffer.
The only messages that must be retained in the mqtt_sendbuf are the CONNECT,
SUBSCRIBE, and PINGREQ messages. Since the CONNECT and SUBSCRIBE
messages are only sent by the mqtt_startup state machine we can carefully manage that
state machine to make sure the ACK for each of those messages is received before
continuing the state machine. This means that the only message that will be retained in
the mqtt_sendbuf during normal operation is the PINGREQ message. That message is
two bytes long. So, we can minimize the size of the mqtt_sendbuf to the point that only
that 2 byte message and the longest of any other MQTT transmit message will fit.
200
Topic Length 2 bytes
Packet ID 2 bytes
Queued Message Header 11 bytes
Total: 64 bytes
The implication of the above is that in NORMAL operation (after MQTT startup) the
mqtt_sendbuf needs to be as large as the Message Queue (12 bytes) plus one PINGREQ
message (13 bytes) plus the longest Publish message (70 bytes), or 108 bytes.
201
Developers: Storing Variables in Flash via
the Application
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code.
Flash Programming
Beginning in April 2021 the ability to have user entered names for each IO pin was
implemented. This required storing those names in Flash memory (not EEPROM).
Following are notes on how this is done.
The following excerpts from the RM0016 and PM0051 clearly indicate that performing
byte and word writes to Flash will stop application execution until the write completes. If
word or byte writes are implemented it is not necessary to have code execution in
RAM. However, block writes to Flash do require code execution in RAM.
It appears that when byte writes are performed they may cause as many as 4 erase/write
cycles on all 4 bytes around a memory location. This is because Flash is actually written
4 bytes at a time even if a single byte is being written. So if you write 4 bytes in a row,
you actually write all 4 bytes 4 times.
For this reason the Word method (4-bytes at a time) will cause less wear on memory. If 4
bytes are going to be written sequentially anyway then writing them as a 4-byte Word
will result in one erase/write cycle on that Word instead of 4 cycles. PM0051 section 4.3
describes how to do this. A logical presumption (because I can’t find it in manuals): The
first byte of a Word must be at an address ending in 0, 4, 8, or C.
Since writes always occur 4 bytes at a time, code should be written to write 4 byte values
as much as possible. So, consideration needs to be taken to accumulate writes in RAM
first, then write them as 4 byte values to Flash. The 4 byte values are on 4 byte
boundaries starting at address 0x0000. Example of a 4 byte write:
unlock_flash();
for (i=0; i<8; i+=2) {
202
// IO_TIMER values are 2 byte values. They are accumulated in RAM first, then
// the sixteen 2 byte values are written to Flash as eight 4 byte values. First
// the values in RAM are compared to what is already in Flash to make sure no
// unnecessary writes are performed.
// Compare 4 bytes at a time. If any miscompare write to Flash 4 bytes at a time.
if (IO_TIMER[i] != Pending_IO_TIMER[i] || IO_TIMER[i+1] !=
Pending_IO_TIMER[i+1]) {
FLASH_CR2 = 0x40;
FLASH_NCR2 = 0xBF;
memcpy(&IO_TIMER[i], &Pending_IO_TIMER[i], 4);
}
}
lock_flash();
There is no protection against code being written to the "reserved" area, so care needs to
be taken that code size doesn't grow too large and over-lap the “reserved” area.
The specification states that there is 32K of Flash (32768 bytes). But the first 128 bytes
(starting at 0x8000) is used for interrupt vectors. So if we use 320 bytes for user data the
maximum code size is 32768 - 128 - 320 = 32320.
The real problem with using Flash for user data is that it has very limited write life. So
frequent changes should be avoided. Caution the user to set IO names and IO timers only
a few times during the life of the device. NEVER use an automated mechanism that
might inadvertantly change the names or timer values a lot of times.
Note that single byte writes should be avoided. A single byte write actually results in a 4
byte write of the targeted byte plus the 3 other bytes in the 4 byte "word". So if you want
to write all 4 bytes in a word and you do that one byte at a time, you will actually write
every byte of the word 4 times. This creates a lot of wear on the Flash, so in this
application data that will be written to the Flash is first accumulated in RAM, then
written to Flash as a series of 4 byte "word" writes.
Note that program execution is suspended by hardware for the 6ms that a Flash write is
being performed. From the PM0047 manual:
203
"Byte programming is done by executing any write instruction (ld, mov...) to a
Flash memory address when the memory is unlocked. The write instruction
initiates the erase/programming cycle and any core access to the memory is
blocked until the cycle is over. This means that program execution from Flash is
stopped until the end of the erase/programming cycle. At the end of the
programming the EOP bit in the FLASH_IAPSR is set and program execution
restarts from the instruction following the write/erase instruction."
A write to Flash requires about 6ms regardless of whether it is a 1 byte or 4 byte write.
Just for reference if the entire 320 byte reserved area of Flash were written at one time it
would take about (320 / 4) * 6ms = 480ms. Since this only occurs when the user makes
changes it is not significant to operation of the device.
From CXSTM8_UsersGuide:
Referencing Absolute Addresses
References to absolute addresses have the general form @<address>, where
<address> is a valid memory location in your environment. For example, to
associate an I/O port at address 0x20 with the identifier name MISCR1, write a
definition of the form:
char MISCR1 @0x20;
where @0x20 indicates an absolute address specification and not a data initializer.
Since input/output on the STM8 architecture is memory mapped, performing I/O
in this way is equivalent to writing in any given location in memory. Such a
declaration does not reserve any space in memory. The compiler still creates a
label, using an equate definition, in order to reference the C object symbolically.
This symbol is made public to allow external usage from any other file.
Flash Unlock/Lock
Unlock: Write 56h then AEh in FLASH_PUKR (00 5062h)
Lock: Reset bit 1 (PUL) in FLASH_IAPSR (00 505Fh)
204
RM0016
Note: In the above “main program memory” is RAM, and “DATA area” is
EEPROM.
RM0016
PM0051
205
PM0051
206
Developers: Flash and EEPROM Wear Notes
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code.
207
Here is the pertinent device specification for the STM8S005C6 from data sheet DS8638
Rev 5 dated September 2018.
208
Developers: How Connections Open and
Close And Relationship to the
“current_webpage” Variable
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code.
Since this issue has flummoxed me several times causing many hours of debug here is a
brief writeup on how connections open and close, and how this relates to the variable
“current_webpage” in the code.
Basics:
When a webpage is sent from the webserver to a browser a connection is opened, the
page sent (even if several packets are required), then the connection is closed. The
variable "current_webpage" is used only while that connection is open so that the
firmware remembers which page is being sent in that connection.
When a client sends a POST or GET request a connection is opened, the POST or GET is
received and processed in the webserver (even if several packets are required), then the
connection is closed.
o When a POST is received in this implementation the connection is closed after
sending a 204 header. That might be an incorrect method – an investigation for
another time. But, the appropriate page repaint occurs, so perhaps I have it right.
o When a GET is received the connection is closed after sending a 200 header with
the requrested information (usually the IOControl or Configuration page but it
could be other actions). In some cases a 204 header is sent with no data when
appropriate.
More detail:
When a POST is received the webserver needs to determine if that POST is coming from
a IOControl page or from a Configuration page. There might be an easier way to do this,
but I use the content of the POST to make this determination as follows:
If the POST is coming from a Configuration page it will look similar to this:
a00=NewDevice000&b00=c0a801c7&b04=c0a80101&b08=ffffff00&c00
=0050&d00=c24d696b0199&j00=IO01&i00=0000&j01=IO02&i01=0000
&j02=IO03&i02=0000&j03=IO04&j04=IO05&j05=IO06&j06=IO07&j0
7=IO08&j08=IO09&j09=IO10&j10=IO11&i10=0000&j11=IO12&j12=I
209
O13&j13=IO14&j14=IO15&j15=IO16&h00=0303030100000000000003
0000000000&i03=0000&i04=0000&i05=0000&i06=0000&i07=0000&i0
8=0000&i09=0000&i11=0000&i12=0000&i13=0000&i14=0000&i15=00
00&g00=00&z00=0
If the POST is coming from a IOControl page it will look similar to this:
h00=80800000000000000000000000000000&z00=0
The thing to note is that while both POSTs contain ‘h00’ data, the Configuration POST
always begins with ‘a00’ data. Thus when parsing it is easy to determine the source of the
data.
Why do we even need to know the source of the POST? It comes down to properly
parsing the ‘h00’ data. That data contains the configuration and state for the IO pins. The
‘h00’ data that comes from the Configuration page contains information like
Input/Output/Disabled and Invert for the pins. The ‘h00’ data that comes from the
IOControl page contains the ON/OFF state of the pin. The code needs to make sure it
properly masks the bits in the returned bytes so that the Configuration page data does not
change the ON/OFF bit, and so that the IOControl data does not change the configuration
bits.
The code examines the incoming POST data and if it starts with the ‘a00’ data we know
it is coming from a Configuration page (and current_webpage is set appropriately),
otherwise it is from a IOControl page. Problem solved.
210
Developers: How Proto-Sockets are
Implemented and Connections Established
NOTE: This information is only needed if you plan to set up your own development
environment to modify and compile code.
Since this code is a collection of efforts from several code sources there are many cases
where layers of obfuscation occur. An important issue is “How are proto-sockets
implemented?” … and unfortunately this is hard to trace through the code. Some notes
since I recently dug into this. I admit ahead of time I may describe some of this with
inaccurate coding terminology as structs and unions always seem to make my head hurt.
In the uip.c and uip.h files you’ll see that data associated with connections is maintained
in an array called “uip_conns[]”. The uip_conns[] array is actually an array of structs as
defined in uip.h:
/* The array containing all uIP connections. */
extern struct uip_conn uip_conns[UIP_CONNS];
and
/**
* Representation of a uIP TCP connection.
* The uip_conn structure is used for identifying a connection. All but one
* field in the structure are to be considered read-only by an application.
* The only exception is the appstate field whos purpose is to let the
* application store application-specific state (e.g., file pointers) for the
* connection. The type of this field is configured in the "uipopt.h" header
* file.
*/
struct uip_conn {
uip_ipaddr_t ripaddr; // The IP address of the remote host.
uint16_t lport; // The local TCP port, in network byte order.
uint16_t rport; // The local remote TCP port, in network byte order.
uint8_t rcv_nxt[4]; // The sequence number that we expect to receive next.
uint8_t snd_nxt[4]; // The sequence number that was last sent by us.
uint16_t len; // Length of the data that was previously sent.
uint16_t mss; // Current maximum segment size for the connection.
uint16_t initialmss; // Initial maximum segment size for the connection.
uint8_t sa; // Retransmission time-out calculation state variable.
uint8_t sv; // Retransmission time-out calculation state variable.
uint8_t rto; // Retransmission time-out.
uint8_t tcpstateflags; // TCP state and flags.
uint8_t timer; // The retransmission timer.
211
uint8_t nrtx; // The number of retransmissions for the last segment sent.
212
Now for some more obfuscation: How are connections established? I’ve had to track the
following down so many times I thought I would document it for my own sanity if
nothing else.
At this point the uip.c code will do some incoming packet processing and validation (like
checking the header) then will call the application (the webserver) to process the
incoming data. Further down in uip.c you’ll find this statement:
UIP_APPCALL();
The above call appears in several places depending on what the uip.c code has
determined is appropriate. But how does UIP_APPCALL() actually invoke the webserver
process?
213
}
}
And, as you’ll recall from the earlier text, HttpDCall() is the webserver processing code.
214
Developers: Timer Internal Operation
IO Timers for the Browser Only builds are stored in 16 bit variables. These variables start
out being equal to the Timer + Units values entered by the user and reported from the
GUI, but thereafter the 14 bit counter part of the variable is decremented as each timer
tick occurs.
The 16 bit values use the 2 most significant bits as the resolution identifier, just like the
data that comes from the GUI. So, each counter really has 14 bits of count with a
maximum value of 16383, just like the data that comes from the GUI.
Users should always use the smallest resolution that will work for them.
If the user enters 100 (0.1 seconds, seconds, minutes, or hours) they will have about 1%
precision. Using a higher value provides higher precision. For instance, a value of 200
will have about 0.5% precision. A value of 16383 will have a precision of about .006%.
The above is not enforced in the GUI. If the user uses a value less than 100 it still works,
but precision is worse.
Inside the code: How to produce 0.1s, 1 second, 1 minute, and 1 hour flags:
A byte named timer_flags is used as a toggle for the second, minute, and hour timers. At
boot time timer_flags is initialized to 0x00000111 with the bits of timer_flags used to
toggle the timers as follows:
1 second timers:
Every 100ms the decrement_pin_timers() function will:
Compare the second_flag to the least significant bit of the second_counter.
o If a match decrement any 1 second pin_timers.
o If a match invert the second_flag, thus arming the flag to enable a repeat
of this process.
215
1 minute timers:
Every 100ms the decrement_pin_timers() function will:
If minute flag == 1 compare the least significant bits of the second_counter to
0x3c (60 decimal).
o If a match decrement any 1 minute pin_timers and clear the minute_flag.
Compare the least significant bits of the second_counter to 0x3d (61 decimal).
o If a match set the minute_flag to enable a repeat of this process.
1 hour timers:
Every 100ms the decrement_pin_timers() function will:
if hour flag == 1 compare the least significant bits of the second_counter to 0xe10
(3600 decimal).
o If a match decrement any 1 hour pin_timers and clear the hour_flag.
Compare the least significant bits of the second_counter to 0xe11 (3601 decimal).
o If a match set the hour_flag to enable a repeat of this process.
If a "1" is entered with any "unit" the timer could immediately time out as code doesn’t
know where the clock edge is. This is why the manual has illustrations indicating that the
user should not enter a time value of less than 100 if it can be avoided.
216
Developers: URL Command Map
The URL Commands (example: the “/55” part of 192.168.1.182/55) can be any hex
number from “00” to “ff”. The original factory code used decimal ‘00’ to ‘31’, and that
pattern continues in this firmware, however, since the command string is interpreted as
hex instead of decimal there are additional URL Commands that could potentially be
placed in the “gaps” between some “decimal” commands. The table shown here makes
that more apparent, and shows where new commands could be inserted. For now I
recommend not placing commands in certain areas of the schema until needed.
217
See Note 1 1b
See Note 1 1c
See Note 1 1d
See Note 1 1e
See Note 1 1f
Output 11 OFF 20 20
Output 11 ON 21 21
Output 12 OFF 22 22
Output 12 ON 23 23
Output 13 OFF 24 24
Output 13 ON 25 25
Output 14 OFF 26 26
Output 14 ON 27 27
Output 15 OFF 28 28
Output 15 ON 29 29
See Note 1 2a
See Note 1 2b
See Note 1 2c
See Note 1 2d
See Note 1 2e
See Note 1 2f
Output 16 OFF 30 30
Output 16 ON 31 31
Output 17 OFF 32 32
Output 17 ON 33 33
Output 18 OFF 34 34
Output 18 ON 35 35
Output 19 OFF 36 36
Output 19 ON 37 37
Output 20 OFF 38 38
Output 20 ON 39 39
See Note 1 3a
See Note 1 3b
See Note 1 3c
See Note 1 3d
See Note 1 3e
See Note 1 3f
Output 21 OFF 40 40
Output 21 ON 41 41
Output 22 OFF 42 42
Output 22 ON 43 43
Output 23 OFF 44 44
Output 23 ON 45 45
Output 24 OFF 46 46
Output 24 ON 47 47
218
48 48
49 49
4a
4b
4c
4d
4e
4f
Mask and Output Pin settings w/ no return page 50 50
Mask and Output Pin settings w/ Short Form return page 51 51
Mask and Output Pin settings plus returns RF Attenuator Settings page 52 52
53 53
54 54
All Outputs ON 55 55
All Outputs OFF 56 56
57 57
58 58
59 59
5a
5b
5c
5d
5e
5f
Show IO Control Page 60 60
Show Configuration Page 61 61
Show PCF8574 IO Control Page 62 62
Show PCF8574 Configuration Page 63 63
64 64
Flash LED 3 times 65 65
Show Link Error Statistics Page 66 66
Clear Link Error Statistics 67 67
Show Network Statistics 68 68
Clear Network Statistics 69 69
6a
6b
6c
6d
6e
6f
Clear “Reset Status Registers” 70 70
Display Temperatures Sensor Serial Numbers 71 71
Load Code Uploader 72 72
Restore 73 73
Erase I2C EEPROM 74 74
219
Show SDR RF Attenuator Settings page 75 75
Show SDR INA226 Measurements page 76 76
Show SDR Power Relay Control page 77 77
Turn off Latching Relay Mode 78 78
User entered INA226 Shunt Resistance option 79 79
7a
7b
7c
7d
7e
7f
Mask and Output Pin settings (will be deprecated) 80 80
Altitude Entry 81 81
User Entered Pinout Option 82 82
User Entered PCF8574 Output Byte (deprecated) 83 83
Short Form Option 84 84
Force HA Delete Msgs for PCF8574 pins 85 85
86 86
87 87
88 88
89 89
8a
8b
8c
8d
8e
8f
90 90
Reboot 91 91
92 92
93 93
94 94
95 95
96 96
97 97
Very Short Form page 98 98
Short Form page 99 99
9a
9b
9c
9d
9e
9f
Turn Response Lock on and off a0 a0
a1-f9
220
Reserved to avoid “favicon.ico” issue fa
fb - ff
Note 1: The URL Commands with “See Note 1” should not be used unless absolutely
necessary.
Note 2: Some effort has been made to “group” certain commands based on their
functionality. While not essential to maintain this approach, here is the general concept:
o Commands 00 to 5f: Used primarily for direct manipulation of IO pins
o Commands 60 to 7f: Used primarily to show specific pages and clear displays on
those pages
o Commands 80 to 8f: Used primarily for “set once” runtime options
221
Developers: MQTT Local Port Numbers
A problem was found wherein multiple Save or Reboot selections in the Configuration
page could cause a very long pause before MQTT settings were implemented within the
MQTT “network”.
The symptom being seen using Wireshark is that when a Network Module reboots it
sends a SYN to establish a TCP connection for MQTT. However, if that reboot occurs
within 120 seconds of the previous shutdown (say, as part of a Reboot or Save button
press on the Configuration page) then no SYNACK is returned from the server. The
Network Module retries the SYN at an exponentially increasing time interval, but the
server does not respond with a SYNACK until about 120 seconds passes.
So the TIME_WAIT requirement was the source of the issue, and it was occurring
because the exact same TCP connection parameters were being used for the TCP
reconnection: the same IP addresses and the same MQTT Host and Local Port numbers.
The solution implemented is to use a rotating list of MQTT Local Port numbers as TCP
Connections are made. The MQTT Host Port number (typically 1883 as set on the
Configuration page) remains the same. But within the code, invisible to the user, 5
randomly selected port numbers from the IANA “Dynamic/Private” port numbers region
are used as the MQTT Local Port number. If you snoop around in the code you’ll find
this associated with variable mqtt_local_port.
What happens if the MQTT Local Port number conflicts with some other application
using the same port number? Eventually there will be an MQTT error, and the code will
go through a process to switch to one of the other port numbers. This will happen without
a reboot. The risk of such a collision is very remote, but the code will handle it.
222
Change Log
June 20, 2020 – Initial Release
August 2, 2020 – Added descriptions of “8 Output / 8 Input” and “16 Input” configurations.
August 6, 2020 – Added a note to make sure people know they don’t need to set up a development
environment unless they need to change the code.
223
Code changes:
o Added the /98 REST command
o Corrected typo in the HELP pages that mis-stated the REST command numbers.
Document changes:
o Added section describing all the REST commands.
December 2, 2020
Code changes:
o Fixed issue regarding browsers on multiple IP addresses.
o Fixed issue regarding browser interference on page changes.
Document changes:
o Added section to describe functional limitations (like number of browser sessions,
browser interference).
o Added section on an alternative method for entering the initial IP Address.
December 4, 2020
Code changes:
o Code change made to reduce or eliminate relay state changes during reboot.
Document changes:
o Added section on alternative hardware design methods for maintaining relays states
during power loss.
224
oChanged reset button routine to prevent hardware watchdog from firing while button is
pressed.
Document changes:
o Added description of Auto Discovery and associated Config setting
225
o Fixed bug that was allowing blank fields in the IP Address, Gateway, Netmask, and
Port fields.
o Fixed bug that was preventing operation of the REST 00-31 commands.
o Fixed bug that was causing the REST 98 and 99 commands to output the wrong values.
Document changes:
o None.
226
o Added hardware design information regarding 16 Channel relay boards
227
o Addressed Issue #83: /98 /99 command does not return the correct size for the page in
the HTML header.
Document changes:
o Added new section on using “Upgradeable” firmware
o Added REST command notes
o Added Developers section: Notes on Proto-Sockets
o Added Developers section: #pragma, Sections, Segments and the .lkf File. Includes
information on Editing the .lkf file, Flash Update and Copy-RAM-to-Flash Code,
_fctcpy, #pragma Sections, and Content of the .lkf File
o Added Developers section: STM8 Address Map
o Added Developers section: Flash Memory Map
o Added Developers section: I2C EEPROM Memory Map, Includes information on I2C
EEPROM Regions for Upgradeable Builds and Addressing the I2C EEPROM Regions
o Added Developers section: Strings File Generation
228
o Added Enhancement Issue #100 “Remove Configuration Button”. This is an option to
disable the Configuration button on the IOControl page.
o Fixed Issue #108: “Temperature sensors loose custom names in HA on NetModule
boot”.
o Updated inline code comments with regard to Debug Bytes and settings to reflect
actual code operation.
Document changes:
o Updated description of the Link Error Statistics Clear button.
o Added description of the Disable Configuration Button enhancement.
o Updated the “Notes on Debug Bytes” section.
o Updated the “Notes on MQTT” section to reflect changes in how Temperature Sensor
config messages are handled.
229
o Fixed an issue in the MQTT transmit code to assure that multiple queued messages all
get sent.
o Changed the code so that Home Assistant sees pin 11 as Disabled when it is being used
for UART based debug functionality.
o Fixed (again!) a bug in proper display of the ENC28J60 revision with the /66
command.
o Fixed some file upload error detection bugs which may have been causing file upload
hangs when byte errors occurred on the network.
o Fixed the input pin debounce of the read_input_pins() function.
o Fixed the encode_16bit_registers() function which was interfering with the
read_input_pins() function.
Document changes:
o Updated the “Adding DS18B20 Temperature Sensors” section.
o Added a description of the new “batch mode” REST command.
o Added a “Reset Button” section.
o Added a “Default Firmware Settings” section.
o Updated the “Developers: Analysis of MQTT sendbuf sizing” section.
o Added note about programming an STM8S105 device
o Updated the “Developers: Notes on Configuration Debug and pin_control Bytes”
section to reflect addition of the Linked pin Type.
o Updated the Screenshots to reflect addition of the Linked pin Type.
o Added a “Notes on Linked Inputs and Outputs” section.
o Fixed typos in the Debug Statistics Display Schema description.
o Added a “Developers: Upgradeable Firmware – How File Upload Works” section.
230
o Moved the “Upgradeable Firmware” section to follow the “Programming the Module”
section.
231
o Addressed Issue #147 "Question for team: How to handle the MQTT state-req message
with PCF8574"
o Addressed Issue #156 "URL command /82 is not returning a valid webpage"
o Addressed Issue #157 "When changing code load types the Configuration settings need
to be checked for compatibility"
o Addressed Issue #158 "BME280 build - all pins are outputs even if defined as an input"
Document changes:
o Added section “Developers: URL Command Map”
o Updated section “Notes on MQTT” to include the new state_req24 command for
PCF8574 hardware configurations per Issue #147.
o Improved the "Selecting Alternative Pinouts" section.
o Added Issue #148 to the 20230312 release notes. It was addressed in that release but
the notation was not included. #148 "When ST-LINK V2 is used to program the device
it starts running before reset is released"
o Addressed Issue #160 “PCF8574 startup: All outputs are "weak pullup" for several
seconds at power on or reboot” by adding section “Notes on PCF8574 Outputs”.
o Added section “LED” to describe the red LED on the Network Module HW-584.
232
o Per Issue #170: Updated the REST commands to add a description of the /85
command.
o Updated buying information on page 2.
o Updated EEPROM byte definitions to reflect addition of the “options1” byte used to
retain additional hardware option settings:
Force PCF8574 pin delete messages
Short Form Option format
PCF8574 presence
Pinout Options
o Removed superfluous “Notes on” part of section headings
233
o Addressed Issue #184 “Problem with Autocomplete on Chrome” by adding section
“Browser Issues” to the manual.
o Updated section “Developers: Debug Bytes” as part of Issue #189
Document changes:
o Moved the Change Log to the end of the document.
o Added a “Quick Start” section.
o Updated section “Developers: Location of EEPROM Variables”
o
234
Code Credits
This project borrows heavily from the work of Simon Kueppers “MicroWebServer”
project available on GitHub. Extract of Simon Kueppers’ code sharing statement:
This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>.
Simon Kueppers work in turn borrows heavily from the work of Adam Dunkels uIP
project, also available on GitHub and other locations. Extract of Adam Dunkels’ code
sharing statement:
/**
* \file
* The uIP TCP/IP stack code.
* \author Adam Dunkels <[email protected]>
*/
/*
* Copyright (c) 2001-2003, Adam Dunkels.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
235
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
With the addition of the MQTT Interface the following statement is applicable:
MIT License
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
236
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
And, finally, I want to credit Carlos Ladeira and Jevgeni Kiski for their very significant
contributions to code and test.
237
Documentation License Note
And now for the GNU Free Documentation License (follows on the next page). If you
read the short preamble the typical user will know all you really need to know.
238
GNU Free Documentation License
Version 1.3, 3 November 2008
0. PREAMBLE
239
You accept the license if you copy, modify or distribute the work
in a way requiring permission under copyright law.
The "Cover Texts" are certain short passages of text that are
listed, as Front-Cover Texts or Back-Cover Texts, in the notice
that says that the Document is released under this License. A
Front-Cover Text may be at most 5 words, and a Back-Cover Text
may be at most 25 words.
240
copy made in an otherwise Transparent file format whose
markup, or absence of markup, has been arranged to thwart or
discourage subsequent modification by readers is not
Transparent. An image format is not Transparent if used for any
substantial amount of text. A copy that is not "Transparent" is
called "Opaque".
The "Title Page" means, for a printed book, the title page itself,
plus such following pages as are needed to hold, legibly, the
material this License requires to appear in the title page. For
works in formats which do not have any title page as such, "Title
Page" means the text near the most prominent appearance of the
work's title, preceding the beginning of the body of the text.
241
warranties: any other implication that these Warranty
Disclaimers may have is void and has no effect on the meaning of
this License.
2. VERBATIM COPYING
You may copy and distribute the Document in any medium, either
commercially or noncommercially, provided that this License, the
copyright notices, and the license notice saying this License
applies to the Document are reproduced in all copies, and that
you add no other conditions whatsoever to those of this License.
You may not use technical measures to obstruct or control the
reading or further copying of the copies you make or distribute.
However, you may accept compensation in exchange for copies.
If you distribute a large enough number of copies you must also
follow the conditions in section 3.
You may also lend copies, under the same conditions stated
above, and you may publicly display copies.
3. COPYING IN QUANTITY
If the required texts for either cover are too voluminous to fit
legibly, you should put the first ones listed (as many as fit
reasonably) on the actual cover, and continue the rest onto
adjacent pages.
242
readable Transparent copy along with each Opaque copy, or
state in or with each Opaque copy a computer-network location
from which the general network-using public has access to
download using public-standard network protocols a complete
Transparent copy of the Document, free of added material. If you
use the latter option, you must take reasonably prudent steps,
when you begin distribution of Opaque copies in quantity, to
ensure that this Transparent copy will remain thus accessible at
the stated location until at least one year after the last time you
distribute an Opaque copy (directly or through your agents or
retailers) of that edition to the public.
4. MODIFICATIONS
243
• E. Add an appropriate copyright notice for your modifications
adjacent to the other copyright notices.
• F. Include, immediately after the copyright notices, a license
notice giving the public permission to use the Modified Version
under the terms of this License, in the form shown in the
Addendum below.
• G. Preserve in that license notice the full lists of Invariant
Sections and required Cover Texts given in the Document's
license notice.
• H. Include an unaltered copy of this License.
• I. Preserve the section Entitled "History", Preserve its Title,
and add to it an item stating at least the title, year, new
authors, and publisher of the Modified Version as given on the
Title Page. If there is no section Entitled "History" in the
Document, create one stating the title, year, authors, and
publisher of the Document as given on its Title Page, then add
an item describing the Modified Version as stated in the
previous sentence.
• J. Preserve the network location, if any, given in the Document
for public access to a Transparent copy of the Document, and
likewise the network locations given in the Document for
previous versions it was based on. These may be placed in the
"History" section. You may omit a network location for a work
that was published at least four years before the Document
itself, or if the original publisher of the version it refers to
gives permission.
• K. For any section Entitled "Acknowledgements" or
"Dedications", Preserve the Title of the section, and preserve
in the section all the substance and tone of each of the
contributor acknowledgements and/or dedications given
therein.
• L. Preserve all the Invariant Sections of the Document,
unaltered in their text and in their titles. Section numbers or
the equivalent are not considered part of the section titles.
• M. Delete any section Entitled "Endorsements". Such a section
may not be included in the Modified Version.
• N. Do not retitle any existing section to be Entitled
"Endorsements" or to conflict in title with any Invariant
Section.
• O. Preserve any Warranty Disclaimers.
244
If the Modified Version includes new front-matter sections or
appendices that qualify as Secondary Sections and contain no
material copied from the Document, you may at your option
designate some or all of these sections as invariant. To do this,
add their titles to the list of Invariant Sections in the Modified
Version's license notice. These titles must be distinct from any
other section titles.
5. COMBINING DOCUMENTS
The combined work need only contain one copy of this License,
and multiple identical Invariant Sections may be replaced with a
single copy. If there are multiple Invariant Sections with the
same name but different contents, make the title of each such
245
section unique by adding at the end of it, in parentheses, the
name of the original author or publisher of that section if known,
or else a unique number. Make the same adjustment to the
section titles in the list of Invariant Sections in the license notice
of the combined work.
6. COLLECTIONS OF DOCUMENTS
246
aggregate, or the electronic equivalent of covers if the Document
is in electronic form. Otherwise they must appear on printed
covers that bracket the whole aggregate.
8. TRANSLATION
9. TERMINATION
247
have received notice of violation of this License (for any work)
from that copyright holder, and you cure the violation prior to 30
days after your receipt of the notice.
11. RELICENSING
248
"CC-BY-SA" means the Creative Commons Attribution-Share Alike
3.0 license published by Creative Commons Corporation, a not-
for-profit corporation with a principal place of business in San
Francisco, California, as well as future copyleft versions of that
license published by that same organization.
249