arduino + IR пульт

vova20081
Offline
Зарегистрирован: 08.08.2015

Уважаемые коллеги подскажите пожалуйста! Есть ардуино, IR пульт, лента ws2812.

Пультом переключаю эффекты.  Если нажата одна кнопка (на пульте) переходим к эффекту номер 1, если другая к эффекту номер 2 и т.д.

ВОПРОС как добиться переключения на другой эффект (пультом) не дожидаясь окончания того эффекта который сейчас крутится. (если кнопка на пульте не нажата эффект бесконечен(например перелив)).

evgta
Offline
Зарегистрирован: 02.09.2016

vova20081 пишет:

Уважаемые коллеги подскажите пожалуйста! Есть ардуино, IR пульт, лента ws2812.

Пультом переключаю эффекты.  Если нажата одна кнопка (на пульте) переходим к эффекту номер 1, если другая к эффекту номер 2 и т.д.

ВОПРОС как добиться переключения на другой эффект (пультом) не дожидаясь окончания того эффекта который сейчас крутится. (если кнопка на пульте не нажата эффект бесконечен(например перелив)).

 

Прерыванием

http://arduino.ru/Reference/AttachInterrupt

 

ну или в цикле постоянно вставляя строку опроса кнопки с таймингом не меньше 0,2 секунды иначе будет неудобно кнопки давить, но такое решения вообще не айс, и применяется только когда ноги прерываний заняты

 

vova20081
Offline
Зарегистрирован: 08.08.2015

Спасибо. Но тогда возникает другой вопрос. Если использовать аппаратные прерывания - где брать управляющий сигнал (для срабатыван ия прерывания)?  Или нужно прерывание по таймеру?

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

Может, хоть скетч покажете? А то ведь там и от него много зависит.

vova20081
Offline
Зарегистрирован: 08.08.2015
код простой. Объеденены два кода IRremote и NeoPixel ( это пока проба)

void loop() 
  {

  if (irrecv.decode(&results)) // Если поступил ИК сигнал.
    {
      if (results.value == 3953409587) // Если поступил (ИК) код 3251046137.
        {
        colorWipe(strip.Color(255, 0, 0), 20); // Red
        }
      if (results.value == 1763856455) // если поступил (ИК)
        {
        colorWipe(strip.Color(0, 255, 0), 20); // Green
        }
     if (results.value == 1962381255) // Иначе если поступил (ИК) 
        {
         rainbow(20);
        }
     if (results.value == 2086802078) // Иначе если поступил (ИК) .
        {
        rainbowCycle(20);
        }                   
      irrecv.resume();
    } 


  }


void colorWipe(uint32_t c, uint8_t wait) 
  {
 ....
  }

void rainbow(uint8_t wait) 
{
  ......
}


void  rainbowCycle(uint8_t wait) 
{
  ......
}

 

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

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

Вот, смотрите, пришла команда запустить эффект, например rainbow. Вот он запустился в строке 18. Теперь вопрос:

1) функция rainbow будет работать пока эффект не кончится? И только потом программа перейдёт к строке 19? Или
2) функция rainbow асинхронная - она запускает эффект, а основная программа спокойно продолжается дальше.

От это собственно и зависит что Вам делать. Если (1), то чтение новой команды надо вставлять в функции эффектов, т.к. строка 6 не выплнится пока эффект не закончится. А если (2), то надо научиться просто прерывать эффект.

Понимаете?

По той информации, что Вы дали ничего не скажешь. 

vova20081
Offline
Зарегистрирован: 08.08.2015

Вообщето 1. Я просто 2 не умею. Подскажите где почитать или пример посмотреть

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

Ну, Вы хоть текст-то дайте полный, сколько просить-то можно?

vova20081
Offline
Зарегистрирован: 08.08.2015
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif
#include <IRremote.h>

int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;
#define PIN 7

Adafruit_NeoPixel strip = Adafruit_NeoPixel(30, PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  #if defined (__AVR_ATtiny85__)
  if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
  #endif
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
  irrecv.enableIRIn();
}


void loop() 
  {

  if (irrecv.decode(&results)) // Если поступил ИК сигнал.
    {
      if (results.value == 3953409587) // Если поступил (ИК) 
        {
        colorWipe(strip.Color(255, 0, 0), 20); // Red
        }
      if (results.value == 1763856455) // если поступил (ИК)
        {
        colorWipe(strip.Color(0, 255, 0), 20); // Green
        }
     if (results.value == 1962381255) // если поступил (ИК) 
        {
         rainbow(20);
        }
     if (results.value == 2086802078) // Иначе если поступил (ИК) .
        {
        rainbowCycle(20);
        }                   
      irrecv.resume();
    } 

  }



 


void colorWipe(uint32_t c, uint8_t wait) 
  {
  for(uint16_t i=0; i<strip.numPixels(); i++) 
    {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
    }
  }

