Точный контроль включения/выключения ИК-светодиода

ir

Моя цель — иметь возможность отправлять/получать IR-сообщения в моем собственном формате и отправлять сообщения длиной ~10 байт. Мой объект сообщения будет сериализован до отдельных битов, которые передаются путем включения/выключения ИК-светодиода в определенные моменты времени по моему выбору для представления логических единиц и нулей. Судя по тому, что я видел, ИК-светодиод можно включать/выключать либо в цикле while, либо в качестве сигнала ШИМ для передачи сообщения. Я предполагаю, что единственное, что можно получить при использовании ШИМ-сигнала, это то, что работа там выполняется по обратному вызову таймера и позволяет другому коду выполняться одновременно. Для простоты я выбрал подход цикла while .

Проблема, которую я вижу, — одна из двух. Либо приемник неправильно считывает тайминги, либо передатчик не включает/выключает светодиод так быстро, как я ожидал.

В приведенном ниже примере кода ИК-светодиод включается на 600 микросекунд и выключается на 300 микросекунд. (В конечном итоге мои пользовательские сообщения будут построены с использованием чего-то подобного.) Однако, как вы можете видеть в примере Выходы ниже приемника не видят ИК-сигнал включенным или выключенным в течение какого-либо периода времени.

Не уверен, проблема ли это в настройке или в чем-то другом. Две платы Arduino, которые я использую, являются платами Arduino Pro ATmega328p. Для платы, отправляющей ИК-сигнал, контакт 6 подключается к резистору сопротивлением 330 Ом, затем к светодиоду, а затем к земле. ИК-приемник на другой плате не имеет резисторов, только прямое подключение к контактам. При считывании ИК-сигналов я держу приёмник на расстоянии нескольких сантиметров от светодиода.

Мои вопросы:

  1. Это жизнеспособная установка? Должно ли это работать? Или я ошибаюсь в своих предположениях и нужно искать другой способ сделать это?
  2. Правильно ли мое предположение о включении/выключении светодиода с помощью цикла while по сравнению с сигналом ШИМ? Или мне следует отказаться от концепции контура и использовать только ШИМ-сигнал.

Код ИК-передачи:

#define IRpin          6

void setup() {
  pinMode(IRpin, OUTPUT);
}

void loop() {
  //Светодиод включен
  PORTD |= (1 << IRpin);
  delayMicroseconds(600);

  //Светодиод выключен
  PORTD &= ~(1 << IRpin);
  delayMicroseconds(300);
}

Код IR-приема (взято из онлайн-примера, внесены только изменения для вывода текста):

#define IRpin_PIN      PIND
#define IRpin          2

// максимальный импульс, который мы будем слушать - 65 миллисекунд - это большой срок
#define MAXPULSE 65000
#define RESOLUTION 20

uint16_t pulses[300][2];  // пара — высокий и низкий импульс
uint8_t currentpulse = 0; // индекс импульсов, которые мы сохраняем

void setup(void) {
  Serial.begin(9600);
  Serial.println("Ready to decode IR!");
}

void loop(void) {
  uint16_t highpulse, lowpulse;  // время временного хранения
  highpulse = lowpulse = 0; // начинаем без длины импульса

  while (IRpin_PIN & (1 << IRpin)) {
    // отсчитываем еще несколько микросекунд
    highpulse++;
    delayMicroseconds(RESOLUTION);

    // Если импульс слишком длинный, у нас «тайм-аут» — либо ничего
    // был получен или код завершен, поэтому выведите то, что
    // мы уже захватили, а затем сбросили
    if ((highpulse >= MAXPULSE) && (currentpulse != 0)) {
      printpulses();
      currentpulse = 0;
      return;
    }
  }
  // время ожидания не истекло, поэтому давайте сохраним показания
  pulses[currentpulse][0] = highpulse;

  // то же, что и выше
  while (! (IRpin_PIN & _BV(IRpin))) {
    // вывод все еще НИЗКИЙ
    lowpulse++;
    delayMicroseconds(RESOLUTION);
    if ((lowpulse >= MAXPULSE)  && (currentpulse != 0)) {
      Serial.println("Breaking - Hit max Pulse Low");
      printpulses();
      currentpulse = 0;
      return;
    }
  }
  pulses[currentpulse][1] = lowpulse;

  // мы успешно читаем один высокий-низкий импульс, продолжаем!
  currentpulse++;
}

