ESP32_ChinaDieselHeater_Con.../Arduino/BTCDieselHeater/Protocol.cpp

366 lines
8.8 KiB
C++
Raw Normal View History

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 08:59:19 +00:00
#include <Arduino.h>
#include "Protocol.h"
#include "debugport.h"
2018-12-01 18:25:10 +00:00
#include "helpers.h"
2018-09-23 08:59:19 +00:00
unsigned short
CProtocol::CalcCRC(int len) const
2018-09-23 08:59:19 +00:00
{
// calculate a CRC-16/MODBUS checksum using the first 22 bytes of the data array
unsigned short wCRCWord = 0xFFFF;
int wLength = len;
const unsigned char* pData = Data;
2018-09-23 08:59:19 +00:00
while (wLength--)
{
unsigned char nTemp = *pData++ ^ wCRCWord;
wCRCWord >>= 8;
wCRCWord ^= wCRCTable[nTemp];
}
return wCRCWord;
}
void
2018-09-23 09:15:49 +00:00
CProtocol::setCRC()
2018-09-23 08:59:19 +00:00
{
setCRC(CalcCRC(22));
}
void
2018-09-23 09:15:49 +00:00
CProtocol::setCRC(unsigned short CRC)
2018-09-23 08:59:19 +00:00
{
Data[22] = (CRC >> 8) & 0xff; // MSB of CRC in Data[22]
Data[23] = (CRC >> 0) & 0xff; // LSB of CRC in Data[23]
}
unsigned short
CProtocol::getCRC() const
2018-09-23 08:59:19 +00:00
{
unsigned short CRC;
CRC = Data[22]; // MSB of CRC in Data[22]
CRC <<= 8;
CRC |= Data[23]; // LSB of CRC in Data[23]
return CRC;
2018-09-23 08:59:19 +00:00
}
// return true for CRC match
bool
CProtocol::verifyCRC(bool bSilent) const
2018-09-23 08:59:19 +00:00
{
unsigned short CRC = CalcCRC(22); // calculate CRC based on first 22 bytes
unsigned short FrameCRC = getCRC();
bool bOK = (FrameCRC == CRC);
if(!bOK && !bSilent) {
DebugPort.print("verifyCRC FAILED: calc:");
DebugPort.print(CRC, HEX);
DebugPort.print(" data:");
DebugPort.println(FrameCRC, HEX);
}
return bOK; // does it match the stored values?
2018-09-23 08:59:19 +00:00
}
2018-09-23 09:15:49 +00:00
CProtocol&
CProtocol::operator=(const CProtocol& rhs)
2018-09-23 08:59:19 +00:00
{
memcpy(Data, rhs.Data, 24);
return *this;
}
void
2018-09-23 09:15:49 +00:00
CProtocol::setFan_Min(short Speed)
2018-09-23 08:59:19 +00:00
{
// Minimum speed set
Controller.MinFanRPM_MSB = (Speed >> 8) & 0xff;
Controller.MinFanRPM_LSB = (Speed >> 0) & 0xff;
}
void
2018-09-23 09:15:49 +00:00
CProtocol::setFan_Max(short Speed)
2018-09-23 08:59:19 +00:00
{
// Minimum speed set
Controller.MaxFanRPM_MSB = (Speed >> 8) & 0xff;
Controller.MaxFanRPM_LSB = (Speed >> 0) & 0xff;
}
short
2018-11-14 11:12:18 +00:00
CProtocol::getFan_Min() const
2018-09-23 08:59:19 +00:00
{
short retval;
// Minimum speed get
retval = Controller.MinFanRPM_MSB;
retval <<= 8;
retval |= Controller.MinFanRPM_LSB;
return retval;
}
short
2018-11-14 11:12:18 +00:00
CProtocol::getFan_Max() const
2018-09-23 08:59:19 +00:00
{
short retval;
// Maximum speed get
retval = Controller.MaxFanRPM_MSB;
retval <<= 8;
retval |= Controller.MaxFanRPM_LSB;
return retval;
}
short
2018-11-14 11:12:18 +00:00
CProtocol::getFan_Actual() const
2018-09-23 08:59:19 +00:00
{
// Rx side, actual
short retval;
retval = Heater.FanRPM_MSB;
retval <<= 8;
retval |= Heater.FanRPM_LSB;
return retval;
}
void
2018-09-23 09:15:49 +00:00
CProtocol::setFan_Actual(short Speed) // Heater side, actual
2018-09-23 08:59:19 +00:00
{
// actual speed set
Heater.FanRPM_MSB = (Speed >> 8) & 0xff;
Heater.FanRPM_LSB = (Speed >> 0) & 0xff;
}
float
2018-11-14 11:12:18 +00:00
CProtocol::getGlowPlug_Current() const // glow plug current
2018-09-23 08:59:19 +00:00
{
short val;
val = Heater.GlowPlugCurrent_MSB;
val <<= 8;
val |= Heater.GlowPlugCurrent_LSB;
return float(val) * 0.01f; // 10mA / digit
2018-09-23 08:59:19 +00:00
}
void
2018-09-23 09:15:49 +00:00
CProtocol::setGlowPlug_Current(short ampsx100) // glow plug current
2018-09-23 08:59:19 +00:00
{
Heater.GlowPlugCurrent_MSB = (ampsx100 >> 8) & 0xff;
Heater.GlowPlugCurrent_LSB = (ampsx100 >> 0) & 0xff;
}
float
2018-11-14 11:12:18 +00:00
CProtocol::getGlowPlug_Voltage() const // glow plug voltage
2018-09-23 08:59:19 +00:00
{
short val;
val = Heater.GlowPlugVoltage_MSB;
val <<= 8;
val |= Heater.GlowPlugVoltage_LSB;
return float(val) * 0.1f; // 0.1V / digit
2018-09-23 08:59:19 +00:00
}
void
2018-09-23 09:15:49 +00:00
CProtocol::setGlowPlug_Voltage(short voltsx10) // glow plug voltage
2018-09-23 08:59:19 +00:00
{
Heater.GlowPlugVoltage_MSB = (voltsx10 >> 8) & 0xff;
Heater.GlowPlugVoltage_LSB = (voltsx10 >> 0) & 0xff;
}
short
CProtocol::getTemperature_HeatExchg() const // temperature of heat exchanger
2018-09-23 08:59:19 +00:00
{
short retval;
retval = Heater.HeatExchgTemp_MSB;
retval <<= 8;
retval |= Heater.HeatExchgTemp_LSB;
return retval;
}
void
2018-09-23 09:15:49 +00:00
CProtocol::setTemperature_HeatExchg(short degC) // temperature of heat exchanger
2018-09-23 08:59:19 +00:00
{
Heater.HeatExchgTemp_MSB = (degC >> 8) & 0xff;
Heater.HeatExchgTemp_LSB = (degC >> 0) & 0xff;
}
float
CProtocol::getFan_Voltage() const // fan voltage
2018-09-23 08:59:19 +00:00
{
if(getRunState()) { // fan volatge sensing goes stupid when main heater relay turns off!
short val;
val = Heater.FanVoltage_MSB;
val <<= 8;
val |= Heater.FanVoltage_LSB;
return float(val) * 0.1;
}
return 0;
2018-09-23 08:59:19 +00:00
}
void
CProtocol::setFan_Voltage(float volts) // fan voltage
2018-09-23 08:59:19 +00:00
{
short val = short(volts * 10);
Heater.FanVoltage_MSB = (val >> 8) & 0xff;
Heater.FanVoltage_LSB = (val >> 0) & 0xff;
2018-09-23 08:59:19 +00:00
}
void
CProtocol::setVoltage_Supply(float volts)
2018-09-23 08:59:19 +00:00
{
short val = short(volts * 10);
Heater.SupplyV_MSB = (val >> 8) & 0xff;
Heater.SupplyV_LSB = (val >> 0) & 0xff;
2018-09-23 08:59:19 +00:00
}
float
2018-12-08 01:39:41 +00:00
CProtocol::getVoltage_SupplyRaw() const
2018-09-23 08:59:19 +00:00
{
short val = 0;
val = Heater.SupplyV_MSB & 0xff;
val <<= 8;
val |= Heater.SupplyV_LSB & 0xff;
float voltage = float(val) * 0.1f;
return voltage;
2018-09-23 08:59:19 +00:00
}
2018-12-08 01:39:41 +00:00
float
CProtocol::getVoltage_Supply() const
{
return getVoltage_SupplyRaw() + 0.6; // compensate for series protection diode
}
2018-09-23 08:59:19 +00:00
void
2018-09-23 09:15:49 +00:00
CProtocol::Init(int FrameMode)
2018-09-23 08:59:19 +00:00
{
if(FrameMode == CtrlMode) {
Controller.Byte0 = 0x76;
Controller.Len = 22;
Controller.Command = 0; // NOP
setTemperature_Actual(18); // 1degC / digit
setTemperature_Desired(20); // 1degC / digit
setPump_Min(1.4f); // Hz
setPump_Max(4.3f); // Hz
2018-09-23 08:59:19 +00:00
setFan_Min(1450); // 1RPM / digit
setFan_Max(4500); // 1RPM / digit
Controller.OperatingVoltage = 120; // 0.1V/digit
Controller.FanSensor = 1; // SN-1 or SN-2
Controller.OperatingMode = 0x32; // 0x32:Thermostat, 0xCD:Fixed
setTemperature_Min(8); // Minimum settable temperature
setTemperature_Max(35); // Maximum settable temperature
Controller.MinTempRise = 5; // temp rise to sense fuel ignition - GLOW PLUG POWER?
2018-09-23 08:59:19 +00:00
Controller.Prime = 0; // 00: normal, 0x5A: fuel prime
Controller.Unknown1_MSB = 0x01; // always 0x01
Controller.Unknown1_LSB = 0x2c; // always 0x2c 16bit: "300 secs = max run without burn detected" ??
Controller.Unknown2_MSB = 0x0d; // always 0x0d
Controller.Unknown2_LSB = 0xac; // always 0xac 16bit: "3500" ?? Ignition fan max RPM????
2018-09-23 08:59:19 +00:00
setCRC();
}
else if(FrameMode == HeatMode){
Heater.Byte0 = 0x76;
Heater.Len = 22;
setRunState(0);
setErrState(0);
setVoltage_Supply(133);
setFan_Actual(0);
setFan_Voltage(0);
setTemperature_HeatExchg(18);
setGlowPlug_Voltage(0);
setGlowPlug_Current(0);
Heater.ActualPumpFreq = 0; // fuel pump freq.: 0.1Hz / digit
Heater.StoredErrorCode = 0; //
2018-09-23 08:59:19 +00:00
Heater.Unknown1 = 0; // always 0x00
Heater.FixedPumpFreq = 23; // fixed mode frequency set point: 0.1Hz / digit
Heater.Unknown2 = 100; // always 0x64 "100 ?"
Heater.Unknown3 = 0; // always 0x00
setCRC();
}
else {
memset(Data, 0, 24);
}
}
void
CProtocol::DebugReport(const char* hdr, const char* ftr)
{
DebugPort.print(hdr); // header
for(int i=0; i<24; i++) {
char str[16];
sprintf(str, " %02X", Data[i]); // build 2 dig hex values
DebugPort.print(str); // and print
}
DebugPort.print(ftr); // footer
}
void
CProtocol::setThermostatMode(unsigned on)
{
Controller.OperatingMode = on ? 0x32 : 0xCD;
if(!on)
setTemperature_Actual(0); // if using fixed mode, actual must be reported as 0
};
2018-12-01 18:25:10 +00:00
const char* Runstates [] PROGMEM = {
" Stopped/Ready ",
"Starting...",
"Igniting...",
" Ignition retry ",
"Ignited",
"Running",
"Stopping",
"Shutting down",
"Cooling",
"Unknown run state"
};
const char*
CProtocolPackage::getRunStateStr() const
{
uint8_t runstate = Heater.getRunState();
UPPERLIMIT(runstate, 9);
return Runstates[runstate];
}
const char* Errstates [] PROGMEM = {
"",
"",
"Low voltage", // E-01
"High voltage", // E-02
"Glow plug fault", // E-03
"Pump fault", // E-04
"Overheat", // E-05
"Motor fault", // E-06
"Comms fault", // E-07
"Flame out", // E-08
"Temp sense", // E-09
"Ignition fail", // E-10
"Unknown error?" // mystery code!
};
const char*
CProtocolPackage::getErrStateStr() const
{
uint8_t errstate = Heater.getErrState();
UPPERLIMIT(errstate, 12);
return Errstates[errstate];
}