diff --git a/README.md b/README.md
index 2d8776b0901b45210bc1b754c587c266625674e6..11ccccd1a2a5c8f55af2d9ddfe5234c2e1f95bc4 100644
--- a/README.md
+++ b/README.md
@@ -22,6 +22,7 @@ Sensors
 - BH1750 light level sensor (`bh1750`)
 - DS18S20, DS1822, DS18B20, DS1825, DS28EA00, MAX31850K one-wire temperature sensors: (`ds18b`)
 - HC-SR04 ultrasonic distance sensor (`hcsr04`)
+- MCP3008 analog digital converter (`mcp3008`)
 
 Streams
 -------
@@ -99,6 +100,74 @@ digital_inputs:
     pullup: yes
     pulldown: no
 ```
+
+#### Temporary Set
+
+You may want to set the output to a given value for a certain amount of time. This can be done using the `/set_on_ms` and `/set_off_ms` topics. If an output is already set to that value, it will stay that value for the given amount of milliseconds and then switch to the opposite.
+
+For example, to set an output named `light` on for one second, publish `1000` as the payload to the `myprefix/output/light/set_on_ms` topic.
+
+If you want to force an output to always set to on/off for a configured amount of time, you can add `timed_set_ms` to your output config. This will mean that if you send "ON" to `myprefix/output/light/set`, then it will turn the light on for however many milliseconds are configured in `timed_set_ms` and then turn it off again. Whether the light is on already or not, sending "ON" will make the light eventually turn off after `timed_set_ms` milliseconds. This also works inversely with sending "OFF", which will turn the light off, then on after `timed_set_ms` milliseconds, so don't expect this to always keep your devices set to on/off.
+
+#### Interrupts
+
+Interrupts may be used for inputs instead of polling for raspberry modules. Specify `interrupt` and a strategy `rising`, `falling` or `both` to switch from polling to interrupt mode. The `bouncetime` is default `100ms` but may be changed (at least 1ms). The interrupt trigger will send a configurable `interrupt_payload` (default: `"INT"`) and not the current value of the pin: reading the current pin value in the ISR, returned 'old' values. Reading again in the ISR after 100ms gave 'changed' value, but waiting in ISR is not a good solution. So only a trigger message is transmitted on each ISR trigger.
+
+```yaml
+digital_inputs:
+  - name: button_left
+    module: raspberrypi
+    pin: 23
+    interrupt_payload: "trigger"
+    pullup: no
+    pulldown: yes
+    interrupt: falling
+    bouncetime: 200
+```
+
+### Modules
+
+The IO modules are pluggable and multiple may be used at once. For example, if you have a Raspberry PI with some GPIO pins in use and also a PCF8574 IO expander on the I2C bus, you'd list two modules in the `gpio_modules` section and set up the inputs and outputs accordingly:
+
+```yaml
+mqtt:
+  host: test.mosquitto.org
+  port: 1883
+  user: ""
+  password: ""
+  topic_prefix: pimqttgpio/mydevice
+
+gpio_modules:
+  - name: raspberrypi
+    module: raspberrypi
+
+  - name: pcf8574
+    module: pcf8574
+    i2c_bus_num: 1
+    chip_addr: 0x20
+
+  - name: orangepi
+    module: orangepi
+    board: r1
+    mode: board
+
+digital_inputs:
+  - name: button
+    module: raspberrypi
+    pin: 21  # This device is connected to pin 21 of the Raspberry PI GPIO
+    on_payload: "ON"
+    off_payload: "OFF"
+    pullup: no
+    pulldown: yes
+
+digital_outputs:
+  - name: bell
+    module: pcf8574
+    pin: 2  # This device is connected to pin 2 of the PCF8574 IO expander
+    on_payload: "ON"
+    off_payload: "OFF"
+```
+
 ### Sensors
 
 Receive updates on the value of a sensor by subscribing to the `home/sensor/<sensor input name>` topic. In the following example, this would be `home/sensor/temperature`:
@@ -112,65 +181,73 @@ mqtt:
   topic_prefix: home
 
 sensor_modules:
-  - name: lm75
+  - name: lm75_sensor
     module: lm75
     i2c_bus_num: 1
     chip_addr: 0x48
     cleanup: no  # This optional boolean value sets whether the module's `cleanup()` function will be called when the software exits.
 
-  - name: dht22
+  - name: dht22_sensor
     module: dht22
     type: AM2302 # can be  DHT11, DHT22 or AM2302
     pin: 4
 
-  - name: bh1750
+  - name: bh1750_sensor
     module: bh1750
     i2c_bus_num: 1
     chip_addr: 0x23
 
-  - name: ds18b22
+  - name: ds18b22_sensor
     module: ds18b
     type: DS18S20
     address: 000803702e49
 
-  - name: hcsr04
+  - name: hcsr04_sensor
     module: hcsr04
     pin_echo: 27
     pin_trigger: 17
     burst: 10  # number of measurements for output of distance value in [cm]
+    
+  - name: mcp3008_sensor
+    module: mcp3008
 
 sensor_inputs:
-  - name: temperature
-    module: lm75
+  - name: lm75_temperature
+    module: lm75_sensor
     interval: 15 #interval in seconds, that a value is read from the sensor and a update is published
     digits: 4 # number of digits to be round
 
 - name: dht22_temperature 
-    module: dht22
+    module: dht22_sensor
     interval: 10 #interval in seconds, that a value is read from the sensor and a update is published
     digits: 4 # number of digits to be round
     type: temperature # Can be temperature or humidity
 
 - name: dht22_humidity 
-    module: dht22
+    module: dht22_sensor
     interval: 10 #interval in seconds, that a value is read from the sensor and a update is published
     digits: 4 # number of digits to be round
     type: humidity # Can be temperature or humidity   
 
 - name: bh1750_lux
-    module: bh1750
+    module: bh1750_sensor
     interval: 10
     digits: 2
 
-- name: ds18b22
-    module: ds18b22
+- name: ds18b22_temperature
+    module: ds18b22_sensor
     interval: 60
     digits: 2
 
-  - name: distance
-    module: hcsr04
+  - name: hcsr04_distance
+    module: hcsr04_sensor
     interval: 10  # measurement every 10s
     digits: 1
+    
+  - name: mcp3008_voltage
+    module: mcp3008_sensor
+    interval: 300  # measurement every 5min
+    channel: CH4 # measure on CH4 of MCP3008
 ```
 
 ### Streams
