2018-11-26 11:58:15 +00:00
|
|
|
/*
|
|
|
|
* This file is part of the "bluetoothheater" distribution
|
|
|
|
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
|
|
|
*
|
|
|
|
* Copyright (C) 2018 Ray Jones <ray@mrjones.id.au>
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program 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 General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2018-09-23 09:15:49 +00:00
|
|
|
#ifndef _CPROTOCOL_H_
|
|
|
|
#define _CPROTOCOL_H_
|
2018-09-24 10:56:37 +00:00
|
|
|
|
2018-12-20 04:19:59 +00:00
|
|
|
#include "../Utility/UtilClasses.h"
|
2019-07-09 12:19:21 +00:00
|
|
|
#include "../Utility/MODBUS-CRC16.h"
|
2018-11-06 09:43:54 +00:00
|
|
|
|
2018-09-23 09:15:49 +00:00
|
|
|
class CProtocol {
|
2019-07-09 12:19:21 +00:00
|
|
|
// CModBusCRC16 _CRCengine;
|
2018-09-22 23:31:47 +00:00
|
|
|
public:
|
|
|
|
union {
|
2019-07-06 13:46:20 +00:00
|
|
|
uint8_t Data[24];
|
2018-09-22 23:31:47 +00:00
|
|
|
struct {
|
2019-07-06 13:46:20 +00:00
|
|
|
uint8_t Byte0; // [0] always 0x76
|
|
|
|
uint8_t Len; // [1] always 0x16 == 22
|
|
|
|
uint8_t Command; // [2] transient commands: 00: NOP, 0xa0 START, 0x05: STOP
|
2019-11-21 08:25:14 +00:00
|
|
|
int8_t ActualTemperature; // [3] 1deg6C / digit
|
|
|
|
int8_t DesiredDemand; // [4] typ. 1degC / digit, but also gets used for Fixed Hx demand too!
|
2019-07-06 13:46:20 +00:00
|
|
|
uint8_t MinPumpFreq; // [5] 0.1Hz/digit
|
|
|
|
uint8_t MaxPumpFreq; // [6] 0.1Hz/digit
|
|
|
|
uint8_t MinFanRPM_MSB; // [7] 16 bit - big endian MSB
|
|
|
|
uint8_t MinFanRPM_LSB; // [8] 16 bit - big endian LSB : 1 RPM / digit
|
|
|
|
uint8_t MaxFanRPM_MSB; // [9] 16 bit - big endian MSB
|
|
|
|
uint8_t MaxFanRPM_LSB; // [10] 16 bit - big endian LSB : 1 RPM / digit
|
|
|
|
uint8_t OperatingVoltage; // [11] 120, 240 : 0.1V/digit
|
|
|
|
uint8_t FanSensor; // [12] SN-1 or SN-2
|
|
|
|
uint8_t OperatingMode; // [13] 0x32:Thermostat, 0xCD:Fixed
|
2019-11-21 08:25:14 +00:00
|
|
|
int8_t MinTemperature; // [14] Minimum settable temperature
|
|
|
|
int8_t MaxTemperature; // [15] Maximum settable temperature
|
2019-07-06 13:46:20 +00:00
|
|
|
uint8_t GlowDrive; // [16] power to supply to glow plug
|
|
|
|
uint8_t Prime; // [17] 00: normal, 0x5A: fuel prime
|
|
|
|
uint8_t Unknown1_MSB; // [18] always 0x01
|
|
|
|
uint8_t Unknown1_LSB; // [19] always 0x2c "300 secs = max run without burn detected"?
|
2020-01-13 08:48:32 +00:00
|
|
|
uint8_t Altitude_MSB; // [20]
|
|
|
|
uint8_t Altitude_LSB; // [21]
|
2019-07-06 13:46:20 +00:00
|
|
|
uint8_t CRC_MSB; // [22]
|
|
|
|
uint8_t CRC_LSB; // [23]
|
2018-09-23 08:59:19 +00:00
|
|
|
} Controller;
|
2018-09-22 23:31:47 +00:00
|
|
|
struct {
|
2019-07-06 13:46:20 +00:00
|
|
|
uint8_t Byte0; // always 0x76
|
|
|
|
uint8_t Len; // always 0x16 == 22 bytes
|
|
|
|
uint8_t RunState; // operating state
|
|
|
|
uint8_t ErrState; // 0: OFF, 1: ON, 2+ (E-0n + 1)
|
|
|
|
uint8_t SupplyV_MSB; // 16 bit - big endian MSB
|
|
|
|
uint8_t SupplyV_LSB; // 16 bit - big endian MSB : 0.1V / digit
|
|
|
|
uint8_t FanRPM_MSB; // 16 bit - big endian MSB
|
|
|
|
uint8_t FanRPM_LSB; // 16 bit - big endian LSB : 1 RPM / digit
|
|
|
|
uint8_t FanVoltage_MSB; // 16 bit - big endian MSB
|
|
|
|
uint8_t FanVoltage_LSB; // 16 bit - big endian LSB : 0.1V / digit
|
|
|
|
uint8_t HeatExchgTemp_MSB; // 16 bit - big endian MSB
|
|
|
|
uint8_t HeatExchgTemp_LSB; // 16 bit - big endian LSB : 1 degC / digit
|
|
|
|
uint8_t GlowPlugVoltage_MSB; // 16 bit - big endian MSB
|
|
|
|
uint8_t GlowPlugVoltage_LSB; // 16 bit - big endian LSB : 0.1V / digit
|
|
|
|
uint8_t GlowPlugCurrent_MSB; // 16 bit - big endian MSB
|
|
|
|
uint8_t GlowPlugCurrent_LSB; // 16 bit - big endian LSB : 10mA / digit
|
|
|
|
uint8_t ActualPumpFreq; // fuel pump freq.: 0.1Hz / digit
|
|
|
|
uint8_t StoredErrorCode; //
|
|
|
|
uint8_t Unknown1; // always 0x00
|
|
|
|
uint8_t FixedPumpFreq; // fixed mode frequency set point: 0.1Hz / digit
|
|
|
|
uint8_t Unknown2; // always 0x64 "100 ?"
|
|
|
|
uint8_t Unknown3; // always 0x00
|
|
|
|
uint8_t CRC_MSB;
|
|
|
|
uint8_t CRC_LSB;
|
2018-09-23 08:59:19 +00:00
|
|
|
} Heater;
|
2018-09-22 23:31:47 +00:00
|
|
|
};
|
2018-09-23 08:59:19 +00:00
|
|
|
static const int CtrlMode = 1;
|
|
|
|
static const int HeatMode = 2;
|
2018-09-22 23:31:47 +00:00
|
|
|
|
|
|
|
public:
|
2018-09-23 09:15:49 +00:00
|
|
|
CProtocol() { Init(0); };
|
|
|
|
CProtocol(int TxMode) { Init(TxMode); };
|
2018-10-20 07:11:23 +00:00
|
|
|
|
2018-09-22 23:31:47 +00:00
|
|
|
void Init(int Txmode);
|
|
|
|
// CRC handlers
|
2018-10-20 07:11:23 +00:00
|
|
|
void setCRC(); // calculate and set the CRC in the buffer
|
2019-07-06 13:46:20 +00:00
|
|
|
void setCRC(uint16_t CRC); // set the CRC in the buffer
|
|
|
|
uint16_t getCRC() const; // extract CRC value from buffer
|
2019-07-09 12:19:21 +00:00
|
|
|
bool verifyCRC(bool silent=false) const; // return true for CRC match
|
2018-10-20 07:11:23 +00:00
|
|
|
|
|
|
|
void setActiveMode() { Controller.Byte0 = 0x76; }; // this allows heater to save tuning params to EEPROM
|
|
|
|
void setPassiveMode() { Controller.Byte0 = 0x78; }; // this prevents heater saving tuning params to EEPROM
|
|
|
|
// command helpers
|
|
|
|
void resetCommand() { setRawCommand(0x00); };
|
|
|
|
void onCommand() { setRawCommand(0xA0); };
|
|
|
|
void offCommand() { setRawCommand(0x05); };
|
|
|
|
// raw command
|
2018-11-14 11:12:18 +00:00
|
|
|
int getRawCommand() const { return Controller.Command; };
|
2018-10-20 07:11:23 +00:00
|
|
|
void setRawCommand(int mode) { Controller.Command = mode; };
|
2018-09-23 08:59:19 +00:00
|
|
|
// Run state
|
2019-07-06 13:46:20 +00:00
|
|
|
uint8_t getRunState() const { return Heater.RunState; };
|
|
|
|
void setRunState(uint8_t state) { Heater.RunState = state; };
|
|
|
|
uint8_t getErrState() const { return Heater.ErrState; };
|
|
|
|
void setErrState(uint8_t state) { Heater.ErrState = state; };
|
|
|
|
uint8_t getStoredErrCode() const { return Heater.StoredErrorCode; };
|
|
|
|
void setStoredErrCode(uint8_t state) { Heater.StoredErrorCode = state; };
|
2018-09-23 08:59:19 +00:00
|
|
|
//
|
2018-12-01 00:36:25 +00:00
|
|
|
float getVoltage_Supply() const;
|
2018-12-08 01:39:41 +00:00
|
|
|
float getVoltage_SupplyRaw() const;
|
2018-12-15 09:34:58 +00:00
|
|
|
void setVoltage_Supply(float volts);
|
2019-01-11 05:40:25 +00:00
|
|
|
float getSystemVoltage() const { return float(Controller.OperatingVoltage) * 0.1; };
|
|
|
|
void setSystemVoltage(float val);
|
2018-09-23 08:59:19 +00:00
|
|
|
|
2018-09-22 23:31:47 +00:00
|
|
|
// fan set/get
|
2019-07-06 13:46:20 +00:00
|
|
|
uint16_t getFan_Actual() const; // Heater side, actual
|
|
|
|
uint16_t getFan_Min() const; // Controller side, define min fan speed
|
|
|
|
uint16_t getFan_Max() const; // Controller side, define max fan speed
|
|
|
|
void setFan_Actual(uint16_t speed); // Heater side, actual
|
|
|
|
void setFan_Min(uint16_t speed); // Controller side, define min fan speed
|
|
|
|
void setFan_Max(uint16_t speed); // Controller side, define max fan speed
|
2018-12-15 09:34:58 +00:00
|
|
|
float getFan_Voltage() const; // fan voltage
|
|
|
|
void setFan_Voltage(float volts); // fan voltage
|
2018-09-23 08:59:19 +00:00
|
|
|
|
2018-09-22 23:31:47 +00:00
|
|
|
// pump set/get
|
2018-11-28 11:15:23 +00:00
|
|
|
void setPump_Min(float Freq) { Controller.MinPumpFreq = (uint8_t)(Freq * 10.f + 0.5f); };
|
|
|
|
void setPump_Max(float Freq) { Controller.MaxPumpFreq = (uint8_t)(Freq * 10.f + 0.5f); };
|
|
|
|
void setPump_Actual(float Freq) { Heater.ActualPumpFreq = (uint8_t)(Freq * 10.f + 0.5f); };
|
|
|
|
void setPump_Fixed(float Freq) { Heater.FixedPumpFreq = (uint8_t)(Freq * 10.f + 0.5f); };
|
2018-11-27 10:44:47 +00:00
|
|
|
float getPump_Min() const { return float(Controller.MinPumpFreq) * 0.1f; }; // Tx side, min pump freq
|
|
|
|
float getPump_Max() const { return float(Controller.MaxPumpFreq) * 0.1f; }; // Tx side, max pump freq
|
|
|
|
float getPump_Actual() const { return float(Heater.ActualPumpFreq) * 0.1f; }; // Rx style, actual
|
|
|
|
float getPump_Fixed() const { return float(Heater.FixedPumpFreq) * 0.1f; }; // Fixed mode pump frequency
|
2018-11-24 11:03:47 +00:00
|
|
|
void setPump_Prime(bool on) { Controller.Prime = on ? 0x5A : 0; };
|
2018-09-22 23:31:47 +00:00
|
|
|
// temperature set/get
|
2019-11-21 08:25:14 +00:00
|
|
|
void setHeaterDemand(int8_t degC) { Controller.DesiredDemand = degC; };
|
|
|
|
void setTemperature_Min(int8_t degC) { Controller.MinTemperature = degC; };
|
|
|
|
void setTemperature_Max(int8_t degC) { Controller.MaxTemperature = degC; };
|
|
|
|
void setTemperature_Actual(int8_t degC) { Controller.ActualTemperature = degC; };
|
|
|
|
int8_t getHeaterDemand() const { return Controller.DesiredDemand; };
|
|
|
|
int8_t getTemperature_Min() const { return Controller.MinTemperature; };
|
|
|
|
int8_t getTemperature_Max() const { return Controller.MaxTemperature; };
|
|
|
|
int8_t getTemperature_Actual() const { return Controller.ActualTemperature; };
|
2019-03-14 10:52:59 +00:00
|
|
|
void setThermostatModeProtocol(unsigned on);
|
2018-11-17 02:08:22 +00:00
|
|
|
bool isThermostat() const { return Controller.OperatingMode == 0x32; };
|
2018-10-20 07:11:23 +00:00
|
|
|
// glow plug
|
2018-11-28 11:15:23 +00:00
|
|
|
float getGlowPlug_Current() const; // glow plug current
|
|
|
|
float getGlowPlug_Voltage() const; // glow plug voltage
|
2019-07-06 13:46:20 +00:00
|
|
|
void setGlowPlug_Current(uint16_t ampsx100); // glow plug current
|
|
|
|
void setGlowPlug_Voltage(uint16_t voltsx10); // glow plug voltage
|
|
|
|
void setGlowDrive(uint8_t val) { Controller.GlowDrive = val; };
|
|
|
|
uint8_t getGlowDrive() const { return Controller.GlowDrive; };
|
2018-10-20 07:11:23 +00:00
|
|
|
// heat exchanger
|
2019-11-21 08:25:14 +00:00
|
|
|
int16_t getTemperature_HeatExchg() const; // temperature of heat exchanger
|
2019-07-06 13:46:20 +00:00
|
|
|
void setTemperature_HeatExchg(uint16_t degC); // temperature of heat exchanger
|
2020-01-13 08:48:32 +00:00
|
|
|
// altitude
|
|
|
|
void setAltitude(float altitude);
|
2020-03-23 05:54:15 +00:00
|
|
|
int getAltitude() const;
|
2018-09-23 06:31:09 +00:00
|
|
|
|
2018-10-31 18:57:21 +00:00
|
|
|
void DebugReport(const char* hdr, const char* ftr);
|
|
|
|
|
2018-09-23 09:15:49 +00:00
|
|
|
CProtocol& operator=(const CProtocol& rhs);
|
2018-09-22 23:31:47 +00:00
|
|
|
};
|
|
|
|
|
2018-11-06 09:43:54 +00:00
|
|
|
class CModeratedFrame : public CProtocol {
|
|
|
|
unsigned long lastTime;
|
|
|
|
public:
|
|
|
|
CModeratedFrame() { lastTime = 0; };
|
|
|
|
void setTime() { lastTime = millis(); };
|
2018-11-24 11:03:47 +00:00
|
|
|
long elapsedTime() { return millis() - lastTime; };
|
2018-11-06 09:43:54 +00:00
|
|
|
};
|
|
|
|
|
2018-12-20 04:19:59 +00:00
|
|
|
|
2018-12-01 00:36:25 +00:00
|
|
|
class CProtocolPackage {
|
|
|
|
CProtocol Heater;
|
|
|
|
CProtocol Controller;
|
2018-12-20 04:19:59 +00:00
|
|
|
CContextTimeStamp _timeStamp;
|
2018-12-01 00:36:25 +00:00
|
|
|
public:
|
2018-12-01 18:25:10 +00:00
|
|
|
void set(const CProtocol& htr, const CProtocol& ctl) { Heater = htr; Controller = ctl; };
|
|
|
|
int getRunState() const { return Heater.getRunState(); };
|
2019-04-04 19:39:58 +00:00
|
|
|
int getRunStateEx() const; // extra support for cyclic thermostat mode
|
2018-12-01 18:25:10 +00:00
|
|
|
const char* getRunStateStr() const;
|
2018-12-21 01:27:03 +00:00
|
|
|
int getErrState() const;
|
2018-12-01 18:25:10 +00:00
|
|
|
const char* getErrStateStr() const;
|
2018-12-16 02:45:13 +00:00
|
|
|
const char* getErrStateStrEx() const;
|
2018-12-01 00:36:25 +00:00
|
|
|
float getBattVoltage() const { return Heater.getVoltage_Supply(); };
|
2018-12-01 18:25:10 +00:00
|
|
|
bool isThermostat() const { return Controller.isThermostat(); };
|
2019-06-15 23:09:29 +00:00
|
|
|
float getHeaterDemand() const { return float(Controller.getHeaterDemand()); };
|
2018-12-01 18:25:10 +00:00
|
|
|
float getTemperature_HeatExchg() const { return float(Heater.getTemperature_HeatExchg()); };
|
2018-12-15 09:34:58 +00:00
|
|
|
float getTemperature_Min() const { return float(Controller.getTemperature_Min()); };
|
|
|
|
float getTemperature_Max() const { return float(Controller.getTemperature_Max()); };
|
2018-12-01 00:36:25 +00:00
|
|
|
float getPump_Fixed() const { return Heater.getPump_Fixed(); };
|
|
|
|
float getPump_Actual() const { return Heater.getPump_Actual(); };
|
|
|
|
float getPump_Min() const { return Controller.getPump_Min(); };
|
|
|
|
float getPump_Max() const { return Controller.getPump_Max(); };
|
|
|
|
float getFan_Actual() const { return Heater.getFan_Actual(); };
|
2019-07-06 13:46:20 +00:00
|
|
|
uint16_t getFan_Min() const { return Controller.getFan_Min(); };
|
|
|
|
uint16_t getFan_Max() const { return Controller.getFan_Max(); };
|
2018-12-15 09:34:58 +00:00
|
|
|
float getFan_Voltage() const { return Heater.getFan_Voltage(); };
|
2019-01-11 05:40:25 +00:00
|
|
|
int getFan_Sensor() const { return Controller.Controller.FanSensor; };
|
2018-12-01 00:36:25 +00:00
|
|
|
float getGlowPlug_Power() const { return Heater.getGlowPlug_Current() * Heater.getGlowPlug_Voltage(); };
|
2018-12-15 09:34:58 +00:00
|
|
|
float getGlow_Voltage() const { return Heater.getGlowPlug_Voltage(); };
|
|
|
|
float getGlow_Current() const { return Heater.getGlowPlug_Current(); };
|
2019-01-11 05:40:25 +00:00
|
|
|
float getSystemVoltage() const { return Controller.getSystemVoltage(); };
|
2019-01-19 11:05:14 +00:00
|
|
|
int getGlow_Drive() const { return Controller.getGlowDrive(); };
|
2020-03-23 05:54:15 +00:00
|
|
|
int getAltitude() const { return Controller.getAltitude(); };
|
2018-12-20 04:19:59 +00:00
|
|
|
|
2018-12-21 21:48:39 +00:00
|
|
|
// void setRefTime();
|
2018-12-20 04:19:59 +00:00
|
|
|
void reportFrames(bool isOEM);
|
2018-12-01 00:36:25 +00:00
|
|
|
};
|
2018-09-23 08:59:19 +00:00
|
|
|
|
2019-06-15 23:09:29 +00:00
|
|
|
extern const CProtocolPackage& getHeaterInfo();
|
2018-12-01 18:25:10 +00:00
|
|
|
|
2018-09-23 06:31:09 +00:00
|
|
|
#endif
|