2018-11-26 11:58:15 +00:00
|
|
|
/*
|
|
|
|
* This file is part of the "bluetoothheater" distribution
|
|
|
|
* (https://gitlab.com/mrjones.id.au/bluetoothheater)
|
|
|
|
*
|
2019-07-21 11:17:54 +00:00
|
|
|
* Copyright (C) 2019 Ray Jones <ray@mrjones.id.au>
|
2018-11-26 11:58:15 +00:00
|
|
|
*
|
|
|
|
* 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-10-28 19:01:26 +00:00
|
|
|
#include "SmartError.h"
|
2018-11-07 10:31:00 +00:00
|
|
|
#include "TxManage.h"
|
2019-07-21 11:17:54 +00:00
|
|
|
#include "../Utility/helpers.h"
|
|
|
|
#include "../Utility/macros.h"
|
|
|
|
#include "../Utility/NVStorage.h"
|
|
|
|
#include "../Utility/DataFilter.h"
|
2020-03-30 05:17:54 +00:00
|
|
|
#include "../Utility/FuelGauge.h"
|
2018-10-28 19:01:26 +00:00
|
|
|
|
|
|
|
CSmartError::CSmartError()
|
|
|
|
{
|
|
|
|
reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
CSmartError::reset()
|
|
|
|
{
|
2019-07-23 11:11:29 +00:00
|
|
|
_prevRunState = 0;
|
|
|
|
_Error = 0;
|
|
|
|
_bInhibit = false;
|
2018-10-28 19:01:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// we use inhibit when we manually command the heater off during preheat
|
|
|
|
// otherwise we'll register an ignition fail event
|
|
|
|
void
|
|
|
|
CSmartError::inhibit()
|
|
|
|
{
|
2019-07-23 11:11:29 +00:00
|
|
|
_bInhibit = true;
|
2019-07-03 10:28:00 +00:00
|
|
|
// m_Error = 0;
|
2018-10-28 19:01:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
2018-12-22 06:34:10 +00:00
|
|
|
CSmartError::monitor(const CProtocol& heaterFrame)
|
2018-10-28 19:01:26 +00:00
|
|
|
{
|
2018-11-06 09:43:54 +00:00
|
|
|
bool bSilent = true;
|
|
|
|
if(heaterFrame.verifyCRC(bSilent)) { // check but don't report dodgy frames to debug
|
2018-10-28 19:01:26 +00:00
|
|
|
// only accept valid heater frames!
|
|
|
|
monitor(heaterFrame.getRunState());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// test the new run state value, comparing to previous
|
|
|
|
// detect abnormal transitions
|
|
|
|
void
|
2019-07-06 13:46:20 +00:00
|
|
|
CSmartError::monitor(uint8_t newRunState)
|
2018-10-28 19:01:26 +00:00
|
|
|
{
|
|
|
|
// check if moving away from heater Idle state (S0)
|
|
|
|
// especially useful if an OEM controller exists
|
2019-07-23 11:11:29 +00:00
|
|
|
if((_prevRunState == 0) && newRunState) {
|
2018-10-28 19:01:26 +00:00
|
|
|
// reset the smart error
|
2019-07-23 11:11:29 +00:00
|
|
|
_Error = 0;
|
|
|
|
_bInhibit = false;
|
2018-10-28 19:01:26 +00:00
|
|
|
}
|
|
|
|
|
2019-07-23 11:11:29 +00:00
|
|
|
if(!_bInhibit) {
|
|
|
|
if(_prevRunState == 2) { // preheat state (S2)
|
2018-10-28 19:01:26 +00:00
|
|
|
if(newRunState == 4) {
|
|
|
|
// transitioned from preheat to ignited
|
|
|
|
// - all good!
|
2019-07-23 11:11:29 +00:00
|
|
|
_Error = 0;
|
2018-10-28 19:01:26 +00:00
|
|
|
}
|
|
|
|
else if(newRunState > 5) {
|
|
|
|
// transitioned from preheat to post glow
|
|
|
|
// - second ignition attempt failed, heater is shutting down
|
2019-07-23 11:11:29 +00:00
|
|
|
_Error = 11; // +1 over displayed error code
|
2018-10-28 19:01:26 +00:00
|
|
|
}
|
|
|
|
else if(newRunState == 3) {
|
|
|
|
// transitioned from preheat to retry
|
|
|
|
// - first ignition attempt failed, heater will retry
|
2019-07-23 11:11:29 +00:00
|
|
|
_Error = 12; // +1 over displayed error code
|
2018-10-28 19:01:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-23 11:11:29 +00:00
|
|
|
if(_prevRunState != newRunState) {
|
2018-11-07 10:31:00 +00:00
|
|
|
// check for transition to startup
|
|
|
|
// - force cancellation of an on request if we generated it
|
2018-11-22 10:30:51 +00:00
|
|
|
if(newRunState >= 2) {
|
2018-11-07 10:31:00 +00:00
|
|
|
TxManage.queueOnRequest(false); // ensure ON request is cancelled
|
|
|
|
}
|
|
|
|
// check for transition to shutdown
|
|
|
|
// - force cancellation of an off request if we generated it
|
2019-01-26 00:58:50 +00:00
|
|
|
if(newRunState >= 7 || newRunState == 0) {
|
2018-11-07 10:31:00 +00:00
|
|
|
TxManage.queueOffRequest(false); // ensure OFF request is cancelled
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-23 11:11:29 +00:00
|
|
|
_prevRunState = newRunState;
|
2019-07-21 11:17:54 +00:00
|
|
|
}
|
|
|
|
|
2019-07-26 22:50:09 +00:00
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// checkVolts(float ipVolts, float glowI, bool throwfault)
|
2019-07-26 12:13:46 +00:00
|
|
|
//
|
2019-07-26 22:50:09 +00:00
|
|
|
// Performs low voltage cutout function / testing
|
|
|
|
// Input voltage drop is compensated here by using the glow plug current, 0.1V/A
|
|
|
|
//
|
|
|
|
// returns:
|
|
|
|
// 0 - OK
|
|
|
|
// 1 - Warning: Above LVC, but less than 12/24 (or .5V over LVC for higher LVC levels)
|
|
|
|
// 2 - Error: LVC tripped
|
2019-07-26 12:13:46 +00:00
|
|
|
int
|
2019-07-23 11:11:29 +00:00
|
|
|
CSmartError::checkVolts(float ipVolts, float glowI, bool throwfault)
|
2019-07-21 11:17:54 +00:00
|
|
|
{
|
2020-03-23 05:54:15 +00:00
|
|
|
const unsigned long LVCholdoffTime = 10000;
|
|
|
|
static unsigned long LVCShutdownHoldoff = 0;
|
2019-07-26 22:50:09 +00:00
|
|
|
// check for low voltage
|
|
|
|
// Native NV values here are x10 integers
|
|
|
|
|
|
|
|
// loom compenstaion, allow 1V drop for 10A current (bit naive but better than no compensation)
|
2019-12-06 10:12:56 +00:00
|
|
|
float cableComp = glowI * 0.1;
|
|
|
|
float usrLVC = NVstore.getHeaterTuning().getLVC();
|
|
|
|
if(usrLVC == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
float threshLVC = usrLVC - cableComp; // NVstore
|
2019-07-26 22:50:09 +00:00
|
|
|
|
|
|
|
// test low voltage cutout
|
|
|
|
if(ipVolts < threshLVC) {
|
2020-03-23 05:54:15 +00:00
|
|
|
if(LVCShutdownHoldoff == 0) {
|
|
|
|
// initial detection of LVC - introduce a hold off period
|
|
|
|
DebugPort.println("LVC holdoff enagaged");
|
|
|
|
LVCShutdownHoldoff = (millis() + LVCholdoffTime) | 1; // ensure non zero!
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
long tDelta = millis() - LVCShutdownHoldoff;
|
|
|
|
if(tDelta > 0) {
|
|
|
|
LVCShutdownHoldoff = 0;
|
|
|
|
if(throwfault) { // only throw faults if directed to do so
|
|
|
|
DebugPort.println("LVC shutting heater down");
|
|
|
|
_Error = 2; // internals error codes are +1 over displayed error code
|
|
|
|
requestOff(); // shut heater down
|
|
|
|
}
|
|
|
|
}
|
2019-07-21 11:17:54 +00:00
|
|
|
}
|
2019-07-26 22:50:09 +00:00
|
|
|
return 2; // Low voltage return value = 2
|
|
|
|
}
|
2020-03-23 05:54:15 +00:00
|
|
|
else {
|
|
|
|
if(LVCShutdownHoldoff)
|
|
|
|
DebugPort.println("LVC holdoff cancelled");
|
|
|
|
LVCShutdownHoldoff = 0; // disable holdoff, voltage now OK
|
|
|
|
}
|
2019-07-26 22:50:09 +00:00
|
|
|
|
|
|
|
// warning threshold
|
|
|
|
float threshWarn = threshLVC + 0.5; // nominally create a warning threshold, 0.5V over LVC threhsold
|
|
|
|
|
|
|
|
if(ipVolts < threshWarn) {
|
|
|
|
return 1; // LVC OK, but below warning threshold, return code = 1
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0; // all good, return code = 0
|
2018-10-28 19:01:26 +00:00
|
|
|
}
|
|
|
|
|
2019-07-23 11:11:29 +00:00
|
|
|
|
2018-10-28 19:01:26 +00:00
|
|
|
// return our smart error, if it exists, as the registered code
|
2019-07-06 13:46:20 +00:00
|
|
|
uint8_t
|
2018-10-28 19:01:26 +00:00
|
|
|
CSmartError::getError()
|
|
|
|
{
|
2019-07-26 22:50:09 +00:00
|
|
|
return _Error;
|
2020-03-30 05:17:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
CSmartError::checkfuelUsage(bool throwfault)
|
|
|
|
{
|
|
|
|
int retval = 0;
|
|
|
|
// const sUserSettings& settings = NVstore.getUserSettings();
|
|
|
|
if(NVstore.getHeaterTuning().maxFuelUsage) {
|
|
|
|
// saved as x10 litres (ala decilitres)
|
|
|
|
uint16_t maxUsage = NVstore.getHeaterTuning().maxFuelUsage;
|
|
|
|
uint16_t actualUsage = (uint16_t)(FuelGauge.Used_mL() * .01); // convert ml to decilitres
|
|
|
|
uint16_t warnUsage = maxUsage - NVstore.getHeaterTuning().warnFuelUsage;
|
|
|
|
|
|
|
|
if(actualUsage >= warnUsage) {
|
|
|
|
retval = 1;
|
|
|
|
}
|
|
|
|
if(actualUsage >= maxUsage) {
|
|
|
|
retval = 2;
|
|
|
|
if(throwfault) {
|
|
|
|
DebugPort.println("Excess fuel usage shutting heater down");
|
|
|
|
_Error = 13; // internals error codes are +1 over displayed error code
|
|
|
|
requestOff(); // shut heater down
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return retval;
|
|
|
|
}
|