Остановка цикла
- Войдите на сайт для отправки комментариев
Втр, 22/09/2020 - 05:39
Добрый день!
Ищу решение по переключению режимов адресной ленты кнопкой.
Дано: адреска, ардуино, сенсорная кнопка, желание сделать переключение между двумя тремя режимами свечения
Проблема: приходится удерживать кнопку нажатой, видимо, пока не закончится один из циклов
Укажите, пожалуйста, на ошибку в коде, из-за которой кнопка не работает мгновенно.
Спасибо, заранее!
#define PIN 13
#define NUM_LEDS 60
#include "Adafruit_NeoPixel.h"
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);
const int buttonPin = 5;
int count = 0;
void setup()
{
pinMode(buttonPin, INPUT);
strip.begin();
strip.setBrightness(50);
strip.clear();
strip.show();
}
void loop()
{
if(digitalRead(buttonPin)) {
count = count + 1;
if(count > 2){
count = 0;
}
}
if(count == 0)
{
for (int i = 0; i < 30; i++ ) {
strip.setPixelColor(i, 0x000000);
strip.show();
delay(50);
}
for (int i = 30; i < 60; i++ ) {
strip.setPixelColor(i, 0x000000);
strip.show();
delay(50);
}
} else if(count == 1)
{
for (int i = 0; i < 30; i++ ) {
strip.setPixelColor(i, 0x51f0ae);
strip.show();
delay(50);
}
for (int i = 30; i < 60; i++ ) {
strip.setPixelColor(i, 0xff7a00);
strip.show();
delay(50);
}
} else
{
for (int i = 0; i < 30; i++ ) {
strip.setPixelColor(i, 0xff007a);
strip.show();
delay(50);
}
for (int i = 30; i < 60; i++ ) {
strip.setPixelColor(i, 0x51aef0);
strip.show();
delay(50);
}
}
}
Использовать прерывание по нажатию кнопки?
Это не ошибка, это неправильный выбор ))
Чтобы кнопка срабатывала мгновенно, ее состояние нужно проверять в каждом из циклов постоянно. Вынесите код проверки кнопки в отдельную процедуру
bool checkButton() { bool result = false; if (digitalRead(buttonPin)) { result = true; count = count + 1; if (count > 2) { count = 0; } } return (result); }И вызывайте ее в цикле
Далее - в лупе вы шесть раз пишете один и тот же код, различающийся только одним параметром. Не лучше ли его тоже вынести в отдельную процедуру?
void setStrip(byte idx, uint32_t color) { for (int i = idx; i < idx + 30; i++ ) { if checkButton() break; strip.setPixelColor(i, color); strip.show(); delay(50); } }И тогда в лупе останется только несколько строк
void loop() { switch (count) { case 0: setStrip(0, 0x000000); setStrip(30, 0x000000); break; case 1: setStrip(0, 0x51f0ae); setStrip(30, 0xff7a00); break; case 2: setStrip(0, 0xff007a); setStrip(30, 0x51aef0); break; } }И еще - возьмите себе в привычку форматировать код. Так он воспринимается гораздо легче, вам же проще будет с ним работать. В Arduino IDE за это отвечает комбинация Ctrl+T
v258, cпасибо, очень помогли все советы
Единственное, каждый раз при нажатии кнопки вылезали разные артефакты, и режимы шли непоследовательно и лента могла включиться наполовину.
Предположил, что это может быть связано с отсутствием задержки в кнопке, добавил делей (в то место, где мне показалось, это нужно (5 строчка), но это не точно :) ), в общем, по крайней мере, теперь порядок. Правда минимальная задержка 500, если ставлю 50, к примеру, снова беда с работой. Видимо все-таки решать надо иначе.
bool checkButton() { bool result = false; if (digitalRead(buttonPin)) { delay(500); result = true; count = count + 1; if (count > 2) { count = 0; } } return (result); }Еще раз спасибо!
Единственное, каждый раз при нажатии кнопки вылезали разные артефакты, и режимы шли непоследовательно и лента могла включиться наполовину.
так извините, вы же сами хотели, чтобы кнопка срабатывала мгновенно? А "мгновенно" - это значит не дожидаясь окончания текущего эффекта, прерывая работу со свето-лентой в любой неподходящий момент.
Отсюда и артефакты, и "лента наполовину" - это все совершенно логично. И, кстати. вставленная вами задержка - не решает абсолютно ничего, можете ее выкинуть. Для того чтоб все работало "чисто" - нужно по нажатию кнопки не грубо прерывать работу текущего эффекта, а аккуратно завершать процесс.
v258, cпасибо, очень помогли все советы
Единственное, каждый раз при нажатии кнопки вылезали разные артефакты, и режимы шли непоследовательно и лента могла включиться наполовину.
Предположил, что это может быть связано с отсутствием задержки в кнопке, добавил делей (в то место, где мне показалось, это нужно (5 строчка), но это не точно :) ), в общем, по крайней мере, теперь порядок полный.
bool checkButton() { bool result = false; if (digitalRead(buttonPin)) { delay(500); result = true; count = count + 1; if (count > 2) { count = 0; } } return (result); }Еще раз спасибо!
Это дребезг контактов. 500 миллисекунд многовато, достаточно 50-100. Вообще есть библиотеки для работы с кнопками, они обычно хорошо отрабатывают дребезг
Это дребезг контактов. 500 миллисекунд многовато, достаточно 50-100. Вообще есть библиотеки для работы с кнопками, они обычно хорошо отрабатывают дребезг
причем тут дребезг и как эта задержка помогает, если вы в вашем коде читаете кнопку только один раз? Посмотрите внимательно - вы наверно собирались читать еее дважды или трижды... судя по переменной count. только вы этого не делаете...
И, кстати. вставленная вами задержка - не решает абсолютно ничего, можете ее выкинуть
Забавно, но решает, если нажимать по завершении эффекта, все работает корректно после добавления этой строчки.
В остальном, конечно, да, - если смена эффекта не закончилась, то быстрое повторное нажатие нарушает схему.
b707, сейчас код выглядит так:
#define PIN 13 // пин DI #define NUM_LEDS 60 // число диодов #include "Adafruit_NeoPixel.h" Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800); const int buttonPin = 5; // Выставляем значения порта, подсоединённого с сигнал-портом кнопки int count = 0; // Переменная, предназначенная для выбора режима работы void setup() { pinMode(buttonPin, INPUT); // Открываем порт для считывания strip.begin(); strip.setBrightness(50); // яркость, от 0 до 255 strip.clear(); // очистить strip.show(); } bool checkButton() { bool result = false; if (digitalRead(buttonPin)) { delay(500); result = true; count = count + 1; if (count > 2) { count = 0; } } return (result); } void setStrip(byte idx, uint32_t color) { for (int i = idx; i < idx + 30; i++ ) { if (checkButton()) break; strip.setPixelColor(i, color); strip.show(); delay(50); } } void loop() { switch (count) { case 0: setStrip(0, 0x000000); setStrip(30, 0x000000); break; case 1: setStrip(0, 0x51f0ae); setStrip(30, 0xff7a00); break; case 2: setStrip(0, 0x51aef0); setStrip(30, 0xff007a); break; } }b707, сейчас код выглядит так:
ок, был неправ. Слушайте коллегу V258. он дело говорит
причем тут дребезг и как эта задержка помогает, если вы в вашем коде читаете кнопку только один раз? Посмотрите внимательно - вы наверно собирались читать еее дважды или трижды... судя по переменной count. только вы этого не делаете...
При том, что без его нейтрализации кнопка срабатывает несколько раз и несколько же раз перезапускает режимы. Отсюда, видимо, и артефакты, выражающиеся в нескольких последовательно прерванных режимах ленты. Задержка позволяет не реагировать на импульсы, следующие после первого. Хотя, конечно, так с дребезгом не борются ))
А завершать или нет текущий режим - это уже дело вкуса, имхо ))
Если нужно корректно завершать режим, то переменную count нужно менять в лупе, а кнопкой просто поднимать флаг смены режима. Типа такого
#define PIN 13 // пин DI #define NUM_LEDS 60 // число диодов #include "Adafruit_NeoPixel.h" Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800); const int buttonPin = 5; // Выставляем значения порта, подсоединённого с сигнал-портом кнопки int count = 0; // Переменная, предназначенная для выбора режима работы bool f = false; void setup() { pinMode(buttonPin, INPUT); // Открываем порт для считывания strip.begin(); strip.setBrightness(50); // яркость, от 0 до 255 strip.clear(); // очистить strip.show(); } void checkButton() { if (digitalRead(buttonPin)) { delay(500); f = true; } } void setStrip(byte idx, uint32_t color) { for (int i = idx; i < idx + 30; i++ ) { checkButton(); strip.setPixelColor(i, color); strip.show(); delay(50); } } void loop() { if (f) { f = false; count = count + 1; if (count > 2) { count = 0; } } switch (count) { case 0: setStrip(0, 0x000000); setStrip(30, 0x000000); break; case 1: setStrip(0, 0x51f0ae); setStrip(30, 0xff7a00); break; case 2: setStrip(0, 0x51aef0); setStrip(30, 0xff007a); break; } }Но тогда реакция на нажатие кнопки будет сильно замедлена. Правда, держать кнопку нажатой тогда будет не нужно и даже вредно ))
пост 11,
там задержку стр 25 можно уменьшать т.к. 34-36 вроде входят в период опроса кнопки, являясь тоже задержкой опроса кнопки. И пока эффект не закончится, он все равно не поменяется.
Единственное, эта задержка задает "подвисание эффекта" и даже можно будет "увидеть" что кнопка нажата... но не на всех эффектах.
пост 11,
там задержку стр 25 можно уменьшать т.к. 34-36 вроде входят в период опроса кнопки, являясь тоже задержкой опроса кнопки. И пока эффект не закончится, он все равно не поменяется.
Единственное, эта задержка задает "подвисание эффекта" и даже можно будет "увидеть" что кнопка нажата... но не на всех эффектах.
Да я знаю, я об этом еще в пятом посте говорил. Здесь же просто переделал имеющийся скетч, а задержку пускай ТС сам регулирует
Да я знаю, я об этом еще в пятом посте говорил. Здесь же просто переделал имеющийся скетч, а задержку пускай ТС сам регулирует
так я просто написал, к какому посту комментарий, и собственно он был вообще коммент к коду