Реле и кнопки arduino ide

Тема в разделе "Arduino & Shields", создана пользователем Airo, 21 янв 2023.

  1. Airo

    Airo Нерд

    Здравствуйте! Подскажите как добавить в код своего рода резервную активацию если кнопка не сработала по каким либо причинам. Каждое нажатие кнопки производит вкл и выкл 2 реле, но во время эксплуатации бывают механические сбои нажатия кнопок необходим участок кода который бы производил действие digitalWrite(10, LOW); digitalWrite(11, HIGH); если кнопка 2 не использовалась более 5 секунд и аналогично digitalWrite(10, HIGH); digitalWrite(11, LOW); если кнопка 3 не использовалась более 5 секунд. Таким образом хочу производить своего рода обнуление.

    Код (C++):
    #include <Servo.h>
    Servo servo1;
    void setup()
    {
      Serial.begin(9600);
      pinMode(2, INPUT_PULLUP);
      pinMode(3, INPUT_PULLUP);
      servo1.attach(5);
      pinMode(10, OUTPUT);
      digitalWrite(10, LOW);
      pinMode(11, OUTPUT);
      digitalWrite(11, LOW);
    }
    bool flag1 = false;
    bool flag2 = false;
    void loop()
    {
      servo1.write(random(10, 80));
      //Serial.println("servo");
      delay(1000);
      servo1.write(random(81, 150));
      //Serial.println("SERVO");
      delay(1000);
    }
    void yield()
    {
      bool btnState1 = !digitalRead(2);
      if (btnState1 && !flag1 )
      {
        // обработчик нажатия
        flag1 = true;
        Serial.println("2");
        digitalWrite(10, LOW);
        digitalWrite(11, HIGH);
      }
      if (!btnState1 && flag1)
      {
        // обработчик отпускания
        flag1 = false;
      }
      bool btnState2 = !digitalRead(3);
      if (btnState2 && !flag2 )
      {
        // обработчик нажатия
        flag2 = true;
        Serial.println("3");
        digitalWrite(10, HIGH);
        digitalWrite(11, LOW);
      }
      if (!btnState2 && flag2)
      {
        // обработчик отпускания
        flag2 = false;
      }
    }
     

    Вложения:

    • Project_0.1.ino
      Размер файла:
      1,1 КБ
      Просмотров:
      49
    Последнее редактирование модератором: 22 янв 2023
  2. User248

    User248 Гик

    Поставить таймер. А зачем тогда вообще кнопки, если можно каждые пять секунд команды подавать?
    Код (C++):

    void loop(){
       static uint32_t timer = millis();
       if(uint32_t(millis() - timer) > 5000)
       {
            timer = millis();
           // ваш код
       }
     
     
  3. Airo

    Airo Нерд

    Спасибо за ответ. Мне скорее не совсем таймер нужен, а резервный способ перезапуска цикла. Попытаюсь объяснить что из себя представляет проект. Реле запускает двигатель который, движет объект по прямой этот объект доходит то кнопки и ударяется об нее, и переключает реле в обратную сторону, и движется к другой кнопке и так по кругу. Кнопки необходимы, но они иногда дают сбой механического характера. Тем самым объект доходит до кнопки, ударяется об нее, но она не подает сигнал переключить реле, что бы объект начал движение в другую сторону. И вот мне нужен такой таймер который включался в тот момент когда происходит такой сбой. Я делал данный проект без кнопок просто задавая через delay движение в одну и другую сторону, но там присутствуют проблемы механического характера объяснять долго.
     
  4. User248

    User248 Гик

    А если при нажатии на кнопку будет происходить "timer = millis()", сбрасывая таймер до его срабатывания? Если кнопка не сработает, то таймер сработает через заданное время.
     
  5. Рокки1945

    Рокки1945 Гуру

    не кнопки а концевики - делайте реверс по последнему срабатыванию
    что-то мешает сделать на индуктивном датчике - как нормально делают
     
  6. Airbus

    Airbus Радиохулиган Модератор

    Согласен. Нужен другой датчег. Ну а здесь можно сделать по условию ИЛИ. Если сработала кнопка ИЛИ прошло period то меняем направление движения и обнуляем period. Причем выбираем это время чуть больше чем нужно для движения из точки в точку. Каретка приходит и упирается и если кнопка не срабатывает то реверс включается по времени. Как то так
     
  7. Airo

    Airo Нерд

    Да вы поняли в точку, что я хочу сделать вкл таймера после нажатия кнопки и если другая кнопка не заработала то по завершению таймера происходит действие. Это по сути внедрение в if mills(). Но у меня не получается это написать с точки зрения программирования. Я пробовал его добавить в if (btnState2 && !flag2 ) но не выходило. Не хватает знания С++.
     
  8. Airo

    Airo Нерд

    Да концевики вы правы, но их у меня нет собираю, так сказать, из чего есть под рукой. Если бы были нормальные концевики тему не заводил.
     
  9. Airo

    Airo Нерд

    Других датчиков нет. И да я так и представлял вписать mills в if, но не хватает знания в с++ что бы сделать это правильно.
     
  10. User248

    User248 Гик

    Для начала, попробуйте вариант с защитой от дребезга контактов.

    Код (C++):

    #include <Servo.h>
    Servo servo1;

    #define DELAY 50

    void setup() {
      Serial.begin(9600);
      pinMode(2, INPUT_PULLUP);
      pinMode(3, INPUT_PULLUP);
      servo1.attach(5);
      pinMode(10, OUTPUT);
      digitalWrite(10, LOW);
      pinMode(11, OUTPUT);
      digitalWrite(11, LOW);

    }

    bool flag1 = false;
    bool flag2 = false;

    void loop() {
      servo1.write(random(10, 80));
      //Serial.println("servo");
      delay(1000);
      servo1.write(random(81, 150));
      //Serial.println("SERVO");
      delay(1000);

      yield();
    }

    void yield() {

      bool btnState1 = !digitalRead(2);
      if (btnState1 && !flag1 ) {  // обработчик нажатия
        flag1 = true;
        Serial.println("2");
        digitalWrite(10, LOW); digitalWrite(11, HIGH);
        delay(DELAY);
      }
      if (!btnState1 && flag1) {  // обработчик отпускания
        flag1 = false;
        delay(DELAY);
      }

      bool btnState2 = !digitalRead(3);
      if (btnState2 && !flag2 ) {  // обработчик нажатия
        flag2 = true;
        Serial.println("3");
        digitalWrite(10, HIGH); digitalWrite(11, LOW);
        delay(DELAY);
      }
      if (!btnState2 && flag2) {  // обработчик отпускания
        flag2 = false;
        delay(DELAY);
      }

    }
     
     
  11. Airo

    Airo Нерд

     
  12. parovoZZ

    parovoZZ Гуру

    концевыми называют выключатели. Как правило, это аварийный элемент безопасности.

    вполне нормально посадить на таймер контроль срабатывания какого-то датчика. В АСУТП это применяется на каждом шагу.
     
  13. Airo

    Airo Нерд

    Да согласен с вами. Вот только не знаю как это реализовать в виде кода. Пробовал вписывать в if (!btnState1 && flag1 || !btnState2 - mills() >= 5000). Пишу по памяти, но вроде так выглядело.
     
  14. parovoZZ

    parovoZZ Гуру

    завести флаг (у меня это timer), отображающий срабатывание таймера (что означает, что таймер своё оттикал). И далее в коде:
    Код (C++):
    if (btn || timer)
    {
    // code here
    }
     
  15. parovoZZ

    parovoZZ Гуру

    я пользуюсь вот такими обработчиками экземпляра таймера:
    Код (C++):
    static volatile SoftClock_t     SoftTime_System = 0uL;



    void SoftTime_SysTick(uint8_t step_value)
    {
        SoftTime_System += step_value;
    }


    void SoftTimer_Disarm(SoftTimer_t* const SoftTimer)
    {
        SoftTimer->Start = 0;
        SoftTimer->End = 0;
    }

    void SoftTimer_ReSet(SoftTimer_t* const SoftTimer)
    {
        SoftTimer->Start = SoftTime_System;
    }  


    void SoftTimer_Set(SoftTimer_t* const SoftTimer, const SoftClock_t SoftTime)
    {
        SoftTimer_ReSet(SoftTimer);
        SoftTimer->End = SoftTime;
    }


    Bool_t SoftTimer_FreeRun(SoftTimer_t* const SoftTimer, const SoftClock_t SoftTime)
    {
        Bool_t  result = FALSE;
       
        if (SOFTTIMER_ARMED == SoftTimer_Status(SoftTimer))
        {
            if (SOFTTIMER_ARMED == SoftTimer_Expired(SoftTimer))
            {
                SoftTimer_Disarm(SoftTimer);
               
                result = TRUE;
            }
        }
        else
            {
                SoftTimer_Set(SoftTimer, SoftTime);
            }
           
        return result;
    }


    Bool_t SoftTimeDeadCheck(SoftClock_t ti, SoftClock_t td)
    {
        Bool_t  result = FALSE;
       
        if ((SoftTime_System - ti) >= td)
        {
            result = TRUE;  
        }      
       
        return result;
    }


    Bool_t SoftTimer_Expired(SoftTimer_t* const SoftTimer)
    {
        Bool_t  result = FALSE;
       
        if (SOFTTIMER_ARMED == SoftTimer_Status(SoftTimer))
        {
            result = SoftTimeDeadCheck(SoftTimer->Start, SoftTimer->End);
        }
       
        return result;
    }


    Bool_t SoftTimer_Status(SoftTimer_t* const SoftTimer)
    {
        Bool_t  result = FALSE;
       
        result = (SoftTimer->End != 0)? TRUE : FALSE;
       
        return result;
    }
    чтобы накинуть таймер, необходимо вызвать SoftTime_SysTick. Например, в прерывании аппаратного таймера или в любом другом месте. Ну а с остальным всё понятно.
     
  16. User248

    User248 Гик

    Я имел в виду что-то типа такого. Можно попробовать удалить строки с комментарием "сброс таймера, если нужно".
    Код (C++):

    #include <Servo.h>
    Servo servo1;

    #define BUTTON1 2
    #define BUTTON2 3

    #define RELAY1 10
    #define RELAY2 11

    #define SERVO 5

    #define DELAY 50

    #define TIMER 5000

    void setup() {
      Serial.begin(9600);
      pinMode(BUTTON1, INPUT_PULLUP);
      pinMode(BUTTON2, INPUT_PULLUP);
      servo1.attach(SERVO);
      pinMode(RELAY1, OUTPUT);
      digitalWrite(RELAY1, LOW);
      pinMode(RELAY2, OUTPUT);
      digitalWrite(RELAY2, LOW);

    }

    bool flag1 = false;
    bool flag2 = false;

    void loop() {
      servo1.write(random(10, 80));
      //Serial.println("servo");
      delay(1000);
      servo1.write(random(81, 150));
      //Serial.println("SERVO");
      delay(1000);

      yield();
    }

    void button1()
    {
      digitalWrite(RELAY1, LOW);
      digitalWrite(RELAY2, HIGH);
    }

    void button2()
    {
      digitalWrite(RELAY1, HIGH);
      digitalWrite(RELAY2, LOW);
    }

    void yield() {

      // button 1 action

      static uint32_t timer1 = millis();
      if (uint32_t(millis() - timer1) > TIMER)
      {
        timer1 = millis(); // сброс таймера, если нужно
        button1();
      }

      bool btnState1 = !digitalRead(BUTTON1);
      if (btnState1 && !flag1 ) {  // обработчик нажатия
        flag1 = true;
        Serial.println("BUTTON1");
        timer1 = millis(); // сброс таймера
        button1();
        delay(DELAY);
      }
      if (!btnState1 && flag1) {  // обработчик отпускания
        flag1 = false;
        delay(DELAY);
      }

      // button 2 action

      static uint32_t timer2 = millis();
      if (uint32_t(millis() - timer2) > TIMER)
      {
        timer2 = millis(); // сброс таймера, если нужно
        button2();
      }

      bool btnState2 = !digitalRead(BUTTON2);
      if (btnState2 && !flag2 ) {  // обработчик нажатия
        flag2 = true;
        Serial.println("BUTTON2");
        timer2 = millis(); // сброс таймера
        button2();
        delay(DELAY);
      }
      if (!btnState2 && flag2) {  // обработчик отпускания
        flag2 = false;
        delay(DELAY);
      }

    }
     
     
    Последнее редактирование: 23 янв 2023
  17. Рокки1945

    Рокки1945 Гуру

    а вдруг он встанет на полпути - ничего не забыл?
     
  18. parovoZZ

    parovoZZ Гуру

    Для этого и нужен таймер. Интервал таймера выбран -> цель не достигнута = проблема.
     
  19. Airo

    Airo Нерд

    Я так и делал не получилось. У меня не получалось сбросить его хоть я и писал timer = millis(); но видимо неверно.
     
  20. Airo

    Airo Нерд

    Красивый код, но срабатывание по таймеру не действует, может я что-то не понял в нем конечно. Как я понял в этом участке и происходит работа таймера:
    staticuint32_t timer1 = millis();
    if(uint32_t(millis()- timer1)> TIMER)
    {
    timer1 = millis();// сброс таймера, если нужно
    button1();
    }

    Прошу прощения. Все заработало.