Garden environmental telemetry project – part 5

Garden environmental telemetry project – part 1 laid out plans for a simple maker / DIY IoT garden environmental telemetry system.

This article documents a change to the sensor configuration and payload formatter adding another temperature and humidity sensor for the greenhouse.

The sensors are now:

  • ID=1 air temperature and humidity;
  • ID=2 soil temperature and humidity.
  • ID=3 greenhouse temperature and humidity.

The payload contains an 8bit payload version number then six 16bit values for the six sensors. This is parsed by the TTN uplink formatter.

RS485-LN firmware has been upgraded to v1.4.

RS485-LN configuration

See the earlier articles in the series for details of the serial port client and configuration.

123456
AT+DEBUG
AT+BAUDR=4800
AT+DATAUP=0
AT+PAYVER=1
AT+DATACUT1=0,0,0
AT+DATACUT2=0,0,0
AT+DATACUT3=0,0,0 
AT+MBFUN=1
AT+COMMAND1=01 04 00 00 00 02,1
AT+COMMAND2=02 04 00 00 00 02,1
AT+COMMAND3=03 04 00 00 00 02,1
AT+CMDDL1=200
AT+CMDDL2=200
AT+CMDDL3=200

Above, the script sends the password (which if already unlocked will cause an error which can be ignored) and commands to configure sampling of the two sensors, and packaging of the results in the payload.

Above is capture of a complete read sequence, a transaction for each of the three MODBUS devices with two sensors each. The entire sequence takes just under 1500ms.

Above, the first transaction expanded. In all transactions, the time from the end of the request to the start of the response is less than 8ms.

Above is a protocol decode of the first master to slave frame in Sigrok.

Above is a protocol decode of the response slave to master frame in Sigrok. In this case the decoded responses are 753 and 108 for H=75.3% and T=10.8°.

Similar can be done in Salaea’s Logic v2. The problem with both of these tools is that the protocol decode does not work on a stream with mixed master-slave and slave-master frames as one sees with full duplex traffic on a single RS485 bus (as shown in the earlier traces).

An alternative is to monitor the signals inside the RS485LN.

Above, the RS485LN uses a MAX3485 RS485 driver, it is U1 at upper left. Using a SOIC8 test clip (clean the clip and the chip pins with alcohol to remove flux residue etc), we can attach the logic tracer to the chip and capture the master to slave and slave to master traffic on separate lines.

Above is capture of a complete read sequence, a transaction for each of the three MODBUS devices with two sensors each. The entire sequence takes just under 1500ms.

Above is a protocol decode of the second response in Sigrok. In this case the decoded responses are 192 and 157 for H=19.2% and T=15.7°.

Similar can be done in Salaea’s Logic v2, but the decode is not quite as good.

Log capture

The log was captured from the serial port to a phone.

Above, the phone, an OTG cable, a FTDI adapter, and serial cable for the RS485_LN.

14:23:22.218 
DRAGINO RS485-LN Device
14:23:22.234 
Image Version: v1.4.0
14:23:22.267 
LoRaWan Stack: DR-LWS-007
14:23:22.282 
Frequency Band: AU915
14:23:22.314 
DevEui= A8 40 41 64 D1 84 7E 08
14:23:22.346 

14:23:22.346 JoinRequest NbTrials= 72
14:23:22.378 
14:23:22.378 
Please use AT+DEBUG to see debug info
14:23:22.426 
14:23:22.426 ***** UpLinkCounter= 0 *****
14:23:22.458 
TX on freq 918.200 MHz at DR 2
14:23:22.666 txDone
14:23:27.667 RX on freq 927.500 MHz at DR 10
14:23:27.795 rxDone
14:23:27.795 Rssi= -57
14:23:27.811 JOINED
14:23:27.811 

