From 255ad5f2f79ce916288af3bb0170272322b330d6 Mon Sep 17 00:00:00 2001 From: "bernhard.trinnes" Date: Tue, 18 Aug 2020 09:42:50 +0200 Subject: [PATCH] added mcp342x --- i2cdevices/i2cdevices.pro | 7 +- i2cdevices/integrationplugini2cdevices.cpp | 42 +++++++++++ i2cdevices/integrationplugini2cdevices.json | 39 +++++++++++ i2cdevices/mcp342xchannel.cpp | 77 ++++++++++++++++++++ i2cdevices/mcp342xchannel.h | 78 +++++++++++++++++++++ 5 files changed, 240 insertions(+), 3 deletions(-) create mode 100644 i2cdevices/mcp342xchannel.cpp create mode 100644 i2cdevices/mcp342xchannel.h diff --git a/i2cdevices/i2cdevices.pro b/i2cdevices/i2cdevices.pro index b6b22cbd..53be0f64 100644 --- a/i2cdevices/i2cdevices.pro +++ b/i2cdevices/i2cdevices.pro @@ -3,10 +3,11 @@ include(../plugins.pri) HEADERS += \ integrationplugini2cdevices.h \ ads1115channel.h \ - pi16adcchannel.h - + pi16adcchannel.h \ + mcp342xchannel.h SOURCES += \ integrationplugini2cdevices.cpp \ ads1115channel.cpp \ - pi16adcchannel.cpp + pi16adcchannel.cpp \ + mcp342xchannel.cpp diff --git a/i2cdevices/integrationplugini2cdevices.cpp b/i2cdevices/integrationplugini2cdevices.cpp index e3f3b0b6..c600f760 100644 --- a/i2cdevices/integrationplugini2cdevices.cpp +++ b/i2cdevices/integrationplugini2cdevices.cpp @@ -33,6 +33,7 @@ #include "pi16adcchannel.h" #include "ads1115channel.h" +#include "mcp342xchannel.h" #include @@ -117,6 +118,18 @@ void IntegrationPluginI2CDevices::discoverThings(ThingDiscoveryInfo *info) info->addThingDescriptor(descriptor); } } + + if (info->thingClassId() == mcp342xThingClassId) { + // The MCP3423 && MCP3424 have selectable addresses from 0x68 to 0x6f + if (scanResult.address >= 0x68 && scanResult.address <= 0x6f) { + ThingDescriptor descriptor(mcp342xThingClassId, "MCP3422/MCP3423/MCP3424", QString("%1: 0x%2").arg(scanResult.portName).arg(scanResult.address, 0, 16)); + ParamList params; + params << Param(mcp342xThingI2cPortParamTypeId, scanResult.portName); + params << Param(mcp342xThingI2cAddressParamTypeId, scanResult.address); + descriptor.setParams(params); + info->addThingDescriptor(descriptor); + } + } } info->finish(Thing::ThingErrorNoError); @@ -200,6 +213,35 @@ void IntegrationPluginI2CDevices::setupThing(ThingSetupInfo *info) } info->finish(Thing::ThingErrorNoError); } + + if (info->thing()->thingClassId() == mcp342xThingClassId) { + QString i2cPortName = info->thing()->paramValue(mcp342xThingI2cPortParamTypeId).toString(); + int i2cAddress = info->thing()->paramValue(mcp342xThingI2cAddressParamTypeId).toInt(); + int gainParam = info->thing()->paramValue(mcp342xThingInputGainParamTypeId).toInt(); + int channel = 1; + MCP342XChannel *mcp342x = new MCP342XChannel(i2cPortName, i2cAddress, channel, MCP342XChannel::Gain(gainParam), this); + if (!hardwareManager()->i2cManager()->open(mcp342x)) { + delete mcp342x; + info->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("Failed to open I2C port.")); + return; + } + + Thing *thing = info->thing(); + connect(mcp342x, &MCP342XChannel::readingAvailable, thing, [this, thing](const QByteArray &data){ + if (data.length() != 2) { + qCWarning(dcI2cDevices()) << "Error reading from" << thing; + return; + } + //const int max = 32768; + //int value = static_cast(data[0]) * 256 + static_cast(data[1]); + //double transformedValue = qMin(1.0 * value / max, 1.0); + //thing->setStateValue(m_ads1115ChannelMap.value(i), transformedValue); + //thing->setStateValue(m_ads1115OvervoltageMap.value(i), value > 32768); + }); + hardwareManager()->i2cManager()->startReading(mcp342x, 5000); + m_i2cDevices.insert(mcp342x, thing); + } + info->finish(Thing::ThingErrorNoError); } void IntegrationPluginI2CDevices::thingRemoved(Thing *thing) diff --git a/i2cdevices/integrationplugini2cdevices.json b/i2cdevices/integrationplugini2cdevices.json index 1f2105a3..7a2b4b4d 100644 --- a/i2cdevices/integrationplugini2cdevices.json +++ b/i2cdevices/integrationplugini2cdevices.json @@ -451,6 +451,45 @@ ] } ] + }, + { + "id": "05a342c1-2f38-469f-a79e-5961b0600ca3", + "name": "microchipTechnology", + "displayName": "Microchip Technology", + "thingClasses": [ + { + "id": "74250c34-1aff-4d8f-82f8-825041f11ae3", + "name": "mcp342x", + "displayName": "mcp3422/mcp3423/mcp3424", + "createMethods": ["user", "discovery"], + "setupMethod": "justAdd", + "paramTypes": [ + { + "id": "22af4227-805b-4211-b4be-6d7bce5f03a8", + "name": "i2cPort", + "displayName": "I2C port", + "type": "QString" + }, + { + "id": "c1a518b6-0139-42f5-bd0e-5bea56f29ac6", + "name": "i2cAddress", + "displayName": "I2C address", + "type": "int" + }, + { + "id": "e58821d2-248d-40e6-b7f5-be517c293d9d", + "name": "inputGain", + "displayName": "Input gain", + "type": "double", + "allowedValues": [ 8, 4, 2, 1 ], + "unit": "Volt", + "defaultValue": 4.096 + } + ], + "stateTypes": [ + ] + } + ] } ] } diff --git a/i2cdevices/mcp342xchannel.cpp b/i2cdevices/mcp342xchannel.cpp new file mode 100644 index 00000000..d02f795c --- /dev/null +++ b/i2cdevices/mcp342xchannel.cpp @@ -0,0 +1,77 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2020, nymea GmbH +* Contact: contact@nymea.io +* +* This file is part of nymea. +* This project including source code and documentation is protected by +* copyright law, and remains the property of nymea GmbH. All rights, including +* reproduction, publication, editing and translation, are reserved. The use of +* this project is subject to the terms of a license agreement to be concluded +* with nymea GmbH in accordance with the terms of use of nymea GmbH, available +* under https://nymea.io/license +* +* GNU Lesser General Public License Usage +* Alternatively, this project may be redistributed and/or modified under the +* terms of the GNU Lesser General Public License as published by the Free +* Software Foundation; version 3. This project is distributed in the hope that +* it will be useful, but WITHOUT ANY WARRANTY; without even the implied +* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* along with this project. If not, see . +* +* For any further details and any questions please contact us under +* contact@nymea.io or see our FAQ/Licensing Information on +* https://nymea.io/license/faq +* +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "mcp342xchannel.h" +#include "extern-plugininfo.h" + +#include + +#define GENERAL_CALL_RESET 0x0006 +#define GENERAL_CALL_LATCH 0x0004 +#define GENERAL_CALL_CONVERSION 0x0008 + +#define CONFIGURATION_REGISTER + + +MCP342XChannel::MCP342XChannel(const QString &portName, int address, int channel, Gain gain, QObject *parent) : + I2CDevice(portName, address, parent), + m_channel(channel), + m_gain(gain) +{ + +} + + +QByteArray MCP342XChannel::readData(int fd) +{ + // Start a configuration conversation + unsigned char writeBuf[1] = {0}; + writeBuf[0] |= (m_channel & 0x0003) << ConfRegisterBits::C0; + writeBuf[0] |= m_gain << ConfRegisterBits::G0; + //writeBuf[0] |= SampleRateSelectionBit::Bits18 << ConfRegisterBits::S0; + writeBuf[0] |= 1 << ConfRegisterBits::OC; // one shot + writeBuf[0] |= 1 << ConfRegisterBits::RDY; // start conversoin + if (write(fd, writeBuf, 1) != 1) { + qCWarning(dcI2cDevices()) << "MCP342X: could not write config register"; + return QByteArray(); + } + + // Wait for device to accept configuration (conversation bit is cleared) + char readBuf[2] = {0}; + do { + if (read(fd, readBuf, 2) != 2) { + qCWarning(dcI2cDevices()) << "MCP342X: could not read ADC data"; + return QByteArray(); + } + } while (!(readBuf[0] & (1 << ConfRegisterBits::RDY))); + + return QByteArray(readBuf, 2); +} + diff --git a/i2cdevices/mcp342xchannel.h b/i2cdevices/mcp342xchannel.h new file mode 100644 index 00000000..f7d2d2d8 --- /dev/null +++ b/i2cdevices/mcp342xchannel.h @@ -0,0 +1,78 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2020, nymea GmbH +* Contact: contact@nymea.io +* +* This file is part of nymea. +* This project including source code and documentation is protected by +* copyright law, and remains the property of nymea GmbH. All rights, including +* reproduction, publication, editing and translation, are reserved. The use of +* this project is subject to the terms of a license agreement to be concluded +* with nymea GmbH in accordance with the terms of use of nymea GmbH, available +* under https://nymea.io/license +* +* GNU Lesser General Public License Usage +* Alternatively, this project may be redistributed and/or modified under the +* terms of the GNU Lesser General Public License as published by the Free +* Software Foundation; version 3. This project is distributed in the hope that +* it will be useful, but WITHOUT ANY WARRANTY; without even the implied +* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* along with this project. If not, see . +* +* For any further details and any questions please contact us under +* contact@nymea.io or see our FAQ/Licensing Information on +* https://nymea.io/license/faq +* +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef MCP342X_H +#define MCP342X_H + +#include +#include + +#include + +class MCP342XChannel: public I2CDevice +{ + Q_OBJECT +public: + + enum Gain { + Gain_1 = 0, + Gain_2 = 1, + Gain_4 = 2, + Gain_8 = 3 + }; + + enum ConfRegisterBits { + G0 = 0, // Gain Selection + G1, // Gain Selection + S0, // Sample Rate + S1, // Sample Rate + OC, // Conversion Mode Bit + C0, // Channel Selection + C1, // Channel Selection + RDY // Ready Bit + }; + + enum SampleRateSelectionBit { + Bits12 = 0, + Bits14 = 1, + Bits16 = 2, + Bits18 = 3 + }; + + explicit MCP342XChannel(const QString &portName, int address, int channel, Gain gain, QObject *parent = nullptr); + + QByteArray readData(int fd) override; + +private: + int m_channel = 0; + Gain m_gain = Gain_1; +}; + +#endif // MCP342X_H