Какие библиотеки для адресной ленты не запрещают прерывания?

i_rick_i

✩✩✩✩✩✩✩
2 Мар 2023
2
0
Есть код для 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(), и причем ничего не выводит в консоль.
Почему так, и как сделать, чтобы и обрабатывалась информация с датчика, выводилась в консоль, и зажигался светодиод?
 

i_rick_i

✩✩✩✩✩✩✩
2 Мар 2023
2
0
Столкнулся с проблемой при написании кода. Проект - адресная лента под управлением ИК пульта. Использую 2 библиотеки - Adafruit_NeoPixel для ленты и NecDecoder для инфракрасного приема. Библиотеки мешают друг-другу, т.к. в NecDecoder используются прерывания для отслеживания ИК сигнала с пина, а Adafruit_NeoPixel во время выполнения своего метода show() на некоторое время запрещает работу с прерываниями (вроде бы для большей точности). Этот запрет очень пагубно влияет на код, причем, до такой степени, что чуть ли не приходится использовать goto.

Подскажите, есть ли библиотеки, которые не перекрывают работу с прерываниями, или как решить эту проблему иначе?
 

Vaqtincha

★✩✩✩✩✩✩
14 Ноя 2022
154
21
Uzbekistan, Fergana
Изменено:

Геннадий П

★★★★★★✩
14 Апр 2021
1,969
632
44
Запрещение прерывания при передаче сделано специально. Для передачи данных на ленту нужны довольно жесткие тайминги, которые нарушаются при любом прерывании.
Как вариант - использовать например ESP32(8266 не подходит), в ней практически на аппаратном уровне реализуется передача данных на адресную ленту, поэтому никакие прерывания не страшны. Но не уверен что это реализовано в ардуиновском ядре.
 

Vaqtincha

★✩✩✩✩✩✩
14 Ноя 2022
154
21
Uzbekistan, Fergana
Это костыль конечно но иначе никак. Не совсем понятно почему люди до сих пор используют ардуино вместо эсп (цена то почти одинаковая)
 

bort707

★★★★★★✩
21 Сен 2020
3,058
910
Этот запрет очень пагубно влияет на код, причем, до такой степени, что чуть ли не приходится использовать goto.
Сдается мне, что вы что-то не так пишете.
Прерывания при выводе на ленту могут мешать приему, но как они влияют на код, вплоть до того чтоб заставить вас использовать goto - это что-то новое.
Покажите свой код

Добавка
Я так понимаю, проблема с кодом описана тут: https://community.alexgyver.ru/threads/pochemu-kod-ostanavlivaetsja-i-ne-rabotaet.8061/
Значит я угадал и проблема вовсе не в прерываниях. Вы просто неправильно пишете программу.
Подробнее описал в той вашей ветке
 
Изменено:

bort707

★★★★★★✩
21 Сен 2020
3,058
910
Почему так, и как сделать, чтобы и обрабатывалась информация с датчика, выводилась в консоль, и зажигался светодиод?
Потому что, похоже, вы не понимаете логику программы.
Функция loop() - это бесконечный цикл, после окончания она исполняется снова и снова.
А теперь посмотрите на свой код - вы снова и снова выводите на ленту один и тот же пиксель. Зачем???
Адресная лента не требует обновления картинки, пока сама картинка не изменилась.
Вы же делаете это сотни раз в секунду. Из-за этого у ИК приемника не остается времени для приема сигнала и ничего не работает.

Обновляйте ленту только тогда, когда вы хотите вывести на нее новую картинку.
Например в вашем коде достаточно вывести пиксель на ленту только один раз, в setup()
 

Сотнег

★★★★★★★
15 Янв 2020
4,366
1,494
@i_rick_i,
или если вы тестированием просто занимаетесь, тогда вставьте в loop()
delay(100);
чтобы дать плате шанс на обработку прерываний и не мучать ленту.
 

Геннадий П

★★★★★★✩
14 Апр 2021
1,969
632
44
Если человек хочет в зависимости от нажатой кнопки менять цвет, то эту обработку нужно делать внутри "if(ir.available()){", а не снаружи чтобы (как выше написали) не делать лишних циклов с выводом данных на ленту.