Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

Вторая жизнь старых пультов: DIY умные устройства на Arduino

Компоненты и материалы

Arduino Nano R3 1 шт.
Красный светодиод 5 мм 3 шт. (один — индикатор режима, остальные — для идентификации)
Зелёный светодиод 5 мм 1 шт.
Жёлтый светодиод 5 мм 1 шт.
Синий светодиод 2 шт.
Беспаяльная макетная плата (полноразмерная) 1 шт.
Перемычки (набор) 1 шт.
Тумблер (Off)-On, SPST 1 шт.
Модуль питания для макетной платы 5V/3.3V (SparkFun) 1 шт. (опционально)
IR-приёмник (например, KY-022, 37.9 кГц) 1 шт.

О проекте

Проект позволяет применить старые пульты от видеомагнитофонов, телевизоров, DVD-проигрывателей для управления бытовыми приборами: лампами, обогревателями и т.д. через реле или силовые транзисторы. В демонстрационной версии управляются 6 светодиодов, но логику можно расширить на любые нагрузки, управляемые 5-вольтовым сигналом.

Принцип работы

Система «запоминает» 6 ИК-кодов с любого пульта (удобно использовать цифры 1–6). Любая другая кнопка работает как сброс — все выходы гаснут. Коды хранятся в EEPROM Arduino (по 4 байта каждый, всего 24 байта из 1024 доступных), поэтому настройки сохраняются после выключения питания.

Для надёжного приёма сигнала автор наклонил фототранзистор приёмника на ~45° и накрыл его картонным коробом с одним открытым концом — это устранило ложные срабатывания от бокового света и обеспечило уверенный приём на 1.5–2.5 метра.

Режимы работы

Все события дублируются в Serial Monitor — удобно для отладки без запоминания кодов мигания.

Дополнение: управление реле

Автор протестировал схему с 5 реле, параллельно соединёнными со светодиодами 1–5 — все переключали настольную лампу 220 В. Для первых 4 выходов потребовалась инверсия сигнала (логический 0 вместо 1) через схему на CD4011 (четырёхканальный NAND). Внимание: работа с сетевым напряжением опасна!

Код (Arduino IDE)

/* Toggle 6 LEDs using an IR remote — repurposing surplus remotes.
   Learns 6 IR codes in "Learn" mode (toggle switch), saves to EEPROM.
   In "Run" mode toggles 6 outputs. Can drive relays, transistors, etc.
   Paul M Dunphy VE1DX, March 2020 */

#include <IRremote.h>
#include <EEPROM.h>

long unsigned int intIRCode;
long unsigned int savedIRCodes[6];
long unsigned int dupeCheck[6];

const int Recv_Pin = 2;
const int PinOne = 12, PinTwo = 11, PinThree = 10, PinFour = 9, PinFive = 8, PinSix = 7;
const int switchPin = 4;
const int statusPin = 5;
const unsigned long int repeatKeyPress = 0xFFFFFFFF;

boolean learnMode, first_iteration;
int togglestate1=0, togglestate2=0, togglestate3=0, togglestate4=0, togglestate5=0, togglestate6=0;
int current_remote_code;
int remote_code_1, remote_code_2, remote_code_3, remote_code_4, remote_code_5, remote_code_6;

IRrecv irrecv(Recv_Pin);
decode_results results;

// EEPROM helper: write 32-bit long
void EEPROMWritelong(int address, long value) {
  byte four = (value & 0xFF);
  byte three = ((value >> 8) & 0xFF);
  byte two = ((value >> 16) & 0xFF);
  byte one = ((value >> 24) & 0xFF);
  EEPROM.write(address, four);
  EEPROM.write(address + 1, three);
  EEPROM.write(address + 2, two);
  EEPROM.write(address + 3, one);
}

long EEPROMReadlong(long address) {
  long four = EEPROM.read(address);
  long three = EEPROM.read(address + 1);
  long two = EEPROM.read(address + 2);
  long one = EEPROM.read(address + 3);
  return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & repeatKeyPress);
}

int Flip_LED(int led, int toggle_state) {
  if (toggle_state == 0) { digitalWrite(led, HIGH); toggle_state = 1; }
  else { digitalWrite(led, LOW); toggle_state = 0; }
  return toggle_state;
}