void rainbow(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256; j++) {
    for(i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i+j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

void rainbowCycle(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

 

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

Что за функция Wheel в строках 70 и 82? Где она определена?

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

Я нашёл функцию Wheel в примере библиотеки.

В связи с этим у меня вопрос: Вы специально надо мною издеваетесь? Я Вас дважды просил привести полный скетч, Вы привели, но опять неполный

А теперь смотрите. Я реально хотел Вам помочь. Но чтобы привести кусок кода надо, чтобы он хотя бы компилировался. Ради этого я:
1) скачал и поставил библиотеку (у меня её не было)
2) завел проект для Ваше скетча

и ... убедился, что он не компилируется из-за того, что Вы дали его неполным! Т.е. моё время ушло в трубу просто потому,  Вы либо не понимаете значения слова "полный", оибо Вам лень продвинуть мыша на несколько строк при копировании, либо ... Вы просто издеваетесь.

Скажите, кому нужно решить Вашу проблему мне или Вам? Подсказка: мне нахрен не нужно. Так какого же ... Вы специально создаёте мне в этом трудности? Ну, когда дважды попросил дать полный код, можно же было и дать!

Так Вам нужно решение Вашей проблемы или Вы просто подразнить тут всех зашли?

vova20081
Offline
Зарегистрирован: 08.08.2015

Дико ПРОШУ ПРОЩЕНИЯ !!!

не скопировалась последняя фунция

вот полный код

все проверил - компилируется

еще раз извиняюсь!!!

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif
#include <IRremote.h>

int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;
#define PIN 7

Adafruit_NeoPixel strip = Adafruit_NeoPixel(30, PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  #if defined (__AVR_ATtiny85__)
  if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
  #endif
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
  irrecv.enableIRIn();
}

void loop() 
  {

  if (irrecv.decode(&results)) // Если поступил ИК сигнал.
    {
      if (results.value == 3953409587) // Если поступил (ИК) код 3251046137.
        {
        colorWipe(strip.Color(255, 0, 0), 20); // Red
        }
      if (results.value == 1763856455) // если поступил (ИК)
        {
        colorWipe(strip.Color(0, 255, 0), 20); // Green
        }
     if (results.value == 1962381255) // Иначе если поступил (ИК) 
        {
         rainbow(20);
        }
     if (results.value == 2086802078) // Иначе если поступил (ИК) .
        {
        rainbowCycle(20);
        }                   
      irrecv.resume();
    } 

  }

void colorWipe(uint32_t c, uint8_t wait) 
  {
  for(uint16_t i=0; i<strip.numPixels(); i++) 
    {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
    }
  }

void rainbow(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256; j++) {
    for(i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i+j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

void rainbowCycle(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

 

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

Попрбоуйте вот так. Только никому не говорите, что это я писал. Написано, чтобы минимизировать изменения в Вашем коде, сам бы я писал совсем по-другому. Везде, где я менял что-то я вставил комментарий /*!*/ - разбирайтесь.

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif
#include <IRremote.h>

int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;
#define PIN 7

Adafruit_NeoPixel strip = Adafruit_NeoPixel(30, PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  #if defined (__AVR_ATtiny85__)
  if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
  #endif
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
  irrecv.enableIRIn();
}

/*!*/
/*!*/static bool weGotSignal = false;
/*!*/bool decodeSignal(void) {
/*!*/	if (!weGotSignal) {
/*!*/		weGotSignal = irrecv.decode(&results);
/*!*/		irrecv.resume();
/*!*/	}
/*!*/	return weGotSignal;
/*!*/}

/*!*///
/*!*///	Эта функция будет использоваться вместо delay
/*!*///	Она даст несколько большую задержку, чем дала бы честная delay
/*!*///	Если это не устраивает, используйте при вызове функций-эффектов 
/*!*/// меньшую задержку (не 20 как у Вас, а там 18 или 17)
/*!*///
/*!*/void smartDelay(uint8_t wait) {
/*!*/	for (uint8_t i = 0; (!decodeSignal()) && (i < wait); i++) delay(1);
/*!*/}


void loop() 
  {

/*!*/	if (decodeSignal()) // Если поступил ИК сигнал.
    {
/*!*/    	weGotSignal = false;
      if (results.value == 3953409587) // Если поступил (ИК) 
        {
        colorWipe(strip.Color(255, 0, 0), 20); // Red
        }
      if (results.value == 1763856455) // если поступил (ИК)
        {
        colorWipe(strip.Color(0, 255, 0), 20); // Green
        }
     if (results.value == 1962381255) // если поступил (ИК) 
        {
         rainbow(20);
        }
     if (results.value == 2086802078) // Иначе если поступил (ИК) .
        {
        rainbowCycle(20);
        }                   
/*!*/ //Здесь я удалил строку
    } 
  }



 


void colorWipe(uint32_t c, uint8_t wait) 
  {
/*!*/  for(uint16_t i=0; (!decodeSignal()) && (i<strip.numPixels()); i++) 
    {
    strip.setPixelColor(i, c);
    strip.show();
/*!*/    smartDelay(wait);
    }
  }

void rainbow(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256; j++) {
/*!*/    for(i=0; (!decodeSignal()) && (i<strip.numPixels()); i++) {
      strip.setPixelColor(i, Wheel((i+j) & 255));
    }
    strip.show();
/*!*/    smartDelay(wait);
  }
}

void rainbowCycle(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
/*!*/    for(i=0; (!decodeSignal()) && (i< strip.numPixels()); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
/*!*/    smartDelay(wait);
  }
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

По идее должна заработать, но мне проверять не на чем, так что если чего - постарайтесь описать проблему повнятнее.

vova20081
Offline
Зарегистрирован: 08.08.2015

спасибо за помощь!

блок 39-41 я понял как и зачем.

в боке 24-31 есть ошибка.

переменная "weGotSignal" в 27 строке всегда =0

проверял поставив посе этой строки - Serial.println(weGotSignal);

еси поставить - Serial.println(results.value); то тоже 0

копаю дальше :-)

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

vova20081 пишет:

спасибо за помощь!

блок 39-41 я понял как и зачем.

в боке 24-31 есть ошибка.

переменная "weGotSignal" в 27 строке всегда =0

проверял поставив посе этой строки - Serial.println(weGotSignal);

еси поставить - Serial.println(results.value); то тоже 0

копаю дальше :-)

Значит неправильно отрабатывает irrecv.decode. Где-то мы её обидели.

Можно уточнить, она что вообще ни разу не становится true или первый раз становится. а потом всегда 0?

vova20081
Offline
Зарегистрирован: 08.08.2015

всегда 0

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

Вы уверены, что сигнал реально приходит. Какая разница был у Вас вызов в loop или мы его в отдельную функцию вынесли? Если сигнал есть, он должен приходить. Проверьте, приходит ли сигнал. И это, Вы точно больше ничего не меняли. Просто если раньше сигнал ловился, то и сейчас ему не с чего не ловиться. Хотя бы в первый праз.

vova20081
Offline
Зарегистрирован: 08.08.2015

загружаю 1 скетч -работает

2- нет

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

1 и 2 - это точно то, что Вы мне давали и я Вам давал? Ничего не менялось. Если хоть что-то трогали, лучше выложите оба свежих скетча

vova20081
Offline
Зарегистрирован: 08.08.2015

1и 2 скопированно из форума в новые проекты. Посе этого в своем скече вынес из loop в отдельную функцию, там все работает.  УВАЖАЕМЫЙ ЕвгенийП огромное спасибо за наводку. Теперь понятно куда копать. 

vova20081
Offline
Зарегистрирован: 08.08.2015

Есть одна маленькая просьба (если возможно). Вы написали "Только никому не говорите, что это я писал. Написано, чтобы минимизировать изменения в Вашем коде, сам бы я писал совсем по-другому." Можно както пояснить (не текстом кода, а идеей)(учусь писать сам, но часто для изучения использую принципы "Бритвы Оккама"- использую для пробы готовые куски кода)

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

Хорошо, что разобрались. Идея-то простая - в любом цикле и при любой задержке спрашивать, а не пришло ли чего. так ведь?

Как бы я делал, я завтра расскажу, постараюсь не забыть.

Mr.Privet
Mr.Privet аватар
Offline
Зарегистрирован: 17.11.2015

Видимо забыл все таки...

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

А ведь, точно! Забыл!

Но, если ТС не напомнил, значит и не надо :)))))))))

