Освой Arduino играючи

Сайт Александра Климова

Шкодим

/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000

Инфракрасный приёмник и пульт

Управление приборами через инфракрасный пульт дистанционного управления знаком каждому современному человеку - телевизор, музыкальный центр, кондиционер. К этому списку вы можете добавить и свой контроллер и управлять, например, роботом на Arduino.

ИК-датчики

Датчики, которые могут служить в качестве приёмника сигналов.

Инфракрасный пульт дистанционного управления

Скорее всего у вас уже есть инфракрасный пульт дистанционного управления, например, от телевизора, который вы можете использовать в своих опытах. В стартовых наборах для Arduino как правило к ИК-датчику прилагается дополнительно маленький пульт от магнитолы.

IR remote control

Библиотека IRremote

Для работы с инфракрасными датчиками используется популярная библиотека IRremote Arduino Library. Установить её можно через менеджер библиотек.

IRremote library

Библиотека поддерживает стандартные форматы NEC, SIRC, RC5, RC6, а также может принимать "сырые" данные.

После установки библиотеки вам станут доступны несколько примеров, которые можете изучить самостоятельно.

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

Напишем простой скетч, который будет принимать сигналы от пульта и выводить их коды на экран в Serial Monitor.


#include <IRremote.h>

int irPin = 2;

IRrecv irReciver(irPin); // указываем вывод, к которому подключён приёмник

decode_results results;

void setup() {
  Serial.begin(9600);
  irReciver.enableIRIn(); // запускаем приём
}

void loop() {
  if (irReciver.decode(&results)) { // если данные пришли
    Serial.println( results.value, HEX ); // выводим данные
    irReciver.resume(); // принимаем следующую команду
  }
}

Этот пример работает для пульта от магнитолы, который представлен на рисунке. Но вполне возможно, что для какого-то другого пульта этого будет недостаточно, в примерах к библиотеки используется более сложный код, который умеет работать с пультами разных фирм.

Теперь вы можете нажимать кнопки пульта и получать данные. Вам надо обрабатывать получаемые данные и принимать решения, что делать с ними. Например, вы можете включать нужные светодиоды от кнопок 1, 2, 3 и т.д.

Вы будете получать данные в виде шестнадцатеричного значения типа FF02FD. Наверняка, вы будете также получать значения FFFFFFFF, которые означают, что нажатая клавиша удерживается.

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

У меня получились следующие результаты для цифровых кнопок.


0 - FF6897
1 - FF30CF
2 - FF18E7
3 - FF7A85
4 - FF10EF
5 - FF38C7
6 - FF5AA5
7 - FF42BD
8 - FF4AB5
9 - FF52AD

Напишем скетч. Будем выводить названия кнопок на экран, кроме того кнопка 3 будет включать встроенный светодиод, а кнопка 7 его выключать.


#include <IRremote.h>

int irPin = 2;

IRrecv irReciver(irPin); // указываем вывод, к которому подключён приёмник

decode_results results;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(9600);
  irReciver.enableIRIn(); // запускаем приём
}

void loop() {
  if (irReciver.decode(&results)) { // если данные пришли
    decodeIR(); // расшифровываем данные
    irReciver.resume(); // принимаем следующую команду
  }
}

// определяем значение нажатой клавиши
void decodeIR() {
  switch (results.value)
  {
    case 0xFF6897:
      Serial.println("0");
      break;
    case 0xFF30CF:
      Serial.println("1");
      break;
    case 0xFF18E7:
      Serial.println("2");
      break;
    case 0xFF7A85:
      Serial.println("3");
      digitalWrite(LED_BUILTIN, HIGH);
      break;
    case 0xFF10EF:
      Serial.println("4");
      break;
    case 0xFF38C7:
      Serial.println("5");
      break;
    case 0xFF5AA5:
      Serial.println("6");
      break;
    case 0xFF42BD:
      Serial.println("7");
      digitalWrite(LED_BUILTIN, LOW);
      break;
    case 0xFF4AB5:
      Serial.println("8");
      break;
    case 0xFF52AD:
      Serial.println("9");
      break;
  }
}

Более сложный пример, когда определяется стандарт сигнала и сырые данные.


#include <IRremote.h>

IRrecv irrecv(2);
decode_results results;

void dump(decode_results *results) {
  int count = results -> rawlen;
  if (results -> decode_type == UNKNOWN) {
    Serial.println("Could not decode message");
  }
  else {
    if (results -> decode_type == NEC) {
      Serial.print("Decoded NEC: ");
    }
    else if (results->decode_type == SONY) {
      Serial.print("Decoded SONY: ");
    }
    else if (results->decode_type == RC5) {
      Serial.print("Decoded RC5: ");
    }
    else if (results->decode_type == RC6) {
      Serial.print("Decoded RC6: ");
    }
    Serial.print(results->value, HEX);
    Serial.print(" (");
    Serial.print(results->bits, DEC);
    Serial.println(" bits)");
  }
  Serial.print("Raw(");
  Serial.print(count, DEC);
  Serial.print("):");
  for (int i = 0; i < count; i++) {
    if ((i % 2) == 1) {
      Serial.print(results->rawbuf[i]*USECPERTICK, DEC);
    }
    else {
      Serial.print(-(int)results->rawbuf[i]*USECPERTICK, DEC);
    }
    Serial.print(" ");
  }
  Serial.println("");
}

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

}

int on = 0;
unsigned long last = millis();

void loop() {
  if (irrecv.decode(&results))
  {
    // If it's been at least 1/4 second since the last
    // IR received, toggle the relay
    if (millis() - last > 250)
    {
      on = !on;
      // digitalWrite(8, on ? HIGH : LOW);
      digitalWrite(13, on ? HIGH : LOW);
      dump(&results);
    }

    last = millis();
    irrecv.resume(); // Receive the next value
  }
}
Реклама