Added under/over temperature threshold for GPIO outputs

This commit is contained in:
Ray Jones 2019-10-30 21:48:25 +11:00
parent 96b3cecdb0
commit f2af9c3fda
11 changed files with 462 additions and 187 deletions

BIN
icons/Thresh.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 B

View File

@ -1585,6 +1585,8 @@ void setupGPIO()
GPIOout2_pin,
NVstore.getUserSettings().GPIO.out1Mode,
NVstore.getUserSettings().GPIO.out2Mode);
GPIOout.setThresh(NVstore.getUserSettings().GPIO.thresh[0],
NVstore.getUserSettings().GPIO.thresh[1]);
// ### MAJOR ISSUE WITH ADC INPUTS ###
//
@ -1592,7 +1594,7 @@ void setupGPIO()
// This is ADC2 channel (#9).
// Unfortunately it was subsequently discovered that any ADC2 input cannot be
// used if Wifi is enabled.
// THIS ISSUE IS NOT RESOLBVABLE IN SOFTWARE.
// THIS ISSUE IS NOT RESOLVABLE IN SOFTWARE.
// *** It is not possible to use ANY of the 10 ADC2 channels if Wifi is enabled :-( ***
//
// Fix is to cut traces to GPIO33 & GPIO26 and swap the connections.

View File

@ -127,6 +127,10 @@ CGPIOInfoScreen::animate()
_drawBitmap(99, 15, UserIconInfo);
_drawBitmap(110, 13, bulbmode ? BulbOnIconInfo : BulbOffIconInfo);
break;
case CGPIOout1::Thresh:
_drawBitmap(99, 15, threshIconInfo);
_drawBitmap(110, 13, bulbmode ? BulbOnIconInfo : BulbOffIconInfo);
break;
}
#if USE_JTAG == 0
@ -138,6 +142,10 @@ CGPIOInfoScreen::animate()
_drawBitmap(99, 27, UserIconInfo);
_drawBitmap(110, 26, bulbmode ? BulbOnIconInfo : BulbOffIconInfo);
break;
case CGPIOout2::Thresh:
_drawBitmap(99, 27, threshIconInfo);
_drawBitmap(110, 26, bulbmode ? BulbOnIconInfo : BulbOffIconInfo);
break;
}

View File