14:23:30.975 ***** UpLinkCounter= 0 *****
14:23:30.991 
TX on freq 917.600 MHz at DR 2
14:23:31.262 RX on freq 923.300 MHz at DR 8
14:23:31.294 txDone
14:23:34.246 AT+DEBUG
14:23:34.266 Enter Debug mode
14:23:34.283 
14:23:34.283 
OK
14:23:36.247 [15068]RX on freq 925700000 Hz at DR 10
14:23:36.343 
14:23:36.343 ADR Message:
14:23:36.359 Channel is CH8_15 
14:23:36.375 TX Datarate change to 4
14:23:36.407 TxPower change to 0
14:23:36.423 NbRep change to 1
14:23:36.455 
14:23:36.455 [15163]rxDone
14:23:36.471 Rssi= -59
14:23:43.006 
14:23:43.006 CMD1     = 01 04 00 00 00 02 71 cb 
14:23:43.054 RETURN1  = 01 04 04 01 64 00 e5 7a 2c 
14:23:43.102 CMD2     = 02 04 00 00 00 02 71 f8 
14:23:43.150 RETURN2  = 02 04 04 00 e7 00 bc 79 02 
14:23:43.198 CMD3     = 03 04 00 00 00 02 70 29 
14:23:43.245 RETURN3  = 03 04 04 01 43 00 f3 68 29 
14:23:43.310 Payload  = 81 01 64 00 e5 00 e7 00 bc 01 43 00 f3 
14:23:43.869 
14:23:43.869 
[22693]***** UpLinkCounter= 1 *****
14:23:43.917 
[22694]TX on freq 918000000 Hz at DR 4
14:23:43.996 [22822]RX on freq 923300000 Hz at DR 8
14:23:44.044 [22824]txDone
14:23:48.998 [27812]RX on freq 926900000 Hz at DR 12
14:23:49.030 
14:23:49.047 [27844]rxDone
14:23:49.062 Rssi= -57

Above is the log file from startup to completion of the first transmission. This illustrates how the payload is build from the responses from the three MODBUS devices.

Uplink formatter

for(var i=0;i<ab.byteLength;i++)abv.setUint8(i,input.bytes[i]);
  var payver=abv.getUint8(0)&0x7f;
  switch(payver){
    case 1:
      if(ab.byteLength<13){return {errors:["Bad payload length"]};}
      result={
        data:{
            field1:abv.getInt16(3)/10,
            field2:abv.getInt16(1)/10,
            field3:abv.getInt16(7)/10,
            field4:abv.getInt16(5)/10,
            field5:abv.getInt16(11)/10,
            field6:abv.getInt16(9)/10
        },
      warnings:[], // optional
      errors:[] // optional (if set, the decoding failed)
      };
      if(abv.getInt16(1)===-1){result.data.field1=null;result.data.field2=null}
      if(abv.getInt16(5)===-1){result.data.field3=null;result.data.field4=null}
      if(abv.getInt16(9)===-1){result.data.field5=null;result.data.field6=null}
      return result;
    default:
      return {errors:["Unknown payver"]};
    }
  }

Above, is the Custom Javascript formatter which writes the measured values into variables fields1-field6 of the data object.

This formatter is for firmware v1.4 which simply returns all ones in fields for MODBUS devices that do not respond with valid data. In this case, the humidity fields should never be -1, so they are used as a test for data valid.

This is not a good general solution. I suggested the following to Dragino:

A possible solution is to add a 16 bit field to the payload with a bit for each AT+COMMANDn to indicate that a valid response was received to that command (ie did not time out waiting for response, good CRC decoded). I could test those bits in the javascript uplink formatter, and supply null if the data was not valid.

This approach would be backwards compatible with v1.03 as it is an additional 16 bit field at the end of the payload, code reading v1.03 payloads would simply ignore the extra two bytes.

Configure Thingspeak channel for the six data fields

The six data fields were displayed in a new channel on Thingspeak.

Write and test Thingspeak webhook

This task is simply collecting the URL and access credentials for write access to the Thingspeak channel.

Above is a capture over some days.

Air time

At this time, the gateway is very close to the RS485-LN, and DR5 (SF7 BW125kHz) is selected by ADR.

Above is a calculation using Semtech’s calculator.

Above is a screenshot from Airtime calculator for LoRaWAN. In checking the Radiocommunications (Low Interference Potential Devices) Class Licence 2015 as ammended 05/03/2022 (latest at time of writing), there is no limitation on dwell time in Australia under that licence. That said, the downloaded MAC data for the device includes “uplink_dwell_time”: true.

To be continued…

Links / references