Because very often the serial comm goes over UART, and attaching a device over wifi is the minimalistic way to avoid wiring.
Because standard modules with well-established firmware are the easiest way.
The method provides just the raw UART over socket. No virtual COM ports. No RFC2217 support for in-band control lines and port setting.
If these are needed, either use another approach (eg. sw_SerialOverIP_RFC2217) or implement out-of-band control of the lines
over GPIOs available.
The surplus GPIOs on the module can be used for attaching additional sensors and ADCs, for eg. monitoring temperature of the device under control, or switching it on/off, via standard Tasmota's HTTP or MQTT API.
The solution is tested with MODBUS protocol. Full binary communication is possible.
When wired communication is needed, another approach can be used, via eg. serial-over-Ethernet modules.
Use a module with ESP8266 or compatible. One of most comfortable firmwares to use is Tasmota
. For the sake of example,
the Wemos D1 Mini is chosen as it is used in the prototype tested.
The ESP8266 has two serial ports, primary (Tx0/Rx0) and secondary (Tx1/Rx1), on these pins:
The primary port is used as Tasmota's serial console. On some modules it is attached to USB-UART converter. The chip's bootloader also outputs data there during boot, typically at 74880 bps, which looks like binary garbage at other speeds and can confuse attached hardware. Disabling the serial console also disposes of the ability to easily reconfigure the device, eg. when changing networks.
The secondary port is therefore a better choice. Not the straightest, though.
The GPIO15 comes with a gotcha that can bite the unwary. At boot time, it serves as a selector between booting from internal flash (pulled L) vs running in SDIO mode (sdcard) (pulled H). To run properly, it has to be pulled L. On Wemos module, this is via a 10k resistor.
The UART is H when inactive. This precludes having the Rx1/GPIO15 connected directly. A diode, preferably Schottky, is a solution; anode to GPIO15, cathode to device's UART.
During tests, with the diode between the device's UART and chip's GPIO15, the chip booted properly. The data sent through the pin were however relayed as binary garbage. Scope check shown nice rectangular serial data on diode's anode, and narrow peaks on the cathode; the pulldown is holding the signal L, and the H spikes are all that gets through the diode's capacitance. Oops.
The internal pullup on the pin is grossly insufficient against the fixed 10k pulldown. It has to be aided with a resistor. But a fixed resistor from Vcc will go against the pulldown necessary on power-on time.
Switched pullup to the rescue.
Sacrifice one of the plentiful GPIOs. Let's choose GPIO12 for being nearby on the module used. Configure it to fixed H state. On power-on moment, it is in high-impedance state. Only after the firmware boots and initializes the pins, it goes high. This provides more than enough time for the chip to start in the proper mode.
The suitable values for the resistor are 2k2 and 3k3, assuming the 10k pulldown. Lower value gives higher current load, higher gives lower voltage at H. Chip datasheet promises H level on input to be guaranteed at 75% of Vcc. 3k3 narrowly reaches over this limit, 2k2 is comfortably within. 1k may be pushing the load of the device's UART.
The Tx line on GPIO13 requires no additional hardware. A pullup resistor of 10-100k can be used if the slave UART on the other side gets random garbage during when the chip is booting and the pin is at high impedance.
2k2 GPIO12/D6 o-----/\/\/\--- | small schottky GPIO15/D8 o--------------*-----|>|-----o | GND o-----/\/\/\--- 10k, built-in
The precompiled firmware flavor used is zbbridge - we are using the same trick as used with bridging Zigbee coordinator modules.
The pins are configured as such:
The port server has to be enabled (and the TCP port specified) after boot. A rule is a convenient way to automate this, for port 8888 as example.
The port speed can be set via command, and is remembered: tcpbaudrate 115200 (max rate)
The port is accessible from the entire local network (security!). Access can be limited to a single individual IP, eg.:
correct:
[160][0.005][100.242]02:41:25.473 SRC: Rule [161][0.000][100.243]02:41:25.474 CMD: Grp 0, Cmd 'TCPSTART', Idx 1, Len 4, Pld 8888, Data '8888' [162][0.007][100.250]02:41:25.477 TCP: Starting TCP server on port 8888 [163][0.002][100.253]02:41:25.484 MQT: stat/SerBridge2/RESULT = {"TCPStart":"Done"}
TCP-serial bridge fails to start:
[105][0.005][20.047]02:40:05.114 SRC: Rule [106][0.000][20.047]02:40:05.115 CMD: Grp 0, Cmd 'TCPSTART', Idx 1, Len 4, Pld 8888, Data '8888' [107][0.009][20.056]02:40:05.120 MQT: stat/SerBridge2/RESULT = {"Command":"Unknown"}common causes:
Detailed description of the TCPserial subsystem at https://tasmota.github.io/docs/Serial-to-TCP-Bridge/.