IRremote не реагирует после нескольких нажатий

Arduino_Starter
Offline
Зарегистрирован: 30.11.2019
Здравствуйте!
 
Написал код для управления светодиодной лентой с пульта. Столкнулся с проблемой, после нескольких нажатий на пульте ардуина перестает реагировать на команды с пульта. Добавил кнопку, она работает без проблем, меняет еффекты, но даже после нажатий на кнопку на пульт не реагирует. Подскажите в чем может быть ошибка?
#include "IRremote.h"
#include <WS2812FX.h>
#include <EEPROM.h>

#define IR_RECV_PIN 4
#define LED_PIN 13
#define LED_COUNT 180
#define BUTTON 2

IRrecv irrecv(IR_RECV_PIN);
decode_results results;

WS2812FX ws2812fx = WS2812FX(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

byte ledMode = 1;
int ledColor = 0;

void setup() {
  EEPROM.get(0,ledMode); 
  
  ws2812fx.init();
  ws2812fx.setBrightness(30);
  ws2812fx.setSpeed(1000);
  ws2812fx.setColor(0xFFFFFF);
  ws2812fx.setMode(ledMode);
  ws2812fx.start();

  irrecv.enableIRIn();

  pinMode(2,INPUT_PULLUP);
  attachInterrupt (digitalPinToInterrupt (BUTTON), btnChangeEffect, CHANGE);
}

void loop() {
  if (irrecv.decode(&results)) {
    switch (results.value) {
      case 0xFFA25D: //---------------------------------------- Key 1
        break;
      case 0xFF629D: //---------------------------------------- Key 2
        break;
      case 0xFFE21D: //---------------------------------------- Key 3
        break;
      case 0xFF22DD: //---------------------------------------- Key 4
        break;
      case 0xFF02FD: //---------------------------------------- Key 5
        break;
      case 0xFFC23D: //---------------------------------------- Key 6
        break;
      case 0xFFE01F: //---------------------------------------- Key 7       Speed -
        if (ws2812fx.getSpeed() <= 0) {ws2812fx.setSpeed(1);}
        else {ws2812fx.setSpeed(ws2812fx.getSpeed() * 0.8);}
        break;
      case 0xFFA857: //---------------------------------------- Key 8
        break;
      case 0xFF906F: //---------------------------------------- Key 9       Speed +
        if (ws2812fx.getSpeed() >= 54600) {ws2812fx.setSpeed(65535);}
        else {ws2812fx.setSpeed(ws2812fx.getSpeed() * 1.2);}
        break;
      case 0xFF9867: //---------------------------------------- Key 0
        break;
      case 0xFF6897: //---------------------------------------- Key *       Brightness -
        if (ws2812fx.getBrightness() <= 25) {ws2812fx.setBrightness(1);}
        else {ws2812fx.decreaseBrightness(25);}
        break;
      case 0xFFB04F: //---------------------------------------- Key #       Brightness +
        if (ws2812fx.getBrightness() >= 230) {ws2812fx.setBrightness(255);}
        else {ws2812fx.increaseBrightness(25);}
        break;
      case 0xFF18E7: //---------------------------------------- Key Up      Color +
        ledColor += 10;
        if (ledColor > 768) {ledColor = 0;}
        changeColor(ledColor);
        break;
      case 0xFF4AB5: //---------------------------------------- Key Down    Color -
        ledColor -= 10;
        if (ledColor <= 10) {ledColor = 768;}
        changeColor(ledColor);
        break;
      case 0xFF10EF: //---------------------------------------- Key Left    Prev effect
        ledMode--;
        if (ledMode < 1) {ledMode = 55;}
        EEPROM.put(0, ledMode);
        ws2812fx.setMode(ledMode);
        break;
      case 0xFF5AA5: //---------------------------------------- Key Right   Next effect
        ledMode++;
        if (ledMode > 55) {ledMode = 1;}
        EEPROM.put(0, ledMode);
        ws2812fx.setMode(ledMode);
        break;
      case 0xFF38C7: //---------------------------------------- Key Ok
        break;
    }
    irrecv.resume(); // Receive the next value
  }
  ws2812fx.service();
}

void btnChangeEffect() {
  if (digitalRead (BUTTON) == HIGH) {
    ledMode++;
    if(ledMode>55) {ledMode=1;}
    EEPROM.put(0, ledMode);
    ws2812fx.setMode(ledMode);
  //  asm volatile ("  jmp 0");
  }
}

void changeColor(int color) {
  uint8_t redIntensity;
  uint8_t greenIntensity;
  uint8_t blueIntensity;

  if (color > 0 && color < 768) {
    if (color <= 255) {
      redIntensity = 255 - color;
      greenIntensity = color;
      blueIntensity = 0;
    }
    else if (color <= 511) {
      redIntensity = 0;
      greenIntensity = 255 - (color - 256);
      blueIntensity = (color - 256);
    }
    else {
      redIntensity = (color - 512);
      greenIntensity = 0;
      blueIntensity = 255 - (color - 512);
    }
  }
  else {
    redIntensity = 255;
    greenIntensity = 255;
    blueIntensity = 255;
  }
  ws2812fx.setColor(redIntensity, greenIntensity, blueIntensity);
}

 

 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018
sadman41
Offline
Зарегистрирован: 19.10.2016

Ошибка, скорее всего, в неправильном алгоритме. Например, функция на строке 96 слишком часто вызывается.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Давайте, я Вам расскажу несколько общих соображений, которые, возможно и не имеют отношения к Вашему конкретному случаю, но, на мой взгляд, небесполезны.

Вы используете вместе библиотеки IRremore и Adafruit_NeoPixel, которые очень плохо дружат между собой. Не то, чтобы их невозможно заставить работать вместе, но это не всегда просто и часто – глюкаво. Дело в том, что обе заточены на точные тайминги. Посмотрите, что делается в самом начале функции Adafruit_NeoPixel::show(void). Одна из первых строк там - noInterrupts(); и далее идёт достаточно длительный отрезок работы с запрещёнными прерываниями (длительность пропорциональна длине ленты). Всё это время IRremore будет тщетно ожидать прерывания, на которое он заточен и это запросто может нарушить его работу.

Я бы на Вашем месте не дожимал этот код, а … ну не знаю, например, вынес бы работу с IR на самостоятельный контроллер (на тиньку типа) и сообщал бы основному контроллеру о готовых командах по мере их прихода. Ну, или наоборот, вынес бы обслуживание ленты на отдельный контроллер. В общем, я бы их разнёс. Adafruit_NeoPixel (особенно при длинных лентах) – огромная нагрузка на контроллер.

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

я когда споткнулся на конфликте IRremote с другими библиотеками, использующими тот же таймер, что и IRremote - залил IRremote в атмегу8(самое доступное, что у меня под рукой было) и передавал код с м8 на основной контроллер по сериалу.

эту архитектуру повторил ещё один форумчанин - сделал контроллер кондиционера. всё очень стабильно работало.

но... если вспомнить, что сериал в дуино занят для заливки и отладки, то фиг его знает - как извращаться.

sadman41
Offline
Зарегистрирован: 19.10.2016

Если пользователь светоинсталляции не пчела, то достаточно просто реже выводить на ленту. Тогда резко снижается вероятность наступления любой широкораспространенной "светодиодной" библиотекой на хвост Irremote.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Клапауций 003 пишет:
конфликте IRremote с другими библиотеками, использующими тот же таймер
Здесь нет такой проблемы, я проверил.

Arduino_Starter
Offline
Зарегистрирован: 30.11.2019

Спасибо всем за ответы. Попробую выводить реже, если не поможет придумаю что то другое.

BOOM пишет:

А где default?

http://arduino.ru/Reference/SwitchCase

насколько я знаю то default не обязателен

 

sadman41 пишет:
Ошибка, скорее всего, в неправильном алгоритме. Например, функция на строке 96 слишком часто вызывается.

в описании к библиотеке в примерах она постоянно в лупе

https://github.com/kitesurfer1404/WS2812FX/blob/master/extras/WS2812FX%20Users%20Guide.md

 

 

У меня скетч сейчас занимает почти всю память в nano и не могу добавить Serial чтоб в мониторе порта посмотреть что происходит. Попробую убрать библиотеку IRemote и Bluetooth модуль HC-06 вместо пульта добавить, но не уверен хватит ли места . Подскажите возможно есть альтернатива Serial менее прожорливая?

 

Arduino_Starter
Offline
Зарегистрирован: 30.11.2019

Нашел вот такую штуку https://github.com/AlexGyver/GyverCore

там указано Добавлен очень быстрый и лёгкий uart (аналог классу Serial)

Но почитав здесь отзывы по поводу AlexGyver, боюсь чтобы не сделать еще хуже))

sadman41
Offline
Зарегистрирован: 19.10.2016

Arduino_Starter пишет:

sadman41 пишет:
Ошибка, скорее всего, в неправильном алгоритме. Например, функция на строке 96 слишком часто вызывается.

в описании к библиотеке в примерах она постоянно в лупе

На то он и пример, чтобы просто показать общий принцип. В этом примере вообще ничего кроме функций библиотеки не дёргается в лупе.