@qqqaa

Почему код останавливается и не работает?

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

#include "Adafruit_NeoPixel.h" //подключаем библиотеку для ленты
#include <NecDecoder.h>        //подключаем библиотеку для ИК транзистора

NecDecoder ir;

Adafruit_NeoPixel strip (84, 5, NEO_GRB + NEO_KHZ800);

void setup(){
  strip.begin();     //инициализируем объект NeoPixel
  strip.show();     //отключаем все пиксели на ленте
  strip.setBrightness(50);     //указываем яркость (максимум 255)

  Serial.begin(9600);
  
  attachInterrupt(0, irIsr, FALLING);
}

void irIsr(){
  ir.tick();
}

int mode;

void loop(){
  if(ir.available()){     //проверка "если поступили данные на ИК транзистор"
    mode = ir.readCommand();     //присваиваем значению переменной значение с ИК транзистора
    Serial.println(mode);     //выводим в порт значение с ИК транзистора
  }

  strip.setPixelColor(1, strip.Color(0, 0, 255));     //помечаем 1 пиксел синим цветом
  strip.show();     //подаем сигнал на ленту
}


По идее, в void loop при условии if( ir.available() ) в консоль должна выводиться информация, полученная с пульта. И она выводится каждый раз, когда я нажимаю на кнопку на пульте, но только в том случае, если удалить код ниже, отвечающий за зажигание 1 пикселя на ленте (нужно удалить именно strip.show()). Если же код strip.show() не удалять, программа зависает на strip.show(), и причем ничего не выводит в консоль.
Почему так, и как сделать, чтобы и обрабатывалась информация с датчика, выводилась в консоль, и зажигался светодиод?
  • Вопрос задан
  • 171 просмотр
Пригласить эксперта
Ответы на вопрос 1
TemaSM
@TemaSM
Fullstack, DevOps, InfSec
Проблема заключается в том, что strip.show() является блокирующей функцией, которая отправляет данные на ленту и ждет, пока они будут обработаны. Таким образом, если strip.show() вызывается внутри цикла, он будет блокироваться каждый раз, когда выполняется. Это может привести к блокировке программы и невозможности обработки других событий, таких как чтение данных с ИК-приемника.

Вы можете решить эту проблему, вызывая strip.show() только тогда, когда есть новые данные с пульта. Для этого вы можете привести код к такому виду:
void loop(){
  if(ir.available()){     //проверка "если поступили данные на ИК транзистор"
    mode = ir.readCommand();     //присваиваем значению переменной значение с ИК транзистора
    Serial.println(mode);     //выводим в порт значение с ИК транзистора

    strip.setPixelColor(1, strip.Color(0, 0, 255));     //помечаем 1 пиксел синим цветом
    strip.show();     //подаем сигнал на ленту
  }
}

- strip.show() будет вызываться только тогда, когда поступит новый сигнал с пульта.

Вы также можете изменить функцию irIsr() следующим образом:
void irIsr(){
  ir.tick();
  strip.show();     //подаем сигнал на ленту
}

Также, можно попробовать использовать неблокирующий способ чтения данных с ИК-приемника, чтобы избежать блокировки программы при ожидании данных. Например, можно использовать библиотеку IRremote и метод irrecv.decode() для проверки наличия данных с приемника без блокировки программы.

Если ответ помог или считаете что может быть полезен другим - не забудьте отметить его как решение вашего вопроса. Успехов!
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы