Git Product home page Git Product logo

skep's Introduction

Skep: MQTT to Modbus on Arduino

Skep a beehive made from wicker plastered with mud and dung.

Uses MQTT to read and write values in an internal Modbus slave.

Hardware requirements

This software is written for an Arduino Mega 2560 with the rev2 Ethernet Shield (Wiznet W5500) from Arduino.org.

Dependencies

If you want TCP keep-alive for the Modbus side you will need to manualy modify the Modbus-Arduino library by going into the ModbusIP2 folder and uncomment the #define TCP_KEEP_ALIVE line in the ModbusIP2.h file. It is highly recommended to do this.

The software

Acting in one part as a MQTT client this software subscribes to a topic waiting for messages with values to write to its internal Modbus memory. The second part acts as a Modbus slave (server) exposing the values to a Modbus masters (client).

With a set interval, data from the Modbus memory can be published back to the MQTT network to achieve two way communication. Currently this is done using a timer and all the data is publishes even if has changed or not. In the future this might change to achieve a more event based solution.

The MQTT side has access to read/write on all Modbus objects in the internal memory. Discretes and Input Registers can thus be used to represent read only values towards the Modbus interface.

Settings

Settings are stored on a uSD on the Ethernet Shield. Allowing for some changes to be made without having to compile and upload a new firmware.

This is the settings format [key=value] and the following keys are allowed: Network

  • mac: MAC address of the Ethernet Shield
  • ip: IPv4 number
  • netmask: IPV4 netmask
  • gw: IPv4 gateway
  • dns: IPV4 DNS server
  • mqtt_gw: IPv4 MQTT server

Records

  • coils: integer number of coils
  • discretes: integer number of discretes
  • ireg: integer number of input registers
  • hreg: integer number of holding registers

MQTT stuff

  • intopic: topic to subscribe to
  • outtopic: topic to publish messages on
  • pub_interval: integer number of seconds for publish interval
  • publish: list of Modbus memory addresses separated by '\n' on the format:
    • 000001-000029,bool
    • 400003-400004,float
    • 400005-400005,int16
    • 400006-400007,int32

Example of a settings.txt file (root of uSD card)

[mac=AA:BB:CC:DD:EE:FF]
[ip=10.0.0.100]
[netmask=255.255.0.0]
[gw=10.0.0.1]
[mqtt_gw=10.0.0.25]
[coils=10]
[discretes=10]
[ireg=10]
[hreg=10]
[intopic=modbus-mqtt/input]
[outtopic=modbus-mqtt/output]
[pub_interval=60]
[publish=
000001-000010,bool
400001-400002,float]

Data encoding and memory explaination

  • coil numbers span from 000001 to 065536
  • discrete input numbers span from 100001 to 165536
  • input register numbers span from 300001 to 365536
  • holding register numbers span from 400001 to 465536

Both int32 and float are encoded as BigEndian in the Modbus memory and are expected to only be in this format when read and published over MQTT.

MQTT messages

The expected format of a MQTT message is JSON encoded data with the following structure.

Subscribe

    {
      "addr": integer or string like "300001",
      "value": true, false, a float value or an integer,
      "type": "bool", "int16", "int32" or "float"
    }

The values true and false are only allowed when the type is set to bool.

Publish To save space and to not continously publish a lot of messages. The ranges specified in the publish setting will group values together into an array.

If the publish declaration specified 300001-300008,int32 then four integer values like [100,200,300,400] will be published in the message. Only four will be parsed since each Modbus register is 16bit long and a int32 is 32bit long we read two registers at a time to extract the ìnt32 value.

Sending 32 coils as an int32 is currently not supported. But would be much more optimal from a space saving viewpoint.

If the declaration specified float the values at those memory addresses will be parsed as float values.

    {
      "addr": Modbus address such as "300001",
      "data": [
        values,
        ...
      ]
    }

pyModbus write example

from pymodbus.constants import Endian
from pymodbus.payload import BinaryPayloadDecoder
from pymodbus.payload import BinaryPayloadBuilder
from pymodbus.client.sync import ModbusTcpClient as ModbusClient

client = ModbusClient('10.0.0.80')
builder = BinaryPayloadBuilder(byteorder=Endian.Big)
builder.add_32bit_float(22.34)
payload = builder.build()
client.write_registers(0, payload, skip_encode=True, unit=1)

skep's People

Contributors

ganehag avatar ganehag-noda avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.