Разблокировка Arduino Hardlid

Я пытаюсь создать анлокер на своем хардлиде для своего ute. Я заменил механизм ручной разблокировки двумя такими https://www.jaycar.com .au/slave-door-lock-actuator/p/LR8813.

Теперь мой код иногда работает, и я не могу понять, почему. Код должен работать так:

  1. Нажмите кнопку разблокировки (количество шагов)
  2. Нажмите кнопку разблокировки еще раз
  3. Когда count = 2, включите реле на 4 секунды, затем выключите.
  4. сбросить счетчик до 0
  5. Если время между нажатиями больше 10 секунд, сбросьте счетчик до 0

Основная схема ниже. Обратите внимание, что кнопка на самом деле подключена к реле, которое срабатывает от пульта дистанционного управления отпиранием автомобиля, а светодиод — это приводы.

Это мой код

int switchPin = 2; // выбираем входной пин (для кнопки)
int relayPin = 4; // выбираем входной пин (для кнопки)
int val = 0; // переменная для чтения состояния пина
int counter = 0;
int currentState = 0;
int previousState = 0;
bool lockOn = false;

unsigned long currentMillis = 0;
unsigned long previousMillis = 0;

unsigned long LockcurrentMillis = 0;
unsigned long LockpreviousMillis = 0;


const long interval = 10000;
const long Lockinterval = 4000;

void setup() {
  Serial.begin(9600);

  pinMode(switchPin, INPUT); // объявляем кнопку как вход
  pinMode(relayPin, OUTPUT); // объявляем кнопку как вход


  Serial.println("Ready");
  Serial.print("IP address: ");

}

void loop() {



  currentMillis = millis();
  LockcurrentMillis = millis();
/*
  Serial.print("Current ");
  Serial.print(currentMillis);
  Serial.print(" | Previous ");
  Serial.println(previousMillis);
    //Serial.println(lockOn);


  Serial.print("Lock Current ");
  Serial.print(LockcurrentMillis);
  Serial.print(" | Lock Previous ");
  Serial.println(LockpreviousMillis);
  */
  if (lockOn == true){

    if (LockcurrentMillis - LockpreviousMillis >= Lockinterval) {
      // сохранить время последнего мигания светодиодом
      LockpreviousMillis = LockcurrentMillis;
      digitalWrite(relayPin, LOW); // выключаем relayPin
      lockOn = false;
      Serial.println("relay off");
    }
  }

  val = digitalRead(switchPin); // чтение входного значения
  if (val == HIGH) { // проверяем, является ли вход ВЫСОКИМ (кнопка отпущена)
    currentState = 1;
  }
  else {
    currentState = 0;
  }
  if (currentState != previousState) {
    if (currentState == 1) {
      counter = counter + 1;
      previousMillis = currentMillis;   //сбросить таймер
      Serial.println(counter);
    }
  }
  if (counter == 2) {
    counter = 0;
    digitalWrite(relayPin, HIGH); // включить relayPin
    // задержка (4000);
    // цифровая запись (relayPin, LOW); // выключаем relayPin
    lockOn = true;
          LockpreviousMillis = LockcurrentMillis;

    Serial.println("relay on");
  }

  previousState = currentState;
  // задержка (250);
  if (currentMillis - previousMillis >= interval) {
    // сохранить время последнего нажатия кнопки
    previousMillis = currentMillis;
    //Заблокировать предыдущую Миллис = Блокироватьтекущую Миллис;
    //если (счетчик >= 1) {
    Serial.println("Took too long reset count");
    counter = 0;
    lockOn = false;
    //}
  }
}

Мы будем очень признательны за любую помощь

Спасибо

, 👍3

Обсуждение

Первое: устраните дребезг кнопки., @Edgar Bonet

Библиотека устранения дребезга кнопок: https://github.com/thomasfredericks/Bounce2, @VE7JRO

Что такое ют? Вы когда-нибудь смотрели фильм «Мой кузен Винни»?, @Delta_G

@Delta_G, лол .... я думал о том же, @jsotola

Уте :) ... https://edge.pxcrush.net/std/car/cil/mxu89gdw4v7sjx3evj47ec64d.jpg?width=900, @Ben


1 ответ


2

Ваш чертеж цепи кажется очень неправильным, но он бесполезен, поскольку, как вы говорите, что это не представляет реальную схему. Пожалуйста, добавьте правильный схема реальной цепи.

Что касается вашей проблемы с надежностью, то я не вникал в логику код, который вы разместили, но я подозреваю, что это может быть вызвано отсутствием устранение дребезга. Вы можете добавить свой собственный код устранения дребезга, но ради простоты, я предлагаю вам вместо этого использовать готовую библиотеку, например Bounce2.

Что касается программы, которую вы пытаетесь написать, я считаю, что логика становится намного легче понять, если вы думаете об этом как о конечном состоянии машина. Это программная конструкция, основанная на идее, что система может находиться в любом из предопределенного набора возможных состояний, и что его поведение и возможные переходы состояний зависят от того, что конкретное состояние, в котором он находится. В этом конкретном случае я бы использовал три состояния:

  • В состоянии LOCKED крышка заблокирована, и вам нужно нажать кнопку кнопку дважды, чтобы разблокировать его. После того, как вы нажмете кнопку один раз, он переходит в состояние WAITING.
  • В состоянии WAITING крышка по-прежнему заблокирована, но первый нажатие кнопки уже зарегистрировано. Если вы нажмете кнопку снова система переходит в состояние UNLOCKED. Если не, после тайм-аута он снова переходит в состояние LOCKED.
  • В состоянии UNLOCKED крышка разблокирована. После очередного тайм-аута переходит обратно в состояние LOCKED.

Записав эту логику, ее можно преобразовать в код на очень простой способ:

#include <Bounce2.h>

const uint8_t  switch_pin = 2;
const uint8_t  relay_pin  = 4;
const uint32_t wait_interval = 10000;  // 10 с
const uint32_t lock_interval =  4000;  // 4 с

Bounce button;

void setup() {
    button.attach(switch_pin, INPUT_PULLUP);
    pinMode(relay_pin, OUTPUT);
    Serial.begin(9600);
    Serial.println("Ready.");
}

void loop() {
    static enum { LOCKED, WAITING, UNLOCKED } state = LOCKED;
    static uint32_t last_change;  // не используется в заблокированном состоянии

    button.update();
    uint32_t now = millis();
    switch (state) {
    case LOCKED:
        if (button.fell()) {
            Serial.println(F("Waiting for second button press."));
            state = WAITING;
            last_change = now;
        }
        break;
    case WAITING:
        if (button.fell()) {
            Serial.println(F("Unlocking."));
            digitalWrite(relay_pin, HIGH);
            state = UNLOCKED;
            last_change = now;
        } else if (now - last_change >= wait_interval) {
            Serial.println(F("Wait time out."));
            state = LOCKED;
        }
        break;
    case UNLOCKED:
        if (now - last_change >= lock_interval) {
            Serial.println(F("Locking."));
            digitalWrite(relay_pin, LOW);
            state = LOCKED;
        }
        break;
    }
}
,

Спасибо, Эдгар. Ваш код, безусловно, выглядит намного проще для чтения и выполнения. Я попробую ваш код сейчас и сообщу. Еще раз спасибо, @Ben

Это работает отлично! Я также обновляю схему. Спасибо, @Ben