void Reset() {
  digitalWrite(PinOne, LOW); digitalWrite(PinTwo, LOW); digitalWrite(PinThree, LOW);
  digitalWrite(PinFour, LOW); digitalWrite(PinFive, LOW); digitalWrite(PinSix, LOW);
  togglestate1 = togglestate2 = togglestate3 = togglestate4 = togglestate5 = togglestate6 = 0;
}

void guessType() {
  Serial.print("Remote appears to be a ");
  switch (results.decode_type) {
    case NEC: Serial.println("NEC"); break;
    case SONY: Serial.println("SONY"); break;
    case RC5: Serial.println("RC5"); break;
    case RC6: Serial.println("RC6"); break;
    case DISH: Serial.println("DISH"); break;
    case SHARP: Serial.println("SHARP"); break;
    case JVC: Serial.println("JVC"); break;
    case SANYO: Serial.println("SANYO"); break;
    case MITSUBISHI: Serial.println("MITSUBISHI"); break;
    case SAMSUNG: Serial.println("SAMSUNG"); break;
    case LG: Serial.println("LG"); break;
    case WHYNTER: Serial.println("WHYNTER"); break;
    case AIWA_RC_T501: Serial.println("AIWA_RC_T501"); break;
    case PANASONIC: Serial.println("PANASONIC"); break;
    case DENON: Serial.println("DENON"); break;
    default: Serial.println("UNKNOWN"); break;
  }
}

int learnCodeRead(int pinCode) {
  if (irrecv.decode(&results)) pinCode = results.value;
  return pinCode;
}

void Confirm() {
  for (int i=0; i<=20; i++) { digitalWrite(statusPin, HIGH); delay(50); digitalWrite(statusPin, LOW); delay(50); }
  digitalWrite(statusPin, HIGH);
}

void learn_Mode() {
  boolean goodCode; int i, j, location = 0;
  int pins[6] = {12,11,10,9,8,7};
  if (first_iteration) { Serial.println(); Serial.println("Entering learn mode"); Serial.println(); }
  intIRCode = 0; goodCode = true; j = 0;
  while (goodCode && j <= 5) {
    for (i=0; i<=25; i++) {
      digitalWrite(pins[j], HIGH); delay(200);
      intIRCode = learnCodeRead(intIRCode);
      digitalWrite(pins[j], LOW); delay(200);
      intIRCode = learnCodeRead(intIRCode);
      goodCode = (intIRCode != repeatKeyPress && intIRCode != 0);
      if (goodCode) i = 30;
      irrecv.resume();
    }
    goodCode = (intIRCode != repeatKeyPress && intIRCode != 0);
    if (goodCode) {
      if (j == 0) guessType();
      Serial.print("Writing to EEPROM Location "); Serial.print(location);
      Serial.print(" IR code = "); Serial.println(intIRCode, HEX);
      EEPROMWritelong(location, intIRCode);
      location += 4; j++; Confirm(); intIRCode = 0; irrecv.resume();
    }
  }
  Serial.println(); Serial.println("Put Arduino back in run mode.");
  while (digitalRead(switchPin) == HIGH) { digitalWrite(statusPin, HIGH); delay(1000); digitalWrite(statusPin, LOW); delay(1000); }
  Serial.println(); Serial.println("Returning to run mode.");
  delay(50); Serial.flush(); delay(50); asm volatile ("jmp 0");
}

void run_Mode() {
  if (first_iteration) Serial.println("Entering run mode");
  if (irrecv.decode(&results)) {
    if (results.value != repeatKeyPress) {
      current_remote_code = results.value;
      Serial.print("Key press detected, IR code = "); Serial.println(current_remote_code, HEX);
      if (current_remote_code == remote_code_1) togglestate1 = Flip_LED(PinOne, togglestate1);
      else if (current_remote_code == remote_code_2) togglestate2 = Flip_LED(PinTwo, togglestate2);
      else if (current_remote_code == remote_code_3) togglestate3 = Flip_LED(PinThree, togglestate3);
      else if (current_remote_code == remote_code_4) togglestate4 = Flip_LED(PinFour, togglestate4);
      else if (current_remote_code == remote_code_5) togglestate5 = Flip_LED(PinFive, togglestate5);
      else if (current_remote_code == remote_code_6) togglestate6 = Flip_LED(PinSix, togglestate6);
      else Reset();
    }
    delay(500); irrecv.resume();
  }
}

