Merge PR #467: New Plugin: MCP3008 SPI DAC
commit
f01e3c09be
|
|
@ -490,6 +490,15 @@ Description: nymea.io plugin for mailnotification
|
|||
This package will install the nymea.io plugin for mailnotification
|
||||
|
||||
|
||||
Package: nymea-plugin-mcp3008
|
||||
Architecture: any
|
||||
Depends: ${misc:Depends},
|
||||
nymea-plugins-translations,
|
||||
python3-pip,
|
||||
Description: MCP3008 DAC integration plugin for nymea
|
||||
This package will install the nymea.io plugin for using the MCP3008 DAC.
|
||||
|
||||
|
||||
Package: nymea-plugin-mqttclient
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends},
|
||||
|
|
@ -1324,6 +1333,7 @@ Depends: nymea-plugin-boblight,
|
|||
nymea-plugin-gpio,
|
||||
nymea-plugin-i2cdevices,
|
||||
nymea-plugin-mqttclient,
|
||||
nymea-plugin-mcp3008,
|
||||
nymea-plugin-remotessh,
|
||||
nymea-plugin-serialportcommander,
|
||||
nymea-plugin-systemmonitor,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
mcp3008/integrationpluginmcp3008.json usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/mcp3008/
|
||||
mcp3008/integrationpluginmcp3008.py usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/mcp3008/
|
||||
mcp3008/requirements.txt usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/mcp3008/
|
||||
|
|
@ -71,7 +71,7 @@
|
|||
"id": "d52cd791-6d92-49e4-b46b-593cb0691d46",
|
||||
"name": "channel3",
|
||||
"displayName": "Channel 3",
|
||||
"displayNameEvent": "Channel 1 value changed",
|
||||
"displayNameEvent": "Channel 3 value changed",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"minValue": 0,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
# MCP3008
|
||||
|
||||
This plugin adds support for the MCP3008 Analog Digital Converter to nymea.
|
||||
|
||||
> Note: This plugin will only work on the Raspberry Pi
|
||||
|
||||
## Supported Things
|
||||
|
||||
* MCP3008
|
||||
|
||||
## Requirements
|
||||
|
||||
* The MCP3008 must be wired up properly to the SPI interface.
|
||||
* The package “nymea-plugin-mcp3008” must be installed
|
||||
|
||||
## More
|
||||
|
||||
[Adafruit tutorial](https://learn.adafruit.com/raspberry-pi-analog-to-digital-converters/mcp3008)
|
||||
[MCP3008 data sheet](https://cdn-shop.adafruit.com/datasheets/MCP3008.pdf)
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
{
|
||||
"name": "mcp3008",
|
||||
"displayName": "MCP3008",
|
||||
"id": "c45ff005-b9e9-4334-babb-4c00d6b7b714",
|
||||
"vendors": [
|
||||
{
|
||||
"name": "microchip",
|
||||
"displayName": "Microchip Technology",
|
||||
"id": "6a416628-edfc-4e15-a530-eb7c7fc00ace",
|
||||
"thingClasses": [
|
||||
{
|
||||
"id": "b22461d4-7961-492d-b2a1-f613abc8a5fb",
|
||||
"name": "mcp3008",
|
||||
"displayName": "MCP3008 SPI ADC",
|
||||
"createMethods": ["User"],
|
||||
"paramTypes": [
|
||||
{
|
||||
"id": "cf97ede3-429a-4a6c-8eeb-99d7afd2eb37",
|
||||
"name": "clk",
|
||||
"displayName": "CLK",
|
||||
"type": "uint",
|
||||
"defaultValue": 11
|
||||
},
|
||||
{
|
||||
"id": "2e84602a-ef28-4f8c-bd0b-233036155da3",
|
||||
"name": "miso",
|
||||
"displayName": "MISO",
|
||||
"type": "uint",
|
||||
"defaultValue": 9
|
||||
},
|
||||
{
|
||||
"id": "7dc0d2f1-2960-4fdc-b77b-3ab93a33fa6c",
|
||||
"name": "mosi",
|
||||
"displayName": "MOSI",
|
||||
"type": "uint",
|
||||
"defaultValue": 10
|
||||
},
|
||||
{
|
||||
"id": "0771e974-008e-4190-bee7-efb6163decc5",
|
||||
"name": "cs",
|
||||
"displayName": "CS",
|
||||
"type": "uint",
|
||||
"defaultValue": 8
|
||||
}
|
||||
],
|
||||
"stateTypes":[
|
||||
{
|
||||
"id": "1c95c1ca-8043-4096-9e0c-62d6a9bcd468",
|
||||
"name": "channel1",
|
||||
"displayName": "Channel 1",
|
||||
"displayNameEvent": "Channel 1 value changed",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"minValue": 0,
|
||||
"maxValue": 3.3,
|
||||
"ioType": "analogInput"
|
||||
},
|
||||
{
|
||||
"id": "cf354a91-f994-47ef-aeeb-2f03e54f1d7a",
|
||||
"name": "channel2",
|
||||
"displayName": "Channel 2",
|
||||
"displayNameEvent": "Channel 2 value changed",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"minValue": 0,
|
||||
"maxValue": 3.3,
|
||||
"ioType": "analogInput"
|
||||
},
|
||||
{
|
||||
"id": "b0beb2b3-cb44-488f-b0e8-a6f3433b6683",
|
||||
"name": "channel3",
|
||||
"displayName": "Channel 3",
|
||||
"displayNameEvent": "Channel 3 value changed",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"minValue": 0,
|
||||
"maxValue": 3.3,
|
||||
"ioType": "analogInput"
|
||||
},
|
||||
{
|
||||
"id": "c4f1cf54-427a-4b91-aa5e-7256e1b130bf",
|
||||
"name": "channel4",
|
||||
"displayName": "Channel 4",
|
||||
"displayNameEvent": "Channel 4 value changed",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"minValue": 0,
|
||||
"maxValue": 3.3,
|
||||
"ioType": "analogInput"
|
||||
},
|
||||
{
|
||||
"id": "593cdc76-25ec-4252-90ce-8a8da01cf328",
|
||||
"name": "channel5",
|
||||
"displayName": "Channel 5",
|
||||
"displayNameEvent": "Channel 5 value changed",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"minValue": 0,
|
||||
"maxValue": 3.3,
|
||||
"ioType": "analogInput"
|
||||
},
|
||||
{
|
||||
"id": "0e3a1f3d-eb4d-4bd5-bfe8-c1404713039e",
|
||||
"name": "channel6",
|
||||
"displayName": "Channel 6",
|
||||
"displayNameEvent": "Channel 6 value changed",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"minValue": 0,
|
||||
"maxValue": 3.3,
|
||||
"ioType": "analogInput"
|
||||
},
|
||||
{
|
||||
"id": "3d53239b-51ee-4097-8028-291ff063b3ca",
|
||||
"name": "channel7",
|
||||
"displayName": "Channel 7",
|
||||
"displayNameEvent": "Channel 7 value changed",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"minValue": 0,
|
||||
"maxValue": 3.3,
|
||||
"ioType": "analogInput"
|
||||
},
|
||||
{
|
||||
"id": "c10ed6ba-0248-477d-98ad-23d7318b6468",
|
||||
"name": "channel8",
|
||||
"displayName": "Channel 8",
|
||||
"displayNameEvent": "Channel 8 value changed",
|
||||
"type": "double",
|
||||
"defaultValue": 0,
|
||||
"minValue": 0,
|
||||
"maxValue": 3.3,
|
||||
"ioType": "analogInput"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
import nymea
|
||||
import RPi.GPIO as GPIO
|
||||
|
||||
pluginTimer = None
|
||||
|
||||
def readadc(adcnum, clockpin, mosipin, misopin, cspin):
|
||||
if ((adcnum > 7) or (adcnum < 0)):
|
||||
return -1
|
||||
GPIO.output(cspin, True)
|
||||
|
||||
GPIO.output(clockpin, False) # start clock low
|
||||
GPIO.output(cspin, False) # bring CS low
|
||||
|
||||
commandout = adcnum
|
||||
commandout |= 0x18 # start bit + single-ended bit
|
||||
commandout <<= 3 # we only need to send 5 bits here
|
||||
for i in range(5):
|
||||
if (commandout & 0x80):
|
||||
GPIO.output(mosipin, True)
|
||||
else:
|
||||
GPIO.output(mosipin, False)
|
||||
commandout <<= 1
|
||||
GPIO.output(clockpin, True)
|
||||
GPIO.output(clockpin, False)
|
||||
|
||||
adcout = 0
|
||||
# read in one empty bit, one null bit and 10 ADC bits
|
||||
for i in range(12):
|
||||
GPIO.output(clockpin, True)
|
||||
GPIO.output(clockpin, False)
|
||||
adcout <<= 1
|
||||
if (GPIO.input(misopin)):
|
||||
adcout |= 0x1
|
||||
|
||||
GPIO.output(cspin, True)
|
||||
|
||||
adcout >>= 1 # first bit is 'null' so drop it
|
||||
return adcout
|
||||
|
||||
|
||||
def setupThing(info):
|
||||
logger.log("SetupThing for MCP3008:", info.thing.name)
|
||||
|
||||
SPICLK = info.thing.paramValue(mcp3008ThingClkParamTypeId)
|
||||
SPIMISO = info.thing.paramValue(mcp3008ThingMisoParamTypeId)
|
||||
SPIMOSI = info.thing.paramValue(mcp3008ThingMosiParamTypeId)
|
||||
SPICS = info.thing.paramValue(mcp3008ThingCsParamTypeId)
|
||||
|
||||
try:
|
||||
GPIO.setwarnings(False)
|
||||
GPIO.setmode(GPIO.BCM) #to specify whilch pin numbering system
|
||||
# set up the SPI interface pins
|
||||
GPIO.setup(SPIMOSI, GPIO.OUT)
|
||||
GPIO.setup(SPIMISO, GPIO.IN)
|
||||
GPIO.setup(SPICLK, GPIO.OUT)
|
||||
GPIO.setup(SPICS, GPIO.OUT)
|
||||
|
||||
logger.log("Reading channel 0")
|
||||
chan0Value = readadc(0, SPICLK, SPIMOSI, SPIMISO, SPICS)
|
||||
logger.log('Raw ADC Value: %s' % chan0Value)
|
||||
logger.log('ADC Voltage: %sV' % str("%.2f"%((chan0Value/1024.)*5)))
|
||||
|
||||
except Exception as e:
|
||||
logger.warn("Unable to open SPI port", str(e))
|
||||
info.finish(nymea.ThingErrorHardwareFailure, "Unable to connect to the device. Please verify it is connected properly to the SPI interface.")
|
||||
return
|
||||
|
||||
info.finish(nymea.ThingErrorNoError)
|
||||
|
||||
global pluginTimer
|
||||
if pluginTimer is None:
|
||||
pluginTimer = nymea.PluginTimer(5, pollChannels)
|
||||
|
||||
|
||||
|
||||
def thingRemoved(thing):
|
||||
del devices[thing]
|
||||
if len(myThings()) == 0:
|
||||
GPIO.cleanup()
|
||||
|
||||
|
||||
|
||||
def pollChannels():
|
||||
for thing in myThings():
|
||||
SPICLK = thing.paramValue(mcp3008ThingClkParamTypeId)
|
||||
SPIMISO = thing.paramValue(mcp3008ThingMisoParamTypeId)
|
||||
SPIMOSI = thing.paramValue(mcp3008ThingMosiParamTypeId)
|
||||
SPICS = thing.paramValue(mcp3008ThingCsParamTypeId)
|
||||
|
||||
try:
|
||||
chan0Value = readadc(0, SPICLK, SPIMOSI, SPIMISO, SPICS)
|
||||
thing.setStateValue(mcp3008Channel1StateTypeId, str("%.2f"%((chan0Value/1024.)*5)))
|
||||
|
||||
chan0Value = readadc(1, SPICLK, SPIMOSI, SPIMISO, SPICS)
|
||||
thing.setStateValue(mcp3008Channel2StateTypeId, str("%.2f"%((chan0Value/1024.)*5)))
|
||||
|
||||
chan0Value = readadc(2, SPICLK, SPIMOSI, SPIMISO, SPICS)
|
||||
thing.setStateValue(mcp3008Channel3StateTypeId, str("%.2f"%((chan0Value/1024.)*5)))
|
||||
|
||||
chan0Value = readadc(3, SPICLK, SPIMOSI, SPIMISO, SPICS)
|
||||
thing.setStateValue(mcp3008Channel4StateTypeId, str("%.2f"%((chan0Value/1024.)*5)))
|
||||
|
||||
chan0Value = readadc(4, SPICLK, SPIMOSI, SPIMISO, SPICS)
|
||||
thing.setStateValue(mcp3008Channel5StateTypeId, str("%.2f"%((chan0Value/1024.)*5)))
|
||||
|
||||
chan0Value = readadc(5, SPICLK, SPIMOSI, SPIMISO, SPICS)
|
||||
thing.setStateValue(mcp3008Channel6StateTypeId, str("%.2f"%((chan0Value/1024.)*5)))
|
||||
|
||||
chan0Value = readadc(6, SPICLK, SPIMOSI, SPIMISO, SPICS)
|
||||
thing.setStateValue(mcp3008Channel7StateTypeId, str("%.2f"%((chan0Value/1024.)*5)))
|
||||
|
||||
chan0Value = readadc(7, SPICLK, SPIMOSI, SPIMISO, SPICS)
|
||||
thing.setStateValue(mcp3008Channel8StateTypeId, str("%.2f"%((chan0Value/1024.)*5)))
|
||||
|
||||
except:
|
||||
logger.warn("Failed to read values from", thing.name)
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
TEMPLATE = aux
|
||||
|
||||
OTHER_FILES = integrationpluginmcp3008.json \
|
||||
integrationpluginmcp3008.py \
|
||||
MCP3008.py
|
||||
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"title": "MCP3008",
|
||||
"tagline": "Connect MCP3008 digital analog converters to nymea.",
|
||||
"icon": "",
|
||||
"stability": "consumer",
|
||||
"offline": false,
|
||||
"technologies": [
|
||||
"SPI"
|
||||
],
|
||||
"categories": [
|
||||
"DYI"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
RPi.GPIO==0.7.0 \
|
||||
--hash=sha256:7424bc6c205466764f30f666c18187a0824077daf20b295c42f08aea2cb87d3f \
|
||||
--hash=sha256:6a4791f41cafc2ee6e4cb70e5bd31fadc66a0cfab29b38df8723a98f6f73ad5a
|
||||
|
|
@ -40,6 +40,7 @@ PLUGIN_DIRS = \
|
|||
netatmo \
|
||||
networkdetector \
|
||||
nuki \
|
||||
mcp3008 \
|
||||
onewire \
|
||||
openuv \
|
||||
openweathermap \
|
||||
|
|
|
|||
Loading…
Reference in New Issue