diff --git a/examples/lime2-mod-io-relay-on_off.py b/examples/lime2-mod-io-relay-on_off.py
index f316c946557ed5b35c90231e27216156ebee8c1c..eecef82fca9ceaaefc109286c5aa3da5ef21d8f9 100644
--- a/examples/lime2-mod-io-relay-on_off.py
+++ b/examples/lime2-mod-io-relay-on_off.py
@@ -47,7 +47,7 @@ olimex@a20-olinuxino:~$ sudo bash
 root@a20-olinuxino:~# apt install htop tig git etckeeper vim curl python3 python3-venv python3-pip
 root@a20-olinuxino:~# python3 -m pip install --upgrade pip setuptools wheel
 root@a20-olinuxino:~# pip3 install pyA20Lime2
-root@a20-olinuxino:~# pip3 install  -U pymodbus
+root@a20-olinuxino:~# pip3 install  -U pymodbus[twisted]
 
 # enable i2c-1 by running and selecting it (temporary step until fixed by Olimex but not needed for debian 10!)
 root@a20-olinuxino:~# olinuxino-overlay
diff --git a/examples/modbus/custom_message.py b/examples/modbus/custom_message.py
new file mode 100644
index 0000000000000000000000000000000000000000..dbb5950408c8565072d5278d46e9d0805df48d5d
--- /dev/null
+++ b/examples/modbus/custom_message.py
@@ -0,0 +1,125 @@
+#!/usr/bin/env python
+"""
+Pymodbus Synchronous Client Examples
+--------------------------------------------------------------------------
+
+The following is an example of how to use the synchronous modbus client
+implementation from pymodbus.
+
+It should be noted that the client can also be used with
+the guard construct that is available in python 2.5 and up::
+
+    with ModbusClient('127.0.0.1') as client:
+        result = client.read_coils(1,10)
+        print result
+"""
+import struct
+# --------------------------------------------------------------------------- #
+# import the various server implementations
+# --------------------------------------------------------------------------- #
+from pymodbus.pdu import ModbusRequest, ModbusResponse, ModbusExceptions
+from pymodbus.client.sync import ModbusTcpClient as ModbusClient
+from pymodbus.bit_read_message import ReadCoilsRequest
+from pymodbus.compat import int2byte, byte2int
+# --------------------------------------------------------------------------- #
+# configure the client logging
+# --------------------------------------------------------------------------- #
+import logging
+logging.basicConfig()
+log = logging.getLogger()
+log.setLevel(logging.DEBUG)
+
+# --------------------------------------------------------------------------- #
+# create your custom message
+# --------------------------------------------------------------------------- #
+# The following is simply a read coil request that always reads 16 coils.
+# Since the function code is already registered with the decoder factory,
+# this will be decoded as a read coil response. If you implement a new 
+# method that is not currently implemented, you must register the request
+# and response with a ClientDecoder factory.
+# --------------------------------------------------------------------------- #
+
+
+class CustomModbusResponse(ModbusResponse):
+    function_code = 55
+    _rtu_byte_count_pos = 2
+
+    def __init__(self, values=None, **kwargs):
+        ModbusResponse.__init__(self, **kwargs)
+        self.values = values or []
+    
+    def encode(self):
+        """ Encodes response pdu
+
+        :returns: The encoded packet message
+        """
+        result = int2byte(len(self.values) * 2)
+        for register in self.values:
+            result += struct.pack('>H', register)
+        return result
+
+    def decode(self, data):
+        """ Decodes response pdu
+
+        :param data: The packet data to decode
+        """
+        byte_count = byte2int(data[0])
+        self.values = []
+        for i in range(1, byte_count + 1, 2):
+            self.values.append(struct.unpack('>H', data[i:i + 2])[0])
+
+
+class CustomModbusRequest(ModbusRequest):
+
+    function_code = 55
+    _rtu_frame_size = 8
+
+    def __init__(self, address=None, **kwargs):
+        ModbusRequest.__init__(self, **kwargs)
+        self.address = address
+        self.count = 16
+
+    def encode(self):
+        return struct.pack('>HH', self.address, self.count)
+
+    def decode(self, data):
+        self.address, self.count = struct.unpack('>HH', data)
+
+    def execute(self, context):
+        if not (1 <= self.count <= 0x7d0):
+            return self.doException(ModbusExceptions.IllegalValue)
+        if not context.validate(self.function_code, self.address, self.count):
+            return self.doException(ModbusExceptions.IllegalAddress)
+        values = context.getValues(self.function_code, self.address,
+                                   self.count)
+        return CustomModbusResponse(values)
+
+# --------------------------------------------------------------------------- #
+# This could also have been defined as
+# --------------------------------------------------------------------------- #
+
+
+class Read16CoilsRequest(ReadCoilsRequest):
+
+    def __init__(self, address, **kwargs):
+        """ Initializes a new instance
+
+        :param address: The address to start reading from
+        """
+        ReadCoilsRequest.__init__(self, address, 16, **kwargs)
+
+# --------------------------------------------------------------------------- #
+# execute the request with your client
+# --------------------------------------------------------------------------- #
+# using the with context, the client will automatically be connected
+# and closed when it leaves the current scope.
+# --------------------------------------------------------------------------- #
+
+
+if __name__ == "__main__":
+    with ModbusClient(host='localhost', port=5020) as client:
+        client.register(CustomModbusResponse)
+        request = CustomModbusRequest(1, unit=1)
+        result = client.execute(request)
+        print(result.values)
+
diff --git a/examples/modbus/modbus-client.py b/examples/modbus/modbus-client.py
new file mode 100644
index 0000000000000000000000000000000000000000..0619200181578dfa051a2cb19a27e672d4e8507d
--- /dev/null
+++ b/examples/modbus/modbus-client.py
@@ -0,0 +1,7 @@
+from pymodbus.client.sync import ModbusTcpClient
+
+client = ModbusTcpClient('localhost')
+client.write_coil(1, True)
+result = client.read_coils(1,1)
+print(result.bits[0])
+client.close()
diff --git a/examples/modbus/modbus-server.py b/examples/modbus/modbus-server.py
new file mode 100644
index 0000000000000000000000000000000000000000..fbf3f1c00f943abbc14eacdf8a0914de64951723
--- /dev/null
+++ b/examples/modbus/modbus-server.py
@@ -0,0 +1,151 @@
+#!/usr/bin/env python
+"""
+Pymodbus Asynchronous Server Example
+--------------------------------------------------------------------------
+
+The asynchronous server is a high performance implementation using the
+twisted library as its backend.  This allows it to scale to many thousands
+of nodes which can be helpful for testing monitoring software.
+"""
+# --------------------------------------------------------------------------- # 
+# import the various server implementations
+# --------------------------------------------------------------------------- # 
+from pymodbus.server.asynchronous import StartTcpServer
+from pymodbus.server.asynchronous import StartUdpServer
+from pymodbus.server.asynchronous import StartSerialServer
+
+from pymodbus.device import ModbusDeviceIdentification
+from pymodbus.datastore import ModbusSequentialDataBlock
+from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext
+from pymodbus.transaction import (ModbusRtuFramer,
+                                  ModbusAsciiFramer,
+                                  ModbusBinaryFramer)
+from custom_message import CustomModbusRequest
+
+# --------------------------------------------------------------------------- # 
+# configure the service logging
+# --------------------------------------------------------------------------- # 
+import logging
+FORMAT = ('%(asctime)-15s %(threadName)-15s'
+          ' %(levelname)-8s %(module)-15s:%(lineno)-8s %(message)s')
+logging.basicConfig(format=FORMAT)
+log = logging.getLogger()
+log.setLevel(logging.DEBUG)
+
+
+def run_async_server():
+    # ----------------------------------------------------------------------- # 
+    # initialize your data store
+    # ----------------------------------------------------------------------- # 
+    # The datastores only respond to the addresses that they are initialized to
+    # Therefore, if you initialize a DataBlock to addresses from 0x00 to 0xFF,
+    # a request to 0x100 will respond with an invalid address exception.
+    # This is because many devices exhibit this kind of behavior (but not all)
+    #
+    #     block = ModbusSequentialDataBlock(0x00, [0]*0xff)
+    #
+    # Continuing, you can choose to use a sequential or a sparse DataBlock in
+    # your data context.  The difference is that the sequential has no gaps in
+    # the data while the sparse can. Once again, there are devices that exhibit
+    # both forms of behavior::
+    #
+    #     block = ModbusSparseDataBlock({0x00: 0, 0x05: 1})
+    #     block = ModbusSequentialDataBlock(0x00, [0]*5)
+    #
+    # Alternately, you can use the factory methods to initialize the DataBlocks
+    # or simply do not pass them to have them initialized to 0x00 on the full
+    # address range::
+    #
+    #     store = ModbusSlaveContext(di = ModbusSequentialDataBlock.create())
+    #     store = ModbusSlaveContext()
+    #
+    # Finally, you are allowed to use the same DataBlock reference for every
+    # table or you you may use a seperate DataBlock for each table.
+    # This depends if you would like functions to be able to access and modify
+    # the same data or not::
+    #
+    #     block = ModbusSequentialDataBlock(0x00, [0]*0xff)
+    #     store = ModbusSlaveContext(di=block, co=block, hr=block, ir=block)
+    #
+    # The server then makes use of a server context that allows the server to
+    # respond with different slave contexts for different unit ids. By default
+    # it will return the same context for every unit id supplied (broadcast
+    # mode).
+    # However, this can be overloaded by setting the single flag to False
+    # and then supplying a dictionary of unit id to context mapping::
+    #
+    #     slaves  = {
+    #         0x01: ModbusSlaveContext(...),
+    #         0x02: ModbusSlaveContext(...),
+    #         0x03: ModbusSlaveContext(...),
+    #     }
+    #     context = ModbusServerContext(slaves=slaves, single=False)
+    #
+    # The slave context can also be initialized in zero_mode which means that a
+    # request to address(0-7) will map to the address (0-7). The default is
+    # False which is based on section 4.4 of the specification, so address(0-7)
+    # will map to (1-8)::
+    #
+    #     store = ModbusSlaveContext(..., zero_mode=True)
+    # ----------------------------------------------------------------------- # 
+    store = ModbusSlaveContext(
+        di=ModbusSequentialDataBlock(0, [17]*100),
+        co=ModbusSequentialDataBlock(0, [17]*100),
+        hr=ModbusSequentialDataBlock(0, [17]*100),
+        ir=ModbusSequentialDataBlock(0, [17]*100))
+    store.register(CustomModbusRequest.function_code, 'cm',
+                   ModbusSequentialDataBlock(0, [17] * 100))
+    context = ModbusServerContext(slaves=store, single=True)
+    
+    # ----------------------------------------------------------------------- # 
+    # initialize the server information
+    # ----------------------------------------------------------------------- # 
+    # If you don't set this or any fields, they are defaulted to empty strings.
+    # ----------------------------------------------------------------------- # 
+    identity = ModbusDeviceIdentification()
+    identity.VendorName = 'Pymodbus'
+    identity.ProductCode = 'PM'
+    identity.VendorUrl = 'http://github.com/bashwork/pymodbus/'
+    identity.ProductName = 'Pymodbus Server'
+    identity.ModelName = 'Pymodbus Server'
+    identity.MajorMinorRevision = '2.3.0'
+    
+    # ----------------------------------------------------------------------- # 
+    # run the server you want
+    # ----------------------------------------------------------------------- # 
+
+    # TCP Server
+
+    StartTcpServer(context, identity=identity, address=("localhost", 502),
+                   custom_functions=[CustomModbusRequest])
+
+    # TCP Server with deferred reactor run
+
+    # from twisted.internet import reactor
+    # StartTcpServer(context, identity=identity, address=("localhost", 5020),
+    #                defer_reactor_run=True)
+    # reactor.run()
+
+    # Server with RTU framer
+    # StartTcpServer(context, identity=identity, address=("localhost", 5020),
+    #                framer=ModbusRtuFramer)
+
+    # UDP Server
+    # StartUdpServer(context, identity=identity, address=("127.0.0.1", 5020))
+
+    # RTU Server
+    # StartSerialServer(context, identity=identity,
+    #                   port='/dev/ttyp0', framer=ModbusRtuFramer)
+
+    # ASCII Server
+    # StartSerialServer(context, identity=identity,
+    #                   port='/dev/ttyp0', framer=ModbusAsciiFramer)
+
+    # Binary Server
+    # StartSerialServer(context, identity=identity,
+    #                   port='/dev/ttyp0', framer=ModbusBinaryFramer)
+
+
+if __name__ == "__main__":
+    run_async_server()
+