Merge branch 'SmartErrors' into 'master'
Smart errors See merge request mrjones.id.au/bluetoothheater!6
This commit is contained in:
commit
1b814cbf3f
8 changed files with 165 additions and 11 deletions
Binary file not shown.
BIN
AppInventor/BluetoothHeaterBTCsmartError.aia
Normal file
BIN
AppInventor/BluetoothHeaterBTCsmartError.aia
Normal file
Binary file not shown.
|
@ -248,7 +248,7 @@ CProtocol::Init(int FrameMode)
|
|||
setGlowPlug_Voltage(0);
|
||||
setGlowPlug_Current(0);
|
||||
Heater.ActualPumpFreq = 0; // fuel pump freq.: 0.1Hz / digit
|
||||
Heater.ErrorCode = 0; //
|
||||
Heater.StoredErrorCode = 0; //
|
||||
Heater.Unknown1 = 0; // always 0x00
|
||||
Heater.FixedPumpFreq = 23; // fixed mode frequency set point: 0.1Hz / digit
|
||||
Heater.Unknown2 = 100; // always 0x64 "100 ?"
|
||||
|
|
|
@ -49,7 +49,7 @@ public:
|
|||
unsigned char GlowPlugCurrent_MSB; // 16 bit - big endian MSB
|
||||
unsigned char GlowPlugCurrent_LSB; // 16 bit - big endian LSB : 10mA / digit
|
||||
unsigned char ActualPumpFreq; // fuel pump freq.: 0.1Hz / digit
|
||||
unsigned char ErrorCode; //
|
||||
unsigned char StoredErrorCode; //
|
||||
unsigned char Unknown1; // always 0x00
|
||||
unsigned char FixedPumpFreq; // fixed mode frequency set point: 0.1Hz / digit
|
||||
unsigned char Unknown2; // always 0x64 "100 ?"
|
||||
|
@ -121,6 +121,8 @@ public:
|
|||
void setRunState(unsigned char state) { Heater.RunState = state; };
|
||||
unsigned char getErrState() { return Heater.ErrState; };
|
||||
void setErrState(unsigned char state) { Heater.ErrState = state; };
|
||||
unsigned char getStoredErrCode() { return Heater.StoredErrorCode; };
|
||||
void setStoredErrCode(unsigned char state) { Heater.StoredErrorCode = state; };
|
||||
//
|
||||
short getVoltage_Supply();
|
||||
void setVoltage_Supply(short voltsx10);
|
||||
|
|
|
@ -67,6 +67,7 @@
|
|||
#include "pins.h"
|
||||
#include "NVStorage.h"
|
||||
#include "debugport.h"
|
||||
#include "SmartError.h"
|
||||
|
||||
#define DEBUG_BTRX
|
||||
|
||||
|
@ -129,13 +130,23 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class CModeratedFrame : public CProtocol {
|
||||
unsigned long lastTime;
|
||||
public:
|
||||
CModeratedFrame() { lastTime = 0; };
|
||||
void setTime() { lastTime = millis(); };
|
||||
unsigned long elapsedTime() { return millis() - lastTime; };
|
||||
};
|
||||
|
||||
CommStates CommState;
|
||||
CTxManage TxManage(TxEnbPin, BlueWireSerial);
|
||||
CProtocol OEMCtrlFrame; // data packet received from heater in response to OEM controller packet
|
||||
CProtocol HeaterFrame1; // data packet received from heater in response to OEM controller packet
|
||||
//CProtocol OEMCtrlFrame; // data packet received from heater in response to OEM controller packet
|
||||
//CProtocol HeaterFrame1; // data packet received from heater in response to OEM controller packet
|
||||
CModeratedFrame OEMCtrlFrame; // data packet received from heater in response to OEM controller packet
|
||||
CModeratedFrame HeaterFrame1; // data packet received from heater in response to OEM controller packet
|
||||
CProtocol HeaterFrame2; // data packet received from heater in response to our packet
|
||||
CProtocol DefaultBTCParams(CProtocol::CtrlMode); // defines the default parameters, used in case of no OEM controller
|
||||
CSmartError SmartError;
|
||||
long lastRxTime; // used to observe inter character delays
|
||||
bool hasOEMController = false;
|
||||
|
||||
|
@ -152,10 +163,6 @@ void PrepareTxFrame(const CProtocol& basisFrame, CProtocol& TxFrame, bool isBTCm
|
|||
|
||||
void setup()
|
||||
{
|
||||
// initialize serial port to interact with the "blue wire"
|
||||
// 25000 baud, Tx and Rx channels of Chinese heater comms interface:
|
||||
// Tx/Rx data to/from heater,
|
||||
// Note special baud rate for Chinese heater controllers
|
||||
pinMode(Tx2Pin, OUTPUT);
|
||||
digitalWrite(Tx2Pin, HIGH);
|
||||
pinMode(Rx2Pin, INPUT_PULLUP);
|
||||
|
@ -163,6 +170,10 @@ void setup()
|
|||
pinMode(KeyPin, OUTPUT);
|
||||
digitalWrite(KeyPin, LOW);
|
||||
|
||||
// initialize serial port to interact with the "blue wire"
|
||||
// 25000 baud, Tx and Rx channels of Chinese heater comms interface:
|
||||
// Tx/Rx data to/from heater,
|
||||
// Note special baud rate for Chinese heater controllers
|
||||
#if defined(__arm__) || defined(__AVR__)
|
||||
BlueWireSerial.begin(25000);
|
||||
pinMode(Rx1Pin, INPUT_PULLUP); // required for MUX to work properly
|
||||
|
@ -181,7 +192,7 @@ void setup()
|
|||
|
||||
TxManage.begin(); // ensure Tx enable pin is setup
|
||||
|
||||
// define defaults should heater controller be missing
|
||||
// define defaults should OEM controller be missing
|
||||
DefaultBTCParams.setTemperature_Desired(23);
|
||||
DefaultBTCParams.setTemperature_Actual(22);
|
||||
DefaultBTCParams.Controller.OperatingVoltage = 120;
|
||||
|
@ -233,6 +244,16 @@ void loop()
|
|||
CommState.is(CommStates::HeaterRx1) ||
|
||||
CommState.is(CommStates::HeaterRx2) ) {
|
||||
|
||||
if(CommState.is(CommStates::OEMCtrlRx)) {
|
||||
DebugPort.println("Timeout collecting OEM controller data, returning to Idle State");
|
||||
}
|
||||
else if(CommState.is(CommStates::HeaterRx1)) {
|
||||
DebugPort.println("Timeout collecting OEM heater response data, returning to Idle State");
|
||||
}
|
||||
else {
|
||||
DebugPort.println("Timeout collecting BTC heater response data, returning to Idle State");
|
||||
}
|
||||
|
||||
CommState.set(CommStates::Idle); // revert to idle mode
|
||||
}
|
||||
}
|
||||
|
@ -295,7 +316,13 @@ void loop()
|
|||
else if( CommState.is(CommStates::OEMCtrlReport) ) {
|
||||
// filled OEM controller frame, report
|
||||
// echo received OEM controller frame over Bluetooth, using [OEM] header
|
||||
Bluetooth_SendFrame("[OEM]", OEMCtrlFrame, true);
|
||||
if(OEMCtrlFrame.elapsedTime() > 700) {
|
||||
Bluetooth_SendFrame("[OEM]", OEMCtrlFrame, true);
|
||||
OEMCtrlFrame.setTime();
|
||||
}
|
||||
else {
|
||||
DebugPort.println("Suppressed delivery of OEM frame");
|
||||
}
|
||||
CommState.set(CommStates::HeaterRx1);
|
||||
}
|
||||
|
||||
|
@ -310,8 +337,19 @@ void loop()
|
|||
|
||||
else if(CommState.is(CommStates::HeaterReport1) ) {
|
||||
// received heater frame (after controller message), report
|
||||
|
||||
// do some monitoring of the heater state variable
|
||||
// if suspicious transitions, introduce a smart error!
|
||||
SmartError.monitor(HeaterFrame1);
|
||||
|
||||
// echo heater reponse data to Bluetooth client
|
||||
Bluetooth_SendFrame("[HTR]", HeaterFrame1);
|
||||
if(HeaterFrame1.elapsedTime() > 700) {
|
||||
Bluetooth_SendFrame("[HTR]", HeaterFrame1);
|
||||
HeaterFrame1.setTime();
|
||||
}
|
||||
else {
|
||||
DebugPort.println("Suppressed delivery of OEM heater response frame");
|
||||
}
|
||||
|
||||
if(digitalRead(ListenOnlyPin)) {
|
||||
bool isBTCmaster = false;
|
||||
|
@ -343,6 +381,11 @@ void loop()
|
|||
|
||||
else if( CommState.is(CommStates::HeaterReport2) ) {
|
||||
// received heater frame (after our control message), report
|
||||
|
||||
// do some monitoring of the heater state variable
|
||||
// if suspicious transitions, introduce a smart error!
|
||||
SmartError.monitor(HeaterFrame2);
|
||||
|
||||
delay(5);
|
||||
if(!hasOEMController) {
|
||||
// only convey these frames to Bluetooth when NOT using an OEM controller!
|
||||
|
@ -391,10 +434,12 @@ void Command_Interpret(const char* pLine)
|
|||
if(strncmp(pLine, "ON", 2) == 0) {
|
||||
TxManage.queueOnRequest();
|
||||
DebugPort.println("Heater ON");
|
||||
SmartError.reset();
|
||||
}
|
||||
else if(strncmp(pLine, "OFF", 3) == 0) {
|
||||
TxManage.queueOffRequest();
|
||||
DebugPort.println("Heater OFF");
|
||||
SmartError.inhibit();
|
||||
}
|
||||
else if(strncmp(pLine, "Pmin", 4) == 0) {
|
||||
pLine += 4;
|
||||
|
|
93
Arduino/SenderTrial2/SmartError.cpp
Normal file
93
Arduino/SenderTrial2/SmartError.cpp
Normal file
|
@ -0,0 +1,93 @@
|
|||
#include "SmartError.h"
|
||||
|
||||
CSmartError::CSmartError()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void
|
||||
CSmartError::reset()
|
||||
{
|
||||
m_prevRunState = 0;
|
||||
m_Error = 0;
|
||||
m_bInhibit = false;
|
||||
}
|
||||
|
||||
// we use inhibit when we manually command the heater off during preheat
|
||||
// otherwise we'll register an ignition fail event
|
||||
void
|
||||
CSmartError::inhibit()
|
||||
{
|
||||
m_bInhibit = true;
|
||||
m_Error = 0;
|
||||
}
|
||||
|
||||
// accept a fresh heater frame
|
||||
// inpsect the advertised run state, tracking when and how it transitions out
|
||||
// of preheat especially.
|
||||
// abnormal transitions are registered and becoem our smart m_Error
|
||||
// In addition, the hetaer frame has the ErrState updated to track the
|
||||
// smart error, providing no heater error exists!
|
||||
void
|
||||
CSmartError::monitor(CProtocol& heaterFrame)
|
||||
{
|
||||
if(heaterFrame.verifyCRC()) {
|
||||
// only accept valid heater frames!
|
||||
monitor(heaterFrame.getRunState());
|
||||
unsigned char HtrErr = heaterFrame.getErrState();
|
||||
if((HtrErr & 0xfe) == 0) {
|
||||
// heater is Idle or Normal running state (E-0X + 1 in protocol!!)
|
||||
unsigned char smartErr = getError();
|
||||
if(smartErr) {
|
||||
heaterFrame.setErrState(smartErr); // 10 = ign fail, 11 = retry
|
||||
heaterFrame.setCRC(); // changed the message, fix the CRC!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// test the new run state value, comparing to previous
|
||||
// detect abnormal transitions
|
||||
void
|
||||
CSmartError::monitor(unsigned char newRunState)
|
||||
{
|
||||
// check if moving away from heater Idle state (S0)
|
||||
// especially useful if an OEM controller exists
|
||||
if((m_prevRunState == 0) && newRunState) {
|
||||
// reset the smart error
|
||||
m_Error = 0;
|
||||
m_bInhibit = false;
|
||||
}
|
||||
|
||||
if(!m_bInhibit) {
|
||||
if(m_prevRunState == 2) { // preheat state (S2)
|
||||
if(newRunState == 4) {
|
||||
// transitioned from preheat to ignited
|
||||
// - all good!
|
||||
m_Error = 0;
|
||||
}
|
||||
else if(newRunState > 5) {
|
||||
// transitioned from preheat to post glow
|
||||
// - second ignition attempt failed, heater is shutting down
|
||||
m_Error = 11;
|
||||
}
|
||||
else if(newRunState == 3) {
|
||||
// transitioned from preheat to retry
|
||||
// - first ignition attempt failed, heater will retry
|
||||
m_Error = 12;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_prevRunState = newRunState;
|
||||
}
|
||||
|
||||
// return our smart error, if it exists, as the registered code
|
||||
unsigned char
|
||||
CSmartError::getError()
|
||||
{
|
||||
if(m_Error) {
|
||||
return m_Error;
|
||||
}
|
||||
return 0;
|
||||
}
|
14
Arduino/SenderTrial2/SmartError.h
Normal file
14
Arduino/SenderTrial2/SmartError.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#include "Protocol.h"
|
||||
|
||||
class CSmartError {
|
||||
unsigned char m_prevRunState;
|
||||
unsigned char m_Error;
|
||||
bool m_bInhibit;
|
||||
public:
|
||||
CSmartError();
|
||||
void reset();
|
||||
void inhibit();
|
||||
void monitor(CProtocol& heaterFrame);
|
||||
void monitor(unsigned char runstate);
|
||||
unsigned char getError();
|
||||
};
|
Binary file not shown.
Loading…
Reference in a new issue