diff --git a/README.md b/README.md
index 5492f95bbdbcfc4225b3a9ae6b18a710d444728a..445254df65aa937224cf9351bed8fc1d17cf0bbd 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,7 @@ GPIO Modules
 ------------
 
 - Raspberry Pi GPIO (`raspberrypi`)
+- Orange Pi GPIO (`orangepi`)
 - PCF8574 IO chip (`pcf8574`)
 - PiFaceDigital 2 IO board (`piface2`)
 - Beaglebone GPIO (`beaglebone`)
@@ -162,6 +163,18 @@ sensor_inputs:
     digits: 2
 ```
 
+### OrangePi boards
+
+You need to specify what OrangePi board you use
+
+```yaml
+gpio_modules:
+  - name: orangepi
+    module: orangepi
+    board: zero # Supported: ZERO, R1, ZEROPLUS, ZEROPLUS2H5, ZEROPLUS2H3, PCPCPLUS, ONE, LITE, PLUS2E, PC2, PRIME
+    mode: board
+```
+
 #### SSL/TLS
 
 You may want to connect to a remote server, in which case it's a good idea to use an encrypted connection. If the server supports this, then you can supply the relevant config values for the [tls_set()](https://github.com/eclipse/paho.mqtt.python#tls_set) command.
@@ -242,6 +255,11 @@ gpio_modules:
     i2c_bus_num: 1
     chip_addr: 0x20
 
+  - name: orangepi
+    module: orangepi
+    board: r1
+    mode: board
+
 digital_inputs:
   - name: button
     module: raspberrypi
diff --git a/config.example.yml b/config.example.yml
index 156bf83b9cb3ba304b6bac0a5bd61a15667820fb..5ead074e0be02e0cce8a58328ea5e1596d00c9da 100644
--- a/config.example.yml
+++ b/config.example.yml
@@ -18,6 +18,11 @@ gpio_modules:
     module: stdio
     cleanup: no
 
+  - name: orangepi
+    module: orangepi
+    board: zero
+    mode: board
+
 sensor_modules:
   - name: lm75
     module: lm75
diff --git a/pi_mqtt_gpio/modules/orangepi.py b/pi_mqtt_gpio/modules/orangepi.py
new file mode 100644
index 0000000000000000000000000000000000000000..e61cf91c9fe06cbe58092433bf0d20886f7a0c73
--- /dev/null
+++ b/pi_mqtt_gpio/modules/orangepi.py
@@ -0,0 +1,75 @@
+from pi_mqtt_gpio.modules import GenericGPIO, PinDirection, PinPullup
+
+ALLOWED_BOARDS = [
+    'zero', 'r1', 'zeroplus', 'zeroplus2h5', 'zeroplus2h3',
+    'pcpcplus', 'one', 'lite', 'plus2e', 'pc2', 'prime'
+]
+ALLOWED_MODES = ['bcm', 'board', 'mode_soc']
+REQUIREMENTS = ("OrangePi.GPIO",)
+CONFIG_SCHEMA = {
+    "board": {
+        "type": "string",
+        "required": True,
+        "empty": False,
+        "allowed": ALLOWED_BOARDS + list(map(str.upper, ALLOWED_BOARDS))
+    },
+    "mode": {
+        "type": "string",
+        "required": True,
+        "empty": False,
+        "default": "bcm",
+        "allowed": ALLOWED_MODES + list(map(str.upper, ALLOWED_MODES))
+    }
+}
+
+DIRECTIONS = None
+PULLUPS = None
+
+
+class GPIO(GenericGPIO):
+    """
+    Implementation of GPIO class for Orange Pi native GPIO.
+    """
+
+    def __init__(self, config):
+        global DIRECTIONS, PULLUPS
+        import OPi.GPIO as gpio
+
+        self.io = gpio
+        DIRECTIONS = {PinDirection.INPUT: gpio.IN, PinDirection.OUTPUT: gpio.OUT}
+
+        PULLUPS = {
+            PinPullup.OFF: gpio.PUD_OFF,
+            PinPullup.UP: gpio.PUD_UP,
+            PinPullup.DOWN: gpio.PUD_DOWN,
+        }
+
+        board = config["board"].upper()
+        mode = config["mode"].upper()
+        if not hasattr(gpio, board):
+            raise AssertionError("%s board not found" % board)
+        gpio.setboard(getattr(gpio, board))
+        gpio.setmode(getattr(gpio, mode))
+
+    def setup_pin(self, pin, direction, pullup, pin_config):
+        direction = DIRECTIONS[direction]
+
+        if pullup is None:
+            pullup = PULLUPS[PinPullup.OFF]
+        else:
+            pullup = PULLUPS[pullup]
+
+        initial = {None: -1, "low": 0, "high": 1}[pin_config.get("initial")]
+        try:
+            self.io.setup(pin, direction, pull_up_down=pullup, initial=initial)
+        except ValueError as e:
+            raise IOError("channel %d setup failed" % pin) from e
+
+    def set_pin(self, pin, value):
+        self.io.output(pin, value)
+
+    def get_pin(self, pin):
+        return self.io.input(pin)
+
+    def cleanup(self):
+        self.io.cleanup()