Вопрос про много режимов работы и, частично, про ШИМ.
- Войдите на сайт для отправки комментариев
Народ, помогите проблему решить. Решил сделать себе подсветку на велосипед. Придумал 3 группы светодиодов (на переднем колесе, на раме, на заднем колесе) и придумал к ним 5 режимов работы, на картинке проиллюстрировал схемку (пятый, когда горят все фулл-тайм). Так вот, написал кусок, как режимы можно переключать, с помощью тактовой кнопки (через switch, я так понял). Но, не могу понять вот что:
1) все пять режимов надо делать отдельно, уж больно разная у них структура, но пихать все в луп, это бред (как мне сейчас кажется), но, надо же как-то сделать так, чтобы при вызове режима он повторялся по кругу (не через goto делать же). Как сделать так, чтобы не будучи в void loop они по кругу шли, а в лупе только выбирклка режимов лежала, например, или как это в лупе все уместить?
2) как сделать бегущую строку, если при этом ножки нужные не идут друг за другом, да еще и в ШИМе, к тому же на схеме видно, что пульсация каждой группы сдвинута на пол-фазы относительно другой. Как сделать так, чтобы вторая/третья группа загоралась, когда первая/вторая группы находятся в апогее?
Я программированием вообще в жизни никогда не занимался, и даже родить переключение режимов с программным тушением дребезга кнопки мне стоило больших усилий. В примерах искал, но они все одинаковые, и даже приблизительно похожего ничего нет. Подскажите, что делать, плз.
Вот схема на имэйджшак img508.imageshack.us/img508/8174/unled1cc.jpg

Конечно не стоит все в loop засовывать, каждый режим оформляй отдельной фунцией и их вызывай в зависимости от выбранного режима через switch.
Схему, кажется, понял, сейчас попробуем. А про бегущий огонь такой хитрый нет идей? Мозг уже сломал, как его так сделать получше
Объяви глобальную переменную (т.е. вне loop и функций) для хранения номера такта и три для хранения номеров выходов led
int led1 = 7; //номера выходов int led2 = 8; int led3 = 9; int tick = 0; //номер текущего такта void runningLight () { switch (tick) { case 0: // тут для первого нулевого такта digitalWrite(led1, HIGH); digitalWrite(led2, LOW); digitalWrite(led3, HIGH); break; case 1: // для второго такта и т.д. break; } //Потом проверяешь не последний ли такт (у тебя их шесть из рисунка if (tick>=5) { tick = 0; } //если последний идешь в начало else {tick++;}//если нет, то просто прибавляешь 1 к номеру такта }Как то так, не забудь выставить pinMode(led1,OUTPUT) для каждого светодиода
А разделить на 6 тактов таким образом я чего-то не догадался, спасибо!
UPD: спасибо, помогло, только чего-то я с последовательностью напутал :) но это мелочи, главное, алгоритм понятен
Вопрос касательно оператора switch. Как в него можно запихать конструкцию, содержащую ШИМ, в смысле управление яркостью светодиода?
конструкция типа этой:
Это только свитч, без остальных кусков программы. При нажатии кнопки к переменной wMode плюсуется один, режим
int brightness = 0; int fadeAmount = 5; switch (wMode) { case 1: analogWrite (9, brightness); brightness = brightness + fadeAmount; if (brightness == 0 || brightness == 255) { fadeAmount = -fadeAmount ; } delay (30) break; case 2: //****** break; }переключается. ШИМ без свитч работает нормально, но запихиваешь его в switch и, такое впечатление, что счетчик плюсует fadeAmaunt только один раз, и скидывает, походу из-за break. Как можно сделать так, чтобы ШИМ работал нормально?
А может проблема в отсутствии ; после delay(30) в 15-ой строке?
М, точку с запятой сейчас забыл, он есть, компилятор бы матерился, если бы его небыло
Приведи весь код.
Весь так весь :)
//выходы/входы****************************************** const int switchPin = 12; //константа для входа кнопки const int ledPin1 = 3; //константа для выхода диода 1 const int ledPin2 = 5; //константа для выхода диода 2 const int ledPin3 = 6; //константа для выхода диода 3 //общие переменные************************************** int wMode = 1; //переменная переключенмя режима мигалки // переменные для дребезга****************************** boolean lastButton = LOW; //состояние кнопки в прошлый раз boolean currentButton = LOW; //хранит текущее положение кнопки //переменные для режима 2******************************* boolean ledState = LOW; //последнее состояние кнопки long prevMillis = 0; //последнее состояние счетчика времени long interval = 500; //интервал мигания //Переменные для режима 3*******************************i int brightness = 0; int fadeAmount = 5; //****************************************************** void setup() { pinMode(switchPin, INPUT); //кнопко-ногу на вход pinMode(ledPin1, OUTPUT); //диодо-ногу 1 на выход pinMode(ledPin2, OUTPUT); //диодо-ногу 2 на выход pinMode(ledPin3, OUTPUT); //диодо-ногу 3 на выход } //*********Стабилизация дребезга кнопки***************** boolean debounce(boolean last) //булевая Функция debounce { boolean current = digitalRead(switchPin); //узнаем текущее положение кнопки if (last != current) //сравниваем ласт и курент, то есть узнаем, нажата ли кнопка { delay(5); //ждем дребезг current = digitalRead(switchPin); // считываем спокойное состояние кнопки еще раз } return current; // возвращаем в функцию значение куррент } void loop() { currentButton = debounce(lastButton); if (lastButton == LOW && currentButton == HIGH) //Проверяем последнее и текущее состояние кнопки { wMode = wMode + 1; //если кнопка нажата плюсуем к переменной кнопки один } switch (wMode) // по нажатию 1 раз, меняем режим из 3 + в случае превышения 4 строкой выше, скидываем до 1 { case 1: // Full time режим**************************************** digitalWrite (ledPin1, HIGH); //мигаем всем пачкой digitalWrite (ledPin2, HIGH); digitalWrite (ledPin3, HIGH); break; case 2: // Blink режим******************************************** { unsigned long curMillis = millis(); if(curMillis - prevMillis > interval) { prevMillis = curMillis; // сохраняем время последнего переключения if (ledState == LOW) // если светодиод не горит, то зажигаем, и наоборот ledState = HIGH; else ledState = LOW; } digitalWrite (ledPin1, ledState); // устанавливаем состояния выхода, чтобы включить или выключить светодиоды digitalWrite (ledPin2, ledState); digitalWrite (ledPin3, ledState); break; } case 3: // Blink режим******************************************** analogWrite (ledPin1, brightness); analogWrite (ledPin2, brightness); analogWrite (ledPin3, brightness); brightness = brightness + fadeAmount; if (brightness == 0 || brightness == 255) { fadeAmount = -fadeAmount ; } delay (30); break; } lastButton = currentButton; }На беглый взгляд все ОК. Я бы порекомендовал вместо brightness == 0 || brightness == 255 всегда использовать brightness <= 0 || brightness >= 255 на случай если переменная пролетит точное значение. В данном случае вроде непринципально, но так обычно безопаснее проверять.
Вставь в setup Serial.begin(9600);
а в case 3 для дебага
и посмотри, что будет возвращать, может мысли придут, еще можно проверить, что у тебя wMode, можно тоже вставить вывод где-нибудь до switch
Хорошая идея на счет больше меньше. Буду смотреть в чем дело. Спасибо
>void loop() {
> currentButton = debounce(lastButton);
> if (lastButton == LOW && currentButton == HIGH) //Проверяем последнее и текущее состояние кнопки
> {
> wMode = wMode + 1; //если кнопка нажата плюсуем к переменной кнопки один
> }
и так далее...
Или я что-то упустил, или wMode принимает у вас значения 1, 2, 3, 4, 5, и так далее - увеличиваясь при каждом новом нажатии кнопки.
Хотите несколько раз вызывать ветви switch'а - сбрасывайте wMode на ноль после превышения максимального значения
ЗЫ:
комментарий с намеком на подобное действо вроде как нашелся:
// по нажатию 1 раз, меняем режим из 3 + в случае превышения 4 строкой выше, скидываем до 1
а вот самого скидывания что-то не видно
Да, у меня дефолтовым действием было скидывание до нуля, удалил наверное
Странное дело: сначала воткнул, потом убрал Serial.begin и всю фигню, и все заработало как надо, сейчас убрал - тоже все ок. Мистика. Ну да ладно. Осталось только две бегущие дорожки прикрутить (с пульсацией и без неё) и энкодер для управления скоростью мигания, а дальше - железячная часть.
Думаю, вопросы еще будут