Read data from Modbus device using NodeMCU

All credit of this post goes to some great tutorial  by Csongor Varga which explains on how to test RS-WS-N01-8 Modbus  temperature and humidity sensor using CAS Modbus scanner and Antony Cartwright (link) which explains how to connect a Modbus device with RS485 connector to Arduino.

Recently I had a chance to integrate Modbus device with NodeMCU .Since I couldn’t find any good material online ,I have been thinking about sharing my learnings on how to read values from Modbus RTU device using NodeMCU for a while.

Modbus is a serial communication protocol and its been used in SCADA system since last 30 years.Versions of the Modbus protocol exist for serial port and for Ethernet and  often referred as Modbus RTU or Modbus TCPIP.There are quite a few documents available online on Modbus and few of my favorites to learn about Modbus protocol is here and here .

The device which we would be using for our testing is RS-WS-N01-8 Modbus  temperature and humidity sensor.I got mine from aliexpress .Unfortunately ,to my surprise it didn’t come with any documentation except for few chinese characters on the device.So I had to spent some time online to get hold of any documents.

Lets talk about testing this device first.There exists a great video by Csongor Varga which explains on how to test this device using CAS Modbus scanner ( download it free from ChipKin) . I recommend to have a look at this since definitely very helpful.Only part where I had to do some more research was on how to connect it to my laptop and test.

RS-WS-N01-8 Modbus sensor has 5 pins.+ and –  pins  should be connected to + and –  of your power source.This sensor exposes RS485 interface so A and B pin should go to A and B of RS485 connector.The last pin should be left free.I got this  USB to RS485  converter (link)  from amazon and it works quite well with our device.Please note other end of this device should go to USB port of your laptop.






Final connection  is as shown below.Please note I am using a 12 V battery as  source to power up RS-WS-N01-8 Modbus sensor.

So by using CAS Modbus scanner we can now test if our modbus sensor is working fine or not.Now lets see how to get our sensor connected with NodeMCU and  read its values.

If we want to connect our Microcontroller to a RS485 device(Modbus sensor in this case) then what we need is a  RS485 to TTL converter.There are different type of RS485 to TTL converter available and the one which normally pops up during search is the one using Max485 chip .

RS-485 can be used either in half duplex mode using a single twisted pair or full duplex using two twisted pair.Most of the cases we would see RS485  in half duplex mode which means same channel(wire) is used for transmitting and receiving signals.Then how does it differentiate  whether to transmit or receive.Well connector has driver enable pins for the same purpose (DE and RE).These pins are connected to any of the GPIO pins of micro-controllers and their value is set HIGH and LOW based on whether we want to transmit or receive. D1 and R0 are transmitter and receiver pins which should go to TX and RX of micro-controller respectively.There is a great video by Antony Cartwright (link) and it explains the whole process on how to give connection and then code as well .

I have tested it with Arduino and it works great with Arduino but this doesn’t work with NodeMCU and the reason is voltage.Though some of the documentation says that it supports anything between 3.3 to 5 V but in reality Max 485 chip based TTL to RS485 converters doesn’t support micro-controllers  running in 3V. There were few discussion in forums as well regarding that.

Recommendation in all those forums was to go with a different connector and the one which I found working was the one given below (link)

Though cost for this converter ended up on a higher side but it works great with NodeMCU. Please note this version of TTL to  RS485  converter module didn’t had pins so I had to solder the pins.It enables automatic transmission so we don’t have to worry about setting the driver enable pins to high or low for transmitter or receiver mode.Also we need to note that RX of this goes to RX of micro controller and TX to TX of microcontroller. The labels are from micro controller point of view and not module so you don’t have to cross connect.TX goes to TX of microcontroller and RX to RX of microcontroller.

The connection goes like this.Like the previous case A and B from TTL to RS485 converter module goes to A and B of Modbus Temperature and Humidity Sensor while the other pin in converter module goes to GND. On the other side VCC and GND pin of converter modulegoes to 3V and GND pin in NodeMCU.TX and RX pin goes to D7 andD8 pin of NodeMCU.Yes D7 and D8 but why?

If we look at pin-layout of NodeMCU  what we would notice is GPIO pins 1 and 3  are defaults for TX and RX.But NodeMCU also gives an extra RX and  TX  which are GPIO pins 13 and 15  and translates to D7 and D8.Snce default RX and TX would be used for flashing the chip we would go ahead with D7 and D8 as our RX and TX pins.

Code exists  in github repo (here) under ESP_MODBUS folder.We use ModbusMaster and SoftwareSerial libraries .ModbusMaster is a  wrapper which makes underlying modbus call very easy for us (documentation).There are few things to understand in this code.

What this code does is to set baud rate of our sensor device. 4800 is baud rate of our Modbus Temperature and Humidity Sensor.This value would change as per your modbus device setting so its good to read device datasheet to know details of Modbus settings.
node.begin(1, mySerial);

Modbus works in a master and slave mode.SlaveID for our sensor device  is preconfigured as 1 by the manufacturer.In majority of the cases setting SlaveID to 1 works but again you need to refer to your device documentation to know what should be the SlaveId.

result = node.readHoldingRegisters(0x40000,2);

Modbus protocol has the concept of Input and Holding registers.The most commonly used register is called a Holding Register, and these can be read or written. The other possible type is Input Register, which is read-only. The exceptions to registers being 16 bits are the coil and the discrete input, which are each 1 bit only.

This function code is used to read the contents of a contiguous block of holding registers in a remote device. In our case starting register value which would hold humidity and temperature value for us is set as 0x4000.We then read the next two register to get these values.Again its always good to refer datasheet of your modbus device to know different holding registers available and their address.

To debug our read operation I have added few extra checks in an “if  loop” like ku8MBSuccess,ku8MBResponseTimedOut,ku8MBInvalidCRC etc.They were added with an intention to give us some pointers incase our call fails.For example, I am working on a pump controller L921/B (datasheet) which uses Modbus protocol to communicate with external unit using RS485 interface and the calls are failing with CRC check code (ku8MBInvalidCRC).Yet to fix this but defintely would write something once I  get it working.

Hope you find this post useful and this helps in configuring and reading values from modbus device which you use with NodeMCU or Arduino.