@ -16,7 +16,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*
*/
#include "128x64OLED.h"
@ -31,6 +31,14 @@ extern CGPIOout GPIOout;
extern CGPIOin GPIOin;
extern CGPIOalg GPIOalg;
int8_t s8abs(int8_t val)
{
if(val >= 0)
return val;
else
return -val;
}
///////////////////////////////////////////////////////////////////////////
//
// CGPIOSetupScreen
@ -53,6 +61,8 @@ CGPIOSetupScreen::CGPIOSetupScreen(C128x64_OLED& display, CScreenManager& mgr) :
_GPIOparams.out1Mode = CGPIOout1::Disabled;
_GPIOparams.out2Mode = CGPIOout2::Disabled;
_GPIOparams.algMode = CGPIOalg::Disabled;
_GPIOparams.thresh[0] = 0;
_GPIOparams.thresh[1] = 0;
_ExtHold = 0;
}
@ -63,6 +73,7 @@ CGPIOSetupScreen::onSelect()
_initUI();
_GPIOparams = NVstore.getUserSettings().GPIO;
_ExtHold = NVstore.getUserSettings().ExtThermoTimeout;
_repeatCount = -1;
}
void
@ -75,6 +86,8 @@ CGPIOSetupScreen::_initUI()
bool
CGPIOSetupScreen::show()
{
char msg[16];
_display.clearDisplay();
static bool animated = false;
@ -138,6 +151,17 @@ CGPIOSetupScreen::show()
case CGPIOout1::Disabled: msgText = "---"; break;
case CGPIOout1::Status: msgText = "Status"; break;
case CGPIOout1::User: msgText = "User"; break;
case CGPIOout1::Thresh:
if(_rowSel == 6) {
sprintf(msg, " %dC", s8abs(_GPIOparams.thresh[0]));
_printMenuText(Column2, Line3, msg, false);
_printMenuText(Column2, Line3, _GPIOparams.thresh[0] >= 0 ? ">" : "<", true);
}
else {
sprintf(msg, "%s %dC", _GPIOparams.thresh[0] >= 0 ? ">" : "<", s8abs(_GPIOparams.thresh[0]));
_printMenuText(Column2, Line3, msg, _rowSel == 8);
}
break;
}
if(msgText)
_printMenuText(Column2, Line3, msgText, _rowSel == 6);
@ -149,6 +173,17 @@ CGPIOSetupScreen::show()
switch(_GPIOparams.out2Mode) {
case CGPIOout2::Disabled: msgText = "---"; break;
case CGPIOout2::User: msgText = "User"; break;
case CGPIOout2::Thresh:
if(_rowSel == 5) {
sprintf(msg, " %d`C", s8abs(_GPIOparams.thresh[1]));
_printMenuText(Column2, Line2, msg, false);
_printMenuText(Column2, Line2, _GPIOparams.thresh[1] >= 0 ? ">" : "<", true);
}
else {
sprintf(msg, "%s %d`C", _GPIOparams.thresh[1] >= 0 ? ">" : "<", s8abs(_GPIOparams.thresh[1]));
_printMenuText(Column2, Line2, msg, _rowSel == 7);
}
break;
}
if(msgText)
_printMenuText(Column2, Line2, msgText, _rowSel == 5);
@ -227,6 +262,12 @@ CGPIOSetupScreen::animate()
switch(_GPIOparams.out2Mode) {
case CGPIOout2::Disabled: pMsg = " Output 2: DISABLED. "; break;
case CGPIOout2::User: pMsg = " Output 2: User controlled. "; break;
case CGPIOout2::Thresh:
if(_GPIOparams.thresh[1] >= 0)
pMsg = " Output 2: Active if over temperature. Hold LEFT to set under. Hold RIGHT to set over. ";
else
pMsg = " Output 2: Active if under temperature. Hold LEFT to set under. Hold RIGHT to set over. ";
break;
}
if(pMsg)
_scrollMessage(56, pMsg, _scrollChar);
@ -237,10 +278,32 @@ CGPIOSetupScreen::animate()
case CGPIOout1::Disabled: pMsg = " Output 1: DISABLED. "; break;
case CGPIOout1::Status: pMsg = " Output 1: LED status indicator. "; break;
case CGPIOout1::User: pMsg = " Output 1: User controlled. "; break;
case CGPIOout1::Thresh:
if(_GPIOparams.thresh[0] >= 0)
pMsg = " Output 1: Active if over temperature. Hold LEFT to set under. Hold RIGHT to set over. ";
else
pMsg = " Output 1: Active if under temperature. Hold LEFT to set under. Hold RIGHT to set over. ";
break;
}
if(pMsg)
_scrollMessage(56, pMsg, _scrollChar);
break;
case 7:
_display.drawFastHLine(0, 52, 128, WHITE);
if(_GPIOparams.thresh[1] >= 0)
pMsg = " Output 2: Active if over temperature. CENTRE to accept. Hold LEFT to set under. ";
else
pMsg = " Output 2: Active if under temperature. CENTRE to accept. Hold RIGHT to set over. ";
_scrollMessage(56, pMsg, _scrollChar);
break;
case 8:
_display.drawFastHLine(0, 52, 128, WHITE);
if(_GPIOparams.thresh[0] >= 0)
pMsg = " Output 1: Active if over temperature. Centre to accept. Hold LEFT to set under. ";
else
pMsg = " Output 1: Active if under temperature. Centre to accept. Hold RIGHT to set over. ";
_scrollMessage(56, pMsg, _scrollChar);
break;
}
return true;
}
@ -251,109 +314,164 @@ CGPIOSetupScreen::animate()
bool
CGPIOSetupScreen::keyHandler(uint8_t event)
{
sUserSettings us;
if(event & keyPressed) {
// press LEFT to select previous screen
if(event & key_Left) {
switch(_rowSel) {
case 0:
_ScreenManager.prevMenu();
break;
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
_scrollChar = 0;
_adjust(-1);
break;
case 10:
_rowSel = 0; // abort save
break;
_repeatCount = 0;
}
if(event & keyRepeat) {
if(_repeatCount >= 0) {
_repeatCount++;
// hold LEFT to toggle GPIO output #1
if(event & key_Left) {
if(_repeatCount > 1) {
_repeatCount = -1; // prevent double handling
if((_rowSel == 6 || _rowSel == 8) && _GPIOparams.out1Mode == CGPIOout1::Thresh) {
_GPIOparams.thresh[0] = -s8abs(_GPIOparams.thresh[0]);
BOUNDSLIMIT(_GPIOparams.thresh[0], -50, -1);
_rowSel = 8;
}
if((_rowSel == 5 || _rowSel == 7) && _GPIOparams.out2Mode == CGPIOout2::Thresh) {
_GPIOparams.thresh[1] = -s8abs(_GPIOparams.thresh[1]);
BOUNDSLIMIT(_GPIOparams.thresh[1], -50, -1);
_rowSel = 7;
}
}
}
if(event & key_Right) {
if(_repeatCount > 1) {
_repeatCount = -1; // prevent double handling
if((_rowSel == 6 || _rowSel == 8) && _GPIOparams.out1Mode == CGPIOout1::Thresh) {
_GPIOparams.thresh[0] = s8abs(_GPIOparams.thresh[0]);
BOUNDSLIMIT(_GPIOparams.thresh[0], 0, 50);
_rowSel = 8;
}
if((_rowSel == 5 || _rowSel == 7) && _GPIOparams.out2Mode == CGPIOout2::Thresh) {
_GPIOparams.thresh[1] = s8abs(_GPIOparams.thresh[1]);
BOUNDSLIMIT(_GPIOparams.thresh[1], 0, 50);
_rowSel = 7;
}
}
}
}
// press RIGHT to select next screen
if(event & key_Right) {
switch(_rowSel) {
case 0:
_ScreenManager.nextMenu();
break;
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
_scrollChar = 0;
_adjust(+1);
break;
case 10:
_rowSel = 0; // abort save
break;
}
}
if(event & key_Down) {
if(_rowSel == 10) {
_rowSel = 0; // abort save
}
else {
_scrollChar = 0;
_rowSel--;
if((_rowSel == 3) && (_GPIOparams.in2Mode != CGPIOin2::Thermostat))
_rowSel--; // force skip if not set to external thermostat
if((_rowSel == 1) && ((getBoardRevision() == BRD_V2_GPIO_NOALG) || (getBoardRevision() == BRD_V3_GPIO_NOALG))) // GPIO but NO analog support
_rowSel--; // force skip if analog input is not supported by PCB
LOWERLIMIT(_rowSel, 0);
}
}
// UP press
if(event & key_Up) {
switch(_rowSel) {
case 0:
if((getBoardRevision() == BRD_V2_GPIO_NOALG) || (getBoardRevision() == BRD_V3_GPIO_NOALG)) // GPIO but NO Analog support
_rowSel++; // force skip if analog input is not supported by PCB
case 1:
case 2:
case 3:
case 4:
case 5:
_scrollChar = 0;
_rowSel++;
if((_rowSel == 3) && (_GPIOparams.in2Mode != CGPIOin2::Thermostat))
_rowSel++; // force skip if not set to external thermostat
UPPERLIMIT(_rowSel, 6);
break;
case 10: // confirmed save
_enableStoringMessage();
us = NVstore.getUserSettings();
us.GPIO = _GPIOparams;
us.ExtThermoTimeout = _ExtHold;
NVstore.setUserSettings(us);
saveNV();
}
setupGPIO();
_rowSel = 0;
break;
}
}
// CENTRE press
if(event & key_Centre) {
switch(_rowSel) {
case 0:
_ScreenManager.selectMenu(CScreenManager::RootMenuLoop); // force return to main menu
break;
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
_rowSel = 10;
break;
if(event & keyReleased) {
// press LEFT to select previous screen
if(_repeatCount == 0) {
if(event & key_Left) {
switch(_rowSel) {
case 0:
_ScreenManager.prevMenu();
break;
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
_scrollChar = 0;
_adjust(-1);
break;
case 10:
_rowSel = 0; // abort save
break;
}
}
// press RIGHT to select next screen
if(event & key_Right) {
switch(_rowSel) {
case 0:
_ScreenManager.nextMenu();
break;
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
_scrollChar = 0;
_adjust(+1);
break;
case 10:
_rowSel = 0; // abort save
break;
}
}
if(event & key_Down) {
if(_rowSel == 10) {
_rowSel = 0; // abort save
}
else {
_scrollChar = 0;
_rowSel--;
if((_rowSel == 3) && (_GPIOparams.in2Mode != CGPIOin2::Thermostat))
_rowSel--; // force skip if not set to external thermostat
if((_rowSel == 1) && ((getBoardRevision() == BRD_V2_GPIO_NOALG) || (getBoardRevision() == BRD_V3_GPIO_NOALG))) // GPIO but NO analog support
_rowSel--; // force skip if analog input is not supported by PCB
LOWERLIMIT(_rowSel, 0);
}
}
// UP press
if(event & key_Up) {
switch(_rowSel) {
case 0:
if((getBoardRevision() == BRD_V2_GPIO_NOALG) || (getBoardRevision() == BRD_V3_GPIO_NOALG)) // GPIO but NO Analog support
_rowSel++; // force skip if analog input is not supported by PCB
case 1:
case 2:
case 3:
case 4:
case 5:
_scrollChar = 0;
_rowSel++;
if((_rowSel == 3) && (_GPIOparams.in2Mode != CGPIOin2::Thermostat))
_rowSel++; // force skip if not set to external thermostat
UPPERLIMIT(_rowSel, 6);
break;
case 10: // confirmed save
_enableStoringMessage();
us = NVstore.getUserSettings();
us.GPIO = _GPIOparams;
us.ExtThermoTimeout = _ExtHold;
NVstore.setUserSettings(us);
saveNV();
setupGPIO();
_rowSel = 0;
break;
}
}
// CENTRE press
if(event & key_Centre) {
switch(_rowSel) {
case 0:
_ScreenManager.selectMenu(CScreenManager::RootMenuLoop); // force return to main menu
break;
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
_rowSel = 10;
break;
case 7:
_rowSel = 5;
break;
case 8:
_rowSel = 6;
break;
}
}
}
_repeatCount = -1;
_ScreenManager.reqUpdate();
}
@ -400,15 +518,35 @@ CGPIOSetupScreen::_adjust(int dir)
case 5: // outputs mode
tVal = _GPIOparams.out2Mode;
tVal += dir;
WRAPLIMITS(tVal, 0, 1);
WRAPLIMITS(tVal, 0, 2);
_GPIOparams.out2Mode = (CGPIOout2::Modes)tVal;
break;
case 6: // outputs mode
tVal = _GPIOparams.out1Mode;
tVal += dir;
WRAPLIMITS(tVal, 0, 2);
WRAPLIMITS(tVal, 0, 3);
_GPIOparams.out1Mode = (CGPIOout1::Modes)tVal;
break;
case 7:
if(_GPIOparams.thresh[1] < 0) {
_GPIOparams.thresh[1] += -dir;
BOUNDSLIMIT(_GPIOparams.thresh[1], -50, -1);
}
else {
_GPIOparams.thresh[1] += dir;
BOUNDSLIMIT(_GPIOparams.thresh[1], 0, 50);
}
break;
case 8:
if(_GPIOparams.thresh[0] < 0) {
_GPIOparams.thresh[0] += -dir;
BOUNDSLIMIT(_GPIOparams.thresh[0], -50, -1);
}
else {
_GPIOparams.thresh[0] += dir;
BOUNDSLIMIT(_GPIOparams.thresh[0], 0, 50);
}
break;
}
}

View File

@ -37,6 +37,7 @@ class CGPIOSetupScreen : public CPasswordScreen
unsigned long _ExtHold;
int _animateCount;
int _scrollChar;
int _repeatCount;
void _initUI();
public:
CGPIOSetupScreen(C128x64_OLED& display, CScreenManager& mgr);

View File

@ -1373,3 +1373,22 @@ const uint8_t PROGMEM passwordIcon[] =
const BITMAP_INFO passwordIconInfo(11, 17, passwordIcon);
//
// Image data for thresh
//
const uint8_t PROGMEM threshIcon[] =
{
0xAA, 0x80, // # # # # #
0x00, 0x00, //
0x30, 0x00, // ##
0x49, 0x00, // # # #
0xFF, 0x80, // #########
0x49, 0x00, // # # #
0x06, 0x00, // ##
0x00, 0x00, //
0xAA, 0x80, // # # # # #
};
const BITMAP_INFO threshIconInfo(9, 9, threshIcon);

View File

@ -158,3 +158,4 @@ extern const BITMAP_INFO _2IconInfo;
extern const BITMAP_INFO algIconInfo;
extern const BITMAP_INFO passwordIconInfo;
extern const BITMAP_INFO threshIconInfo;

View File

@ -48,11 +48,13 @@ const char* GPIOin2Names[] = {
const char* GPIOout1Names[] = {
"Disabled",
"Status",
"User"
"User",
"Thresh"
};
const char* GPIOout2Names[] = {
"Disabled",
"User"
"User",
"Thresh"
};
const char* GPIOalgNames[] = {
@ -307,8 +309,105 @@ CGPIOin::simulateKey(uint8_t newKey)
_Input2.manage((newKey & 0x02) != 0);
}
/*********************************************************************************************************
** GPIO out root
** GPIO out base class
*********************************************************************************************************/
CGPIOoutBase::CGPIOoutBase()
{
_pin = 0;
_thresh = 0;
_userState = 0;
}
void
CGPIOoutBase::begin(int pin)
{
_pin = pin;
if(pin) {
pinMode(pin, OUTPUT); // GPIO output pin #1
digitalWrite(pin, LOW);
}
}
void
CGPIOoutBase::setThresh(int thresh)
{
_thresh = thresh;
}
void
CGPIOoutBase::setState(bool state)
{
_userState = state;
}
bool
CGPIOoutBase::_getUserState()
{
return _userState;
};
void
CGPIOoutBase::_setPinState(int state)
{
digitalWrite(_pin, state);
}
int
CGPIOoutBase::_getPinState()
{
return digitalRead(_pin);
};
void
CGPIOoutBase::_doUser()
{
// DebugPort.println("GPIOout::_doUser2()");
if(_pin) {
digitalWrite(_pin, _userState ? HIGH : LOW);
}
}
void
CGPIOoutBase::_doThresh()
{
if(_thresh) {
float tAct = getTemperatureSensor(0);
if(digitalRead(_pin)) {
// output is currently active
if(_thresh > 0) { // active when OVER threshold mode
if((tAct + 0.1) < _thresh) { // test if under threshold +0.1deg hysteresis
digitalWrite(_pin, LOW); // deactivate output when less than threshold
}
}
else { // active if UNDER threshold mode
if(tAct > -_thresh) { // inactive if over threshold
digitalWrite(_pin, LOW); // deactivate output when over threshold
}
}
}
else {
// output is not currently active
if(_thresh > 0) { // active when OVER threshold mode
if(tAct > _thresh) { // test if over threshold
digitalWrite(_pin, HIGH); // activate output when over threshold
}
}
else { // active if UNDER threshold mode
if((tAct + 0.1) < -_thresh) { // test if under threshold +0.1deg hysteresis
digitalWrite(_pin, HIGH); // activate output when under threshold
}
}
}
}
}
/*********************************************************************************************************
** GPIO out manager
*********************************************************************************************************/
@ -330,6 +429,13 @@ CGPIOout::setMode(CGPIOout1::Modes mode1, CGPIOout2::Modes mode2)
_Out2.setMode(mode2);
};
void
CGPIOout::setThresh(int op1, int op2)
{
_Out1.setThresh(op1);
_Out2.setThresh(op2);
}
CGPIOout1::Modes
CGPIOout::getMode1() const
{
@ -374,26 +480,21 @@ CGPIOout::getState(int channel)
*********************************************************************************************************/
CGPIOout1::CGPIOout1()
CGPIOout1::CGPIOout1() : CGPIOoutBase()
{
_Mode = Disabled;
_pin = 0;
_breatheDelay = 0;
_statusState = 0;
_statusDelay = 0;
_userState = 0;
_prevState = -1;
}
void
CGPIOout1::begin(int pin, CGPIOout1::Modes mode)
CGPIOout1::begin(int pin, CGPIOout1::Modes mode)
{
_pin = pin;
if(pin) {
pinMode(pin, OUTPUT); // GPIO output pin #1
digitalWrite(pin, LOW);
ledcSetup(0, 500, 8); // create PWM channel for GPIO1: 500Hz, 8 bits
}
CGPIOoutBase::begin(pin);
ledcSetup(0, 500, 8); // create PWM channel for GPIO1: 500Hz, 8 bits
setMode(mode);
}
@ -401,10 +502,11 @@ CGPIOout1::begin(int pin, CGPIOout1::Modes mode)
void
CGPIOout1::setMode(CGPIOout1::Modes mode)
{
if(mode >= Disabled && mode <= User)
if(mode >= Disabled && mode <= Thresh)
_Mode = mode;
_prevState = -1;
ledcDetachPin(_pin); // ensure PWM detached from IO line
if(_getPin())
ledcDetachPin(_getPin()); // ensure PWM detached from IO line
};
CGPIOout1::Modes CGPIOout1::getMode() const
@ -416,16 +518,18 @@ void
CGPIOout1::manage()
{
switch (_Mode) {
case Disabled: break;
case Status: _doStatus(); break;
case User: _doUser(); break;
case CGPIOout1::Disabled: break;
case CGPIOout1::Status: _doStatus(); break;
case CGPIOout1::User: _doUser(); break;
case CGPIOout1::Thresh: _doThresh(); break;
}
}
void
CGPIOout1::_doStatus()
{
if(_pin == 0)
int pin = _getPin();
if(pin == 0)
return;
// DebugPort.println("GPIOout::_doStatus()");
@ -466,30 +570,30 @@ CGPIOout1::_doStatus()
_statusDelay = millis() + BREATHINTERVAL;
switch(statusMode) {
case 0:
ledcDetachPin(_pin); // detach PWM from IO line
digitalWrite(_pin, LOW);
ledcDetachPin(pin); // detach PWM from IO line
_setPinState(LOW);
_ledState = 0;
break;
case 1:
ledcAttachPin(_pin, 0); // attach PWM to GPIO line
ledcAttachPin(pin, 0); // attach PWM to GPIO line
ledcWrite(0, _statusState);
_breatheDelay = millis() + BREATHINTERVAL;
break;
case 2:
ledcDetachPin(_pin); // detach PWM from IO line
digitalWrite(_pin, HIGH);
ledcDetachPin(pin); // detach PWM from IO line
_setPinState(HIGH);
_ledState = 1;
break;
case 3:
ledcAttachPin(_pin, 0); // attach PWM to GPIO line
ledcAttachPin(pin, 0); // attach PWM to GPIO line
_statusState = 255;
ledcWrite(0, _statusState);
_breatheDelay = millis() + BREATHINTERVAL;
break;
case 4:
ledcDetachPin(_pin); // detach PWM from IO line
ledcDetachPin(pin); // detach PWM from IO line
_breatheDelay += (FLASHPERIOD - ONFLASHINTERVAL); // extended off
digitalWrite(_pin, LOW);
_setPinState(LOW);
break;
}
}
@ -500,14 +604,6 @@ CGPIOout1::_doStatus()
}
}
void
CGPIOout1::_doUser()
{
// DebugPort.println("GPIOout::_doUser2()");
if(_pin) {
digitalWrite(_pin, _userState ? HIGH : LOW);
}
}
void
CGPIOout1::_doStartMode() // breath up PWM
@ -547,12 +643,12 @@ CGPIOout1::_doSuspendMode() // brief flash
_statusState++;
if(_statusState & 0x01) {
_breatheDelay += ONFLASHINTERVAL; // brief flash on
digitalWrite(_pin, HIGH);
_setPinState(HIGH);
stretch = (millis() + 250) | 1; // pulse extend for UI purposes, ensure non zero
}
else {
_breatheDelay += (FLASHPERIOD - ONFLASHINTERVAL); // extended off
digitalWrite(_pin, LOW);
_setPinState(LOW);
}
}
if(stretch) {
@ -563,41 +659,34 @@ CGPIOout1::_doSuspendMode() // brief flash
_ledState = stretch ? 1 : 0;
}
void
CGPIOout1::setState(bool state)
{
_userState = state;
}
uint8_t
CGPIOout1::getState()
{
switch(_Mode) {
case User: return _userState;
case Status: return _ledState; // special pulse extender for suspend mode
default: return 0;
}
case User:
case Thresh:
return _getPinState();
case Status:
return _ledState; // special pulse extender for suspend mode
default:
return 0;
}
}
/*********************************************************************************************************
** GPIO2
*********************************************************************************************************/
CGPIOout2::CGPIOout2()
CGPIOout2::CGPIOout2() : CGPIOoutBase()
{
_Mode = Disabled;
_pin = 0;
_userState = 0;
}
void
CGPIOout2::begin(int pin, Modes mode)
{
_pin = pin;
if(pin) {
pinMode(pin, OUTPUT); // GPIO output pin #2
digitalWrite(pin, LOW);
ledcSetup(1, 500, 8); // create PWM channel for GPIO2: 500Hz, 8 bits
}
CGPIOoutBase::begin(pin);
ledcSetup(1, 500, 8); // create PWM channel for GPIO2: 500Hz, 8 bits
setMode(mode);
}
@ -605,10 +694,11 @@ CGPIOout2::begin(int pin, Modes mode)
void
CGPIOout2::setMode(CGPIOout2::Modes mode)
{
if(mode >= Disabled && mode <= User)
if(mode >= Disabled && mode <= Thresh)
_Mode = mode;
if(_pin)
ledcDetachPin(_pin); // ensure PWM detached from IO line
int pin = _getPin();
if(pin)
ledcDetachPin(pin); // ensure PWM detached from IO line
};
CGPIOout2::Modes CGPIOout2::getMode() const
@ -622,27 +712,21 @@ CGPIOout2::manage()
switch (_Mode) {
case CGPIOout2::Disabled: break;
case CGPIOout2::User: _doUser(); break;
case CGPIOout2::Thresh: _doThresh(); break;
}
}
void
CGPIOout2::_doUser()
{
if(_pin) {
digitalWrite(_pin, _userState ? HIGH : LOW);
}
}
void
CGPIOout2::setState(bool state)
{
_userState = state;
}
uint8_t
CGPIOout2::getState()
{
return _userState;
switch (_Mode) {
case CGPIOout2::User:
case CGPIOout2::Thresh:
return _getPinState();
default:
return 0;
}
}
// expected external analogue circuit is a 10k pot.

