Смена световых эфектов от кнопки по прерываниям
- Войдите на сайт для отправки комментариев
Ср, 12/07/2017 - 16:52
Помогите разобраться товарищи делаю моргалку на светодиодах WS2812. Ожидаемый алгаритм такой имеем 14 режимов работы. Где первые 13 режимов это 13 световых эффектов + 14 режим в котором все эти 13 эффектов меняются по таймеру каждые 5сек. наблюдаются тормоза при смене эффектов наверно что то неправильно сделал
//----------------------------------------------------------------------------------------- // Adafruit_NeoPixel //----------------------------------------------------------------------------------------- #include <Adafruit_NeoPixel.h> #include <PinChangeInt.h> #ifdef __AVR__ #include <avr/power.h> #endif //----------------------------------------------------------------------------------------- #define PIN 6 #define NUM_LEDS 144 #define CHANGE_TIME 5 // интервал смены эффектов, сек #define EFFECTS_COUNT 14 // количество эффектов #define START_PIN 7 // кнопка старт #define PROCESS (1 << 0) //---------------------------------------------------------------------------------------- uint8_t State = 0; byte effectNumber; // переменная для хранения номера эффекта byte effectNumber2; // переменная для хранения номера эффекта unsigned long timeStamp; // переменная для хранения времени последней смены эффекта Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800); //----------------------------------------------------------------------------------------- void showStrip() { #ifdef ADAFRUIT_NEOPIXEL_H // NeoPixel strip.show(); #endif #ifndef ADAFRUIT_NEOPIXEL_H // FastLED FastLED.show(); #endif } //----------------------------------------------------------------------------------------- void setAll(byte red, byte green, byte blue) { for(int i = 0; i < NUM_LEDS; i++) { setPixel(i, red, green, blue); } showStrip(); } //----------------------------------------------------------------------------------------- void setPixel(int Pixel, byte red, byte green, byte blue) { #ifdef ADAFRUIT_NEOPIXEL_H // NeoPixel strip.setPixelColor(Pixel, strip.Color(red, green, blue)); #endif #ifndef ADAFRUIT_NEOPIXEL_H // FastLED leds[Pixel].r = red; leds[Pixel].g = green; leds[Pixel].b = blue; #endif } //----------------------------------------------------------------------------------------- void setup() { Serial.begin(9600); digitalWrite(START_PIN, HIGH); PCintPort::attachInterrupt(START_PIN, &START_ISR, FALLING); effectNumber = 1; // задаем эффект (при включении питания) effectNumber2 = 1; // задаем эффект (при включении питания) strip.begin(); strip.show(); // Initialize all pixels to 'off' } //----------------------------------------------------------------------------------------- void loop() { if ((State & PROCESS) != PROCESS)// кнопка старт нажата { Serial.print("State:"); Serial.println(State); Serial.print("Effect:"); Serial.println(effectNumber); switch(effectNumber)// включаем заданный эффект { case 1: RGBLoop(); break; case 2: Strobe(0x25, 0x20, 0x25, 10, 50, 1000); break; case 3: CylonBounce(0xff, 0, 0, 4, 10, 50); break; case 4: NewKITT(0xff, 0, 0, 8, 10, 50); break; case 5: Twinkle(0xff, 0, 0, 10, 100, false); break; case 6: TwinkleRandom(20, 100, false); break; case 7: Sparkle(0xFF, 0xFF, 0xFF, 50); break; case 8: SnowSparkle(0x10, 0x10, 0x10, 20, random(100, 1000)); break; case 9: RunningLights(0,0xFF, 0xFF, 50); break; case 10: colorWipe(0x00,0x00,0xff, 20); colorWipe(0x00,0xff,0x00, 20); colorWipe(0xff,0x00,0x00, 20); colorWipe(0x10,0x10,0x10, 20); colorWipe(0xff,0xff,0xff, 20); break; case 11: rainbowCycle(20); break; case 12: theaterChase(0xff,0,0,50); break; case 13: Fire(55, 120, 15); break; case 14: while(millis() - timeStamp < CHANGE_TIME * 1000L) // в течение интервала { switch(effectNumber2)// включаем заданный эффект { case 1: RGBLoop(); break; case 2: Strobe(0x25, 0x20, 0x25, 10, 50, 1000); break; case 3: CylonBounce(0xff, 0, 0, 4, 10, 50); break; case 4: NewKITT(0xff, 0, 0, 8, 10, 50); break; case 5: Twinkle(0xff, 0, 0, 10, 100, false); break; case 6: TwinkleRandom(20, 100, false); break; case 7: Sparkle(0xFF, 0xFF, 0xFF, 50); break; case 8: SnowSparkle(0x10, 0x10, 0x10, 20, random(100, 1000)); break; case 9: RunningLights(0,0xFF, 0xFF, 50); break; case 10: colorWipe(0x00,0x00,0xff, 20); colorWipe(0x00,0xff,0x00, 20); colorWipe(0xff,0x00,0x00, 20); colorWipe(0x10,0x10,0x10, 20); colorWipe(0xff,0xff,0xff, 20); break; case 11: rainbowCycle(20); break; case 12: theaterChase(0xff,0,0,50); break; case 13: Fire(55, 120, 15); break; } // когда интервал превышен effectNumber2++; // увеличиваем счетчик if (effectNumber2 > 13) effectNumber2 = 1; // защита timeStamp = millis(); // запоминаем время начала эфекта } break; } if (effectNumber > EFFECTS_COUNT) effectNumber = 1; // защита } else // если кнопка Старт ненажата. { effectNumber++; // увеличиваем счетчик Serial.print("State:"); Serial.println(State); State &= ~PROCESS;// изменяем состояние на противоположное }//Конец обработки кнопки Старт. } //----------------------------------------------------------------------------------------- // Эфекты //----------------------------------------------------------------------------------------- void RGBLoop() { for(int j = 0; j < 3; j++ ) { // Fade IN for(int k = 0; k < 256; k++) { switch(j) { case 0: setAll(k,0,0); break; case 1: setAll(0,k,0); break; case 2: setAll(0,0,k); break; } showStrip(); delay(3); } // Fade OUT for(int k = 255; k >= 0; k--) { switch(j) { case 0: setAll(k,0,0); break; case 1: setAll(0,k,0); break; case 2: setAll(0,0,k); break; } showStrip(); delay(3); } } } //----------------------------------------------------------------------------------------- void Strobe(byte red, byte green, byte blue, int StrobeCount, int FlashDelay, int EndPause) { for(int j = 0; j < StrobeCount; j++) { setAll(red,green,blue); showStrip(); delay(FlashDelay); setAll(0,0,0); showStrip(); delay(FlashDelay); } delay(EndPause); } //----------------------------------------------------------------------------------------- void CylonBounce(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) { for(int i = 0; i < NUM_LEDS-EyeSize-2; i++) { setAll(0,0,0); setPixel(i, red/10, green/10, blue/10); for(int j = 1; j <= EyeSize; j++) { setPixel(i+j, red, green, blue); } setPixel(i+EyeSize+1, red/10, green/10, blue/10); showStrip(); delay(SpeedDelay); } delay(ReturnDelay); for(int i = NUM_LEDS-EyeSize-2; i > 0; i--) { setAll(0,0,0); setPixel(i, red/10, green/10, blue/10); for(int j = 1; j <= EyeSize; j++) { setPixel(i+j, red, green, blue); } setPixel(i+EyeSize+1, red/10, green/10, blue/10); showStrip(); delay(SpeedDelay); } delay(ReturnDelay); } //----------------------------------------------------------------------------------------- void NewKITT(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) { RightToLeft(red, green, blue, EyeSize, SpeedDelay, ReturnDelay); LeftToRight(red, green, blue, EyeSize, SpeedDelay, ReturnDelay); OutsideToCenter(red, green, blue, EyeSize, SpeedDelay, ReturnDelay); CenterToOutside(red, green, blue, EyeSize, SpeedDelay, ReturnDelay); LeftToRight(red, green, blue, EyeSize, SpeedDelay, ReturnDelay); RightToLeft(red, green, blue, EyeSize, SpeedDelay, ReturnDelay); OutsideToCenter(red, green, blue, EyeSize, SpeedDelay, ReturnDelay); CenterToOutside(red, green, blue, EyeSize, SpeedDelay, ReturnDelay); } //----------------------------------------------------------------------------------------- void CenterToOutside(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) { for(int i =((NUM_LEDS-EyeSize)/2); i>=0; i--) { setAll(0,0,0); setPixel(i, red/10, green/10, blue/10); for(int j = 1; j <= EyeSize; j++) { setPixel(i+j, red, green, blue); } setPixel(i+EyeSize+1, red/10, green/10, blue/10); setPixel(NUM_LEDS-i, red/10, green/10, blue/10); for(int j = 1; j <= EyeSize; j++) { setPixel(NUM_LEDS-i-j, red, green, blue); } setPixel(NUM_LEDS-i-EyeSize-1, red/10, green/10, blue/10); showStrip(); delay(SpeedDelay); } delay(ReturnDelay); } //----------------------------------------------------------------------------------------- void OutsideToCenter(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) { for(int i = 0; i<=((NUM_LEDS-EyeSize)/2); i++) { setAll(0,0,0); setPixel(i, red/10, green/10, blue/10); for(int j = 1; j <= EyeSize; j++) { setPixel(i+j, red, green, blue); } setPixel(i+EyeSize+1, red/10, green/10, blue/10); setPixel(NUM_LEDS-i, red/10, green/10, blue/10); for(int j = 1; j <= EyeSize; j++) { setPixel(NUM_LEDS-i-j, red, green, blue); } setPixel(NUM_LEDS-i-EyeSize-1, red/10, green/10, blue/10); showStrip(); delay(SpeedDelay); } delay(ReturnDelay); } //----------------------------------------------------------------------------------------- void LeftToRight(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) { for(int i = 0; i < NUM_LEDS-EyeSize-2; i++) { setAll(0,0,0); setPixel(i, red/10, green/10, blue/10); for(int j = 1; j <= EyeSize; j++) { setPixel(i+j, red, green, blue); } setPixel(i+EyeSize+1, red/10, green/10, blue/10); showStrip(); delay(SpeedDelay); } delay(ReturnDelay); } //----------------------------------------------------------------------------------------- void RightToLeft(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) { for(int i = NUM_LEDS-EyeSize-2; i > 0; i--) { setAll(0,0,0); setPixel(i, red/10, green/10, blue/10); for(int j = 1; j <= EyeSize; j++) { setPixel(i+j, red, green, blue); } setPixel(i+EyeSize+1, red/10, green/10, blue/10); showStrip(); delay(SpeedDelay); } delay(ReturnDelay); } //----------------------------------------------------------------------------------------- void Twinkle(byte red, byte green, byte blue, int Count, int SpeedDelay, boolean OnlyOne) { setAll(0,0,0); for (int i=0; i<Count; i++) { setPixel(random(NUM_LEDS),red,green,blue); showStrip(); delay(SpeedDelay); if(OnlyOne) { setAll(0,0,0); } } delay(SpeedDelay); } //----------------------------------------------------------------------------------------- void TwinkleRandom(int Count, int SpeedDelay, boolean OnlyOne) { setAll(0,0,0); for (int i=0; i<Count; i++) { setPixel(random(NUM_LEDS),random(0,255),random(0,255),random(0,255)); showStrip(); delay(SpeedDelay); if(OnlyOne) { setAll(0,0,0); } } delay(SpeedDelay); } //----------------------------------------------------------------------------------------- void Sparkle(byte red, byte green, byte blue, int SpeedDelay) { int Pixel = random(NUM_LEDS); setPixel(Pixel,red,green,blue); showStrip(); delay(SpeedDelay); setPixel(Pixel,0,0,0); } //----------------------------------------------------------------------------------------- void SnowSparkle(byte red, byte green, byte blue, int SparkleDelay, int SpeedDelay) { setAll(red,green,blue); int Pixel = random(NUM_LEDS); setPixel(Pixel,0xff,0xff,0xff); showStrip(); delay(SparkleDelay); setPixel(Pixel,red,green,blue); showStrip(); delay(SpeedDelay); } //----------------------------------------------------------------------------------------- void RunningLights(byte red, byte green, byte blue, int WaveDelay) { int Position=0; for(int i=0; i<NUM_LEDS*2; i++) { Position++; // = 0; //Position + Rate; for(int i=0; i<NUM_LEDS; i++) { // sine wave, 3 offset waves make a rainbow! //float level = sin(i+Position) * 127 + 128; //setPixel(i,level,0,0); //float level = sin(i+Position) * 127 + 128; setPixel(i,((sin(i+Position) * 127 + 128)/255)*red, ((sin(i+Position) * 127 + 128)/255)*green, ((sin(i+Position) * 127 + 128)/255)*blue); } showStrip(); delay(WaveDelay); } } //----------------------------------------------------------------------------------------- void colorWipe(byte red, byte green, byte blue, int SpeedDelay) { for(uint16_t i=0; i<NUM_LEDS; i++) { setPixel(i, red, green, blue); showStrip(); delay(SpeedDelay); } } //----------------------------------------------------------------------------------------- void rainbowCycle(int SpeedDelay) { byte *c; uint16_t i, j; for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel for(i=0; i< NUM_LEDS; i++) { c=Wheel(((i * 256 / NUM_LEDS) + j) & 255); setPixel(i, *c, *(c+1), *(c+2)); } showStrip(); delay(SpeedDelay); } } //----------------------------------------------------------------------------------------- byte * Wheel(byte WheelPos) { static byte c[3]; if(WheelPos < 85) { c[0]=WheelPos * 3; c[1]=255 - WheelPos * 3; c[2]=0; } else if(WheelPos < 170) { WheelPos -= 85; c[0]=255 - WheelPos * 3; c[1]=0; c[2]=WheelPos * 3; } else { WheelPos -= 170; c[0]=0; c[1]=WheelPos * 3; c[2]=255 - WheelPos * 3; } return c; } //----------------------------------------------------------------------------------------- void theaterChase(byte red, byte green, byte blue, int SpeedDelay) { for (int j=0; j<10; j++) { //do 10 cycles of chasing for (int q=0; q < 3; q++) { for (int i=0; i < NUM_LEDS; i=i+3) { setPixel(i+q, red, green, blue); //turn every third pixel on } showStrip(); delay(SpeedDelay); for (int i=0; i < NUM_LEDS; i=i+3) { setPixel(i+q, 0,0,0); //turn every third pixel off } } } } //----------------------------------------------------------------------------------------- void Fire(int Cooling, int Sparking, int SpeedDelay) { static byte heat[NUM_LEDS]; int cooldown; // Step 1. Cool down every cell a little for( int i = 0; i < NUM_LEDS; i++) { cooldown = random(0, ((Cooling * 10) / NUM_LEDS) + 2); if(cooldown>heat[i]) { heat[i]=0; } else { heat[i]=heat[i]-cooldown; } } // Step 2. Heat from each cell drifts 'up' and diffuses a little for( int k= NUM_LEDS - 1; k >= 2; k--) { heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2]) / 3; } // Step 3. Randomly ignite new 'sparks' near the bottom if( random(255) < Sparking ) { int y = random(7); heat[y] = heat[y] + random(160,255); //heat[y] = random(160,255); } // Step 4. Convert heat to LED colors for( int j = 0; j < NUM_LEDS; j++) { setPixelHeatColor(j, heat[j] ); } showStrip(); delay(SpeedDelay); } //----------------------------------------------------------------------------------------- void setPixelHeatColor (int Pixel, byte temperature) { // Scale 'heat' down from 0-255 to 0-191 byte t192 = round((temperature/255.0)*191); // calculate ramp up from byte heatramp = t192 & 0x3F; // 0..63 heatramp <<= 2; // scale up to 0..252 // figure out which third of the spectrum we're in: if( t192 > 0x80) { // hottest setPixel(Pixel, 255, 255, heatramp); } else if( t192 > 0x40 ) { // middle setPixel(Pixel, 255, heatramp, 0); } else { // coolest setPixel(Pixel, heatramp, 0, 0); } } //----------------------------------------------------------------------------------------- void START_ISR() { State |= PROCESS; } //------------------------------------------------------------------------------------------
Прерывание не панацея. Не важно, как сделана кнопка - от прерывания или просто в лупе - если остальной код на делеях - смены эффекта не будет, он не перейдет на новый пока не кончится цикл.
короче в эфектах нужно заменить delay на таймер и жизнь наладится
короче в эфектах нужно заменить delay на таймер и жизнь наладится
Не совсем так. Точнее не только это. В эффектах надо отслеживать состояние кнопки (либо непосредственно, либо через флаг) - и выходить из эффекта не дожидаясь конца цикла.
Но в чем вы правы - с делеями это вряд ли возможно.
А как раз прерывания в этом коде не обязательны.
Прерывания убрать. Заменить delay в формировании эффекта на MyDelay, в которой цикл по миллис ждет завершения заданого интервала, а внутри себя проверяет кнопку. Если кнопка нажата - MyDelay завершаем досрочно. Можна возвращать результат по которому определять что была нажата кнопка. Но это не обязательно. Ну а в лопе просто проверять нажатие и отрабатывать его.
Метод не самый лучший, зато самый простой. Лучший - переписать эффекты в виде класса с методами старт, стоп и процесс, которые вызывать снаружи.
На какой плате можно запустить эфект ?
Помогите разобраться товарищи делаю моргалку на светодиодах WS2812. Ожидаемый алгаритм такой имеем 14 режимов работы. Где первые 13 режимов это 13 световых эффектов + 14 режим в котором все эти 13 эффектов меняются по таймеру каждые 5сек. наблюдаются тормоза при смене эффектов наверно что то неправильно сделал
На какой плате запускали скетч ?
У меня на UNO R3 не загрузилась . Выбрал весь скетч и попробовал загрузить ( вылезают ошибки ошибка компилятции . Может что не так делаю ) .
сообщение компилятора скопируй сюда
но скорее всего тебе нужно скачать эти библиотеки и поместить в папку с библиотеками ардуино D:\Program Files\arduino-1.6.8\libraries
https://github.com/adafruit/Adafruit_NeoPixel
https://github.com/GreyGnome/PinChangeInt
сообщение компилятора скопируй сюда
но скорее всего тебе нужно скачать эти библиотеки и поместить в папку с библиотеками ардуино D:\Program Files\arduino-1.6.8\libraries
https://github.com/adafruit/Adafruit_NeoPixel
https://github.com/GreyGnome/PinChangeInt
У меня версия 1.8.2 . В этом проблемка и в отсутствии библеотеке .
у меня в 1,8,4 компилится
Скетч загрузился . Кнопку подключил на землю и 2пин разъема ( в скетчи указал 2 пин ) . Но смена не происходит .
ну да непроисходит на это я и жловался когда создавал тему. пока удаётся менять эфекты только по таймеру
Вот много режимов . https://yadi.sk/d/i1VkByjz3SMNzd
Спасибо посмотрю
Спасибо посмотрю
Нашол смена эфектов по кнопке . Все работает ( только 50 диодов на линию паталок ) . . https://yadi.sk/d/4xeORNPj3SRKBM
Картина "Копипастеры обсуждают стыренные скетчи"