Кнопка переключения режимов для switch и delay в этих режимах

verhmax
Offline
Зарегистрирован: 21.12.2014

С Новым Годом!

учусь прогать, наткнулся на такую проблемку:

есть одна кнопка, при нажатии переключает режимы, switch смотрет значение режима и включает нужную функцию, но, все функции используют delay и при нажатии кнопки не всегда происходит переключение режимов, они переключаются, только тогда, когда кнопка нажата в момент окончания цикла режима.

как сделать чтоб при нажатии кнопки режим переключался не зависимо от режимов и количества delay в них?

Andrey-S
Offline
Зарегистрирован: 02.01.2015

verhmax пишет:

С Новым Годом!

учусь прогать, наткнулся на такую проблемку:

есть одна кнопка, при нажатии переключает режимы, switch смотрет значение режима и включает нужную функцию, но, все функции используют delay и при нажатии кнопки не всегда происходит переключение режимов, они переключаются, только тогда, когда кнопка нажата в момент окончания цикла режима.

как сделать чтоб при нажатии кнопки режим переключался не зависимо от режимов и количества delay в них?

Я хоть и сам новичок в этом, но, думаю, код бы свой выложить неплохо было, чтобы знающие люди посмотели))

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014
verhmax
Offline
Зарегистрирован: 21.12.2014

вот мой код, я так понял нужно сделать прерывания, но если я беру switch в функцию и эту функцию прописываю в attachInterrupt то у меня вообще ниодин режим не работает

#include "Ai_WS2811.h"
#define NUM_PIXELS 4
#define DATA_PIN 8
Ai_WS2811 ws2811;
const int buttonPin = 2;
int buttonState = 0;
int program=1;
struct CRGB {
  unsigned char g;
  unsigned char r;
  unsigned char b;
} *leds;
void setup()
{
  pinMode(buttonPin, INPUT);
  ws2811.init(DATA_PIN,NUM_PIXELS);
  leds = (struct CRGB*)ws2811.getRGBData();
}

void loop(){

   buttonState = digitalRead(buttonPin); 
  if (buttonState == HIGH) {  
     if(program==6) {program=1;delay(500);}
     else{program++;delay(500);}
  }
  else {}

    switch (program) {
    case 1: blink_one_led(); break;
    case 2: white(); break;
    case 3: red(); break;
    case 4: snake(); break;
    case 5: snake2(); break;
    case 6: medlenno_blue(); break;
    }
}

 

vvadim
Offline
Зарегистрирован: 23.05.2012

А не проще для начала отказаться от delay

verhmax
Offline
Зарегистрирован: 21.12.2014

и ещё я не понял с пинами на прерывания: я сейчас пытаюсь с одной кнопкой научиться, а если мне нужно к UNO 4 кнопки подключить и все с прерываниями, у меня это не выйдет?

vvadim
Offline
Зарегистрирован: 23.05.2012

читаем описание 

  • Внешнее прерывание: 2 и 3. Данные выводы могут быть сконфигурированы на вызов прерывания либо на младшем значении, либо на переднем или заднем фронте, или при изменении значения. Подробная информация находится в описании функции attachInterrupt().
vvadim
Offline
Зарегистрирован: 23.05.2012

Избавляемся от delay и зачем вам вообще прерывания

verhmax
Offline
Зарегистрирован: 21.12.2014

я бы с удовольствием избавился от delay()

но почитав пример, я так и не понял, как мне это сделать.

вот моя функция мигания к примеру

void blink()
{
red тра-та-та
delay(500);
green тра-та-та
delay(500);
blue тра-та-та
delay(500);
}

вроде ничего сложного, но я не понял как мне переключать свечение светодиодов без delay()

это я привел простой пример, а так у меня функции намного сложней так как это управлялка ws2812 светодиодами

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

verhmax пишет:

я бы с удовольствием избавился от delay()

но почитав пример, я так и не понял, как мне это сделать.

вот моя функция мигания к примеру

void blink()
{
red тра-та-та
delay(500);
green тра-та-та
delay(500);
blue тра-та-та
delay(500);
}

вроде ничего сложного, но я не понял как мне переключать свечение светодиодов без delay()

это я привел простой пример, а так у меня функции намного сложней так как это управлялка ws2812 светодиодами

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

Даю подсказку - вам нужна точка отсчета, и нужно знать сколько времени прошло, с момента определения этой точки. Вторая подсказка - millis().

