Electronics Home Automation Solar Power

ModBus to MQTT WiFi Bridge for a Solis 1.5kW Inverter

Using an ESP32 WiFi module to create a ModBus to MQTT WiFi Bridge for a Solis 1.5kW Solar PV Inverter too log data with Home Assistant

In a previous blog post we set up a monitoring system for our Solis PV inverter using a Raspberry Pi. This has worked well for the past 5 months but we now need a Raspberry Pi for another project and as they are very hard to find, we decided that it would be a good opportunity to replace the solar logging Raspberry Pi with something simpler and more energy efficient.

After looking at the various options available we settled on using an ESP32 WiFi module as a bridge between the Modbus interfaces on the Solis inverter and energy meter and the MQTT broker on our home server which runs Home Assistant to log all our smart home data.

Hardware Design

The design would consist of four modules. The ESP32, an RS-485 interface, a temperature sensor for measuring the ambient temperature near the inverter and a light sensor so we can check if the lights have been left on in the room where the inverter is installed.

For the ESP32 module we used an ESP32-WROOM-32U which uses an external antenna. When we first installed the Raspberry Pi, we intended to use the built in WiFi to connect to our server but after testing we found that the signal strength was too low to get a good connection. The 3 metres of concrete between the Raspberry Pi and the WiFi router probably didn’t help. By using the ESP32 module with the antenna socket we could use an external high gain antenna which would provide a better connection to the WiFi router.

PCB and Stencil
PCB and Stencil

The RS-485 module uses a SN65HVD72D transceiver from Texas Instruments. This is the same chip that we use on the RS485 Pi expansion boards that we sell so we were able to copy the schematic from the RS485 Pi with a few small modifications like component sizes and 348R pull-up and pull-down resistors on the RS-485 bus.

The temperature sensor uses a MCP9803-M/SN from Microchip. This is an I2C based 12-bit digital temperature sensor that we have used on several other projects in the past, so we have a good supply of the chips.

For the light sensor a photoresistor was used alongside a 1 megaohm resistor to create a voltage divider. This was connected to one of the ADC inputs on the ESP32 so the voltage would rise and fall with different light levels. Using this approach it would be easy to set a threshold light level for when the light in the room is turned on and off.

To power the circuit we decided to keep using the existing 5V USB charger which powered the Raspberry Pi. As the ESP32 module uses 3.3V a switch-mode power supply was added to drop the 5V down to 3.3V. After looking at the various switch-mode ICs that were available to buy we chose the ST1S40IDR from ST. The ST1S40IDR has a 3A output current and can take a 4.0V to 18V input which will allow us to power the circuit from higher voltage power supplies if needed.

We decided to use the existing DIN rail Raspberry Pi enclosure for the new project so the whole circuit was designed to fit within the size of a Raspberry Pi hat. A USB micro socket was used for the power supply and was positioned in the same location as on a Raspberry Pi so it would align with the existing hole in the enclosure. A 2 pin screw terminal was also added for the power input to give us the option of using wires instead of USB if needed. A 9 pin D-sub connector was used for the RS-485 bus allowing a simple swap with the RS485 Pi used on the existing Raspberry Pi setup.

To increase the accuracy of the temperature sensor the PCB was designed with cut-outs around the sensor IC to reduce thermal bridging with the ESP32 module. The sensor was placed at the bottom of the board with cut-outs in the enclosure below and above the sensor so air convection would bring outside air in past the temperature sensor first before it could be heated by the ESP32 module. After testing we found that this approach gave a temperature reading almost identical to the external 1-wire sensor used on the Raspberry Pi design.

Test points were added around the PCB to allow testing of each section and programming pads were added so we could use a new pogo pin connector which was designed for this and future projects.

After designing and building the board we found a small mistake with a missing pull-up resistor on the PSU enable pin. This was fixed by soldering an 0603 10K resistor between pins 3 and 4 on the IC. The schematic and PCB Gerber files available to download in our GitHub repository include the fix for this error.

Apart from this one mistake the circuit worked well without needing any other modifications.

PCB Soldered
PCB Soldered
PCB Completed
PCB Completed

Software Design

The software for the project was designed in Visual Studio Code using the Platform IO plugin. External libraries were used for the MQTT client, Modbus and Software Serial interfaces.

The software flow is fairly simple. On boot a WiFi connection is established, an MQTT connection is made to our server and a hardware timer is started on a 1-minute interval.

On each timer tick the program first checks that the WiFi and MQTT connections are still active and a reconnection is made if necessary. Next the temperature is read from the sensor and published to the MQTT broker. Data is then fetched from each register address on the energy meter and the values are formatted and published to the MQTT broker.

The solar inverter goes to sleep at night so before fetching the register values from the inverter a test connection is made to check if the inverter is awake. If it is online the register values are fetched and published for all of the relevant data such as power output, PV voltage and current and device temperature. If the inverter is offline zero values are published for most of the registers.

For measuring the light level this was done in the main program loop instead of inside the timer event. This allows any changes in light level to be detected immediately and posted to the MQTT broker. By added an alert event into Home Assistant we can use this as a rudimentary fire / burglar detector, working along side the existing smoke detector which is situated close to the inverter.

To make software development easier we designed a Modbus emulator on a Raspberry Pi which consisted of a python script that creates a Modbus slave device with the same register addresses and values as the real energy meter and solar inverter.

Installation and Testing

Fitted into the DIN rail case
Fitted into the DIN rail case

With the hardware and software complete we fitted the new device in the existing enclosure alongside the solar inverter. After plugging it in and connecting the RS-485 cable we found a couple bugs in the code where 32 bit registers were being read in the wrong byte order, but apart from that everything worked as expected.

Some power measurements were made to compare against the old Raspberry Pi setup and we found that the new ESP32 based design uses between 0.2W and 0.5W when running compared to the 2 to 5W of the Raspberry Pi.



Leave a reply

Your email address will not be published. Required fields are marked *

Share this post

Support the blog

AB Electronics Raspberry Pi shop