void printpulses(void) {
  uint32_t totalMicroseconds = 0;
  for (uint8_t i = 0; i < currentpulse - 1; i++) {
    Serial.print("On(");
    Serial.print(pulses[i][1] * RESOLUTION , DEC);
    Serial.print(");");
    Serial.println("");
    Serial.print("   Off(");
    Serial.print(pulses[i + 1][0] * RESOLUTION , DEC);
    Serial.println(");");

    totalMicroseconds += pulses[i][1] * RESOLUTION;
    totalMicroseconds += pulses[i + 1][0] * RESOLUTION;

    if (i % 8 == 0) {
      Serial.println("");
    }
  }

  Serial.print("On(");
  Serial.print(pulses[currentpulse - 1][1] * RESOLUTION, DEC);
  Serial.print(");");
  totalMicroseconds += pulses[currentpulse - 1][1] * RESOLUTION;

  Serial.println("");
  Serial.print("Total Microseconds: ");
  Serial.println(totalMicroseconds, DEC);
}

Примеры результатов:

Ready to decode IR!
On(20);
   Off(62064);

On(0);
   Off(12060);
On(360);
   Off(1860);
On(440);
   Off(8940);
On(20);
   Off(15460);
On(80);
   Off(25672);
On(40);
Total Microseconds: 127016
On(40);
   Off(6740);

On(300);
   Off(6740);
On(20);
   Off(8520);
On(40);
   Off(6740);
On(1540);
   Off(15720);
On(40);
   Off(34860);
On(20);
Total Microseconds: 81320

On(3000);
   Off(35384);

On(40);
   Off(14180);
On(1220);
   Off(54440);
On(980);
Total Microseconds: 109244

On(200);
Total Microseconds: 200
On(20);
   Off(29160);

On(60);
   Off(26700);
On(60);
   Off(22880);
On(20);
   Off(2928);
On(20);
Total Microseconds: 81848

, 👍0

Обсуждение

Я не знаю наверняка, но я предполагаю, что, хотя 65 миллисекунд — это большой срок для микропроцессора, для светодиодного освещения и приема это может быть не так уж много. Например, светодиоду может потребоваться больше времени, чем вы или я думаем, чтобы излучать его на читаемом уровне - я не знаю. Я бы, по крайней мере, подумал о том, чтобы замедлить процесс на несколько секунд - например, на несколько секунд - и посмотреть, получите ли вы надежную передачу и прием на очень-очень медленных скоростях. Возможно, вам также придется учитывать влияние внешнего света, движение руки и т. д., @mikeY

@mikeY - См. [Какова задержка светодиода?](https://electronics.stackexchange.com/q/86717/64015). В зависимости от типа светодиода: от 2 нс до 1,2 мкс, @Greenonline


1 ответ


0

В конечном итоге я также задал этот вопрос на сайтеelectronics.stackexchange.com. Я знаю, что это не одобряется, но эта тема действительно находится на грани между темой Arduino и электроникой.

Подводя итог принятому ответу, никакие IR-сообщения не могут быть отправлены/получены так, как я думал. ИК-светодиод должен включаться/выключаться на частоте, соответствующей настройке приемника. В общем 38х. Итак, включено на 13 микросекунд, затем выключено на 13 микросекунд. Затем повторите.

https://electronics.stackexchange.com/questions /417387/точное управление включением-выключением для ИК-светодиода/417391

,