verhmax
Offline
Зарегистрирован: 21.12.2014

да, я этот пример с millis() и пробывал, но оно у меня циклично очень мега быстро перебирает режим работы, может delay(500) и разница между точкой отсчета (millis() + 500 > текущее) совсем не те величины? может для millis() нужны другие величины чем у delay ?

и ещё вопрос, если я все режимы переведу в временные, то к примеру режим эффекта, который длится в цикле 20 сек, я смогу переключить в любой момент, или всеже прийдется ждать конца цикла этой функции мигания?

Sanchogus
Offline
Зарегистрирован: 02.01.2015

verhmax пишет:

да, я этот пример с millis() и пробывал, но оно у меня циклично очень мега быстро перебирает режим работы, может delay(500) и разница между точкой отсчета (millis() + 500 > текущее) совсем не те величины? может для millis() нужны другие величины чем у delay ?

и ещё вопрос, если я все режимы переведу в временные, то к примеру режим эффекта, который длится в цикле 20 сек, я смогу переключить в любой момент, или всеже прийдется ждать конца цикла этой функции мигания?

Как насчет посчитать время всего цикла.

Допустим это 2 сек = 2000 мс = looptime.

Смотрим текущее время millis() и берем остаток от деления на время цикла looptime  = 2000 мс

Т.е. у нас всегда будет число time = millis() % looptime в диапазоне от 0 до 2000.









int time = millis() % looptime   // получим число от 0 до 2000

//далее условия при которых вкл диоды.

if (time > 1500) greenLED()

else if (time > 1000) redLED()

else if (time > 500) yellowLED()

Ну, надеюсь, в целом идея понятна.

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

verhmax пишет:

да, я этот пример с millis() и пробывал, но оно у меня циклично очень мега быстро перебирает режим работы, может delay(500) и разница между точкой отсчета (millis() + 500 > текущее) совсем не те величины? может для millis() нужны другие величины чем у delay ?

unsigned long int delayCounter = 500;
unsigned long int lastMillis = 0;

void loop(){
unsigned long int currentMillis = millis();
if(currentMillis - lastMillis >= delayCounter){
// код

lastMillis = currentMillis;

}

}

 

Цитата:

и ещё вопрос, если я все режимы переведу в временные, то к примеру режим эффекта, который длится в цикле 20 сек, я смогу переключить в любой момент, или всеже прийдется ждать конца цикла этой функции мигания?

Вопрос не понятен.

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

Изменил пример:

unsigned long int lastMillis = millis();

нужно инициализировать нулем.

verhmax
Offline
Зарегистрирован: 21.12.2014

да... идея и логика мне понятна, но, что-то у меня ничего с временем не получается, диоды бешено мигают, и ещё дляменя мало понятно, как быть, если у меня лента и включаю я диоды циклом for

void svet(){
for (int led = 0; led < NUM_PIXELS; led++) 
{
setHue(100,0,0, led);
ws2811.sendLedData();
delay(500);
}
}

как мне в такой примитивной функции сделать паузу без delay я вообще понять не могу :(

 

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

verhmax пишет:

да... идея и логика мне понятна, но, что-то у меня ничего с временем не получается, диоды бешено мигают, и ещё дляменя мало понятно, как быть, если у меня лента и включаю я диоды циклом for

void svet(){
for (int led = 0; led < NUM_PIXELS; led++) 
{
setHue(100,0,0, led);
ws2811.sendLedData();
delay(500);
}
}

как мне в такой примитивной функции сделать паузу без delay я вообще понять не могу :(

 

Если в данном конкретном случае delay() тоже мешает, то нужно отказаться от цикла for() в пользу while().

Вы не могли бы с нуля, step-by-step, пояснить, что хотите получить? Дайте ссылку на библиотеку. Тяжело вникать в обрывки кода, не понимая общей картины...

Sanchogus
Offline
Зарегистрирован: 02.01.2015

verhmax пишет:

да... идея и логика мне понятна, но, что-то у меня ничего с временем не получается, диоды бешено мигают, и ещё дляменя мало понятно, как быть, если у меня лента и включаю я диоды циклом for





void svet(){
for (int led = 0; led < NUM_PIXELS; led++) 
{
setHue(100,0,0, led);
ws2811.sendLedData();
delay(500);
}
}

как мне в такой примитивной функции сделать паузу без delay я вообще понять не могу :(

 

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