Задача такая. Нужно, чтобы при нажатии на кнопку, лента "дорожкой" загоралась и продолжала вся светиться, пока не отпущу кнопку, тогда она обратной дорожкой должна погаснуть. Тыкался много часов, лучшее, что я добился, это тот или иной эффект, но совместить их не получилось. загорается вся и в итоге обратно не тухнет.. Может кто помочь скетчем?
у меня всё получилось http://forum.amperka.ru/threads/450-ws2812-на-attiny1614-и-немного-кода.20663/ Чтобы дорожка бежала обратно, необходимо перевернуть алгоритм.
Вот код, который у меня работает "наполовину" Код (C++): #define STRIP_PIN 10 #define NUMLEDS 40 #include <microLED.h> microLED< NUMLEDS, STRIP_PIN, LED_WS2815, ORDER_GRB, CLI_AVER> strip; const int buttonPin = 6; int buttonState = 0; void setup() { strip.setBrightness(255); pinMode(buttonPin, INPUT); } void loop() { buttonState = digitalRead(buttonPin); if (buttonState == HIGH) { up(); } if (buttonState == LOW) { down(); } strip.show(); delay(30); } void up() { static int counter = 0; strip.clear(); strip.fill(0, counter, mRed); counter++; if (counter >= NUMLEDS) counter = NUMLEDS; } void down() { static int counter = NUMLEDS; strip.clear(); strip.fill(0, counter, mWhite); counter--; if (counter <=0) counter = -1; }
Я с библиотекой microLED не работал. Сейчас ознакомился с ней бегло. Глядя на ваш код я не понимаю, про какую "половину" вы говорите? Оно не должно работать вообще. Опустим инициализацию ленты, наверное там правильно. Переходим в основной цикл. При нажатии кнопки вы вызываете функцию up. Код (C++): void up() { static int counter = 0; strip.clear(); strip.fill(0, counter, mRed); counter++; if (counter >= NUMLEDS) counter = NUMLEDS; } В ней вы обнуляете counter, очищаете буфер, и командой strip.fill(0, counter, mRed) записываете в буфер - залить красным цветом светодиоды с номера 0 по counter. Потом инкреминируете counter, проверяече, что-бы counter не вышел за пределы числа светодиодов в ленте и возвращаетесь в основной цикл. Там вы командой strip.show() запуливаете содержимое буфера в ленту, ждёте 10 милисекунд и снова в начало loop. Кнопка по прежнему нажата, по этому снова в up. А там снова Код (C++): static int counter = 0; Так-что далее светодиода под номером ноль вы не сдвинетесь. В функцию down я даже не заглядывал.
Не должно, но полуработает. Код взял из примера алекса гайвера и попытался его адаптировать под себя. Не получилось. Буду тыкаться далее))
нормальный код. Оно сейчас должно работать так - при нажатии кнопки постепенно заполняет ленту красными пикселями. Доходя до верха - горит полностью красным, пока держишь. Если отпустить кнопку - засвечивает всю ленту белым и начинает постепенно убывать. Угадал?
да, должно работать так, но по факту работает не до конца. с отключенной кнопкой белым с конца в начало уходит, как и должно, при нажатии так же красным до заполнения, как и должно, НО: по какой-то причине на этом происходит затык, если дать красному дойти до последнего диода, то больше на нажатие-отпускание кнопки ардуинка не реагирует. А если не дать красному всё заполнить и отпустить раньше, то всё работает как надо, пока не заполнится всё красным.. PS если кому интересно - это подсветка плинтуса, когда основной свет включают, сигнал пойдёт на ардуинку (вместо кнопки), лента зажжется заполнением полностью, а когда выключат свет, лента обратным заполнением погаснет. PSS кнопка к земле разумеется подтянута
Возможно я что-то недопонимаю. Но разве после строки Код (C++): static int counter = 0; переменная counter не должна стать равной нулю? Что-то я начинаю сильно путаться в Си. Я тут как раз с такой лентой эксперементирую на самоизоляции. Для общего развития набросал на ASM зажигание и гашение ленты как хотел ТС, но без кнопок.
Кстати, если сюда в конце if добавить через запятую "loop()", то всё работает, но белый соответственно бегает циклично. За то нет затыка на красном)) Код (C++): void down() { static int counter = NUMLEDS; strip.clear(); strip.fill(0, counter, mWhite); counter--; if (counter <=0) counter = -1,loop(); }
я сам не очень, вернее очень не, соображаю в си, в частности в ардуино иде, только поверхностно, но мне кажется, не даёт снова обнулиться каунтеру именно "static" int
Сел, подумал и решил проблему подумав логически, но почему так происходит, я так и не понял. Вот тут если сравнивать counter не с NUMLEDS, а отнять от него единицу (NUMLEDS-1), то всё начинает работать так, как и задумано. Почему - мне не ясно, но всё заработало) Код (C++): void up() { strip.clear(); strip.fill(0, counter, mWhite); counter++; if (counter >= NUMLEDS-1) counter = NUMLEDS; } ********************** Если кому ещё захочется сделать "такое", вот код с подробным описанием, как смог Код (C++): // Sanya0017, за основу взят код из примера описания библиотеки microLED от AlexGyver #define STRIP_PIN 10 // пин, к которому подключена лента #define NUMLEDS 40 // количество светодиодов #include <microLED.h> // подключение библиотеки microLED (3 версия) microLED< NUMLEDS, STRIP_PIN, MLED_NO_CLOCK, LED_WS2815, ORDER_GRB, CLI_AVER> strip; // инициализация ленты const int buttonPin = 6; // пин, к которому подключена кнопка int buttonState = 0; // состояние кнопки int counter = 0; // счётчик int counteer = NUMLEDS; // второй счётчик void setup() { pinMode(buttonPin, INPUT); // настраиваем пин кнопки на "вход" } void loop() { buttonState = digitalRead(buttonPin); // слушаем кнопку if (buttonState == HIGH) { // если нажата, то делаем: counteer = NUMLEDS; // закидываем во второй счётчик количество светодиодов up(); // переходим в void up() } if (buttonState == LOW) { // если не нажата, то делаем: counter = 0; //закидываем в счётчик 0 down(); // переходим в void down() } strip.setBrightness(50); // устанавливаем яркость strip.show(); // вывод изображения на ленту delay(30); // задержка (устанавливает fps) } void up() { strip.clear(); // очищаем ленту strip.fill(0, counter, mWhite); // заливаем ленту цветом (mWhite) с 0 диода по номеру диода, находящемуся в счётчике counter++; // добавляем к счётчику единицу if (counter >= NUMLEDS-1) counter = NUMLEDS; // если счётчик выше или равен значения NUMLEDS-1, то кидаем в него значение NUMLEDS, чтобы не пыталось считать дальше } void down() { strip.clear(); // очищаем ленту strip.fill(0, counteer, mWhite); // заливаем ленту с 0 диода по номеру диода, находящемуся в счётчике counteer--; // отнимаем от счётчика единицу if (counteer <=0) counter = -1; //если счётчик меньше либо равен 0, то кидаем в него значения -1 (со значением 0 будет гореть первый диод), чтобы не пыталось считать дальше }
Статические переменные инициализируются один раз - при первом заходе в функцию. Далее они сохраняют свое значение между запусками функции... на то они и "статические"
нелогичная фраза "Подумав логически" и "так и не понял" - несовместимо. То что вы сделали, называется иначе - "поменял наобум - а оно и заработало" Кстати, я вижу что вы не только поменяли NUMLEDS на NUMLEDS-1, но и сделали переменную counter общей в обоих процедурах. Это, кстати, могло иметь решающее значение. Причина, почему смена NUMLEDS на NUMLEDS-1 могла сказаться на работе - в кривости Гайверовской либы microled Когда вы используете процедуру Код (C++): strip.fill(0, counter, mWhite); - микроЛЕД не проверяет, лежат ли заданные индексы "внутри" ленты. Поскольку в ленте длиной NUMLEDS пикселей последний диод имеет индекс NUMLEDS-1 (индексы ведь считаются с нуля) - то когда вы пытаетесь запустить fill от 0 до NUMLEDS - вы попадаете за границу массива и "распахиваете" память. Кстати, правильнее будет поставить NUMLEDS-1 не только в условии, но и в присваивании счетчику:: Код (C++): void up() { strip.clear(); // очищаем ленту strip.fill(0, counter, mWhite); // заливаем ленту цветом (mWhite) с 0 диода по номеру диода, находящемуся в счётчике counter++; // добавляем к счётчику единицу if (counter >= NUMLEDS-1) counter = NUMLEDS-1; // если счётчик выше или равен значения NUMLEDS-1, то кидаем в него значение NUMLEDS, чтобы не пыталось считать дальше } В либах Гайвера куча подобных ляпов, когда есть альтернатива - советую выбирать другие библиотекию Для вашего примера лучше было взять FastLED
Не совсем) я логическим путём понял, в какой именно момент происходит зависание и понял из-за чего, но почему - не понял, но вы объяснили про отсчёт не с 1, а с 0 и недоделку библиотеки, которая позволяет в этом случае всему крашиться, спасибо). Первый пример, который я нашёл, был как раз на микролед, а т.к. я что-то на фастледе делал с год-два назад, то я совсем забыл что там и как и решил остановиться на этом Пробую сижу бегущую радугу сделать, а не заливку, пока получилась только статичная радуга, но с заполнением xD