Управление миганием светодиода через инфракрасный передатчик

Тема в разделе "Arduino & Shields", создана пользователем Denniz, 24 сен 2015.

  1. Denniz

    Denniz Нуб

    Всем добрый вечер!
    При нажатии на кнопку инфракрасного пульта светодиод начинает мигать. Как сделать так, чтобы при повторном нажатии на эту же кнопку пульта светодиод перестал мигать?
    Если кто подскажет, какой цикл лучше использовать или сразу алгоритм опубликует, буду признателен! Спасибо!
     
  2. Salk

    Salk Гик

    Подозреваю что нужно использовать флаг. Некая переменная, которая будет хранить в себе режимы работы светодиода.
    Например:
    int flag;
    if (reseult == код)
    {
    flag += 1; // каждый раз при нажатии кнопки пульта к переменной прибавляется 1
    // определяем кол-во действий, сколько нам нужно повесить на кнопку пульта, и не даём расти переменной до бесконечности
    if (flag == 2)
    {
    flag = 0;
    }
    }
    // далее в цикле
    if (flag == 0)
    {
    делаем одно действие
    }
    if (flag == 1)
    {
    делаем второе действие
    }

    Это работает, если ваш пульт не имеет автоповтора кода, в таким ситуациях у каждой кнопки пульта есть два кода вместо одного, тогда мы просто на каждое действие вешаем по коду.
     
  3. Denniz

    Denniz Нуб

    Спасибо, но думаю, что это немного не то, что мне нужно. Представьте автомобиль, у которого включена аварийка. Также и здесь - нажимаю на кнопку и аварийка мигает, второй раз нажал - все погасло. Если снова нажал на кнопку - опять мигает.
     
  4. Salk

    Salk Гик

    Не понял в чем проблема, вроде предложил код, который подходит под ваше описание. Вы же говорите про пульт и используете библиотеку IRremote? Можете опубликовать код, который сейчас у вас имеется?
     
  5. Denniz

    Denniz Нуб

    Сейчас попробую Вашим методом. А вот мои мысли. Диод после получения команды начинает мигать как надо. При повторном нажатии на кнопку продолжает мигать.
    ...
    boolean d = false;
    ...
    if (results.value == 0xEFA857 && WORK==true){
    d = !d;
    if (d==true) {
    digitalWrite(13, HIGH);
    delay(800);
    digitalWrite(13, LOW);
    delay(500);
    }
    }
     
  6. Salk

    Salk Гик

    Так конечно он у вас продолжит мигать, т.к. вы нигде не запрещаете светодиоду этого не делать. Вы просто меняете состояние d с false на true.
    boolean d = false;
    if (results.value == 0xEFA857 && WORK==true)
    {
    d = !d;
    }
    if (d == true)
    {
    digitalWrite(13, HIGH);
    delay(800);
    digitalWrite(13, LOW);
    delay(500);
    }
    else
    {
    digitalWrite(13, LOW);
    }

    Тоже самое, что я предложил с переменной flag, только с boolean.
     
  7. Denniz

    Denniz Нуб

    Согласен) Однако теперь диод один раз мигнул после получения команды и погас. Второе нажатие на кнопку - никакого результата. еще раз наживаю - опять мигнул и все. Сейчас собрал код воедино со всеми правками. Пока результата нет) Вот код.

    #include <IRremote.h>

    int RECV_PIN = 11;
    IRrecv irrecv(RECV_PIN);
    decode_results results;
    boolean d = false;
    boolean WORK = false;

    void setup()
    {
    irrecv.enableIRIn();
    pinMode(13, OUTPUT);
    pinMode(2, OUTPUT);

    void loop() {
    if (irrecv.decode(&results)) {
    delay(300);

    if (results.value == 0xEFE817) {
    WORK = !WORK;
    digitalWrite(13, HIGH);
    delay(100);
    digitalWrite(13, LOW);
    delay(100);
    digitalWrite(13, HIGH);
    delay(100);
    digitalWrite(13, LOW);
    }


    if (results.value == 0xEFA857 && WORK==true){
    d = !d;
    }
    if (d==true)
    {
    digitalWrite(13, HIGH);
    delay(800);
    digitalWrite(13, LOW);
    delay(500);
    }
    else
    {
    digitalWrite(13, LOW);
    }

    irrecv.resume();
    }
    }
     
  8. Salk

    Salk Гик

    Зачем вам Work? Что она должна делать? Условие проверки d нужно вынести в основной цикл loop вне скобок работы с пультом. Примерно так:
    Код (C++):
    #include <IRremote.h>

    int RECV_PIN = 11;
    IRrecv irrecv(RECV_PIN);
    decode_results results;
    boolean d = false;
    boolean WORK = false;

    void setup()
    {
      irrecv.enableIRIn();
      pinMode(13, OUTPUT);
      pinMode(2, OUTPUT);
    }

    void loop()
    {
      if (irrecv.decode(&results))
      {
        // delay(300); // зачем тут delay ?
        /*
            if (results.value == 0xEFE817)
            {
              WORK = !WORK;
              digitalWrite(13, HIGH);
              delay(100);
              digitalWrite(13, LOW);
              delay(100);
              digitalWrite(13, HIGH);
              delay(100);
              digitalWrite(13, LOW);
            }
        */


        if (results.value == 0xEFA857)
        {
          d = !d;
        }
        irrecv.resume();
      }

      if (d == true)
      {
        digitalWrite(13, HIGH);
        delay(800);
        digitalWrite(13, LOW);
        delay(500);
      }
      else
      {
        digitalWrite(13, LOW);
      }
    }
     
  9. Denniz

    Denniz Нуб

    WORK - переменная, которая как бы "активирует" все остальные кнопки. Пока первую кнопку не нажали (сигнализацию автомобиля не убрали), остальные кнопки(функции) не работают.
    Поэтому и пытаюсь сделать выполнение отдельных простых функций от каждой кнопки на пульте. Но при этом первая кнопка является как бы "главной".
    delay(300) - от случайного двойного нажатия. Полагаете не нужно?

    Делаю нечто подобное:

     
  10. Salk

    Salk Гик

    С Work понятно, попробуйте сейчас код выше, пока без активации, работает как надо? Потом добавите Work.
    Насчет задержки, смотрите сами, но от delay лучше отказаться, т.к. она тормозит весь процесс исполнения кода, замените его millis(). Что-то вроде - нажали на кнопку пульта, а действие произошло только спустя 300 мс. Хотя задержка же стоит в работе с пультом ... можно и delay оставить.

    Код (C++):
    #include <IRremote.h>

    int RECV_PIN = 11;
    IRrecv irrecv(RECV_PIN);
    decode_results results;
    boolean d = false;
    boolean WORK = false;

    void setup()
    {
      irrecv.enableIRIn();
      pinMode(13, OUTPUT);
      pinMode(2, OUTPUT);
    }

    void loop()
    {
      if (irrecv.decode(&results))
      {
        // delay(300); // зачем тут delay
        if (results.value == 0xEFE817)
        {
          WORK = !WORK;
          digitalWrite(13, HIGH);
          delay(100);
          digitalWrite(13, LOW);
          delay(100);
          digitalWrite(13, HIGH);
          delay(100);
          digitalWrite(13, LOW);
        }

        if (results.value == 0xEFA857 && WORK == true)
        {
          d = !d;
        }
        irrecv.resume();
      }

      if (d == true)
      {
        digitalWrite(13, HIGH);
        delay(800);
        digitalWrite(13, LOW);
        delay(500);
      }
      else
      {
        digitalWrite(13, LOW);
      }
    }
     
    Последнее редактирование: 25 сен 2015
  11. Denniz

    Denniz Нуб

    Спасибо огромное, работает. Попытался добавить теперь третью кнопку, которая просто включает габариты. Однако она не работает из-за того, что у нас вынесена проверка d. Вот добавленная кнопка (integer b). Понятно, что при практической работе с 3-й кнопкой 13-й пин будет заменен на другой. Но на данном этапе с учетом одного светодиода эти конфликты убрать возможно?

    if (results.value == 0xEF6897 && WORK==true)
    {
    b=b+1;
    }
    if (b==1)
    {
    digitalWrite(13, HIGH);
    }
    else
    {
    digitalWrite(13, LOW);
    b=0;
    }
     
    Последнее редактирование: 25 сен 2015
  12. Salk

    Salk Гик

    Код (C++):
    #include <IRremote.h>

    int RECV_PIN = 11;
    IRrecv irrecv(RECV_PIN);
    decode_results results;
    boolean d = false;
    boolean WORK = false;
    int b;

    void setup()
    {
      irrecv.enableIRIn();
      pinMode(13, OUTPUT);
      pinMode(2, OUTPUT);
    }

    void loop()
    {
      if (irrecv.decode(&results))
      {
        // delay(300); // зачем тут delay
        if (results.value == 0xEFE817)
        {
          WORK = !WORK;
          digitalWrite(13, HIGH);
          delay(100);
          digitalWrite(13, LOW);
          delay(100);
          digitalWrite(13, HIGH);
          delay(100);
          digitalWrite(13, LOW);
        }

        if (results.value == 0xEFA857 && WORK == true)
        {
          d = !d;
        }
        // Третья кнопка
        if (results.value == 0xEF6897 && WORK == true)
        {
          d = false; // Если мы нажали третью кнопку, то запрещаем работу условия d
          b += 1;
          if (b == 2) // сбрасываем b в 0 после третьего нажатия на кнопку
          {
            b = 0;
          }
        }
        irrecv.resume();
      }

      if (d == true)
      {
        b = 0;
        digitalWrite(13, HIGH);
        delay(800);
        digitalWrite(13, LOW);
        delay(500);
      }
      else // иначе
      {
        if (b == 1) // если мы нажали кнопку пульта 1 раз, то постоянно зажигаем светодиод
        {
          digitalWrite(13, HIGH);
        }
        else // светодиод гаснет, если мы нажали повторно третью кнопку пульта
        {
          digitalWrite(13, LOW);
        }
      }
    }
     
    Последнее редактирование: 25 сен 2015
  13. Denniz

    Denniz Нуб

    Да вы маэстро, сударь! Спасибо))
     
  14. Salk

    Salk Гик

    Работает хоть, так как хотелось? :)

    Забыл сбросить b в 0, если мы после постоянно горящего светодиода отключаем все (Work = 0). Должно быть так:
    Код (C++):
    if (d == true)
      {
        b = 0;
        digitalWrite(13, HIGH);
        delay(800);
        digitalWrite(13, LOW);
        delay(500);
      }
      else // иначе
      {
        if (b == 1) // если мы нажали кнопку пульта 1 раз, то постоянно зажигаем светодиод
        {
          digitalWrite(13, HIGH);
        }
        else // светодиод гаснет, если мы нажали повторно третью кнопку пульта
        {
          digitalWrite(13, LOW);
        }
      }
     
    Последнее редактирование: 25 сен 2015
  15. Denniz

    Denniz Нуб

    Работает, но я, как вы понимаете, только в начале пути. По механике вроде пока вопросов нет, только по программированию)
    Если будет у вас время, может закомментируете вот этот код, чтобы по-русски и человеческим языком понять, что натворил тут японец:
    http://yahoo.jp/box/GxDDdY