anz_mu
Offline
Зарегистрирован: 06.06.2017

Доброго времени суток! Буду очень благодарен за помощь!

У меня возникла аналогичная проблема: приходиться ждать завершения цикла для смены скорости этого же эффекта, только в моем случае управление происходит через com-порт.

Никак не могу понять как работает эта функция:

/*!*/static bool weGotSignal = false;
/*!*/bool decodeSignal(void) {
/*!*/	if (!weGotSignal) {
/*!*/		weGotSignal = irrecv.decode(&results);
/*!*/		irrecv.resume();
/*!*/	}
/*!*/	return weGotSignal;
/*!*/

Вот код моего скетча:

#include <Adafruit_NeoPixel.h>
#include <EEPROM.h>
#define PIN 4
#define NUMPIXELS 1
#define delayval 500
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
char rec;
void setup() 
{
  Serial.begin(9600);
  strip.begin();
  strip.show();
}


void loop() {
  if (Serial.available() > 0) 
   {
     rec = Serial.read();
     if (rec =='o')             // turn off
        {
          EEPROM.write(0, 0);
          EEPROM.write(1, 0);
          EEPROM.write(2, 0);
        }
     if (rec == '~')            // rainbow wave
        { 
          EEPROM.write(0, 0);
          EEPROM.write(1, 0);
          EEPROM.write(2, 0);
          EEPROM.write(3, rec);
          delay(100); 
          Serial.println(rec);
        }
     if (rec =='s')             // wave speed
          {
            EEPROM.write(4, Serial.parseInt());
            delay(100);
          }
      
   }
 if (EEPROM.read(3) == '~')
   {
    
    rainbowCycle(EEPROM.read(4));
   }
}
void rainbowCycle(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256; j++) { 
    
    for(i=0; i< strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

На маленьких значениях "wait" цикл быстро завершается, но когда значение "wait" больше 10 приходиться ждать.

Не пойму как прерывать этот цикл. Вроде придумываю алгоритм - а он не работает.