changed to protocol.h/.cpp
This commit is contained in:
parent
9818b33e47
commit
961c5b8b29
6 changed files with 447 additions and 326 deletions
|
@ -1,169 +0,0 @@
|
||||||
#include <Arduino.h>
|
|
||||||
#include "CFrame.h"
|
|
||||||
|
|
||||||
unsigned short
|
|
||||||
CFrame::CalcCRC(int len)
|
|
||||||
{
|
|
||||||
// calculate a CRC-16/MODBUS checksum using the first 22 bytes of the data array
|
|
||||||
unsigned short wCRCWord = 0xFFFF;
|
|
||||||
|
|
||||||
int wLength = len;
|
|
||||||
unsigned char* pData = Data;
|
|
||||||
while (wLength--)
|
|
||||||
{
|
|
||||||
unsigned char nTemp = *pData++ ^ wCRCWord;
|
|
||||||
wCRCWord >>= 8;
|
|
||||||
wCRCWord ^= wCRCTable[nTemp];
|
|
||||||
}
|
|
||||||
|
|
||||||
return wCRCWord;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CFrame::setCRC()
|
|
||||||
{
|
|
||||||
setCRC(CalcCRC(22));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CFrame::setCRC(unsigned short CRC)
|
|
||||||
{
|
|
||||||
Data[22] = (CRC >> 8) & 0xff; // MSB of CRC in Data[22]
|
|
||||||
Data[23] = (CRC >> 0) & 0xff; // LSB of CRC in Data[23]
|
|
||||||
}
|
|
||||||
|
|
||||||
CFrame&
|
|
||||||
CFrame::operator=(CFrame& rhs)
|
|
||||||
{
|
|
||||||
memcpy(Data, rhs.Data, 24);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
unsigned short
|
|
||||||
CFrame::getCRC()
|
|
||||||
{
|
|
||||||
unsigned short CRC;
|
|
||||||
CRC = Data[22]; // MSB of CRC in Data[22]
|
|
||||||
CRC <<= 8;
|
|
||||||
CRC |= Data[23]; // LSB of CRC in Data[23]
|
|
||||||
}
|
|
||||||
|
|
||||||
// return true for CRC match
|
|
||||||
bool
|
|
||||||
CFrame::verifyCRC()
|
|
||||||
{
|
|
||||||
unsigned short CRC = CalcCRC(22); // calculate CRC based on first 22 bytes
|
|
||||||
return (getCRC() == CRC); // does it match the stored values?
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CFrame::setFan_Min(short Speed)
|
|
||||||
{
|
|
||||||
// Minimum speed set
|
|
||||||
Tx.MinFanRPM_MSB = (Speed >> 8) & 0xff;
|
|
||||||
Tx.MinFanRPM_LSB = (Speed >> 0) & 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CFrame::setFan_Max(short Speed)
|
|
||||||
{
|
|
||||||
// Minimum speed set
|
|
||||||
Tx.MaxFanRPM_MSB = (Speed >> 8) & 0xff;
|
|
||||||
Tx.MaxFanRPM_LSB = (Speed >> 0) & 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
short
|
|
||||||
CFrame::getFan_Min()
|
|
||||||
{
|
|
||||||
short retval;
|
|
||||||
// Minimum speed get
|
|
||||||
retval = Tx.MinFanRPM_MSB;
|
|
||||||
retval <<= 8;
|
|
||||||
retval |= Tx.MinFanRPM_LSB;
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
short
|
|
||||||
CFrame::getFan_Max()
|
|
||||||
{
|
|
||||||
short retval;
|
|
||||||
// Maximum speed get
|
|
||||||
retval = Tx.MaxFanRPM_MSB;
|
|
||||||
retval <<= 8;
|
|
||||||
retval |= Tx.MaxFanRPM_LSB;
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
short
|
|
||||||
CFrame::getFan_Actual()
|
|
||||||
{
|
|
||||||
// Rx side, actual
|
|
||||||
short retval;
|
|
||||||
retval = Rx.FanRPM_MSB;
|
|
||||||
retval <<= 8;
|
|
||||||
retval |= Rx.FanRPM_LSB;
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
short
|
|
||||||
CFrame::getTemperature_GlowPin() // temperature of glow pin
|
|
||||||
{
|
|
||||||
short retval;
|
|
||||||
retval = Rx.GlowPinTemp_MSB;
|
|
||||||
retval <<= 8;
|
|
||||||
retval |= Rx.GlowPinPWMDuty_LSB;
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
short
|
|
||||||
CFrame::getTemperature_HeatExchg() // temperature of heat exchanger
|
|
||||||
{
|
|
||||||
short retval;
|
|
||||||
retval = Rx.HeatExchgTemp_MSB;
|
|
||||||
retval <<= 8;
|
|
||||||
retval |= Rx.HeatExchgTemp_LSB;
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
short
|
|
||||||
CFrame::getTemperature_Inlet() // temperature near inlet
|
|
||||||
{
|
|
||||||
short retval;
|
|
||||||
retval = Rx.InletTemp_MSB;
|
|
||||||
retval <<= 8;
|
|
||||||
retval |= Rx.InletTemp_LSB;
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CFrame::Init(int Txmode)
|
|
||||||
{
|
|
||||||
if(Txmode) {
|
|
||||||
Tx.Byte0 = 0x76;
|
|
||||||
Tx.Len = 22;
|
|
||||||
Tx.Command = 0; // NOP
|
|
||||||
setTemperature_Actual(18); // 1degC / digit
|
|
||||||
setTemperature_Desired(20); // 1degC / digit
|
|
||||||
setPump_Min(14); // 0.1Hz/digit
|
|
||||||
setPump_Max(43); // 0.1Hz/digit
|
|
||||||
setFan_Min(1450); // 1RPM / digit
|
|
||||||
setFan_Max(4500); // 1RPM / digit
|
|
||||||
Tx.OperatingVoltage = 120; // 0.1V/digit
|
|
||||||
Tx.FanSensor = 1; // SN-1 or SN-2
|
|
||||||
Tx.OperatingMode = 0x32; // 0x32:Thermostat, 0xCD:Fixed
|
|
||||||
setTemperature_Min(8); // Minimum settable temperature
|
|
||||||
setTemperature_Max(35); // Maximum settable temperature
|
|
||||||
Tx.MinTempRise = 5; // temp rise to sense fuel ignition
|
|
||||||
Tx.Prime = 0; // 00: normal, 0x5A: fuel prime
|
|
||||||
Tx.Unknown1_MSB = 0x01; // always 0x01
|
|
||||||
Tx.Unknown1_LSB = 0x2c; // always 0x2c 16bit: "300 secs = max run without burn detected" ??
|
|
||||||
Tx.Unknown2_MSB = 0x0d; // always 0x0d
|
|
||||||
Tx.Unknown2_LSB = 0xac; // always 0xac 16bit: "3500" ??
|
|
||||||
setCRC();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
memset(Data, 0, 24);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
267
Arduino/SenderTrial2/Protocol.cpp
Normal file
267
Arduino/SenderTrial2/Protocol.cpp
Normal file
|
@ -0,0 +1,267 @@
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include "Protocol.h"
|
||||||
|
|
||||||
|
unsigned short
|
||||||
|
CFrame::CalcCRC(int len)
|
||||||
|
{
|
||||||
|
// calculate a CRC-16/MODBUS checksum using the first 22 bytes of the data array
|
||||||
|
unsigned short wCRCWord = 0xFFFF;
|
||||||
|
|
||||||
|
int wLength = len;
|
||||||
|
unsigned char* pData = Data;
|
||||||
|
while (wLength--)
|
||||||
|
{
|
||||||
|
unsigned char nTemp = *pData++ ^ wCRCWord;
|
||||||
|
wCRCWord >>= 8;
|
||||||
|
wCRCWord ^= wCRCTable[nTemp];
|
||||||
|
}
|
||||||
|
|
||||||
|
return wCRCWord;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CFrame::setCRC()
|
||||||
|
{
|
||||||
|
setCRC(CalcCRC(22));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CFrame::setCRC(unsigned short CRC)
|
||||||
|
{
|
||||||
|
Data[22] = (CRC >> 8) & 0xff; // MSB of CRC in Data[22]
|
||||||
|
Data[23] = (CRC >> 0) & 0xff; // LSB of CRC in Data[23]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned short
|
||||||
|
CFrame::getCRC()
|
||||||
|
{
|
||||||
|
unsigned short CRC;
|
||||||
|
CRC = Data[22]; // MSB of CRC in Data[22]
|
||||||
|
CRC <<= 8;
|
||||||
|
CRC |= Data[23]; // LSB of CRC in Data[23]
|
||||||
|
}
|
||||||
|
|
||||||
|
// return true for CRC match
|
||||||
|
bool
|
||||||
|
CFrame::verifyCRC()
|
||||||
|
{
|
||||||
|
unsigned short CRC = CalcCRC(22); // calculate CRC based on first 22 bytes
|
||||||
|
return (getCRC() == CRC); // does it match the stored values?
|
||||||
|
}
|
||||||
|
|
||||||
|
CFrame&
|
||||||
|
CFrame::operator=(const CFrame& rhs)
|
||||||
|
{
|
||||||
|
memcpy(Data, rhs.Data, 24);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
CFrame::getCommand()
|
||||||
|
{
|
||||||
|
return Controller.Command;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CFrame::setCommand(int cmd)
|
||||||
|
{
|
||||||
|
Controller.Command = cmd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*unsigned char getCommand();
|
||||||
|
void setCommand(int mode);*/
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CFrame::setFan_Min(short Speed)
|
||||||
|
{
|
||||||
|
// Minimum speed set
|
||||||
|
Controller.MinFanRPM_MSB = (Speed >> 8) & 0xff;
|
||||||
|
Controller.MinFanRPM_LSB = (Speed >> 0) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CFrame::setFan_Max(short Speed)
|
||||||
|
{
|
||||||
|
// Minimum speed set
|
||||||
|
Controller.MaxFanRPM_MSB = (Speed >> 8) & 0xff;
|
||||||
|
Controller.MaxFanRPM_LSB = (Speed >> 0) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
short
|
||||||
|
CFrame::getFan_Min()
|
||||||
|
{
|
||||||
|
short retval;
|
||||||
|
// Minimum speed get
|
||||||
|
retval = Controller.MinFanRPM_MSB;
|
||||||
|
retval <<= 8;
|
||||||
|
retval |= Controller.MinFanRPM_LSB;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
short
|
||||||
|
CFrame::getFan_Max()
|
||||||
|
{
|
||||||
|
short retval;
|
||||||
|
// Maximum speed get
|
||||||
|
retval = Controller.MaxFanRPM_MSB;
|
||||||
|
retval <<= 8;
|
||||||
|
retval |= Controller.MaxFanRPM_LSB;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
short
|
||||||
|
CFrame::getFan_Actual()
|
||||||
|
{
|
||||||
|
// Rx side, actual
|
||||||
|
short retval;
|
||||||
|
retval = Heater.FanRPM_MSB;
|
||||||
|
retval <<= 8;
|
||||||
|
retval |= Heater.FanRPM_LSB;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CFrame::setFan_Actual(short Speed) // Heater side, actual
|
||||||
|
{
|
||||||
|
// actual speed set
|
||||||
|
Heater.FanRPM_MSB = (Speed >> 8) & 0xff;
|
||||||
|
Heater.FanRPM_LSB = (Speed >> 0) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
short
|
||||||
|
CFrame::getGlowPlug_Current() // glow plug current
|
||||||
|
{
|
||||||
|
short retval;
|
||||||
|
retval = Heater.GlowPlugCurrent_MSB;
|
||||||
|
retval <<= 8;
|
||||||
|
retval |= Heater.GlowPlugCurrent_LSB;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CFrame::setGlowPlug_Current(short ampsx100) // glow plug current
|
||||||
|
{
|
||||||
|
Heater.GlowPlugCurrent_MSB = (ampsx100 >> 8) & 0xff;
|
||||||
|
Heater.GlowPlugCurrent_LSB = (ampsx100 >> 0) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
short
|
||||||
|
CFrame::getGlowPlug_Voltage() // glow plug voltage
|
||||||
|
{
|
||||||
|
short retval;
|
||||||
|
retval = Heater.GlowPlugVoltage_MSB;
|
||||||
|
retval <<= 8;
|
||||||
|
retval |= Heater.GlowPlugVoltage_LSB;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
CFrame::setGlowPlug_Voltage(short voltsx10) // glow plug voltage
|
||||||
|
{
|
||||||
|
Heater.GlowPlugVoltage_MSB = (voltsx10 >> 8) & 0xff;
|
||||||
|
Heater.GlowPlugVoltage_LSB = (voltsx10 >> 0) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
short
|
||||||
|
CFrame::getTemperature_HeatExchg() // temperature of heat exchanger
|
||||||
|
{
|
||||||
|
short retval;
|
||||||
|
retval = Heater.HeatExchgTemp_MSB;
|
||||||
|
retval <<= 8;
|
||||||
|
retval |= Heater.HeatExchgTemp_LSB;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CFrame::setTemperature_HeatExchg(short degC) // temperature of heat exchanger
|
||||||
|
{
|
||||||
|
Heater.HeatExchgTemp_MSB = (degC >> 8) & 0xff;
|
||||||
|
Heater.HeatExchgTemp_LSB = (degC >> 0) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
short
|
||||||
|
CFrame::getFan_Voltage() // temperature near inlet
|
||||||
|
{
|
||||||
|
short retval;
|
||||||
|
retval = Heater.FanVoltage_MSB;
|
||||||
|
retval <<= 8;
|
||||||
|
retval |= Heater.FanVoltage_LSB;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CFrame::setFan_Voltage(short voltsx10) // temperature near inlet
|
||||||
|
{
|
||||||
|
Heater.FanVoltage_MSB = (voltsx10 >> 8) & 0xff;
|
||||||
|
Heater.FanVoltage_LSB = (voltsx10 >> 0) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CFrame::setVoltage_Supply(short voltsx10)
|
||||||
|
{
|
||||||
|
Heater.SupplyV_MSB = (voltsx10 >> 8) & 0xff;
|
||||||
|
Heater.SupplyV_LSB = (voltsx10 >> 0) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
short
|
||||||
|
CFrame::getVoltage_Supply()
|
||||||
|
{
|
||||||
|
short retval = 0;
|
||||||
|
retval = Heater.SupplyV_MSB & 0xff;
|
||||||
|
retval <<= 8;
|
||||||
|
retval |= Heater.SupplyV_LSB & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CFrame::Init(int FrameMode)
|
||||||
|
{
|
||||||
|
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(14); // 0.1Hz/digit
|
||||||
|
setPump_Max(43); // 0.1Hz/digit
|
||||||
|
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
|
||||||
|
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" ??
|
||||||
|
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.ErrorCode = 0; //
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -30,24 +30,24 @@ public:
|
||||||
unsigned char Unknown2_LSB; // [21] always 0xac "3500 ?"
|
unsigned char Unknown2_LSB; // [21] always 0xac "3500 ?"
|
||||||
unsigned char CRC_MSB; // [22]
|
unsigned char CRC_MSB; // [22]
|
||||||
unsigned char CRC_LSB; // [23]
|
unsigned char CRC_LSB; // [23]
|
||||||
} Tx;
|
} Controller;
|
||||||
struct {
|
struct {
|
||||||
unsigned char Byte0; // always 0x76
|
unsigned char Byte0; // always 0x76
|
||||||
unsigned char Len; // always 0x16 == 22
|
unsigned char Len; // always 0x16 == 22 bytes
|
||||||
unsigned char RunState; // operating state
|
unsigned char RunState; // operating state
|
||||||
unsigned char OnOff; // 0: OFF, 1: ON
|
unsigned char ErrState; // 0: OFF, 1: ON, 2+ (E-0n + 1)
|
||||||
unsigned char SupplyV_MSB; // 16 bit - big endian MSB
|
unsigned char SupplyV_MSB; // 16 bit - big endian MSB
|
||||||
unsigned char SupplyV_LSB; // 16 bit - big endian MSB : 0.1V / digit
|
unsigned char SupplyV_LSB; // 16 bit - big endian MSB : 0.1V / digit
|
||||||
unsigned char FanRPM_MSB; // 16 bit - big endian MSB
|
unsigned char FanRPM_MSB; // 16 bit - big endian MSB
|
||||||
unsigned char FanRPM_LSB; // 16 bit - big endian LSB : 1 RPM / digit
|
unsigned char FanRPM_LSB; // 16 bit - big endian LSB : 1 RPM / digit
|
||||||
unsigned char InletTemp_MSB; // 16 bit - big endian MSB
|
unsigned char FanVoltage_MSB; // 16 bit - big endian MSB
|
||||||
unsigned char InletTemp_LSB; // 16 bit - big endian LSB : 1 degC / digit
|
unsigned char FanVoltage_LSB; // 16 bit - big endian LSB : 0.1V / digit
|
||||||
unsigned char HeatExchgTemp_MSB; // 16 bit - big endian MSB
|
unsigned char HeatExchgTemp_MSB; // 16 bit - big endian MSB
|
||||||
unsigned char HeatExchgTemp_LSB; // 16 bit - big endian LSB : 1 degC / digit
|
unsigned char HeatExchgTemp_LSB; // 16 bit - big endian LSB : 1 degC / digit
|
||||||
unsigned char GlowPinPWMDuty_MSB; // 16 bit - big endian MSB
|
unsigned char GlowPlugVoltage_MSB; // 16 bit - big endian MSB
|
||||||
unsigned char GlowPinPWMDuty_LSB; // 16 bit - big endian LSB : 1% / digit
|
unsigned char GlowPlugVoltage_LSB; // 16 bit - big endian LSB : 0.1V / digit
|
||||||
unsigned char GlowPinTemp_MSB; // 16 bit - big endian MSB
|
unsigned char GlowPlugCurrent_MSB; // 16 bit - big endian MSB
|
||||||
unsigned char GlowPinTemp_LSB; // 16 bit - big endian LSB : 1 degC / digit
|
unsigned char GlowPlugCurrent_LSB; // 16 bit - big endian LSB : 10mA / digit
|
||||||
unsigned char ActualPumpFreq; // fuel pump freq.: 0.1Hz / digit
|
unsigned char ActualPumpFreq; // fuel pump freq.: 0.1Hz / digit
|
||||||
unsigned char ErrorCode; //
|
unsigned char ErrorCode; //
|
||||||
unsigned char Unknown1; // always 0x00
|
unsigned char Unknown1; // always 0x00
|
||||||
|
@ -56,9 +56,10 @@ public:
|
||||||
unsigned char Unknown3; // always 0x00
|
unsigned char Unknown3; // always 0x00
|
||||||
unsigned char CRC_MSB;
|
unsigned char CRC_MSB;
|
||||||
unsigned char CRC_LSB;
|
unsigned char CRC_LSB;
|
||||||
} Rx;
|
} Heater;
|
||||||
};
|
};
|
||||||
static const int TxMode = 1;
|
static const int CtrlMode = 1;
|
||||||
|
static const int HeatMode = 2;
|
||||||
const unsigned short wCRCTable[256] = {
|
const unsigned short wCRCTable[256] = {
|
||||||
0X0000, 0XC0C1, 0XC181, 0X0140, 0XC301, 0X03C0, 0X0280, 0XC241,
|
0X0000, 0XC0C1, 0XC181, 0X0140, 0XC301, 0X03C0, 0X0280, 0XC241,
|
||||||
0XC601, 0X06C0, 0X0780, 0XC741, 0X0500, 0XC5C1, 0XC481, 0X0440,
|
0XC601, 0X06C0, 0X0780, 0XC741, 0X0500, 0XC5C1, 0XC481, 0X0440,
|
||||||
|
@ -99,35 +100,59 @@ public:
|
||||||
CFrame(int TxMode) { Init(TxMode); };
|
CFrame(int TxMode) { Init(TxMode); };
|
||||||
void Init(int Txmode);
|
void Init(int Txmode);
|
||||||
// CRC handlers
|
// CRC handlers
|
||||||
unsigned short CalcCRC(int len); // calculate and set the CRC upon first 22 bytes
|
unsigned short CalcCRC(int len); // calculate and set the CRC upon len bytes
|
||||||
void setCRC(); // calculate and set the CRC in the buffer
|
void setCRC(); // calculate and set the CRC in the buffer
|
||||||
void setCRC(unsigned short CRC); // set the CRC in the buffer
|
void setCRC(unsigned short CRC); // set the CRC in the buffer
|
||||||
unsigned short getCRC(); // extract CRC value from buffer
|
unsigned short getCRC(); // extract CRC value from buffer
|
||||||
bool verifyCRC(); // return true for CRC match
|
bool verifyCRC(); // return true for CRC match
|
||||||
|
// command
|
||||||
|
int getCommand();
|
||||||
|
void setCommand(int mode);
|
||||||
|
// Run state
|
||||||
|
unsigned char getRunState() { return Heater.RunState; };
|
||||||
|
void setRunState(unsigned char state) { Heater.RunState = state; };
|
||||||
|
unsigned char getErrState() { return Heater.ErrState; };
|
||||||
|
void setErrState(unsigned char state) { Heater.ErrState = state; };
|
||||||
|
//
|
||||||
|
short getVoltage_Supply();
|
||||||
|
void setVoltage_Supply(short voltsx10);
|
||||||
|
|
||||||
// fan set/get
|
// fan set/get
|
||||||
short getFan_Actual(); // Rx side, actual
|
short getFan_Actual(); // Heater side, actual
|
||||||
short getFan_Min(); // Tx side, define min fan speed
|
short getFan_Min(); // Controller side, define min fan speed
|
||||||
short getFan_Max(); // Tx side, define max fan speed
|
short getFan_Max(); // Controller side, define max fan speed
|
||||||
void setFan_Min(short speed); // Tx side, define min fan speed
|
void setFan_Actual(short speed); // Heater side, actual
|
||||||
void setFan_Max(short speed); // Tx side, define max fan speed
|
void setFan_Min(short speed); // Controller side, define min fan speed
|
||||||
|
void setFan_Max(short speed); // Controller side, define max fan speed
|
||||||
|
short getFan_Voltage(); // fan voltage
|
||||||
|
void setFan_Voltage(short voltsx10); // fan voltage
|
||||||
|
|
||||||
// pump set/get
|
// pump set/get
|
||||||
void setPump_Min(unsigned short Freq) { Tx.MinPumpFreq = Freq; };
|
void setPump_Min(unsigned short Freq) { Controller.MinPumpFreq = Freq; };
|
||||||
void setPump_Max(unsigned short Freq) { Tx.MaxPumpFreq = Freq; };
|
void setPump_Max(unsigned short Freq) { Controller.MaxPumpFreq = Freq; };
|
||||||
unsigned char getPump_Min() { return Tx.MinPumpFreq; }; // Tx side, min pump freq
|
void setPump_Actual(unsigned char Freq) { Heater.ActualPumpFreq = Freq; };
|
||||||
unsigned char getPump_Max() { return Tx.MaxPumpFreq; }; // Tx side, max pump freq
|
void setPump_Fixed(unsigned char Freq) { Heater.FixedPumpFreq = Freq; };
|
||||||
unsigned char getPump_Actual() { return Rx.ActualPumpFreq; }; // Rx style, actual
|
unsigned char getPump_Min() { return Controller.MinPumpFreq; }; // Tx side, min pump freq
|
||||||
unsigned char getPump_Fixed() { return Rx.FixedPumpFreq; }; // Fixed mode pump frequency
|
unsigned char getPump_Max() { return Controller.MaxPumpFreq; }; // Tx side, max pump freq
|
||||||
|
unsigned char getPump_Actual() { return Heater.ActualPumpFreq; }; // Rx style, actual
|
||||||
|
unsigned char getPump_Fixed() { return Heater.FixedPumpFreq; }; // Fixed mode pump frequency
|
||||||
// temperature set/get
|
// temperature set/get
|
||||||
void setTemperature_Desired(unsigned char degC) { Tx.DesiredTemperature = degC; };
|
void setTemperature_Desired(unsigned char degC) { Controller.DesiredTemperature = degC; };
|
||||||
void setTemperature_Min(unsigned char degC) { Tx.MinTemperature = degC; };
|
void setTemperature_Min(unsigned char degC) { Controller.MinTemperature = degC; };
|
||||||
void setTemperature_Max(unsigned char degC) { Tx.MaxTemperature = degC; };
|
void setTemperature_Max(unsigned char degC) { Controller.MaxTemperature = degC; };
|
||||||
void setTemperature_Actual(unsigned char degC) { Tx.ActualTemperature = degC; };
|
void setTemperature_Actual(unsigned char degC) { Controller.ActualTemperature = degC; };
|
||||||
unsigned char getTemperature_Desired() { return Tx.DesiredTemperature; };
|
unsigned char getTemperature_Desired() { return Controller.DesiredTemperature; };
|
||||||
short getTemperature_GlowPin(); // temperature of glow pin
|
unsigned char getTemperature_Min() { return Controller.MinTemperature; };
|
||||||
|
unsigned char getTemperature_Max() { return Controller.MaxTemperature; };
|
||||||
|
short getGlowPlug_Current(); // glow plug current
|
||||||
|
short getGlowPlug_Voltage(); // glow plug voltage
|
||||||
|
void setGlowPlug_Current(short ampsx100); // glow plug current
|
||||||
|
void setGlowPlug_Voltage(short voltsx10); // glow plug voltage
|
||||||
short getTemperature_HeatExchg(); // temperature of heat exchanger
|
short getTemperature_HeatExchg(); // temperature of heat exchanger
|
||||||
short getTemperature_Inlet(); // temperature near inlet
|
void setTemperature_HeatExchg(short degC); // temperature of heat exchanger
|
||||||
|
|
||||||
CFrame& operator=(CFrame& rhs);
|
CFrame& operator=(const CFrame& rhs);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -1,55 +1,68 @@
|
||||||
/*
|
/*
|
||||||
Chinese Heater Half Duplex Serial Data Send Test Tool
|
Chinese Heater Half Duplex Serial Data Sending Tool
|
||||||
|
|
||||||
Connects to the blue wire of a Chinese heater, which is the half duplex serial link.
|
Connects to the blue wire of a Chinese heater, which is the half duplex serial link.
|
||||||
Receives data from serial port 1.
|
Sends and receives data from serial port 1.
|
||||||
|
|
||||||
Terminology: Tx is to the heater unit, Rx is from the heater unit.
|
Terminology: Tx is to the heater unit, Rx is from the heater unit.
|
||||||
|
|
||||||
The binary data is received from the line.
|
|
||||||
If it has been > 100ms since the last activity this indicates a new frame
|
|
||||||
sequence is starting, synchronise as such then count off the next 48 bytes
|
|
||||||
storing them in the Data array.
|
|
||||||
|
|
||||||
The "outer loop" then detects the count of 48 and packages the data to be sent
|
|
||||||
over Serial to the USB attached PC.
|
|
||||||
|
|
||||||
Typical data frame timing on the blue wire is:
|
Typical data frame timing on the blue wire is:
|
||||||
__Tx_Rx____________________________Tx_Rx____________________________Tx_Rx___________
|
__Tx_Rx____________________________Tx_Rx____________________________Tx_Rx___________
|
||||||
|
|
||||||
|
This software can connect to the blue wire in a normal OEM system, detecting the
|
||||||
|
OEM controller and allowing extraction of the data or injecting on/off commands.
|
||||||
|
|
||||||
|
The binary data is received from the line.
|
||||||
|
If it has been > 100ms since the last blue wire activity this indicates a new frame
|
||||||
|
sequence is starting from the OEM controller.
|
||||||
|
Synchronise as such then count off the next 24 bytes storing them in the Controller's
|
||||||
|
data array. These bytes are then reported over USB to the PC in ASCII.
|
||||||
|
|
||||||
|
It is then expected the heater wil lrespond with it's 24 bytes.
|
||||||
|
Capture those bytes and store them in the Heater1 data array.
|
||||||
|
Once again these bytes are then reported over USB to the PC in ASCII.
|
||||||
|
|
||||||
|
If no activity is sensed in a second, it is assumed no controller is attached and we
|
||||||
|
have full control over the heater.
|
||||||
|
|
||||||
|
Either way we can now inject a message onto the blue wire allowing our custom
|
||||||
|
on/off control.
|
||||||
|
We must remain synchronous with the OEM controller if it exists otherwise E-07
|
||||||
|
faults will be caused.
|
||||||
|
|
||||||
|
Typical data frame timing on the blue wire is then:
|
||||||
|
__OEMTx_HtrRx__OurTx_HtrRx____________OEMTx_HtrRx__OurTx_HtrRx____________OEMTx_HtrRx__OurTx_HtrRx_________
|
||||||
|
|
||||||
Rx to next Tx delay is always > 100ms and is paced by the controller.
|
The second HtrRx to the next OEMTx delay is always > 100ms and is paced by the OEM controller.
|
||||||
The delay before seeing Rx data after Tx is usually much less than 10ms.
|
The delay before seeing Heater Rx data after any Tx is usually much less than 10ms.
|
||||||
**The heater only ever sends Rx data in response to a data frame from the controller**
|
But this does rise if new max/min or voltage settings are sent.
|
||||||
|
**The heater only ever sends Rx data in response to a data frame from a controller**
|
||||||
|
|
||||||
Resultant data is tagged and sent out on serial port 0 (the default debug port),
|
|
||||||
along with a timestamp for relative timing.
|
This code only works with boards that have more than one hardware serial port like Arduino
|
||||||
|
|
||||||
This example works only with boards with more than one serial port like Arduino
|
|
||||||
Mega, Due, Zero etc.
|
Mega, Due, Zero etc.
|
||||||
|
|
||||||
|
|
||||||
The circuit:
|
The circuit:
|
||||||
- Blue wire connected to Serial 1 Rx input - preferably with series 680ohm resistor.
|
- a Tx Rx multiplexer is required to combine the Arduino's Tx1 And Rx1 pins onto the blue wire.
|
||||||
- Serial logging software on Serial port 0 via USB link
|
- a Tx Enable signal from pin 20 controls the multiplexer
|
||||||
|
- Serial logging software on Serial0 via USB link
|
||||||
|
|
||||||
created 24 Aug 2018 by Ray Jones
|
created 23 Sep 2018 by Ray Jones
|
||||||
|
|
||||||
modified 25 Aug by Ray Jones
|
|
||||||
- simplifed to read 48 bytes, synchronised by observing a long pause
|
|
||||||
between characters. The heater only sends when prompted.
|
|
||||||
No longer need to discrimate which packet of data would be present.
|
|
||||||
|
|
||||||
This example code is in the public domain.
|
This example code is in the public domain.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "CFrame.h"
|
#include "Protocol.h"
|
||||||
#include "TxManage.h"
|
#include "TxManage.h"
|
||||||
|
|
||||||
void SerialReport(const char* hdr, const unsigned char* pData, const char* ftr);
|
void SerialReport(const char* hdr, const unsigned char* pData, const char* ftr);
|
||||||
|
|
||||||
class CommStates {
|
class CommStates {
|
||||||
public:
|
public:
|
||||||
|
// comms states
|
||||||
enum eCS {
|
enum eCS {
|
||||||
Idle, CtrlRx, CtrlRpt, HtrRx1, HtrRpt1, SelfTx, HtrRx2, HtrRpt2
|
Idle, ControllerRx, ControllerReport, HeaterRx1, HeaterReport1, SelfTx, HeaterRx2, HeaterReport2
|
||||||
};
|
};
|
||||||
CommStates() {
|
CommStates() {
|
||||||
set(Idle);
|
set(Idle);
|
||||||
|
@ -61,7 +74,7 @@ class CommStates {
|
||||||
bool is(eCS eState) {
|
bool is(eCS eState) {
|
||||||
return m_State == eState;
|
return m_State == eState;
|
||||||
}
|
}
|
||||||
bool rxData(unsigned char* pData, unsigned char val, int limit = 24) { // return true if buffer filled
|
bool saveData(unsigned char* pData, unsigned char val, int limit = 24) { // returns true when buffer filled
|
||||||
pData[m_Count++] = val;
|
pData[m_Count++] = val;
|
||||||
return m_Count == limit;
|
return m_Count == limit;
|
||||||
}
|
}
|
||||||
|
@ -70,17 +83,19 @@ private:
|
||||||
int m_Count;
|
int m_Count;
|
||||||
};
|
};
|
||||||
|
|
||||||
const int TxEnbPin = 17;
|
UARTClass& USB(Serial);
|
||||||
|
UARTClass& BlueWire(Serial1);
|
||||||
|
UARTClass& BlueTooth(Serial2);
|
||||||
|
|
||||||
|
const int TxEnbPin = 20;
|
||||||
CommStates CommState;
|
CommStates CommState;
|
||||||
CFrame Controller(CFrame::TxMode);
|
|
||||||
CFrame TxFrame(CFrame::TxMode);
|
|
||||||
CTxManage TxManage(TxEnbPin, Serial1);
|
CTxManage TxManage(TxEnbPin, Serial1);
|
||||||
CFrame Heater1;
|
CFrame Controller; // most recent data packet received from OEM controller found on blue wire
|
||||||
CFrame Heater2;
|
CFrame Heater1; // data packet received from heater in response to OEM controller packet
|
||||||
long lastRxTime; // used to calculate inter character delay
|
CFrame Heater2; // data packet received from heater in response to our packet
|
||||||
long TxEnbTime; // used to reset TxEnb low
|
CFrame SelfParams(CFrame::CtrlMode); // holds our local parameters, used in case on no OEM controller
|
||||||
bool bOnEvent = false;
|
long lastRxTime; // used to observe inter character delays
|
||||||
bool bOffEvent = false;
|
|
||||||
|
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
|
@ -88,16 +103,25 @@ void setup()
|
||||||
// initialize listening serial port
|
// initialize listening serial port
|
||||||
// 25000 baud, Tx and Rx channels of Chinese heater comms interface:
|
// 25000 baud, Tx and Rx channels of Chinese heater comms interface:
|
||||||
// Tx/Rx data to/from heater, special baud rate for Chinese heater controllers
|
// Tx/Rx data to/from heater, special baud rate for Chinese heater controllers
|
||||||
Serial1.begin(25000);
|
BlueWire.begin(25000);
|
||||||
pinMode(19, INPUT_PULLUP);
|
pinMode(19, INPUT_PULLUP); // required for MUX to work properly
|
||||||
|
|
||||||
// initialise serial monitor on serial port 0
|
// initialise serial monitor on serial port 0
|
||||||
Serial.begin(115200);
|
USB.begin(115200);
|
||||||
|
|
||||||
// prepare for first long delay detection
|
// prepare for first long delay detection
|
||||||
lastRxTime = millis();
|
lastRxTime = millis();
|
||||||
|
|
||||||
TxManage.begin();
|
TxManage.begin(); // ensure Tx enable pin setup
|
||||||
|
|
||||||
|
// define defaults should heater controller be missing
|
||||||
|
SelfParams.setTemperature_Desired(23);
|
||||||
|
SelfParams.setTemperature_Actual(22);
|
||||||
|
SelfParams.Controller.OperatingVoltage = 120;
|
||||||
|
SelfParams.setPump_Min(16);
|
||||||
|
SelfParams.setPump_Max(55);
|
||||||
|
SelfParams.setFan_Min(1680);
|
||||||
|
SelfParams.setFan_Max(4500);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,8 +130,8 @@ void loop()
|
||||||
unsigned long timenow = millis();
|
unsigned long timenow = millis();
|
||||||
|
|
||||||
// check for test commands received from PC Over USB
|
// check for test commands received from PC Over USB
|
||||||
if(Serial.available()) {
|
if(USB.available()) {
|
||||||
char rxval = Serial.read();
|
char rxval = USB.read();
|
||||||
if(rxval == '+') {
|
if(rxval == '+') {
|
||||||
TxManage.RequestOn();
|
TxManage.RequestOn();
|
||||||
}
|
}
|
||||||
|
@ -116,12 +140,11 @@ void loop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle time interval where we send data to the blue wire
|
||||||
if(CommState.is(CommStates::SelfTx)) {
|
if(CommState.is(CommStates::SelfTx)) {
|
||||||
// Interval where we should send data to the blue wire
|
lastRxTime = timenow; // we are pumping onto blue wire, track this activity!
|
||||||
lastRxTime = timenow; // not expecting rx data, but we are pumping onto blue wire!
|
if(TxManage.CheckTx(timenow) ) { // monitor our data delivery
|
||||||
TxManage.Tick(timenow); // keep trying to send our data
|
CommState.set(CommStates::HeaterRx2); // then await heater repsonse
|
||||||
if(!TxManage.isBusy()) { // until completed
|
|
||||||
CommState.set(CommStates::HtrRx2); // then await heater repsonse
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,72 +158,71 @@ void loop()
|
||||||
// OEM controller probably not connected.
|
// OEM controller probably not connected.
|
||||||
// Skip to SelfTx, sending our own settings.
|
// Skip to SelfTx, sending our own settings.
|
||||||
CommState.set(CommStates::SelfTx);
|
CommState.set(CommStates::SelfTx);
|
||||||
bool bSelfParams = true;
|
bool bOurParams = true;
|
||||||
TxManage.Send(timenow, bSelfParams);
|
TxManage.Start(SelfParams, timenow, bOurParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
// precaution if 24 bytes were not received whilst expecting them
|
// precaution action if all 24 bytes were not received whilst expecting them
|
||||||
if(RxTimeElapsed > 50) {
|
if(RxTimeElapsed > 150) {
|
||||||
if( CommState.is(CommStates::CtrlRx) ||
|
if( CommState.is(CommStates::ControllerRx) ||
|
||||||
CommState.is(CommStates::HtrRx1) ||
|
CommState.is(CommStates::HeaterRx1) ||
|
||||||
CommState.is(CommStates::HtrRx2) ) {
|
CommState.is(CommStates::HeaterRx2) ) {
|
||||||
|
|
||||||
CommState.set(CommStates::Idle);
|
CommState.set(CommStates::Idle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// read from port 1, the "blue wire" (to/from heater), store according to CommState
|
// read from port 1, the "blue wire" (to/from heater), store according to CommState
|
||||||
if (Serial1.available()) {
|
if (BlueWire.available()) {
|
||||||
|
|
||||||
lastRxTime = timenow;
|
lastRxTime = timenow;
|
||||||
|
|
||||||
if( CommState.is(CommStates::Idle) && (RxTimeElapsed > 100)) { // this indicates the start of a new frame sequence from another controller
|
// detect start of a new frame sequence from OEM controller
|
||||||
CommState.set(CommStates::CtrlRx);
|
if( CommState.is(CommStates::Idle) && (RxTimeElapsed > 100)) {
|
||||||
|
CommState.set(CommStates::ControllerRx);
|
||||||
}
|
}
|
||||||
|
|
||||||
int inByte = Serial1.read(); // read hex byte
|
int inByte = BlueWire.read(); // read hex byte
|
||||||
|
|
||||||
if( CommState.is(CommStates::CtrlRx) ) {
|
if( CommState.is(CommStates::ControllerRx) ) {
|
||||||
if(CommState.rxData(Controller.Data, inByte) ) {
|
if(CommState.saveData(Controller.Data, inByte) ) {
|
||||||
CommState.set(CommStates::CtrlRpt);
|
CommState.set(CommStates::ControllerReport);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if( CommState.is(CommStates::HtrRx1) ) {
|
else if( CommState.is(CommStates::HeaterRx1) ) {
|
||||||
if( CommState.rxData(Heater1.Data, inByte) ) {
|
if( CommState.saveData(Heater1.Data, inByte) ) {
|
||||||
CommState.set(CommStates::HtrRpt1);
|
CommState.set(CommStates::HeaterReport1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if( CommState.is(CommStates::HtrRx2) ) {
|
else if( CommState.is(CommStates::HeaterRx2) ) {
|
||||||
if( CommState.rxData(Heater2.Data, inByte) ) {
|
if( CommState.saveData(Heater2.Data, inByte) ) {
|
||||||
CommState.set(CommStates::HtrRpt2);
|
CommState.set(CommStates::HeaterReport2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // Serial1.available
|
} // BlueWire.available
|
||||||
|
|
||||||
|
|
||||||
if( CommState.is(CommStates::CtrlRpt) ) {
|
if( CommState.is(CommStates::ControllerReport) ) {
|
||||||
// filled controller frame, report
|
// filled controller frame, report
|
||||||
SerialReport("Ctrl ", Controller.Data, " ");
|
SerialReport("Ctrl ", Controller.Data, " ");
|
||||||
CommState.set(CommStates::HtrRx1);
|
CommState.set(CommStates::HeaterRx1);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(CommState.is(CommStates::HtrRpt1) ) {
|
else if(CommState.is(CommStates::HeaterReport1) ) {
|
||||||
// received heater frame (after controller message), report
|
// received heater frame (after controller message), report
|
||||||
SerialReport("Htr1 ", Heater1.Data, "\r\n");
|
SerialReport("Htr1 ", Heater1.Data, "\r\n");
|
||||||
|
|
||||||
TxManage.Copy(Controller); // replicate last obtained controller data
|
bool bOurParams = false;
|
||||||
TxManage.Send(timenow, false);
|
TxManage.Start(Controller, timenow, bOurParams);
|
||||||
CommState.set(CommStates::SelfTx);
|
CommState.set(CommStates::SelfTx);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if( CommState.is(CommStates::HtrRpt2) ) {
|
else if( CommState.is(CommStates::HeaterReport2) ) {
|
||||||
// received heater frame (after our control message), report
|
// received heater frame (after our control message), report
|
||||||
|
|
||||||
SerialReport("Htr2 ", Heater2.Data, "\r\n");
|
SerialReport("Htr2 ", Heater2.Data, "\r\n");
|
||||||
|
|
||||||
CommState.set(CommStates::Idle);
|
CommState.set(CommStates::Idle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,11 +230,11 @@ void loop()
|
||||||
|
|
||||||
void SerialReport(const char* hdr, const unsigned char* pData, const char* ftr)
|
void SerialReport(const char* hdr, const unsigned char* pData, const char* ftr)
|
||||||
{
|
{
|
||||||
Serial.print(hdr); // header
|
USB.print(hdr); // header
|
||||||
for(int i=0; i<24; i++) {
|
for(int i=0; i<24; i++) {
|
||||||
char str[16];
|
char str[16];
|
||||||
sprintf(str, "%02X ", pData[i]); // build 2 dig hex values
|
sprintf(str, "%02X ", pData[i]); // build 2 dig hex values
|
||||||
Serial.print(str); // and print
|
USB.print(str); // and print
|
||||||
}
|
}
|
||||||
Serial.print(ftr); // footer
|
USB.print(ftr); // footer
|
||||||
}
|
}
|
|
@ -5,12 +5,11 @@ extern void SerialReport(const char* hdr, const unsigned char* pData, const char
|
||||||
|
|
||||||
CTxManage::CTxManage(int TxEnbPin, USARTClass& serial) :
|
CTxManage::CTxManage(int TxEnbPin, USARTClass& serial) :
|
||||||
m_Serial(serial),
|
m_Serial(serial),
|
||||||
m_Frame(CFrame::TxMode)
|
m_Frame(CFrame::CtrlMode)
|
||||||
{
|
{
|
||||||
m_bOnReq = false;
|
m_bOnReq = false;
|
||||||
m_bOffReq = false;
|
m_bOffReq = false;
|
||||||
m_bTxPending = false;
|
m_bTxPending = false;
|
||||||
m_bSelf = true;
|
|
||||||
m_nStartTime = 0;
|
m_nStartTime = 0;
|
||||||
m_nTxEnbPin = TxEnbPin;
|
m_nTxEnbPin = TxEnbPin;
|
||||||
}
|
}
|
||||||
|
@ -33,31 +32,23 @@ CTxManage::RequestOff()
|
||||||
m_bOffReq = true;
|
m_bOffReq = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CTxManage::Copy(CFrame& ref)
|
CTxManage::Start(const CFrame& ref, unsigned long timenow, bool self)
|
||||||
{
|
{
|
||||||
m_Frame = ref;
|
m_Frame = ref;
|
||||||
}
|
// 0x78 prevents the controller showing bum information when we parrot the OEM controller
|
||||||
|
// heater is happy either way, the OEM controller has set the max/min stuff already
|
||||||
|
m_Frame.Data[0] = self ? 0x76 : 0x78;
|
||||||
|
|
||||||
bool
|
|
||||||
CTxManage::isBusy()
|
|
||||||
{
|
|
||||||
return m_nStartTime != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CTxManage::Send(unsigned long timenow, bool self)
|
|
||||||
{
|
|
||||||
if(timenow == 0)
|
if(timenow == 0)
|
||||||
timenow++;
|
timenow++;
|
||||||
|
|
||||||
m_nStartTime = timenow;
|
m_nStartTime = timenow;
|
||||||
m_bSelf = self;
|
|
||||||
m_bTxPending = true;
|
m_bTxPending = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
CTxManage::Tick(unsigned long timenow)
|
CTxManage::CheckTx(unsigned long timenow)
|
||||||
{
|
{
|
||||||
if(m_nStartTime) {
|
if(m_nStartTime) {
|
||||||
|
|
||||||
|
@ -78,38 +69,26 @@ CTxManage::Tick(unsigned long timenow)
|
||||||
digitalWrite(m_nTxEnbPin, LOW);
|
digitalWrite(m_nTxEnbPin, LOW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return m_nStartTime == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CTxManage::_send()
|
CTxManage::_send()
|
||||||
{
|
{
|
||||||
if(m_bSelf) {
|
// install on/off commands if required
|
||||||
m_Frame.Data[0] = 0x76; // required for heater to use the max min information
|
|
||||||
m_Frame.Data[1] = 0x16;
|
|
||||||
m_Frame.setTemperature_Desired(35);
|
|
||||||
m_Frame.setTemperature_Actual(22);
|
|
||||||
m_Frame.Tx.OperatingVoltage = 120;
|
|
||||||
m_Frame.setPump_Min(16);
|
|
||||||
m_Frame.setPump_Max(55);
|
|
||||||
m_Frame.setFan_Min(1680);
|
|
||||||
m_Frame.setFan_Max(4500);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
m_Frame.Data[0] = 0x78; // this prevents the controller trying to show bum information, heater uses controller max/min settings
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_bOnReq) {
|
if(m_bOnReq) {
|
||||||
m_bOnReq = false;
|
m_bOnReq = false;
|
||||||
m_Frame.Tx.Command = 0xa0;
|
m_Frame.Controller.Command = 0xa0;
|
||||||
}
|
}
|
||||||
else if(m_bOffReq) {
|
else if(m_bOffReq) {
|
||||||
m_bOffReq = false;
|
m_bOffReq = false;
|
||||||
m_Frame.Tx.Command = 0x05;
|
m_Frame.Controller.Command = 0x05;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_Frame.Tx.Command = 0x00;
|
m_Frame.Controller.Command = 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ensure CRC valid
|
||||||
m_Frame.setCRC();
|
m_Frame.setCRC();
|
||||||
|
|
||||||
// send to heater - using binary
|
// send to heater - using binary
|
||||||
|
|
|
@ -3,14 +3,16 @@
|
||||||
|
|
||||||
class CTxManage
|
class CTxManage
|
||||||
{
|
{
|
||||||
|
const int m_nStartDelay = 20;
|
||||||
|
const int m_nFrameTime = 14;
|
||||||
|
const int m_nFrontPorch = 2;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CTxManage(int TxEnbPin, USARTClass& serial);
|
CTxManage(int TxEnbPin, USARTClass& serial);
|
||||||
void RequestOn();
|
void RequestOn();
|
||||||
void RequestOff();
|
void RequestOff();
|
||||||
void Copy(CFrame& ref);
|
void Start(const CFrame& ref, unsigned long timenow, bool self);
|
||||||
bool isBusy();
|
bool CheckTx(unsigned long timenow);
|
||||||
void Tick(unsigned long timenow);
|
|
||||||
void Send(unsigned long timenow, bool self);
|
|
||||||
void Report();
|
void Report();
|
||||||
void begin();
|
void begin();
|
||||||
|
|
||||||
|
@ -19,15 +21,10 @@ private:
|
||||||
bool m_bOnReq;
|
bool m_bOnReq;
|
||||||
bool m_bOffReq;
|
bool m_bOffReq;
|
||||||
bool m_bTxPending;
|
bool m_bTxPending;
|
||||||
bool m_bSelf;
|
|
||||||
int m_nTxEnbPin;
|
int m_nTxEnbPin;
|
||||||
unsigned long m_nStartTime;
|
unsigned long m_nStartTime;
|
||||||
USARTClass& m_Serial;
|
USARTClass& m_Serial;
|
||||||
|
|
||||||
const int m_nStartDelay = 20;
|
|
||||||
const int m_nFrameTime = 14;
|
|
||||||
const int m_nFrontPorch = 2;
|
|
||||||
|
|
||||||
void _send();
|
void _send();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue