Remove obstruction detection using the obstruction signal and use flag provided by opener
This commit is contained in:
parent
49487afde1
commit
f0b8380fa5
|
@ -10,7 +10,6 @@ ratgdo:
|
|||
id: ${id_prefix}
|
||||
input_gdo_pin: ${uart_rx_pin}
|
||||
output_gdo_pin: ${uart_tx_pin}
|
||||
input_obst_pin: ${input_obst_pin}
|
||||
remote_id: 0x539
|
||||
|
||||
sensor:
|
||||
|
|
|
@ -19,8 +19,6 @@ CONF_INPUT_GDO = "input_gdo_pin"
|
|||
DEFAULT_INPUT_GDO = (
|
||||
"D2" # D2 red control terminal / GarageDoorOpener (UART1 RX) pin is D2 on D1 Mini
|
||||
)
|
||||
CONF_INPUT_OBST = "input_obst_pin"
|
||||
DEFAULT_INPUT_OBST = "D7" # D7 black obstruction sensor terminal
|
||||
|
||||
CONF_REMOTE_ID = "remote_id"
|
||||
DEFAULT_REMOTE_ID = 0x539
|
||||
|
@ -36,9 +34,6 @@ CONFIG_SCHEMA = cv.Schema(
|
|||
cv.Optional(
|
||||
CONF_INPUT_GDO, default=DEFAULT_INPUT_GDO
|
||||
): pins.gpio_input_pin_schema,
|
||||
cv.Optional(
|
||||
CONF_INPUT_OBST, default=DEFAULT_INPUT_OBST
|
||||
): pins.gpio_input_pin_schema,
|
||||
cv.Optional(
|
||||
CONF_REMOTE_ID, default=DEFAULT_REMOTE_ID
|
||||
): cv.uint64_t,
|
||||
|
@ -64,8 +59,6 @@ async def to_code(config):
|
|||
cg.add(var.set_output_gdo_pin(pin))
|
||||
pin = await cg.gpio_pin_expression(config[CONF_INPUT_GDO])
|
||||
cg.add(var.set_input_gdo_pin(pin))
|
||||
pin = await cg.gpio_pin_expression(config[CONF_INPUT_OBST])
|
||||
cg.add(var.set_input_obst_pin(pin))
|
||||
cg.add(var.set_remote_id(config[CONF_REMOTE_ID]))
|
||||
|
||||
cg.add_library(
|
||||
|
|
|
@ -25,15 +25,6 @@ namespace ratgdo {
|
|||
static const uint8_t MAX_CODES_WITHOUT_FLASH_WRITE = 3;
|
||||
static const uint32_t FLASH_WRITE_INTERVAL = 10000;
|
||||
|
||||
void IRAM_ATTR HOT RATGDOStore::isrObstruction(RATGDOStore* arg)
|
||||
{
|
||||
if (arg->input_obst.digital_read()) {
|
||||
arg->lastObstructionHigh = millis();
|
||||
} else {
|
||||
arg->obstructionLowCount++;
|
||||
}
|
||||
}
|
||||
|
||||
void RATGDOComponent::setup()
|
||||
{
|
||||
this->pref_ = global_preferences->make_preference<int>(734874333U);
|
||||
|
@ -43,18 +34,12 @@ namespace ratgdo {
|
|||
|
||||
this->output_gdo_pin_->setup();
|
||||
this->input_gdo_pin_->setup();
|
||||
this->input_obst_pin_->setup();
|
||||
|
||||
this->store_.input_obst = this->input_obst_pin_->to_isr();
|
||||
|
||||
this->output_gdo_pin_->pin_mode(gpio::FLAG_OUTPUT);
|
||||
this->input_gdo_pin_->pin_mode(gpio::FLAG_INPUT | gpio::FLAG_PULLUP);
|
||||
this->input_obst_pin_->pin_mode(gpio::FLAG_INPUT);
|
||||
|
||||
this->swSerial.begin(9600, SWSERIAL_8N1, this->input_gdo_pin_->get_pin(), this->output_gdo_pin_->get_pin(), true);
|
||||
|
||||
this->input_obst_pin_->attach_interrupt(RATGDOStore::isrObstruction, &this->store_, gpio::INTERRUPT_ANY_EDGE);
|
||||
|
||||
// save counter to flash every 10s if it changed
|
||||
set_interval(FLASH_WRITE_INTERVAL, std::bind(&RATGDOComponent::saveCounter, this, 1));
|
||||
|
||||
|
@ -66,7 +51,6 @@ namespace ratgdo {
|
|||
|
||||
void RATGDOComponent::loop()
|
||||
{
|
||||
obstructionLoop();
|
||||
gdoStateLoop();
|
||||
statusUpdateLoop();
|
||||
}
|
||||
|
@ -76,7 +60,6 @@ namespace ratgdo {
|
|||
ESP_LOGCONFIG(TAG, "Setting up RATGDO...");
|
||||
LOG_PIN(" Output GDO Pin: ", this->output_gdo_pin_);
|
||||
LOG_PIN(" Input GDO Pin: ", this->input_gdo_pin_);
|
||||
LOG_PIN(" Input Obstruction Pin: ", this->input_obst_pin_);
|
||||
ESP_LOGCONFIG(TAG, " Rolling Code Counter: %d", this->rollingCodeCounter);
|
||||
ESP_LOGCONFIG(TAG, " Remote ID: %d", this->remote_id);
|
||||
}
|
||||
|
@ -133,6 +116,8 @@ namespace ratgdo {
|
|||
|
||||
uint16_t RATGDOComponent::readRollingCode()
|
||||
{
|
||||
static bool have_obstruction_status_retry = false;
|
||||
|
||||
uint32_t rolling = 0;
|
||||
uint64_t fixed = 0;
|
||||
uint32_t data = 0;
|
||||
|
@ -171,11 +156,39 @@ namespace ratgdo {
|
|||
this->lockState = static_cast<LockState>(byte2 & 1);
|
||||
this->motionState = MotionState::MOTION_STATE_CLEAR; // when the status message is read, reset motion state to 0|clear
|
||||
this->motorState = MotorState::MOTOR_STATE_OFF; // when the status message is read, reset motor state to 0|off
|
||||
// this->obstructionState = static_cast<ObstructionState>((byte1 >> 6) & 1);
|
||||
ESP_LOGD(TAG, "Status: door=%s light=%s lock=%s",
|
||||
this->obstructionState = ((byte2 >> 2) & 1) == 1 ? ObstructionState::OBSTRUCTION_STATE_OBSTRUCTED : ObstructionState::OBSTRUCTION_STATE_CLEAR;
|
||||
uint8_t motorEnabled = (byte1 >> 6) & 1; // motor enabled? bit that gets cleared about 4s after an obstruction and is set after the obstruction clears
|
||||
|
||||
if (motorEnabled && !this->motorEnabled) {
|
||||
// if motor is enabled after having been disabled, clear obstruction flag
|
||||
this->obstructionState = ObstructionState::OBSTRUCTION_STATE_CLEAR;
|
||||
}
|
||||
this->motorEnabled = motorEnabled;
|
||||
|
||||
if (this->obstructionState == ObstructionState::OBSTRUCTION_STATE_OBSTRUCTED) {
|
||||
// no status sent when onstruction is cleared,
|
||||
// query status with back-off until obstruction is cleared
|
||||
if (!have_obstruction_status_retry) {
|
||||
set_retry("obstruction_status", 1000, 100, [=] (uint8_t call){
|
||||
ESP_LOGD(TAG, "Get obstruction status: %d", call);
|
||||
transmit(command::GET_STATUS);
|
||||
return RetryResult::RETRY;
|
||||
}, 1.5);
|
||||
have_obstruction_status_retry = true;
|
||||
}
|
||||
} else {
|
||||
if (have_obstruction_status_retry) {
|
||||
ESP_LOGD(TAG, "Cancel get obstruction status");
|
||||
cancel_retry("obstruction_status");
|
||||
have_obstruction_status_retry = false;
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Status: door=%s light=%s lock=%s obstruction=%s",
|
||||
door_state_to_string(this->doorState),
|
||||
light_state_to_string(this->lightState),
|
||||
lock_state_to_string(this->lockState));
|
||||
lock_state_to_string(this->lockState),
|
||||
obstruction_state_to_string(this->obstructionState));
|
||||
} else if (cmd == command::LIGHT) {
|
||||
if (nibble == 0) {
|
||||
this->lightState = LightState::LIGHT_STATE_OFF;
|
||||
|
@ -272,42 +285,6 @@ namespace ratgdo {
|
|||
this->txRollingCode[18]);
|
||||
}
|
||||
|
||||
/*************************** OBSTRUCTION DETECTION ***************************/
|
||||
|
||||
void RATGDOComponent::obstructionLoop()
|
||||
{
|
||||
long currentMillis = millis();
|
||||
static unsigned long lastMillis = 0;
|
||||
|
||||
// the obstruction sensor has 3 states: clear (HIGH with LOW pulse every 7ms), obstructed (HIGH), asleep (LOW)
|
||||
// the transitions between awake and asleep are tricky because the voltage drops slowly when falling asleep
|
||||
// and is high without pulses when waking up
|
||||
|
||||
// If at least 3 low pulses are counted within 50ms, the door is awake, not obstructed and we don't have to check anything else
|
||||
|
||||
// Every 50ms
|
||||
if (currentMillis - lastMillis > 50) {
|
||||
// check to see if we got between 3 and 8 low pulses on the line
|
||||
if (this->store_.obstructionLowCount >= 3 && this->store_.obstructionLowCount <= 8) {
|
||||
// obstructionCleared();
|
||||
this->obstructionState = ObstructionState::OBSTRUCTION_STATE_CLEAR;
|
||||
|
||||
// if there have been no pulses the line is steady high or low
|
||||
} else if (this->store_.obstructionLowCount == 0) {
|
||||
// if the line is high and the last high pulse was more than 70ms ago, then there is an obstruction present
|
||||
if (this->input_obst_pin_->digital_read() && currentMillis - this->store_.lastObstructionHigh > 70) {
|
||||
this->obstructionState = ObstructionState::OBSTRUCTION_STATE_OBSTRUCTED;
|
||||
// obstructionDetected();
|
||||
} else {
|
||||
// asleep
|
||||
}
|
||||
}
|
||||
|
||||
lastMillis = currentMillis;
|
||||
this->store_.obstructionLowCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void RATGDOComponent::gdoStateLoop()
|
||||
{
|
||||
static bool reading_msg = false;
|
||||
|
|
|
@ -98,15 +98,6 @@ namespace ratgdo {
|
|||
};
|
||||
}
|
||||
|
||||
struct RATGDOStore {
|
||||
ISRInternalGPIOPin input_obst;
|
||||
|
||||
int obstructionLowCount = 0; // count obstruction low pulses
|
||||
long lastObstructionHigh = 0; // count time between high pulses from the obst ISR
|
||||
|
||||
static void IRAM_ATTR HOT isrObstruction(RATGDOStore* arg);
|
||||
};
|
||||
|
||||
class RATGDOComponent : public Component {
|
||||
public:
|
||||
void setup() override;
|
||||
|
@ -124,6 +115,8 @@ namespace ratgdo {
|
|||
uint16_t previousOpenings { 0 }; // number of times the door has been opened
|
||||
uint16_t openings { 0 }; // number of times the door has been opened
|
||||
|
||||
uint8_t motorEnabled { 1 };
|
||||
|
||||
DoorState previousDoorState { DoorState::DOOR_STATE_UNKNOWN };
|
||||
DoorState doorState { DoorState::DOOR_STATE_UNKNOWN };
|
||||
|
||||
|
@ -147,7 +140,6 @@ namespace ratgdo {
|
|||
|
||||
void set_output_gdo_pin(InternalGPIOPin* pin) { this->output_gdo_pin_ = pin; };
|
||||
void set_input_gdo_pin(InternalGPIOPin* pin) { this->input_gdo_pin_ = pin; };
|
||||
void set_input_obst_pin(InternalGPIOPin* pin) { this->input_obst_pin_ = pin; };
|
||||
void set_remote_id(uint64_t remote_id) { this->remote_id = remote_id & 0xffffff; }; // not sure how large remote_id can be, assuming not more than 24 bits
|
||||
|
||||
/********************************** FUNCTION DECLARATION
|
||||
|
@ -157,7 +149,6 @@ namespace ratgdo {
|
|||
void sync();
|
||||
|
||||
void gdoStateLoop();
|
||||
void obstructionLoop();
|
||||
void statusUpdateLoop();
|
||||
|
||||
void saveCounter(int threshold);
|
||||
|
@ -195,11 +186,9 @@ namespace ratgdo {
|
|||
std::vector<RATGDOClient*> children_;
|
||||
bool rollingCodeUpdatesEnabled_ { true };
|
||||
bool forceUpdate_ { false };
|
||||
RATGDOStore store_ {};
|
||||
|
||||
InternalGPIOPin* output_gdo_pin_;
|
||||
InternalGPIOPin* input_gdo_pin_;
|
||||
InternalGPIOPin* input_obst_pin_;
|
||||
uint64_t remote_id;
|
||||
|
||||
}; // RATGDOComponent
|
||||
|
|
|
@ -4,7 +4,6 @@ substitutions:
|
|||
friendly_name: "RATGDOv2"
|
||||
uart_tx_pin: D4
|
||||
uart_rx_pin: D2
|
||||
input_obst_pin: D7
|
||||
status_door_pin: D0
|
||||
status_obstruction_pin: D8
|
||||
dry_contact_open_pin: D5
|
||||
|
|
|
@ -4,7 +4,6 @@ substitutions:
|
|||
friendly_name: "ratgdov2"
|
||||
uart_tx_pin: D4
|
||||
uart_rx_pin: D2
|
||||
input_obst_pin: D7
|
||||
status_door_pin: D0
|
||||
status_obstruction_pin: D8
|
||||
dry_contact_open_pin: D5
|
||||
|
|
Loading…
Reference in New Issue