View File

@ -102,54 +102,66 @@ public:
}
};
class CGPIOout1 {
class CGPIOoutBase {
int _thresh;
bool _userState;
int _pin;
protected:
void _doThresh();
void _doUser();
bool _getUserState();
int _getPin() { return _pin; };
void _setPinState(int state);
int _getPinState();
public:
CGPIOoutBase();
void setState(bool state);
void setThresh(int val);
void begin(int pin);
};
class CGPIOout1 : public CGPIOoutBase {
public:
enum Modes {
Disabled,
Status,
User
User,
Thresh
};
CGPIOout1();
void begin(int pin, Modes mode);
void setMode(Modes mode);
void manage();
void setState(bool state);
uint8_t getState();
Modes getMode() const;
private:
Modes _Mode;
int _pin;
void _doStatus();
void _doUser();
int _prevState;
int _statusState;
int _statusDelay;
unsigned long _breatheDelay;
bool _userState;
uint8_t _ledState;
void _doStartMode();
void _doStopMode();
void _doSuspendMode();
};
class CGPIOout2 {
class CGPIOout2 : public CGPIOoutBase {
public:
enum Modes {
Disabled,
User
User,
Thresh
};
CGPIOout2();
void begin(int pin, Modes mode);
void setMode(Modes mode);
void manage();
void setState(bool state);
uint8_t getState();
Modes getMode() const;
private:
Modes _Mode;
int _pin;
bool _userState;
void _doUser();
};
class CGPIOout {
@ -161,6 +173,7 @@ public:
void begin(int pin1, int pin2, CGPIOout1::Modes mode1, CGPIOout2::Modes mode2);
void manage();
void setState(int channel, bool state);
void setThresh(int thr1, int thr2);
uint8_t getState(int channel);
CGPIOout1::Modes getMode1() const;
CGPIOout2::Modes getMode2() const;
@ -190,6 +203,7 @@ struct sGPIOparams {
CGPIOout1::Modes out1Mode;
CGPIOout2::Modes out2Mode;
CGPIOalg::Modes algMode;
int8_t thresh[2];
};
struct sGPIO {

View File

@ -414,8 +414,10 @@ sUserSettings::load()
preferences.putUChar("GPIOout1Mode", GPIO.out1Mode); // set new
preferences.putUChar("GPIOout2Mode", GPIO.out2Mode); // set new
}
validatedLoad("GPIOout1Mode", tVal, 0, u8inBounds, 0, 2); GPIO.out1Mode = (CGPIOout1::Modes)tVal;
validatedLoad("GPIOout2Mode", tVal, 0, u8inBounds, 0, 1); GPIO.out2Mode = (CGPIOout2::Modes)tVal;
validatedLoad("GPIOout1Mode", tVal, 0, u8inBounds, 0, 3); GPIO.out1Mode = (CGPIOout1::Modes)tVal;
validatedLoad("GPIOout2Mode", tVal, 0, u8inBounds, 0, 2); GPIO.out2Mode = (CGPIOout2::Modes)tVal;
validatedLoad("GPIOout1Thresh", GPIO.thresh[0], 0, s8inBounds, -50, 50);
validatedLoad("GPIOout2Thresh", GPIO.thresh[1], 0, s8inBounds, -50, 50);
validatedLoad("GPIOalgMode", tVal, 0, u8inBounds, 0, 2); GPIO.algMode = (CGPIOalg::Modes)tVal;
validatedLoad("MenuOnTimeout", HomeMenu.onTimeout, 0, u8inBounds, 0, 3);
validatedLoad("MenuonStart", HomeMenu.onStart, 0, u8inBounds, 0, 3);
@ -450,6 +452,8 @@ sUserSettings::save()
preferences.putUChar("GPIOin2Mode", GPIO.in2Mode);
preferences.putUChar("GPIOout1Mode", GPIO.out1Mode);
preferences.putUChar("GPIOout2Mode", GPIO.out2Mode);
preferences.putChar("GPIOout1Thresh", GPIO.thresh[0]);
preferences.putChar("GPIOout2Thresh", GPIO.thresh[1]);
preferences.putUChar("GPIOalgMode", GPIO.algMode);
preferences.putUChar("MenuOnTimeout", HomeMenu.onTimeout);
preferences.putUChar("MenuonStart", HomeMenu.onStart);

View File

@ -332,6 +332,8 @@ struct sUserSettings : public CESP32_NVStorage {
GPIO.out1Mode = CGPIOout1::Disabled;
GPIO.out2Mode = CGPIOout2::Disabled;
GPIO.algMode = CGPIOalg::Disabled;
GPIO.thresh[0] = 0;
GPIO.thresh[1] = 0;
FrameRate = 1000;
cyclic.init();
HomeMenu.init();
@ -357,6 +359,8 @@ struct sUserSettings : public CESP32_NVStorage {
GPIO.out1Mode = rhs.GPIO.out1Mode;
GPIO.out2Mode = rhs.GPIO.out2Mode;
GPIO.algMode = rhs.GPIO.algMode;
GPIO.thresh[0] = rhs.GPIO.thresh[0];
GPIO.thresh[1] = rhs.GPIO.thresh[1];
FrameRate = rhs.FrameRate;
cyclic = rhs.cyclic;
HomeMenu = rhs.HomeMenu;