@@ -229,6 +306,7 @@ gpio_modules:
     board: zero # Supported: ZERO, R1, ZEROPLUS, ZEROPLUS2H5, ZEROPLUS2H3, PCPCPLUS, ONE, LITE, PLUS2E, PC2, PRIME
     mode: board
 ```
+### MQTT configuration
 
 #### SSL/TLS
 
@@ -265,74 +343,7 @@ mqtt:
     insecure: yes
 ```
 
-#### Temporary Set
-
-You may want to set the output to a given value for a certain amount of time. This can be done using the `/set_on_ms` and `/set_off_ms` topics. If an output is already set to that value, it will stay that value for the given amount of milliseconds and then switch to the opposite.
-
-For example, to set an output named `light` on for one second, publish `1000` as the payload to the `myprefix/output/light/set_on_ms` topic.
-
-If you want to force an output to always set to on/off for a configured amount of time, you can add `timed_set_ms` to your output config. This will mean that if you send "ON" to `myprefix/output/light/set`, then it will turn the light on for however many milliseconds are configured in `timed_set_ms` and then turn it off again. Whether the light is on already or not, sending "ON" will make the light eventually turn off after `timed_set_ms` milliseconds. This also works inversely with sending "OFF", which will turn the light off, then on after `timed_set_ms` milliseconds, so don't expect this to always keep your devices set to on/off.
-
-#### Interrupts
-
-Interrupts may be used for inputs instead of polling for raspberry modules. Specify `interrupt` and a strategy `rising`, `falling` or `both` to switch from polling to interrupt mode. The `bouncetime` is default `100ms` but may be changed (at least 1ms). The interrupt trigger will send a configurable `interrupt_payload` (default: `"INT"`) and not the current value of the pin: reading the current pin value in the ISR, returned 'old' values. Reading again in the ISR after 100ms gave 'changed' value, but waiting in ISR is not a good solution. So only a trigger message is transmitted on each ISR trigger.
-
-```yaml
-digital_inputs:
-  - name: button_left
-    module: raspberrypi
-    pin: 23
-    interrupt_payload: "trigger"
-    pullup: no
-    pulldown: yes
-    interrupt: falling
-    bouncetime: 200
-```
-
-### Modules
-
-The IO modules are pluggable and multiple may be used at once. For example, if you have a Raspberry PI with some GPIO pins in use and also a PCF8574 IO expander on the I2C bus, you'd list two modules in the `gpio_modules` section and set up the inputs and outputs accordingly:
-
-```yaml
-mqtt:
-  host: test.mosquitto.org
-  port: 1883
-  user: ""
-  password: ""
-  topic_prefix: pimqttgpio/mydevice
-
-gpio_modules:
-  - name: raspberrypi
-    module: raspberrypi
-
-  - name: pcf8574
-    module: pcf8574
-    i2c_bus_num: 1
-    chip_addr: 0x20
-
-  - name: orangepi
-    module: orangepi
-    board: r1
-    mode: board
-
-digital_inputs:
-  - name: button
-    module: raspberrypi
-    pin: 21  # This device is connected to pin 21 of the Raspberry PI GPIO
-    on_payload: "ON"
-    off_payload: "OFF"
-    pullup: no
-    pulldown: yes
-
-digital_outputs:
-  - name: bell
-    module: pcf8574
-    pin: 2  # This device is connected to pin 2 of the PCF8574 IO expander
-    on_payload: "ON"
-    off_payload: "OFF"
-```
-
-### MQTT Status Topic
+#### MQTT Status Topic
 
 MQTT supports a "last will and testament" (LWT) feature which means the server will publish to a configured topic with a message of your choosing if it loses connection to the client unexpectedly. Using this feature, this project can be configured to publish to a status topic as depicted in the following example config:
 
