Как можно при нажатии на кнопку отображать ее имя

Мне нужно распознавать сигнал от ИК-пульта, а не использовать библиотеку для работы с ИК-пультами/приемниками. Как можно при нажатии на кнопку отображать ее имя. У меня есть микроконтроллер PIC12F615 с этим кодом: code и к нему подключено 5 кнопок и мне нужно распознать какая кнопка нажата. У меня есть код, но он дает разные шестнадцатеричные коды, если я нажимаю одну и ту же кнопку.

byte IRpin = 2;

volatile boolean remote = false;
volatile unsigned long irCode = 0;

void remoting ()
{
  if ( remote )
  {
    remote = false;
    unsigned long T;
    for ( byte n = 0; n < 32; n ++ )
    {
      do
      {
        T = pulseIn ( IRpin, HIGH, 2200 );
      }
      while ( T < 64 );
      bitWrite ( irCode, n, T > 1120 );
    }
  }
}

void setup ()
{
  Serial.begin ( 9600 );
  Serial.println ( "\n\tReady for keyboard reading!\n" );
  pinMode ( IRpin, INPUT_PULLUP );
  attachInterrupt ( digitalPinToInterrupt ( IRpin ), remoting, FALLING );
}

void loop ()
{
  if (irCode)
  {
    Serial.println (irCode, HEX);
    irCode = 0;
  }
  delay (40);
  remote = true;
}

Схема:

, 👍1

Обсуждение

пульт дистанционного управления может выводить изменяющийся код, @jsotola

и как мне сделать так чтобы при нажатии на кнопку отображалось ее название, @Good York

пожалуйста, не задавайте вопрос в комментарии ... отредактируйте свой пост и добавьте свой вопрос, @jsotola

У вас есть PIC12F615, как в вашем вопросе, или Uno, как в тегах и на схеме?, @Nick Gammon

Похоже, вы используете pulseIn() в процедуре обслуживания прерывания для того же вывода, который используется для инициирования прерывания. Это конечно странно. pulseIn() может быть ненадежным в ISR, и вам в любом случае не следует блокировать ISR. Это, безусловно, новое решение — попытаться интерпретировать протокол NEC IR, сгенерированный этим PIC., @6v6gt

Работает ли Arduino или PIC (или оба) на симуляторе?, @6v6gt

Оба работают на симуляторе, @Good York

Этот симулятор работает в реальном времени? Если нет, есть ли способ проверить, что все моделируемые объекты работают в одной и той же временной области, скажем, путем попытки (быстрой) последовательной связи между ними?, @6v6gt

работаю в протеусе, @Good York

В Proteus есть логический анализатор. Подключите его к контакту 5 PIC и одновременно к контакту 2 Arduino. Добавьте примеры трассировок и соответствующие выходные данные последовательной консоли arduino к исходному вопросу. Это должно помочь выяснить, является ли это проблемой PIC, Proteus или Arduino., @6v6gt

Я использовал осциллограф [ссылка](https://imgur.com/t7bStKQ), желтый контакт 5, синий контакт 2, @Good York


1 ответ


Лучший ответ:

1

Функция pulseIn() имеет следующий комментарий в исходном коде: "Эта функция лучше работает с короткими импульсами в контексте noInterrupt()" см.: https://github.com/arduino/ArduinoCore-avr/blob/ master/cores/arduino/wiring_pulse.c. Неясно, нарушает ли ваш код "короткий импульс" правило, однако, блокирование процедуры обслуживания прерывания (в вашем случае, процедуры обратного вызова внешнего прерывания remoting() ) для всей длины потока данных IR наверняка вызовет другие проблемы, например, с таймером millis().

Это соответствует стилю вашего кода, но не использует прерывания. Он был протестирован с пультом дистанционного управления NEC и дает воспроизводимые результаты. Ваш код не прошел тот же тест.

byte IRpin = 2;

unsigned long irCode = 0;

void setup ()
{
  Serial.begin ( 9600 );
  Serial.println ( "\n\tReady for keyboard reading!\n" );
  pinMode ( IRpin, INPUT_PULLUP );
}

void loop () {
  while ( digitalRead ( IRpin ) );  // ждем начала первого импульса
  unsigned long T;
  uint8_t validPulses = 0 ;
  for ( byte n = 0; n < 36 ; n ++ ) // достаточно, чтобы удалить длинный заголовок
  {
    T = pulseIn ( IRpin, HIGH , 12000 );  // тайм-аут 12 мс
    if ( T < 4000 && T > 400 && validPulses < 32 ) {
      // действительный импульс
      bitWrite ( irCode, validPulses++, T > 1120 );
    }
  }
  if (irCode > 0 ) Serial.println (irCode, HEX);
  else Serial.println ("no code");
  irCode = 0 ;
}

,

можно ли это сделать через прерывание по пину или прерывание по таймеру?, @Good York

@GoodYork Действительно есть, и я бы порекомендовал в вашем случае использовать режим захвата ввода Таймера 1. Это было бы неблокирующим, если бы все было сделано осторожно. Есть ли в этом упражнении какие-либо другие ограничения, например, какой вывод использовать или что использование pulseIn() является обязательным? Если это так, добавьте все это в свой исходный вопрос. В любом случае, с тем, что у вас есть, вы сможете проверить, работает ли PIC., @6v6gt

Задача: При написании программы НЕ допускается использование библиотек для работы с ИК-пультами/приемниками. Сигнал от приемника должен обрабатываться с помощью внешнего прерывания. Ваш код работает, вот у меня есть код, который работает через таймер 1, но это не работает, @Good York