feat(firmware): IM1281C driver
This commit is contained in:
125
hardware/firmware/lib/IM1281C/src/IM1281C.cpp
Normal file
125
hardware/firmware/lib/IM1281C/src/IM1281C.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
#include "IM1281C.h"
|
||||
|
||||
IM1281C::IM1281C()
|
||||
: _serial(nullptr),
|
||||
_slaveAddress(1),
|
||||
_lastAResult(0xFF),
|
||||
_lastBResult(0xFF)
|
||||
{
|
||||
}
|
||||
|
||||
bool IM1281C::begin(HardwareSerial &serial,
|
||||
int8_t rxPin,
|
||||
int8_t txPin,
|
||||
uint8_t slaveAddress,
|
||||
uint32_t baudRate,
|
||||
uint32_t serialConfig)
|
||||
{
|
||||
_serial = &serial;
|
||||
_slaveAddress = slaveAddress;
|
||||
_a = IM1281CAData{};
|
||||
_b = IM1281CBData{};
|
||||
_lastAResult = 0xFF;
|
||||
_lastBResult = 0xFF;
|
||||
|
||||
_serial->begin(baudRate, serialConfig, rxPin, txPin);
|
||||
_node.begin(_slaveAddress, *_serial);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IM1281C::readA()
|
||||
{
|
||||
return readAll();
|
||||
}
|
||||
|
||||
bool IM1281C::readB()
|
||||
{
|
||||
return readAll();
|
||||
}
|
||||
|
||||
bool IM1281C::readAll()
|
||||
{
|
||||
if (_serial == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// IM1281C datasheet addresses are effectively 32-bit data items.
|
||||
// Requesting 0x0010 from 0x0048 yields 64 data bytes (0x40), which covers A/B block.
|
||||
const uint8_t result = _node.readHoldingRegisters(0x0048, 16);
|
||||
_lastAResult = result;
|
||||
_lastBResult = result;
|
||||
|
||||
if (result != _node.ku8MBSuccess)
|
||||
{
|
||||
_a.valid = false;
|
||||
_b.valid = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint32_t aVoltageRaw = combineWords(_node.getResponseBuffer(0), _node.getResponseBuffer(1));
|
||||
const uint32_t aCurrentRaw = combineWords(_node.getResponseBuffer(2), _node.getResponseBuffer(3));
|
||||
const uint32_t aPowerRaw = combineWords(_node.getResponseBuffer(4), _node.getResponseBuffer(5));
|
||||
const uint32_t aEnergyRaw = combineWords(_node.getResponseBuffer(6), _node.getResponseBuffer(7));
|
||||
const uint32_t aPfRaw = combineWords(_node.getResponseBuffer(8), _node.getResponseBuffer(9));
|
||||
const uint32_t aCo2Raw = combineWords(_node.getResponseBuffer(10), _node.getResponseBuffer(11));
|
||||
const uint32_t aTempRaw = combineWords(_node.getResponseBuffer(12), _node.getResponseBuffer(13));
|
||||
const uint32_t aFreqRaw = combineWords(_node.getResponseBuffer(14), _node.getResponseBuffer(15));
|
||||
|
||||
_a.voltage = scaleValue(aVoltageRaw, 0.0001f);
|
||||
_a.current = scaleValue(aCurrentRaw, 0.0001f);
|
||||
_a.power = scaleValue(aPowerRaw, 0.0001f);
|
||||
_a.energy = scaleValue(aEnergyRaw, 0.0001f);
|
||||
_a.powerFactor = scaleValue(aPfRaw, 0.001f);
|
||||
_a.co2 = scaleValue(aCo2Raw, 0.0001f);
|
||||
_a.temperature = scaleValue(aTempRaw, 0.01f);
|
||||
_a.frequency = scaleValue(aFreqRaw, 0.01f);
|
||||
_a.valid = true;
|
||||
|
||||
const uint32_t bVoltageRaw = combineWords(_node.getResponseBuffer(16), _node.getResponseBuffer(17));
|
||||
const uint32_t bCurrentRaw = combineWords(_node.getResponseBuffer(18), _node.getResponseBuffer(19));
|
||||
const uint32_t bPowerRaw = combineWords(_node.getResponseBuffer(20), _node.getResponseBuffer(21));
|
||||
const uint32_t bEnergyRaw = combineWords(_node.getResponseBuffer(22), _node.getResponseBuffer(23));
|
||||
const uint32_t bPfRaw = combineWords(_node.getResponseBuffer(24), _node.getResponseBuffer(25));
|
||||
const uint32_t bCo2Raw = combineWords(_node.getResponseBuffer(26), _node.getResponseBuffer(27));
|
||||
|
||||
_b.voltage = scaleValue(bVoltageRaw, 0.0001f);
|
||||
_b.current = scaleValue(bCurrentRaw, 0.0001f);
|
||||
_b.power = scaleValue(bPowerRaw, 0.0001f);
|
||||
_b.energy = scaleValue(bEnergyRaw, 0.0001f);
|
||||
_b.powerFactor = scaleValue(bPfRaw, 0.001f);
|
||||
_b.co2 = scaleValue(bCo2Raw, 0.0001f);
|
||||
_b.valid = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const IM1281CAData &IM1281C::a() const
|
||||
{
|
||||
return _a;
|
||||
}
|
||||
|
||||
const IM1281CBData &IM1281C::b() const
|
||||
{
|
||||
return _b;
|
||||
}
|
||||
|
||||
uint8_t IM1281C::lastAResult() const
|
||||
{
|
||||
return _lastAResult;
|
||||
}
|
||||
|
||||
uint8_t IM1281C::lastBResult() const
|
||||
{
|
||||
return _lastBResult;
|
||||
}
|
||||
|
||||
uint32_t IM1281C::combineWords(uint16_t highWord, uint16_t lowWord)
|
||||
{
|
||||
return (static_cast<uint32_t>(highWord) << 16) | static_cast<uint32_t>(lowWord);
|
||||
}
|
||||
|
||||
float IM1281C::scaleValue(uint32_t raw, float scale)
|
||||
{
|
||||
return static_cast<float>(raw) * scale;
|
||||
}
|
||||
65
hardware/firmware/lib/IM1281C/src/IM1281C.h
Normal file
65
hardware/firmware/lib/IM1281C/src/IM1281C.h
Normal file
@@ -0,0 +1,65 @@
|
||||
#ifndef HELIOS_IM1281C_H
|
||||
#define HELIOS_IM1281C_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <ModbusMaster.h>
|
||||
|
||||
struct IM1281CAData
|
||||
{
|
||||
float voltage = 0.0f;
|
||||
float current = 0.0f;
|
||||
float power = 0.0f;
|
||||
float energy = 0.0f;
|
||||
float powerFactor = 0.0f;
|
||||
float co2 = 0.0f;
|
||||
float temperature = 0.0f;
|
||||
float frequency = 0.0f;
|
||||
bool valid = false;
|
||||
};
|
||||
|
||||
struct IM1281CBData
|
||||
{
|
||||
float voltage = 0.0f;
|
||||
float current = 0.0f;
|
||||
float power = 0.0f;
|
||||
float energy = 0.0f;
|
||||
float powerFactor = 0.0f;
|
||||
float co2 = 0.0f;
|
||||
bool valid = false;
|
||||
};
|
||||
|
||||
class IM1281C
|
||||
{
|
||||
public:
|
||||
IM1281C();
|
||||
|
||||
bool begin(HardwareSerial &serial,
|
||||
int8_t rxPin,
|
||||
int8_t txPin,
|
||||
uint8_t slaveAddress = 1,
|
||||
uint32_t baudRate = 4800,
|
||||
uint32_t serialConfig = SERIAL_8N1);
|
||||
|
||||
bool readA();
|
||||
bool readB();
|
||||
bool readAll();
|
||||
|
||||
const IM1281CAData &a() const;
|
||||
const IM1281CBData &b() const;
|
||||
uint8_t lastAResult() const;
|
||||
uint8_t lastBResult() const;
|
||||
|
||||
private:
|
||||
static uint32_t combineWords(uint16_t highWord, uint16_t lowWord);
|
||||
static float scaleValue(uint32_t raw, float scale);
|
||||
|
||||
ModbusMaster _node;
|
||||
HardwareSerial *_serial;
|
||||
uint8_t _slaveAddress;
|
||||
uint8_t _lastAResult;
|
||||
uint8_t _lastBResult;
|
||||
IM1281CAData _a;
|
||||
IM1281CBData _b;
|
||||
};
|
||||
|
||||
#endif // HELIOS_IM1281C_H
|
||||
Reference in New Issue
Block a user