RGB лента и arduino mega
- Войдите на сайт для отправки комментариев
Доброго времени суток, форумчане. На форуме человек новый, еще не освоился, так что если есть решение моей проблемы - ткните носом пожалуйста "новичка".
Суть проблемы такая.. Задался соорудить такой проект - http://cxem.net/beginner/beginner61.php. Собрал, зашил код - все работает. Потом вдруг захотелось немного модернизировать это все дело и добавить несколько кнопок, чтоб можно было управлять светом (горит только красный, только синий, зеленый и кнопка выключения всего этого). Как эти кнопки подключать к ардуине нашел. Вроде непроблема. Там же и был код программы. Схему пока не собирал, не все элементы есть. Собрал кусок кода со своим и вот, что получилось.
//оглашение пинов контроллера #define REDPIN 5 //подключение контактов ленты #define GREENPIN 6 #define BLUEPIN 3 #define FADESPEED 5 //скорость затухания const int FADEBTN = 7; //кнопки const int REDBTN = 8; const int GREENBTN = 9; const int BLUEBTN = 10; const int PWRBTN = 11; void setup() { pinMode(FADEBTN, INPUT); //Входы pinMode(REDBTN, INPUT); pinMode(GREENBTN, INPUT); pinMode(BLUEBTN, INPUT); pinMode(PWRBTN, INPUT); pinMode(REDPIN, OUTPUT); //Выходы pinMode(GREENPIN, OUTPUT); pinMode(BLUEPIN, OUTPUT); } void loop() { int r, g, b; int fadeButtonState = 0; //первоначальное состояние кнопок int redButtonState = 0; int greenButtonState = 0; int blueButtonState = 0; int pwrButtonState = 0; fadeButtonState = digitalRead(FADEBTN); //считываются состояния кнопок redButtonState = digitalRead(REDBTN); greenButtonState = digitalRead(GREENBTN); blueButtonState = digitalRead(BLUEBTN); pwrButtonState = digitalRead(PWRBTN); if (fadeButtonState == HIGH) { //если нажата кнопка fade - режим затуханий for (r = 0; r < 256; r++) { analogWrite(REDPIN, r); delay(FADESPEED); } for (b = 255; b > 0; b--) { analogWrite(BLUEPIN, b); delay(FADESPEED); } for (g = 0; g < 256; g++) { analogWrite(GREENPIN, g); delay(FADESPEED); } for (r = 255; r > 0; r--) { analogWrite(REDPIN, r); delay(FADESPEED); } for (b = 0; b < 256; b++) { analogWrite(BLUEPIN, b); delay(FADESPEED); } for (g = 255; g > 0; g--) { analogWrite(GREENPIN, g); delay(FADESPEED); } } else if (redButtonState == HIGH) //если нажата кнопка red - красный свет { r = 256; b = 0; g = 0; analogWrite(REDPIN, r); } else if (blueButtonState == HIGH) //если нажата кнопка blue - синий свет { r = 0; b = 256; g = 0; analogWrite(BLUEPIN, b); } else if (greenButtonState == HIGH) //если нажата кнопка green - зеленый свет { r = 0; b = 0; g = 256; analogWrite(GREENPIN, g); } else if (pwrButtonState == HIGH) //если нажата кнопка pwr - отключить { r = 0; b = 0; g = 0; analogWrite(GREENPIN, g); analogWrite(BLUEPIN, b); analogWrite(REDPIN, r); } }
Хотел бы уточнить, все ли правильно написал?
>>Хотел бы уточнить, все ли правильно написал?<<
Если работает , то правильно. Насколько я понял ваша программа проходит по спектру циклично ?
В режиме fade - Да. Просто реализовать схему с кнопками нет возможности (нет под рукой всех элементов), буду пробовать вечером... Сам код загонял в отладчик - ошибок не обнаружилось. Думал может есть возможность сократить его и кто-то эту возможность подскажет. Скажем так, с программированием не силен, делал все на логике уже готовых кодов...
Я бы оставил одну кнопку. И управлял бы посредством переключения режимов.
То есть, если я правильно Вас понял, управление реализовать как в гирлянде китайской, по нажатию кнопки переключать по порядку режими? =)
Именно так. Ну максимум две-три кнопки. Не вижу смысла разводит клавиатуру.
хм... думал про это... попробую... осталось додумать как это все реализовать в коде... спасибо за подсказки =)
nestandart, не могли бы проглядеть модернизированный код под "одну" кнопку - не "зациклюсь" ли я в нем?
В принципе работать должно.
Но я бы сделал так.
Не зудьте про подтяжки.
О, я тоже думал все на оператор switch повесить... про подтягивающий резистор помню.... а вот такой еще вопрос... я питаю кусок светодиодной ленты от внешнего источника питания в 12V через вывод ардуины VIN. Если я добавлю кнопку, то ее надо запитать от 5V, вот вопрос - можно ли одновременно питать ардуино сразу от двух источников питания - внешнего и от USB?
О, я тоже думал все на оператор switch повесить... про подтягивающий резистор помню.... а вот такой еще вопрос... я питаю кусок светодиодной ленты от внешнего источника питания в 12V через вывод ардуины VIN. Если я добавлю кнопку, то ее надо запитать от 5V, вот вопрос - можно ли одновременно питать ардуино сразу от двух источников питания - внешнего и от USB?
Если вы питаете плату внешним источником на 12V, то 5В для кнопки можно взять с пина +5V. В ардуине есть стабилизатор напряжения.
Если вы питаете плату внешним источником на 12V, то 5В для кнопки можно взять с пина +5V. В ардуине есть стабилизатор напряжения.
Спасибо. Буду знать. =)
Эээх. Собрал схему. Видоизменил код под оператор switch, но происходит так, что при одном нажатии кнопки запускается режим мигания (то бишь case 1), а дальше на нажатия кнопки не реагирует...=(( Что сделал не так, не пойму...
Эээх. Собрал схему. Видоизменил код под оператор switch, но происходит так, что при одном нажатии кнопки запускается режим мигания (то бишь case 1), а дальше на нажатия кнопки не реагирует...=(( Что сделал не так, не пойму...
А как долго держите кнопку? Может быть, вам посчастливилось нажатием попадать именно в исполнение кода "режим 1"? Попробуйте кнопку повесить на прерывание. Ну или сделайте:
Что бы видеть, распозналось ли нажатие кнопки.
Нажатие короткое. Нажал - бросил. Чуть позже попробую добавить строку вывода сообщения.
Нажатие короткое. Нажал - бросил. Чуть позже попробую добавить строку вывода сообщения.
Подержите её, пока цикл режима 1 не закончится. Он у вас, если я не ошибся в подсчётах - чуть больше 7 секунд длиться. Код, считывающий состояние кнопки - мгновение по сравнению с этим, скорее всего действительно не попадаете.
Подержите её, пока цикл режима 1 не закончится. Он у вас, если я не ошибся в подсчётах - чуть больше 7 секунд длиться. Код, считывающий состояние кнопки - мгновение по сравнению с этим, скорее всего действительно не попадаете.
Спасибо за подсказку. Сейчас попробую. Уже все собрал. Проблема только с выводом сообщения. У меня на ПК стоит Debian и почему то программная среда из под линукса не видит вывод сообщений.
Спасибо за подсказку. Сейчас попробую. Уже все собрал. Проблема только с выводом сообщения. У меня на ПК стоит Debian и почему то программная среда из под линукса не видит вывод сообщений.
У меня под дебианом, убунтой и федорой всё выводится. Может быть, порт не тот выбран?
У меня под дебианом, убунтой и федорой всё выводится. Может быть, порт не тот выбран?
Возможно. У меня выбран порт Tools->Serial Port-> /dev/ttyUSB0. Программа заливается на ура... может что-то недонастроил?
Еще вопросик, чтоб увидеть вывод сообщения это ж ардуина должна быть подключена юсб кабелем. Одновременно у меня она питается от внешних 12В. Это ж не смертельно для дуины??
Еще вопросик, чтоб увидеть вывод сообщения это ж ардуина должна быть подключена юсб кабелем. Одновременно у меня она питается от внешних 12В. Это ж не смертельно для дуины??
Если прошивка заливается, и дым не идёт, значит не смертельно.
Собственно, я понял, в чём проблема. Нужно же ещё в setup() написать:
Serial.begin(9600);
Если прошивка заливается, и дым не идёт, значит не смертельно.
Собственно, я понял, в чём проблема. Нужно же ещё в setup() написать:
Serial.begin(9600);
Про дым улыбнуло =) Страшно по незнанию спалить довольно-таки недешевый контроллер. Спасибо за поправку. Я тоже как то пропустил строку инициализации порта и монитора. Запустил. Результат такой, что не всегда срабатывает кнопка - т.е. нажимаю первый раз - мигание, нажимаю через 7 сек. второй раз - в мониторе ничего не пишет. Нажимаю сразу третий раз - включился почему то 4-й case. Видимо что-то не так в программе... ((
Если прошивка заливается, и дым не идёт, значит не смертельно.
Собственно, я понял, в чём проблема. Нужно же ещё в setup() написать:
Serial.begin(9600);
Про дым улыбнуло =) Страшно по незнанию спалить довольно-таки недешевый контроллер. Спасибо за поправку. Я тоже как то пропустил строку инициализации порта и монитора. Запустил. Результат такой, что не всегда срабатывает кнопка - т.е. нажимаю первый раз - мигание, нажимаю через 7 сек. второй раз - в мониторе ничего не пишет. Нажимаю сразу третий раз - включился почему то 4-й case. Видимо что-то не так в программе... ((
На самом деле, микросхемы работают на дыме. Когда дым выходит, микросхема перестаёт работать. Ничего страшного не будет при таком подключении. Разве что компьютер может отказаться определять ардуину потому, что она по USB не потребляет ток.
В коде вроде всё верно. Попробуйте сделать режимы "попроще". Например. Режим 1 - просто постоянно горит красный, 2 - синий, 3 - зелёный, 4 - все сразу. И на простом коде отлаживайте.
Да, была у меня мысль попробовать с одноцветными режимами. Ну что ж, буду пробовать отлаживать. Спасибо за подсказки и помощь. Постараюсь отписаться если все получится...
Отчитаюсь. Сделал все по простому... одноцветные режими. Все работает, но только наблюдается "дребезг" кнопки, т.е. нажимаю один раз, а в мониторе отображается два нажатия, соответственно режими перескакивают. =((
Отчитаюсь. Сделал все по простому... одноцветные режими. Все работает, но только наблюдается "дребезг" кнопки, т.е. нажимаю один раз, а в мониторе отображается два нажатия, соответственно режими перескакивают. =((
Ну дык... Можно "по хардкору" добавить delay(150); после считывания состояния кнопки. Можно по умному. "Умных" вариантов несколько. Библиотека Bounce, засекание времени от момента последнего изменения состояния кнопки, конструкция с RC-цепью и компаратором... Подробности в гугле.
Собственно, мне пока всегда delay(150); хватало.
150 много. delay(10); после того как изменили regim.
Спасибо всем откликнувшимся... буду экспериментировать...
Как бы отчет. Все заработало с delay(50). Добавил его сразу перед увеличением переменной Regim. Когда ставил его после увеличения, то все равно присутствовал "дребезг".
Еще раз спасибо откликнувшимся. На вашем форуме можно узнать много интересного и полезного...
А "сложный" алгоритм теперь работает нормально?
К сожалению нет. =( С этим пока не разобрался. Сделал так, что "сложный" алгоритм вставил в конец подпрограммы.
Как только нажимаю 5-й раз кнопку режим мигания включается и "зацикливается", т.е. на нажатия кнопок не реагирует (монитор показывает что кнопка не нажимается)... еще не понял как сделать прерывание этого алгоритма по нажатию кнопки... но думаю, что я "победю" =))) его!
Как только нажимаю 5-й раз кнопку режим мигания включается и "зацикливается", т.е. на нажатия кнопок не реагирует (монитор показывает что кнопка не нажимается)... еще не понял как сделать прерывание этого алгоритма по нажатию кнопки... но думаю, что я "победю" =))) его!
Тоже сначала пугался прерываний. А всё просто же. Примерно так:
Теперь нажатие кнопки (которая теперь должна "висеть" на втором пине обработаются в любом случае. Но режим не изменится мгновенно. Что бы режим мгновенно менялся, после нажатия кнопки, нужно сделать так (выглядит плохо, но ничего умнее я не придумал): "маленькие" режимы и так отрабатывают быстро (это с первого по четвёртый), а для пятого, во все циклы for нужно написать так:
if ( ! REGIM == 5 ) {break;} это заставит цикл мгновенно завершиться, если режим изменился. Что бы не городить такой "костыль" я бы значение ШИМ для каждого цвета хранил в глобальных переменных (rPWM, gPWM, bPWM), а внутри case просто выводил бы значение на пины и инкрементировал переменные. Примерно так:
Этот код раскрывает мою идею и не работает так, как нужно вам. Нужна ещё туча условий и дополнительные переменные. Так что непонятно, какой из вариантов на самом деле "костыль" :)
Плюс. Переменную REGIM нужно обьявить как volatile ( volatile
int
REGIM=0;).
И теперь снова вернётся проблема дребезга, но в нутри обработчика прерываний не работает delay(). Так что придётся завести отдельную переменную unsigned long timestamp=0; В которую писать время последнего вызова прерывания. и проверять её значение во время обработки прерывания. Примерно таким должен стать обработчик:
P.S.
Призываю дядек поумнее. А то может оказаться, что мои решения не особенно красивы и оптимальны.
Преклоняюсь перед Вашим знанием программирования, но я ввиду своей "лени" решил пойти может и неправильным, но более простым путем. Изучив как следует принцип работы сложного алгоритма, я просто-напросто добавил в каждый цикл перебора цветового спектра проверку "нажатия кнопки", тем самым у меня получилось прерывание по нажатию. Вот кусок "сложного" case'a:
Возможно код не получился компактным, но он работает! Спасибо огромное за подсказки и ликбез всех участников. =)