@@ -356,13 +367,13 @@ mqtt:
 
 the status messages will appear on topic `home/office/status`.
 
-### MQTT Client ID
+#### MQTT Client ID
 
 The MQTT client ID identifies your instance of pi-mqtt-gpio with your MQTT broker. It allows the broker to keep track of the state of your instance so that it can resume when it reconnects. This means that the ID _must_ be unique for each instance that connects to the MQTT broker.
 
 Since the MQTT client ID for each instance of pi-mqtt-gpio is based on the `topic_prefix` supplied in config (#24), having multiple instances share the same `topic_prefix` will require you to set a different `client_id` for each:
 
-#### Device 1
+##### Device 1
 
 ```yaml
 mqtt:
@@ -371,7 +382,7 @@ mqtt:
   topic_prefix: home/office
 ```
 
-#### Device 2
+##### Device 2
 
 ```yaml
 mqtt:
diff --git a/pi_mqtt_gpio/modules/mcp3008.py b/pi_mqtt_gpio/modules/mcp3008.py
new file mode 100644
index 0000000000000000000000000000000000000000..18c583a5464cf0437d45d56018208d85e7b72b85
--- /dev/null
+++ b/pi_mqtt_gpio/modules/mcp3008.py
@@ -0,0 +1,58 @@
+from pi_mqtt_gpio.modules import GenericSensor
+import logging
+
+REQUIREMENTS = ("adafruit-mcp3008",)
+
+SENSOR_SCHEMA = {
+    "channel": dict(
+        type="string",
+        required=False,
+        empty=False,
+        default="CH0",
+        allowed=["CH0", "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7",
+                 "DF0", "DF1", "DF2", "DF3", "DF4", "DF5", "DF6", "DF7"],
+    )
+}
+
+_LOG = logging.getLogger("mqtt_gpio")
+
+class Sensor(GenericSensor):
+    """
+    Implementation of MCP3008 ADC sensor.
+    """
+    def __init__(self, config):
+        import Adafruit_MCP3008
+        import Adafruit_GPIO.SPI as SPI
+
+        """init the mcp on SPI CE0"""
+        SPI_PORT   = 0
+        SPI_DEVICE = 0
+        self.mcp = Adafruit_MCP3008.MCP3008(spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE))
+
+        self.channels = {
+          "CH0": 0,
+          "CH1": 1,
+          "CH2": 2,
+          "CH3": 3,
+          "CH4": 4,
+          "CH5": 5,
+          "CH6": 6,
+          "CH7": 7
+        }
+
+    def setup_sensor(self, config):
+        return True  # nothing to do here
+
+    def get_value(self, config):
+        """get the analog value from the adc for the configured channel"""
+        channel = self.channels.get(config["channel"], "invalid")
+        _LOG.warning("MCP3008: Reading from channel %r", channel)
+        if channel == "invalid":
+            raise Exception("Channel '" + config["channel"] + "' not found!")
+        value = self.mcp.read_adc(channel)
+        _LOG.warning("MCP3008: value %d", value)
+        return value
+
+    def cleanup(self):
+        """close the adc, to proper shut down the spi bus"""
+        #self.adc.close()