Skip to content
Snippets Groups Projects
Unverified Commit d74f49a8 authored by Ellis Percival's avatar Ellis Percival Committed by GitHub
Browse files

Merge pull request #115 from flyte/feature/mcp3008

Feature/mcp3008
parents 3d836282 bf36c321
No related branches found
No related tags found
No related merge requests found
...@@ -22,6 +22,7 @@ Sensors ...@@ -22,6 +22,7 @@ Sensors
- BH1750 light level sensor (`bh1750`) - BH1750 light level sensor (`bh1750`)
- DS18S20, DS1822, DS18B20, DS1825, DS28EA00, MAX31850K one-wire temperature sensors: (`ds18b`) - DS18S20, DS1822, DS18B20, DS1825, DS28EA00, MAX31850K one-wire temperature sensors: (`ds18b`)
- HC-SR04 ultrasonic distance sensor (`hcsr04`) - HC-SR04 ultrasonic distance sensor (`hcsr04`)
- MCP3008 analog digital converter (`mcp3008`)
Streams Streams
------- -------
...@@ -99,6 +100,74 @@ digital_inputs: ...@@ -99,6 +100,74 @@ digital_inputs:
pullup: yes pullup: yes
pulldown: no 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 ### 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`: 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: ...@@ -112,65 +181,73 @@ mqtt:
topic_prefix: home topic_prefix: home
sensor_modules: sensor_modules:
- name: lm75 - name: lm75_sensor
module: lm75 module: lm75
i2c_bus_num: 1 i2c_bus_num: 1
chip_addr: 0x48 chip_addr: 0x48
cleanup: no # This optional boolean value sets whether the module's `cleanup()` function will be called when the software exits. 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 module: dht22
type: AM2302 # can be DHT11, DHT22 or AM2302 type: AM2302 # can be DHT11, DHT22 or AM2302
pin: 4 pin: 4
- name: bh1750 - name: bh1750_sensor
module: bh1750 module: bh1750
i2c_bus_num: 1 i2c_bus_num: 1
chip_addr: 0x23 chip_addr: 0x23
- name: ds18b22 - name: ds18b22_sensor
module: ds18b module: ds18b
type: DS18S20 type: DS18S20
address: 000803702e49 address: 000803702e49
- name: hcsr04 - name: hcsr04_sensor
module: hcsr04 module: hcsr04
pin_echo: 27 pin_echo: 27
pin_trigger: 17 pin_trigger: 17
burst: 10 # number of measurements for output of distance value in [cm] burst: 10 # number of measurements for output of distance value in [cm]
- name: mcp3008_sensor
module: mcp3008
sensor_inputs: sensor_inputs:
- name: temperature - name: lm75_temperature
module: lm75 module: lm75_sensor
interval: 15 #interval in seconds, that a value is read from the sensor and a update is published 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 digits: 4 # number of digits to be round
- name: dht22_temperature - 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 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 digits: 4 # number of digits to be round
type: temperature # Can be temperature or humidity type: temperature # Can be temperature or humidity
- name: dht22_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 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 digits: 4 # number of digits to be round
type: humidity # Can be temperature or humidity type: humidity # Can be temperature or humidity
- name: bh1750_lux - name: bh1750_lux
module: bh1750 module: bh1750_sensor
interval: 10 interval: 10
digits: 2 digits: 2
- name: ds18b22 - name: ds18b22_temperature
module: ds18b22 module: ds18b22_sensor
interval: 60 interval: 60
digits: 2 digits: 2
- name: distance - name: hcsr04_distance
module: hcsr04 module: hcsr04_sensor
interval: 10 # measurement every 10s interval: 10 # measurement every 10s
digits: 1 digits: 1
- name: mcp3008_voltage
module: mcp3008_sensor
interval: 300 # measurement every 5min
channel: CH4 # measure on CH4 of MCP3008
``` ```
### Streams ### Streams
...@@ -229,6 +306,7 @@ gpio_modules: ...@@ -229,6 +306,7 @@ gpio_modules:
board: zero # Supported: ZERO, R1, ZEROPLUS, ZEROPLUS2H5, ZEROPLUS2H3, PCPCPLUS, ONE, LITE, PLUS2E, PC2, PRIME board: zero # Supported: ZERO, R1, ZEROPLUS, ZEROPLUS2H5, ZEROPLUS2H3, PCPCPLUS, ONE, LITE, PLUS2E, PC2, PRIME
mode: board mode: board
``` ```
### MQTT configuration
#### SSL/TLS #### SSL/TLS
...@@ -265,74 +343,7 @@ mqtt: ...@@ -265,74 +343,7 @@ mqtt:
insecure: yes insecure: yes
``` ```
#### Temporary Set #### MQTT Status Topic
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 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: 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: ...@@ -356,13 +367,13 @@ mqtt:
the status messages will appear on topic `home/office/status`. 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. 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: 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 ```yaml
mqtt: mqtt:
...@@ -371,7 +382,7 @@ mqtt: ...@@ -371,7 +382,7 @@ mqtt:
topic_prefix: home/office topic_prefix: home/office
``` ```
#### Device 2 ##### Device 2
```yaml ```yaml
mqtt: mqtt:
......
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()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment