Ожидание выполнения функции

artivad2
Offline
Зарегистрирован: 16.03.2018

Вопрос по программе. Есть лента с управляемыми светодиодами. Функция loop ожидает завершение выполнения кода - функции RainbowCycle (радуга). Необходимо по нажатию кнопки немедленно ее прервать и начать другую функцию (ту же RainbowCycle но с задержкой). Оператор break не помогает, условие в цикле функции - тоже.

void loop() { 
buttonState = digitalRead(buttonPin); 
if (buttonState == LOW) { 
rainbowCycle(); //Функция без задержки
} else { 
rainbowCycleDelay(); //Функция с задержкой
 
//Функция без задержки
void rainbowCycle() { 
    uint16_t i, j; 
    for(j=0; j<256 && buttonState == LOW; j++) { // 5 cycles of all colors on wheel 
    for(i=0; i< strip.numPixels() && buttonState == LOW; i++) {
    strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255)); 
    } 
    strip.show();  
    }    
 
//Функция с задержкой
void rainbowCycleDelay() { 
    uint16_t i, j; 
    for(j=0; j<256 && buttonState == HIGH; j++) { // 5 cycles of all colors on wheel 
    for(i=0; i< strip.numPixels() && buttonState == HIGH; i++) { 
    strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255)); 
    } 
    delay(1);
    strip.show(); 
    }
}

 

artivad2
Offline
Зарегистрирован: 16.03.2018

Что не так делаю?

b707
Offline
Зарегистрирован: 26.05.2017

покажите код, как вы добавляли "условие в цикле", которое не сработало. Только выложите код как положено http://arduino.ru/forum/obshchii/vstavka-programmnogo-koda-v-temukommentarii

artivad2
Offline
Зарегистрирован: 16.03.2018

Добавлю просто как текст пока, чтобы было понятно - выделил жирным

for(j=0; j<256 && buttonState == LOW; j++) { // 5 cycles of all colors on wheel 

for(j=0; j<256 && buttonState == HIGH; j++) { // 5 cycles of all colors on wheel 

b707
Offline
Зарегистрирован: 26.05.2017

1. Переменная buttonState - глобальная?

2. Какая кнопка (тактовая. с фиксацией. сенсор) и как  подключена (на Лоу или на Хай. есть ли подтяжка)

artivad2
Offline
Зарегистрирован: 16.03.2018

Переменная заводилась как глобальная -  в самом начале кода. Запись в нее идет в цикле loop - состояние кнопки.

А кнопка на данный момент это просто 2 проводка, которые я замыкаю. Они работают исправно, без наводок - подключены через светодиодный пин - 13. Он загорается когда замыкаю. Пробовал другие программы - реагируют нормально. Подтяжки нет. Но дело ведь не в этом, плата реагирует на контакт. Сам цикл ждет окончания выполнения функции.

kalapanga
Offline
Зарегистрирован: 23.10.2016

Если речь именно об этом скетче, то Вы уверены, что замечаете задержку в одну миллисекунду? Может у Вас вполне всё переключается?

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

В loop() , проверяйте кнопку. Если она не нажата - просто вызывайте rainbowCycle() с параметром j, который в будет увеличиваться в loop(). Если нажата - делайте то, что называете "прерыванием эффекта". Или делайте в лупе delay(delayTime) после вызова rainbowCycle(). Нажата кнопка - одно значение delayTime, не нажата - другое.

Если этого хватит, то ок. Нет - нужно проводить более серьёзную операцию с миллисами и стейтмашиной.

artivad2
Offline
Зарегистрирован: 16.03.2018

Да. Я вижу разницу, она просто отрабатывает не сразу. Если ставить задержку в 2 мс, то цикл будет выполнятся медленнее и соответственно ждать придется дольше

artivad2
Offline
Зарегистрирован: 16.03.2018

Можно пример кода с параметром j?

И не понял насчет Delay. Что это должно мне дать? Задержки мне и так хватает сейчас..

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

Пример:

void rainbowCycleDelay(uint8_t j) {
  ...
}

void loop() {
  static uint8_t j = 0;
  uint32_t delayTime;
  buttonState = digitalRead(buttonPin);
  j++;
  rainbowCycle(j);
  if (buttonState == LOW) {
    delayTime = 0;
  } else {
    delayTime = 200;
  }
  delay(delayTime)
}

Думаю, что цикл с j вы сумеете сами выкинуть из функции. И проверки buttonState тоже.

Далее почитайте статью "blink без delay" и модифицируйте соответсвенно код. Тогда всё будет почти мгновенно работать.

 

artivad2
Offline
Зарегистрирован: 16.03.2018

Вроде правильно сделал. Огоньки теперь не бегут вообще. А продвигаются разово на несколько позиций при зажатии контактов. А так стоят на месте.

Про то что делэй лучше не использовать - я знаю. Но в данной программе он практически не останавливает выполнение кода.

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

Не знаю, что вы там сделали, но если правильно - то должно работать.

А... Вобщем, нужно один только rainbowCycle() оставить - они же только дилеем отличаются. Его, оставленного, и вызывать.

artivad2
Offline
Зарегистрирован: 16.03.2018

Второй RainbowCycle у меня больше не вызывается. Вот код (название функции другое):

void loop() {
  static uint8_t j = 0;
  buttonState = digitalRead(buttonPin);
  j++;
  rainbowCycleHigh(j);
  if (buttonState == LOW) {
    delayTime = 0;
  } else {
    delayTime = 200;
  }
  delay(delayTime);
}

void rainbowCycleHigh(uint8_t j) { 
    uint16_t i; 
    for(i=0; i< strip.numPixels() && buttonState == HIGH; i++) { 
    strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255)); 
    } 
    strip.show(); 
} 

 

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

Я же просил вас выкинуть проверки buttonState, а вы оставили. Они и изначально там не нужны были.

b707
Offline
Зарегистрирован: 26.05.2017

должны медленно меняться, пока кнопку держите. Как отпускаете - все остановилось, так?

Ну а что вы хотели - оно так и должно быть. Вам же сказали условие buttonState == HIGH из цикла выкинуть, а вы не послушали.

artivad2
Offline
Зарегистрирован: 16.03.2018

Ой. Извиняюсь. Забыл убрать. Теперь всё работает, спасибо!

Объясните, почему цикл не останавливался по условию или по break'у?

А, понял. У меня же состояние кнопки только в loop считывается.

artivad2
Offline
Зарегистрирован: 16.03.2018

В общем сделал я таки по своему. Просто вместо ButtonState прописал digitalRead(buttonPin), чтобы состояние всегда было актуальным. Из второго цикла убрал эту проверку. Моя невнимательность.. Спасибо еще раз.