void setup() {
  first_iteration = true;
  Serial.begin(9600);
  irrecv.enableIRIn();
  pinMode(PinOne, OUTPUT); pinMode(PinTwo, OUTPUT); pinMode(PinThree, OUTPUT);
  pinMode(PinFour, OUTPUT); pinMode(PinFive, OUTPUT); pinMode(PinSix, OUTPUT);
  Reset();
  pinMode(statusPin, OUTPUT); pinMode(switchPin, INPUT);

  // Проверка "сырого" EEPROM (0xFFFFFFFF) — подмена на коды Sony RM-YD104
  boolean defaultToSony = false;
  long unsigned int IRCode = 0; int location = 0;
  for (int i=0; i<=5; i++) { IRCode = EEPROMReadlong(location); if (IRCode == repeatKeyPress) defaultToSony = true; location += 4; }
  if (defaultToSony) {
    Serial.println("HEX FFFFFFFF found in EEPROM. Setting codes for Sony RM-YD104 remote.");
    EEPROMWritelong(0, 0x10); delay(50);
    EEPROMWritelong(4, 0x810); delay(50);
    EEPROMWritelong(8, 0x410); delay(50);
    EEPROMWritelong(12, 0xC10); delay(50);
    EEPROMWritelong(16, 0x210); delay(50);
    EEPROMWritelong(20, 0xA10); delay(50);
  }

  // Чтение сохранённых кодов
  Serial.println(); Serial.println("Reading stored IR remote codes ...");
  location = 0;
  for (int j=0; j<=5; j++) {
    savedIRCodes[j] = EEPROMReadlong(location);
    Serial.print("Location "); Serial.print(location); Serial.print(" = "); Serial.println(savedIRCodes[j], HEX);
    location += 4; dupeCheck[j] = savedIRCodes[j];
  }
  // Проверка на дубликаты (последовательные)
  for (int i=0; i<5; i++) for (int j=i+1; j<6; j++)
    if (dupeCheck[i] == dupeCheck[j]) {
      Serial.println("Duplicate codes found. Suggest re-running learn mode");
      for (int k=0; k<=5; k++) {
        digitalWrite(pins[i], HIGH); digitalWrite(pins[j], HIGH); delay(1000);
        digitalWrite(pins[i], LOW); digitalWrite(pins[j], LOW); delay(1000);
      }
    }
  remote_code_1 = savedIRCodes[0]; remote_code_2 = savedIRCodes[1];
  remote_code_3 = savedIRCodes[2]; remote_code_4 = savedIRCodes[3];
  remote_code_5 = savedIRCodes[4]; remote_code_6 = savedIRCodes[5];
  delay(1000); Serial.println("Stored codes read."); Serial.println();
}

void loop() {
  learnMode = (digitalRead(switchPin) == HIGH);
  if (learnMode) { first_iteration = true; Reset(); digitalWrite(statusPin, HIGH); learn_Mode(); Reset(); first_iteration = false; }
  else { digitalWrite(statusPin, LOW); run_Mode(); first_iteration = false; }
}

Схема подключения

См. раздел «Schematics» оригинала: два варианта — с 6 светодиодами через MOSFET и с 5-вольтовым питанием / 3.3-вольтовой логикой.

Производственный процесс

  1. Светодиоды (LED): от зарождения к 100-летнему ресурсу
  2. Удалённый мониторинг погоды на Raspberry Pi 3 с PubNub
  3. Создание профессионального универсального пульта на Raspberry Pi с LIRC
  4. Система удалённого мониторинга сердечного ритма с алертами AWS IoT
  5. Проект Arduino: мелодия Coffin Dance — сборка и воспроизведение вирусного трека
  6. Превращаем старый кнопочный телефон в умный удаленный выключатель
  7. Рисование светом одним светодиодом: построение динамических изображений на DIY-манипуляторе
  8. Звукоактивируемый светодиодный дисплей 8 LED на Arduino
  9. 5 ключевых критериев выбора контроллерной платформы
  10. Безопасная и эффективная утилизация устаревшего промышленного оборудования