Figure 1. SHT30 RS485 Sensor “zts-3008-ws-n01”

Intro

I recently picked up a very affordable SHT30 temperature and humidity sensor from AliExpress to use with my STM32 RS485 Modbus embedded controller project. I chose this particular unit because it had a built-in DIN-rail mount, communicated via Modbus RTU over RS485, and was a great candidate for testing hybrid master/slave communication on my controller.

As you might expect with ultra-budget hardware, documentation was practically non-existent – and that turned out to be the main challenge.

While digging around, I came across a GitHub repository linked in a YouTube video, which referenced a similar model number that was printed on the sensor (zts-3008-ws-n01). That repo included a copy of the manufacturer’s Windows configuration tool, which I used to successfully read and write the sensor’s baud rate and slave ID.

However, I’m not a big fan of using black-box software from an unknown source, so I decided to listen to the serial communications to work out what was going on behind the scenes.

Reverse Engineering

I used a serial port sniffer on Windows to capture communication between the configuration tool and the sensor. What I found was a simple 7-byte command protocol (not standard Modbus RTU) that wraps baud/slave configuration into a minimal frame.

Figure 2. Serial communication captured between the manufacturers software and the sensor

What I found

The device accepts a custom 7-byte frame that looks like:

FD FD FD [baud ID] [slave ID] [CRC_L] [CRC_H]
  • Want to query the current baud and slave ID? Set both to 00 and the sensor replies with the real values (in the same frame format, just with the values inserted).
  • Want to set a new baud rate? Set the slave ID to 00 and the baud ID to what you wish to select (0x01 for 2400, 0x02 for 4800, 0x03 for 9600).
  • Want to set the slave ID? Just the opposite – set the baud ID to 00 and pick a new slave ID.

It’s quite simple – just remember to append the CRC which is a standard Modbus RTU CRC16, little-endian, over the first five bytes.

Modbus Data Format

After setup, the sensor behaves like a regular Modbus RTU slave. It supports:

  • Functions 0x03 and 0x04 (Read holding/input registers)
  • Register 0x00 = Relative Humidity
  • Register 0x01 = Temperature

You’ll need to divide the value of the humidity and temperature by 10 to get the proper reading.

Full Protocol + Examples

I’ve documented the entire protocol in a GitHub README, including frame examples and register maps