• Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search

    Indoor Air Quality (IAQ) sensor modbus connection not working

    Official EVOK API
    2
    4
    107
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • B
      Balardo last edited by

      Hello,
      I'm trying to connect an RW-TH version of the Unipi indoor air quality sensor (IAQ) to an Axon S105 via modbus on RS-485 (port 3).
      After modifying /etc/evok.conf and adding /etc/hw_definitions/testIAQ.yaml the web interface does not show the system parameters and I can't poll any IAQ parameters via json or rest API.

      /etc/evok.conf:

      #!!! Do not use '#' for comments !!!
      
      [MAIN]                                          ; !!! ALL MAIN SECTION OPTIONS ARE MANDATORY !!!
      config_version = 2.5                            ; Configuration file version, DO NOT CHANGE!
      use_schema_verification = False                 ; Enabling this will deny any requests that do not match the JSON Schema; NOTE THAT THIS RESULTS IN A SIGNIFICANT INCREASE IN LATENCY AND SHOULD NOT BE USED EXCEPT FOR TESTING
      log_level = DEBUG                               ; Minimum severity of messages to be logged; one of INFO, DEBUG, WARNING, ERROR, CRITICAL
      log_file = /var/log/evok.log                    ; Log file to use; will be cleared on boot
      port = 8080                                     ; !!! Internal API port - only change if you are certain you know what you are doing; FOR OUR WEB INTERFACE THE PORT SHOULD BE CHANGED IN "/etc/evok-nginx.conf" INSTEAD !!!
      webhook_enabled = False                         ; Enables webhook notification - see e.g. https://sendgrid.com/blog/whats-webhook/
      webhook_address = http://127.0.0.1:80           ; Put your server endpoint address here (e.g. http://123.123.123.123:/wh )
      webhook_device_mask = ["input","wd"]            ; List of device types to notify on (written as a JSON list) - adding AI will generate a large amount of messages!
      webhook_complex_events = False                  ; EVOK will send POST requests with the same data as WebSocket, rather than an empty GET request
      soap_server_enabled = False                     ; Enables the simple SOAP server; use only if you need the functionality
      soap_server_port = 8081                         ; !!! IF SOAP SERVER IS ENABLED, THIS PORT NEEDS TO BE UNIQUE (i.e. different from the port setting above) !!!
      force_immediate_state_changes = False           ; Outputs will return the value they are set to, rather than the value that the device is currently aware of
      websocket_all_filtered = False                  ; 'All' WebSocket requests will be subject to the filtering set by 'filter'
      
      [NEURON_1]
      global_id = 1                                   ; Mandatory, REQUIRED TO BE UNIQUE
      allow_register_access = False                   ; Optional, False default
      scan_frequency = 10                             ; Optional, 10 default, scanning frequency in [Hz]
      scan_enabled = True                             ; Optional, True default
      
      ; Below you can find examples for connecting devices over UART; first example is a Neuron extension while the second is a custom third-party device
      ; Devices sharing a port use the port settings of the first device on that port (baud rate, parity, stop bits)
      ; !!! Note that device_name has to match a filename in the /etc/hw_definitions directory !!! See /etc/hw_definitions/CUSTOM_MODBUS_DEVICE.yaml for an example
      
      [EXTENSION_1]
      global_id = 2                                   ; Mandatory, REQUIRED TO BE UNIQUE
      device_name = testIAQ                           ; Mandatory, must match name of .yaml modbus map file in /etc/hw_definitions
      modbus_uart_port = /dev/ttyS1                   ; Mandatory
      neuron_uart_circuit = 1_01                      ; Optional, allows associating extensions with specific Neuron UART-over-Modbus ports (not possible for non-Modbus UART ports, e.g. /dev/ttyUSB0 or /dev/ttyS0)
      allow_register_access = True                    ; Optional, False default, is mandatory with third-party devices
      address = 1                                     ; Optional, 1 default
      scan_frequency = 10                             ; Optional, 10 default, scanning frequency in [Hz]
      scan_enabled = True                             ; Optional, True default
      ; Note that the following settings will be inherited by other devices sharing the same port, i.e. /dev/extcomm/0/0
      baud_rate = 19200                               ; Optional, NEEDS UNIPI IMAGE TO WORK WITH UNIPI SERIAL PORTS! USE API TO CONFIGURE UART MANUALLY IF USING STANDARD RASPBIAN
      parity = N                                      ; Optional, NEEDS UNIPI IMAGE TO WORK WITH UNIPI SERIAL PORTS! USE API TO CONFIGURE UART MANUALLY IF USING STANDARD RASPBIAN
      stop_bits = 1                                   ; Optional, NEEDS UNIPI IMAGE TO WORK WITH UNIPI SERIAL PORTS! USE API TO CONFIGURE UART MANUALLY IF USING STANDARD RASPBIAN
      
      ;[EXTENSION_2]
      ;global_id = 3                                  ; Mandatory, REQUIRED TO BE UNIQUE
      ;device_name = CUSTOM MODBUS DEVICE             ; Mandatory, must match name of .yaml modbus map file in /etc/hw_definitions
      ;modbus_uart_port = /dev/extcomm/0/0            ; Mandatory
      ;neuron_uart_circuit = 1_01                     ; Optional, allows associating extensions with specific Neuron UART-over-Modbus ports (not possible for non-Modbus UART ports, e.g. /dev/ttyUSB0 or /dev/ttyS0)
      ;allow_register_access = True                   ; Mandatory with third-party devices
      ;address = 1                                    ; Optional, 15 default
      ;scan_frequency = 2                             ; Optional, 1 default, scanning frequency in [Hz]
      ;scan_enabled = True                            ; Optional, True default
      
      [OWBUS_1]
      owbus = /dev/i2c-0                              ; Mandatory, scanned bus (--i2c=/dev/i2c-1:ALL or localhost:2122 or 'u' for USB dongle)
      interval = 3                                    ; Mandatory, [s] length of sensor reading
      scan_interval = 300                             ; Mandatory, [s] How often the scanning is done
      
      ; See below for 1Wire extension module configuration
      ; Example for the 1W-4R/4DI extension module, 1W-8R is almost the same, only with inputs instead of relays
      ;
      ; - Map a new 1Wire sensor with the appropriate address, type and interval
      ; - The syntax can be either SENSOR or 1WDEVICE
      ; - Setting the correct reading interval is crucial to achieve ideal performance; the default interval is 15s
      ;
      ;[1WDEVICE_2]
      ;bus = 1
      ;address = 29F39A17000000BC
      ;type = DS2408
      ;interval = 1
      ;
      ;[1WRELAY_10]
      ;sensor = 2
      ;pin = 0
      ;
      ;[1WRELAY_11]
      ;sensor = 2
      ;pin = 1
      ;
      ;[1WRELAY_12]
      ;sensor = 2
      ;pin = 2
      ;
      ;[1WRELAY_13]
      ;sensor = 2
      ;pin = 3
      ;
      ;[1WINPUT_20]
      ;sensor = 2
      ;pin = 4
      ;
      ;[1WINPUT_21]
      ;sensor = 2
      ;pin = 5
      ;
      ;[1WINPUT_22]
      ;sensor = 2
      ;pin = 6
      ;
      ;[1WINPUT_23]
      ;sensor = 2
      ;pin = 7
      
      

      /etc/hw_definitions/testIAQ.yaml:

      # unipi iaq1926 - Indoor air quality sensor
      # File version: 1.0
      # Min. firmware version: 3.00
      ---
      type: testIAQ
      modbus_register_blocks:
          - board_index : 1
            start_reg   : 0
            count       : 86
            frequency   : 50
            type        : input
      
      modbus_features:
          - type        : UNIT_REGISTER
            name        : "temperature"
            count       : 1
            major_group : 1
            value_reg   : 0
            unit        : "  C"
            datatype    : float32
      
          - type        : UNIT_REGISTER
            name        : "rel_humid"
            count       : 1
            major_group : 1
            value_reg   : 6
            unit        : "%"
            datatype    : float32
      
          - type        : UNIT_REGISTER
            name        : "dew_point"
            count       : 1
            major_group : 1
            value_reg   : 8
            unit        : "  C"
            datatype    : float32
      
          - type        : UNIT_REGISTER
            name        : "abs_humid"
            count       : 1
            major_group : 1
            value_reg   : 10
            unit        : "%"
            datatype    : float32
      
          - type        : UNIT_REGISTER
            name        : "CO2"
            count       : 1
            major_group : 1
            value_reg   : 18
            unit        : "ppm"
            datatype    : float32
      
          - type        : UNIT_REGISTER
            name        : "VOC_index"
            count       : 1
            major_group : 1
            value_reg   : 26
            unit        : "N/A"
            datatype    : float32
      
          - type        : UNIT_REGISTER
            name        : "VOC_precision"
            count       : 1
            major_group : 1
            value_reg   : 28
            unit        : "N/A"
            datatype    : float32
      
          - type        : UNIT_REGISTER
            name        : "VOC_CO2_eq"
            count       : 1
            major_group : 1
            value_reg   : 34
            unit        : "ppm"
            datatype    : float32
      
          - type        : UNIT_REGISTER
            name        : "ambient_light"
            count       : 1
            major_group : 1
            value_reg   : 42
            unit        : "lux"
            datatype    : float32
      
          - type        : UNIT_REGISTER
            name        : "atm_pressure"
            count       : 1
            major_group : 1
            value_reg   : 76
            unit        : "hPa"
            datatype    : float32
      
          - type        : UNIT_REGISTER
            name        : "uptime"
            count       : 1
            major_group : 1
            value_reg   : 84
            unit        : "sec"
            datatype    : float32
      
      

      Config web page before enabling modbus extension:
      modbus disabled.JPG
      Config web page after enabling modbus extension:
      modbus enabled testIAQ.JPG

      The Axon is polling the IAQ sensor periodically as expected, and the sensor responds. The waveforms look good on the oscilloscope.
      When polling the sensor manually from command line with mbpoll, the received data looks good:

      root@S105-sn715:/home/unipi# mbpoll -1 -a 1 -b 19200 -t 3 -r 0 -c 86 -P none /dev/ttyS1 -0
      mbpoll 1.4-12 - FieldTalk(tm) Modbus(R) Master Simulator
      Copyright © 2015-2019 Pascal JEAN, https://github.com/epsilonrt/mbpoll
      This program comes with ABSOLUTELY NO WARRANTY.
      This is free software, and you are welcome to redistribute it
      under certain conditions; type 'mbpoll -w' for details.
      
      Protocol configuration: Modbus RTU
      Slave configuration...: address = [1]
                              start reference = 0, count = 86
      Communication.........: /dev/ttyS1,      19200-8N1
                              t/o 1.00 s, poll rate 1000 ms
      Data type.............: 16-bit register, input register table
      
      -- Polling slave 1...
      [0]:    16824
      [1]:    59049 (-6487)
      [2]:    32704
      [3]:    0
      [4]:    32704
      [5]:    0
      [6]:    16913
      [7]:    53026 (-12510)
      [8]:    16620
      [9]:    53073 (-12463)
      [10]:   16624
      [11]:   48977 (-16559)
      [12]:   32704
      [13]:   0
      [14]:   32704
      [15]:   0
      [16]:   32704
      [17]:   0
      [18]:   32704
      [19]:   0
      [20]:   32704
      [21]:   0
      [22]:   32704
      [23]:   0
      [24]:   32704
      [25]:   0
      [26]:   16864
      [27]:   30269
      [28]:   16256
      [29]:   0
      [30]:   32704
      [31]:   0
      [32]:   32704
      [33]:   0
      [34]:   17404
      [35]:   44002 (-21534)
      [36]:   32704
      [37]:   0
      [38]:   32704
      [39]:   0
      [40]:   32704
      [41]:   0
      [42]:   16757
      [43]:   9542
      [44]:   32704
      [45]:   0
      [46]:   32704
      [47]:   0
      [48]:   32704
      [49]:   0
      [50]:   32704
      [51]:   0
      [52]:   32704
      [53]:   0
      [54]:   32704
      [55]:   0
      [56]:   32704
      [57]:   0
      [58]:   32704
      [59]:   0
      [60]:   32704
      [61]:   0
      [62]:   32704
      [63]:   0
      [64]:   32704
      [65]:   0
      [66]:   32704
      [67]:   0
      [68]:   32704
      [69]:   0
      [70]:   32704
      [71]:   0
      [72]:   32704
      [73]:   0
      [74]:   32704
      [75]:   0
      [76]:   17532
      [77]:   61276 (-4260)
      [78]:   32704
      [79]:   0
      [80]:   32704
      [81]:   0
      [82]:   32704
      [83]:   0
      [84]:   17590
      [85]:   40960 (-24576)
      

      The /var/log/evok.log does not contain any useful information despite the fact that the log level was set to DEBUG:

      2020-09-18 16:09:19,489 - evok - INFO - Starting using config file /etc/evok.conf
      2020-09-18 16:09:19,554 - evok - INFO - YAML Definition loaded: xG18.yaml, type: 3, definition count 0
      2020-09-18 16:09:19,624 - evok - INFO - YAML Definition loaded: xS10.yaml, type: 3, definition count 1
      2020-09-18 16:09:19,708 - evok - INFO - YAML Definition loaded: xS50.yaml, type: 3, definition count 2
      2020-09-18 16:09:19,777 - evok - INFO - YAML Definition loaded: xS40.yaml, type: 3, definition count 3
      2020-09-18 16:09:19,879 - evok - INFO - YAML Definition loaded: /etc/hw_definitions/BuiltIn/S105.yaml, type: UniPiBuiltIn
      2020-09-18 16:09:19,944 - evok - INFO - YAML Definition loaded: xS11.yaml, type: 3, definition count 4
      2020-09-18 16:09:19,974 - evok - INFO - YAML Definition loaded: CUSTOM_MODBUS_DEVICE.yaml, type: 3, definition count 5
      2020-09-18 16:09:20,041 - evok - INFO - YAML Definition loaded: xS30.yaml, type: 3, definition count 6
      2020-09-18 16:09:20,125 - evok - INFO - YAML Definition loaded: xS51.yaml, type: 3, definition count 7
      2020-09-18 16:09:20,215 - evok - INFO - YAML Definition loaded: testIAQ.yaml, type: 3, definition count 8
      2020-09-18 16:09:20,226 - evok - INFO - YAML Definition loaded: evok-alias.yaml, type: 2, definition count 0
      2020-09-18 16:09:20,264 - evok - INFO - HTTP server listening on port: 8080
      2020-09-18 16:09:20,311 - evok - INFO - SPI client started
      2020-09-18 16:09:20,317 - evok - INFO - Entering OWW loop with PID 739
      2020-09-18 16:09:20,318 - evok - INFO - Reading the UART board on Modbus address 1
      2020-09-18 16:09:20,325 - evok - INFO - Reading SPI boards
      2020-09-18 16:09:20,344 - evok - INFO - No board on SPI 2
      2020-09-18 16:09:20,350 - evok - INFO - No board on SPI 3
      2020-09-18 16:09:20,351 - evok - INFO - Alias loaded: <neuron.Relay object at 0xffff81ed5210> al_lights_kitchen
      2020-09-18 16:09:20,353 - evok - INFO - Alias loaded: <neuron.Relay object at 0xffff81ed5390> al_lights_bedroom
      2020-09-18 16:09:20,461 - evok - INFO - Alias loaded: <neuron.Relay object at 0xffff81ed5210> al_lights_kitchen
      2020-09-18 16:09:20,464 - evok - INFO - Alias loaded: <neuron.Relay object at 0xffff81ed5390> al_lights_bedroom
      2020-09-18 16:09:30,402 - evok - DEBUG - New WebSocket client connected
      2020-09-18 16:10:00,860 - evok - DEBUG - New WebSocket client connected
      

      There seems to be a problem with the parsing of the incoming modbus data.
      I would really appreciate some ideas on how to get this to work.
      Thank you!

      1 Reply Last reply Reply Quote 0
      • M
        martin_triska administrators last edited by

        Hello @Balardo,

        can you please share reply to the /rest/all GET request?
        e.g. type http://<IP OF YOUR UNIT>/rest/all to your browser.

        1 Reply Last reply Reply Quote 0
        • B
          Balardo last edited by

          Hello @martin_triska,

          There is the result of the /rest/all request:

          [{"counter_modes": ["Enabled", "Disabled"], "glob_dev_id": 1, "modes": ["Simple", "DirectSwitch"], "value": 0, "circuit": "1_01", "debounce": 50, "counter": 0, "counter_mode": "Enabled", "dev": "input", "mode": "Simple"}, {"counter_modes": ["Enabled", "Disabled"], "glob_dev_id": 1, "modes": ["Simple", "DirectSwitch"], "value": 0, "circuit": "1_02", "debounce": 50, "counter": 0, "counter_mode": "Enabled", "dev": "input", "mode": "Simple"}, {"counter_modes": ["Enabled", "Disabled"], "glob_dev_id": 1, "modes": ["Simple", "DirectSwitch"], "value": 0, "circuit": "1_03", "debounce": 50, "counter": 0, "counter_mode": "Enabled", "dev": "input", "mode": "Simple"}, {"counter_modes": ["Enabled", "Disabled"], "glob_dev_id": 1, "modes": ["Simple", "DirectSwitch"], "value": 0, "circuit": "1_04", "debounce": 50, "counter": 0, "counter_mode": "Enabled", "dev": "input", "mode": "Simple"}, {"relay_type": "digital", "glob_dev_id": 1, "pwm_duty": 0, "dev": "relay", "modes": ["Simple", "PWM"], "pwm_freq": 39, "value": 0, "alias": "al_lights_kitchen", "mode": "Simple", "circuit": "1_01", "pending": false}, {"relay_type": "digital", "glob_dev_id": 1, "pwm_duty": 0, "dev": "relay", "modes": ["Simple", "PWM"], "pwm_freq": 39, "value": 0, "alias": "al_lights_bedroom", "mode": "Simple", "circuit": "1_02", "pending": false}, {"pwm_duty": 0, "glob_dev_id": 1, "pwm_freq": 39, "modes": ["Simple", "PWM"], "value": 0, "circuit": "1_03", "pending": false, "relay_type": "digital", "dev": "relay", "mode": "Simple"}, {"pwm_duty": 0, "glob_dev_id": 1, "pwm_freq": 39, "modes": ["Simple", "PWM"], "value": 0, "circuit": "1_04", "pending": false, "relay_type": "digital", "dev": "relay", "mode": "Simple"}, {"glob_dev_id": 1, "unit": "V", "range_modes": ["10.0"], "value": 0.012965346525057231, "circuit": "1_01", "modes": ["Voltage", "Current"], "range": "10.0", "dev": "ai", "mode": "Voltage"}, {"modes": ["Voltage", "Current", "Resistance"], "value": 0.0, "glob_dev_id": 1, "dev": "ao", "circuit": "1_01", "unit": "V", "mode": "Voltage"}, {"value": 0, "circuit": "1_01", "dev": "led", "glob_dev_id": 1}, {"value": 0, "circuit": "1_02", "dev": "led", "glob_dev_id": 1}, {"value": 0, "circuit": "1_03", "dev": "led", "glob_dev_id": 1}, {"value": 0, "circuit": "1_04", "dev": "led", "glob_dev_id": 1}, {"circuit": "1_01", "value": 0, "glob_dev_id": 1, "dev": "wd", "timeout": 5000, "was_wd_reset": 0, "nv_save": 0}, {"glob_dev_id": 1, "last_comm": 0.03806304931640625, "ver2": "0.2", "sn": 715, "circuit": "1", "model": "S105", "dev": "neuron", "board_count": 1}, {"uart_circuit": "1_01", "dev": "extension", "glob_dev_id": 2, "last_comm": 4.979914903640747, "circuit": "UART_1_2", "model": "testIAQ", "uart_port": "/dev/ttyS1"}, {"conf_value": 3262, "glob_dev_id": 1, "sw_address": 0, "parity_modes": ["None", "Odd", "Even"], "stopb_modes": ["One", "Two"], "speed_modes": ["2400bps", "4800bps", "9600bps", "19200bps", "38400bps", "57600bps", "115200bps"], "dev": "uart", "circuit": "1_01", "parity_mode": "None", "stopb_mode": "One", "speed_mode": "19200bps"}, {"bus": "/dev/i2c-0", "interval": 3.0, "dev": "owbus", "scan_interval": 300.0, "circuit": "1", "do_scan": false, "do_reset": false}, {"name": "dew_point", "value": 12.253130912780762, "glob_dev_id": 2, "dev": "unit_register", "circuit": "UART_1_2_8", "unit": "\u00b0C"}, {"name": "CO2", "value": NaN, "glob_dev_id": 2, "dev": "unit_register", "circuit": "UART_1_2_18", "unit": "ppm"}, {"name": "rel_humid", "value": 57.526512145996094, "glob_dev_id": 2, "dev": "unit_register", "circuit": "UART_1_2_6", "unit": "%"}, {"name": "temperature", "value": 20.957672119140625, "glob_dev_id": 2, "dev": "unit_register", "circuit": "UART_1_2_0", "unit": "\u00b0C"}, {"name": "abs_humid", "value": 10.488215446472168, "glob_dev_id": 2, "dev": "unit_register", "circuit": "UART_1_2_10", "unit": "%"}, {"name": "VOC_CO2_eq", "value": 490.800048828125, "glob_dev_id": 2, "dev": "unit_register", "circuit": "UART_1_2_34", "unit": "ppm"}, {"name": "VOC_index", "value": 19.734819412231445, "glob_dev_id": 2, "dev": "unit_register", "circuit": "UART_1_2_26", "unit": "N/A"}, {"name": "uptime", "value": 1274.0, "glob_dev_id": 2, "dev": "unit_register", "circuit": "UART_1_2_84", "unit": "sec"}, {"name": "ambient_light", "value": 22.00320053100586, "glob_dev_id": 2, "dev": "unit_register", "circuit": "UART_1_2_42", "unit": "lux"}, {"name": "atm_pressure", "value": 999.4600219726562, "glob_dev_id": 2, "dev": "unit_register", "circuit": "UART_1_2_76", "unit": "hPa"}, {"name": "VOC_precision", "value": 1.0, "glob_dev_id": 2, "dev": "unit_register", "circuit": "UART_1_2_28", "unit": "N/A"}]
          

          It looks like the IAQ sensor is being read, the data looks good.
          Interestingly /rest/all works, but /json/all returns {"status": "error", "message": "Internal Server Error", "code": 500}
          What could be the problem with the json request?
          On what address could we read the sensor? (ex: /res/testIAQ/temperature)
          Thank you for you help.

          1 Reply Last reply Reply Quote 0
          • M
            martin_triska administrators last edited by

            Hello @Balardo,

            you are right - there was a bug in schema validation for /json/all endpoint. It should be fixed in the next release.

            According to the direct Modbus unit register access - you can use e.g.
            http://<your IP>/json/unit_register/UART_15_2_42

            to get the ambient_light register:

            {"status": "success", "data": {"name": "ambient_light", "value": 122.51519775390625, "glob_dev_id": 2, "dev": "unit_register", "circuit": "UART_15_2_42", "unit": "lux"}}
            

            Register values has been also added to the web control panel:

            01638744-d5ad-43e4-bc7f-e98cca7e5678-image.png

            You can test it by install the test version:

            sudo su
            apt update && apt install evok=2.3.3.test.20200923165635*
            
            1 Reply Last reply Reply Quote 0
            • First post
              Last post