Подсветка лестницы
- Войдите на сайт для отправки комментариев
Сб, 22/09/2012 - 21:53
Работаю электриком. Начал изучать программирование Arduino. Загорелся написать код, для включения ступенек лестницы. Если нажал на кнопку в низу лестницы, то ступеньки должны загораться по очереди вверх. А если дошел до верха и там нажал на кнопку, то ступеньки должны выключится в такой последовательности с низу на верх. Когда идешь с верху в низ, то ступеньки должны включаться и выключаться сверху в низ. А у меня почему то выключаются со второй кнопки в обратном порядке. Немогу сам додуматься. ПОМОГИТЕ.
int knopka=0; int knopka2=0; void setup () { pinMode(2,OUTPUT); pinMode(3,OUTPUT); pinMode(4,OUTPUT); pinMode(5,OUTPUT); pinMode(12,INPUT); pinMode(11,INPUT); } void loop () { if(digitalRead(12)==LOW&&knopka2==0)//если кнопка нажата // и перемення "knopka2" равна 0 , то ... { delay(50); knopka2++;//пишем 1 в переменную кнопка //это нужно для того что бы с каждым нажатием кнопки //происходило только одно действие digitalWrite(2, !digitalRead(2));//меняем значение порта на противоположное delay(1000); digitalWrite(3, !digitalRead(3)); delay(1000); digitalWrite(4, !digitalRead(4)); delay(1000); digitalWrite(5, !digitalRead(5)); delay(1000); } if(digitalRead(12)==HIGH&&knopka2==1)//если кнопка НЕ нажата //и переменная knopka2 равна - 1 ,то ... { knopka2=0;//обнуляем переменную "knopka2" } if(digitalRead(11)==LOW&&knopka==0)//если кнопка нажата // и перемення "knopka" равна 0 , то ... { delay(50);//защита от дребезга knopka++;//пишем 1 в переменную кнопка //это нужно для того что бы с каждым нажатием кнопки //происходило только одно действие digitalWrite(5, !digitalRead(5));//меняем значение порта на противоположное delay(1000); digitalWrite(4, !digitalRead(4)); delay(1000); digitalWrite(3, !digitalRead(3)); delay(1000); digitalWrite(2, !digitalRead(2)); delay(1000); } if(digitalRead(11)==HIGH&&knopka==1)//если кнопка НЕ нажата //и переменная knopka равна - 1 ,то ... { knopka=0;//обнуляем переменную "knopka" } }
Надо с алгоритмом определиться...
Типа :
- кнопка НИЗ ( идём вверх )
- ступенчатое вкл ступеней вверх
- кнопка Верх ( дошёл )
- ступенчатое выкл ступеней вверх
- НЕТ кнопки Верх ( передумал идти )
- гашение подстветки
.
вниз - так же....
.
...надо граф состояний построить, Вы в логике событий чуть запутались....
Моя - тоже начинающий.... Но - не в логике.....
Ваша задача - тока без кнопок :)
http://habrahabr.ru/post/142685/
Моя бы пошла по Вашему пути, с кнопками.... На макете....
Оставьте тот же порядок, что и при нажатии на первую кнопку
Код по смыслу идентичный тому который дал Максим.
Только номера светиков оформил массивом (что-бы легче было менять пины и их количество) и убрал дублирование кода выносом переключения состояния светиков в отдельную фукнцию.
Не каждый новенький - опытный..... Нельзя ли открыть ветку - " "чЯйники" и их вопросы " ?
WZV - если Ваши ответы поймёт, то "не неопытный" ! Мне трудно понять, что Вы наговорили..... Сразу понять...
....терпение, тока терпение :(
Перед регистрацией - или СРАЗУ после - стОит преподать навыки пользования новичку.....
....а не потом вгонять его в ступор - посмотри там, посмотри сям :(
Это критика была...... :(
....в защиту МАЛЕНЬКИХ !!!!!!
Ну вот чуть чуть опоздал со своей помощью. Но один фиг заброшу свой код, может кому прегодится.
Вот надеюсь будит работать так как надо. Сам не дуине не проверял, но вот тестовый код на ЯВЕ заработал так как надо.
Тут пример на JAVA
Есть лесница, предположим, что в данном случае кнопка 1 находится на нижней ступеньке, а кнопка 2 на верхней, когда мы идем на верх, то ступеньки поочередно подсвечиваются снизу в верх и поочередно тухнут тоже с низу в верх. По логике вещей надо бы чтобы когда мы идем в обратном напрравлении (то есть спускаемся по леснице) ступеньки подсвечивались/тухли с верху в низ.
Этот алгоритм реализован в коде ich'а, я подредактировал вариант leshak'а, получилось как-то так:
На сколько чисто освобождает этот кусочик, кнопку от дребезга?
Я как-то пытался на лабе освободить кнопку от дребезга с помощью кондёров и резисторов, нифига не вышло. Пришлось мутить с NOT-IC и т.д.
Я обычно ставлю 150 - 200, этого в полне достаточно для устранения дребезга при нажатии пальцем, а точнее это минимальное время между нажатиями, которые можно сделать пальцем. Дребезга при этом не замечал. Странно что не получилось избавиться от дребезга кондерами...
В данном случае нет смысла избавляться от дребезга при нажатии, так как после первого же срабатывания кнопки начнется цикл подсветки, а он длится долго. Но есть смысл поставить задержку для устранения дребезга при отпускании кнопки... но это только в том случае если кнопка еще не отпущена, а цикл подсветки уже закончился.
....а не потом вгонять его в ступор - посмотри там, посмотри сям :(
Ветки прикрепленные - есть. Только их же никто не читает. Заходят на форум, не пытаются, для начала посмотреть "что уже есть" - сразу заводить свою. Даже если такая же тема уже есть тремя строками ниже.
Если бы их читали - половина "посмотри там, посмотри сям" - небыло-бы. А втроая половина эта - банальный здравый смысл и уважение к другим. Его в FAQ никак не напишешь. Что нужно написать в faq? Перед постом прочитайте глазами другого человека? Задумайтесь соотвествует ли тема тому что вы дальше будете писать? Имеет ли она хоть какой-то смысл? Дайте ссылки/схемы на то что вы используете? Если не предполагать в новичках здравый смысл, то FAQ будет на 5-ть страниц. И его, опять-таки, никто читать не будет. Повесить большими буквами "пишите со смыслом"?
На сколько чисто освобождает этот кусочик, кнопку от дребезга?
Смотря что вы подразумеваете под "чисто". Если "от ложных сработок" - то да. довольно нормально (особенно если, как сказал Максим, число чутьб ольше сделать".
Смотрите что у вас происходит.
При нажатии кнопки ( предположим она 0 - не нажата, 1 - нажата) вот такая картина на ней.
0,0,0, (начинаем-нажимать), 1,0,0,1,0,1,1,0,1 , (дожалось плотно, дребезг прекратился), 1,1,1,1,1,1, (отпустили), 0,1,1,0,1,0,0 (полностью отжалась) ,0,0,0,0,0,0
Вот такая картину у нас без "анти дребезга". Как видим у нас, хотя мы нажали один раз имеется куча "нажатий отпусканий". Спасает то что они "очень кратковременны". Теперь. Если мы, после первой же 1 вставили delay(), то контроллер просто перестает на что-либо реагировать (пока delay() работает). И если он "проснулся" к тому времени когда кнопка уже пришла в состояние "полностью отжалась" - все "дребезги", он "проспал".
Вообщем мы как бы "выкинули" из его жизни то кусок времени когда происходит дребезг.
Если же вы имеете ввиду под "чисто" - какие-то побочные эффекты, то... да. delay() - крайне нежелательная функция в реальных скетчках. Он останавливает скетч. В этот момент ничего не происходит. Например если в этот момент будет нажата другая кнопка - мы провороним это (или какой-то счетчик импульсов у нас, или степеер в этот момент хотим крутить и т.п.). У нас нет "многозадачности". А delay() - все забрал на себя.
Поэтому, в реальных скетчках, идет скорее такой подход.
Запоминаем, где-то в конце loop, предыдущие состояние кнопки. В начале loop, читаем кнопки сравниваем "предыдущие и текущие" состояние. И выясняем поменялось оно или нет (и куда, нажали или отжали). Этим макаром мы избавляемся от многократных сработок типа "нажали кнопку и держат". Далее когда мы заметили что состояние "изменилось" - мы с помощью millis() - запоминаем когда изменилось. И теперь, кроме проверки того-что изменилось, проверяем еще "а сколько прошло времени с прошлого изменения". Если меньше какой-то порога - игнорируем (значит это дребезг).
Или, вместо "запомнили когда было изменения", просто делаем опрос кнопок не при каждом проходе loop, а раз, к примеру в 200 msec. Тогда, опять-таки, все "мелкие дребезги" мы проморгаем.
Но, естественно, при таких подходих и при зажигании/гашении диодов желательно отказатся от использования delay().
Кстати побочным эффектом этого, станет возможно завести "аварийную кнопку". Типа диоды пошли зажигатся, а мы передумали и нажали "стоп". С deley() - это не возможно. Пока он выполняется "мы глухи и слепы".
Я Вам всем благодарен господа за помощь. Прошу не судить меня строго, я ведь обычный электрик, который в свои 46 лет заинтересовался программированием Arduino. А ведь понять программирование в одиночку, в таком возрасте, не очень легко. Но я окунувшись в это, влюбился в Arduino. Да и для моей работы это дает большие возможности, поэтому не смотря ни на что, я буду развиваться в этом направлении.
Смотря что вы подразумеваете под "чисто". Если "от ложных сработок" - то да. довольно нормально (особенно если, как сказал Максим, число чутьб ольше сделать".
...
Если же вы имеете ввиду под "чисто" - какие-то побочные эффекты, то... да. delay() - крайне нежелательная функция в реальных скетчках. Он останавливает скетч.
Спасибо, как всегда на высоте и доступно.
Под "чисто" конечно я имел в виду всётаки второй вариант. Так как знаю что delay() замараживает всю работу программы.
Я бы конечно пытался бы лучше решать пробоему дребезга не с программной стороны а с железячной. Но как я уже пЫсал, кондёров и резисторов не достаточно. Или у меня руки золотые и ростут из золотой ...ы . Хотя нет, я ведь на Лабе не один был, по этому шанс корявых рук тендирует к нулю.
Я бы конечно пытался бы лучше решать пробоему дребезга не с программной стороны а с железячной. Но как я уже пЫсал, кондёров и резисторов не достаточно. Или у меня руки золотые и ростут из золотой ...ы . Хотя нет, я ведь на Лабе не один был, по этому шанс корявых рук тендирует к нулю.
А я не вижу чем тут железное лучше (кроме экономии памяти). Фактически вы делаете обсолютно тоже самое - импульсы меньше какой-то длины "сжираете" конденсатором. Делаете их не существующими для контроллера. Но... становитесь зависимы от точности самих деталей. У них же тоже параметры гуляют. Как он производителя, так и от температуры, качества дорожек и т.п. Плюс, на конденсаторе если "шумящие ипульсы" идут слишком часто он может "переполнится" и не отфильтровать все помехи. Это как на машине. Одинокую яму - амортизатор отработает. А вот если у вас 300 метров стиральной доски - в итоге удары уже пойдут на корпус. Он не будет испевать "разжиматся". "Програмный" - не имеет памяти. Ему что 10, что 100 импульсов по 5-ть мсек - без разницы. Главное что все они "меньше порога".
Аппаратный - так легко не подстроишь. 50 мсек, на 200 мсек - легкиим движением не поменяешь. Да и вообще четко "вот ровно 200 порог" - не сделаете. Поменялась температура - поменились харрактеристики вашей RC-цепочки и т.п. Решили на другом вольтаже работать - опять переделывай... . Аккум подсел - поплыли временные характеристики...
Вообщем, возможно во мне говорит программер :) Мне всегда програмное нравится больше. Так как оно более подконтрольно и детерменировано. По крайней мере для меня.
P.S. Плюс чем больше делателей тем дороже, больше размер, меньше надежность (больше возможных точек отказа).
Прошу не судить меня строго,
Мне вот интерестно, почему все новички ждут что тут будут кого-то судить? Ардуино - платформа любителей (не потому что "она слаба", а маркетинг так ее спозиционировал). А если и будуn, то вам-то что? Ваша жизнь поменяется от мнения незнакомых вам людей? :)
Негатив и тыкание носом, обычно, происходят не от малых "програмерских знаний", а на уровне межчеловеческого общения. Когда человек "не читает ответы", не дает достаточно инфы о своей проблеме, ленится сам приложить усилия, хочет что-бы ему на блюде все подали....и т.п.
По поводу возраста - поверте освоить рояль намного сложней :) И не накручивайте сами себя по поводу "это сложно". Да и все.
Хотя, конечно, возможно, будет немного сложновато перестроить мышления с "аналогового", на "дискретный". Вы, как электрик, скорее всего привыкли что у вас все происходит "одновременно", а тут не так. Когда пишите програму, пытайтесь себя представить контролером, а программу "пошаговым рецептом". Причем за раз может выполнятся только один шаг. Приучайтесь смотреть на программу и пытатся выполнить ее в голове вместо контроллера. Вообразить "что при этом происходит". На каждой строчке.
Можете, для облегчение понимания логики програмы, взять бумажку. Нарисовать на ней овалы в которых подписаны состояния вашего контроллера, типа "диоды выключены", "зажигаем_диоды" (процесс), "диоды включены", между ними стрелочки указывающе из какого состояния в какой можно переходить. Над стрелочками подписать при каких условиях может происходть этот переход. Например из "диоды выключены" в "диоды включены" переходим при "нажата кнопка 1".
Такая бумажка и вам может помочь разложить "по полочкам", и, если эту картинку на форуме опубликуете, другим понять "что же выхотите". Быстрее найти различие между "что нужно" и "как это реализовано в коде".
Переименовал тему в более отражающую "суть". А то меня каждый раз "типает", от взгляда на главную страницу с такой темой:) Надеюсь не будете возражать.
Поправил только здесь: if(digitalRead(knopka1) == LOW) и if(digitalRead(knopka2) == LOW)
Заработало хорошо в варианте верняя кнопка нажата. Вариант, нижняя кнопка нажата, спупени включаются в нужном порядке, после этого кнопки на сигнал не реагируют, Arduino зависает нужно делать reset. Долго искал причину, но ума не хватило.
Выложите крайнюю версию скетча, пожста.
Извиняюсь не написал что использовал код ich
код ich
Лучше весь снова, с Вашими исправлениями..... Хочется тоже изучить, как пишут опытные....
Поправил только здесь: if(digitalRead(knopka1) == LOW) и if(digitalRead(knopka2) == LOW)
Интересно, а какая у вас логика в кноках? При нажатии на кнопку вы садите её на "LOW-минус" а при отпущенной на "HIGH-плюс"?
Arduino зависает нужно делать reset. Долго искал причину, но ума не хватило.
...
Извиняюсь не написал что использовал код ich
Я на ардуине не пробывал, но явавский-алгоритм работал как надо. Завтро если будет время гляну ещё разок.
Интересно, а какая у вас логика в кноках? При нажатии на кнопку вы садите её на "LOW-минус" а при отпущенной на "HIGH-плюс"?
А чему вы так удевляетесь?
1. У ATMega нет PULL-DOWN, но есть PULL-UP резисторы, поэтому более логично использовать именно такую логику, дабы не паять лишние подтягивающие резисторы.
2. Это мугут быть и не кнопки, а какие-нибудь датчики, у которых сигнальный вывод при срабатывании "опускается" к GND, я бы даже сказал, что большенство цифровых датчиков именно так и работает.
А так ?
Тестовый вариант :
Боевой :
Попробуйте помаргать LED на 13 Пине для чтобы точно знать что Дуина повисла, а не ушла в неизвестное состояние. В верхнем коде я добавил маргание Info-LED. Нажимаете кнопку лампочка загарелась, алгоритм прокрутился лампочка потухла. Таким оброзом можно отследить нажатие кнопок и за одно понять висит дуина или нет.
Заодно и вопрос :
Прерывания 0 и 1 имеют приоритеты между собой ?
Пока тестил по 2 секунды на ступенку заметил, что пока выполняется ВВЕРХ - нет реакции на прерывание 1.
И пока выполняется ВНИЗ - нет реакции на прерывание 0.
Расскажите, пожста, в описаниях - не нашёл.....
Заодно и вопрос :
Прерывания 0 и 1 имеют приоритеты между собой ?
Да имеют - 0 приоритней 1.
Пока тестил по 2 секунды на ступенку заметил, что пока выполняется ВВЕРХ - нет реакции на прерывание 1.
И пока выполняется ВНИЗ - нет реакции на прерывание 0.
Расскажите, пожста, в описаниях - не нашёл.....
Прерывания срабатывают, но в тот момент, когда идет цикл подсветки никак не влияют на ход программы.
Только я логику поменял....
Нажали внизу - вкл_1 - секунда - выкл_1 и вкл_2 - секунда - выкл_2 и вкл_3 - секунда - выкл_3 и вкл_4 - секунда - выкл_4 .
Нажали вверху - бегущая ступенька вниз.
Ваша задумка :
Нажали внизу - вкл_1 - секунда - вкл_1 и вкл_2 - секунда - вкл_1 и вкл_2 и вкл_3 - секунда - вкл_1 и вкл_2 и вкл_3 и вкл_4 .
Светятся 4 ступени.
Передумали подниматься - нажали внизу - подсветка всех ступеней выкл.
Всё-таки взобрались и нажали вверху - выкл_1 - секунда - выкл_2 - секунда - выкл_3 - секунда - выкл_4 .
Сверху вниз - идентично.
Вы так задумали ?
Когда выполняется void GetUp() или void GetDown() - нет реакции на прерывания !!!!!!
В этот момент уже мы вышли же из прерывающих void GetUpIR() или void GetDownIR()......
И в чём приоритет 0 перед 1 ? Если выполняется прерывающая_1 и пришло прерывание_0 - будет выход из прерывающей_1 и запустится прерывающая_0 ?
А чему вы так удевляетесь?
1. У ATMega нет PULL-DOWN, но есть PULL-UP резисторы, поэтому более логично использовать именно такую логику, дабы не паять лишние подтягивающие резисторы.
2. Это мугут быть и не кнопки, а какие-нибудь датчики, у которых сигнальный вывод при срабатывании "опускается" к GND, я бы даже сказал, что большенство цифровых датчиков именно так и работает.
И действительно, Вы правы. Прсто я пока начинаю осваивать апарат, навыка ещё нету чтобы сразу очевидне в глаза бросилось. Я бы к Вашему примеру поткрепил бы ещё вот эту ссылку . Так как для новичков не сразу понятно что происходит в Вашем примере. Мне прешлось по "Гогэлить" чтобы понять что Вы придумали. ;-)
Это не мой пример.
Ага... Я цитирует Максима, а ответил мне....
Спасибо за подсказку, буду комментить всё - что прерывания использованы и прямое управления выходами через регистры микроконтроллера Atmega.
Попробуйте помаргать LED на 13 Пине для чтобы точно знать что Дуина повисла, а не ушла в неизвестное состояние. В верхнем коде я добавил маргание Info-LED. Нажимаете кнопку лампочка загарелась, алгоритм прокрутился лампочка потухла. Таким оброзом можно отследить нажатие кнопок и за одно понять висит дуина или нет.
В варианте "Верхняя кнопка нажата" LED на 13 Пине в начале алгоритма включается, в конце алгоритма выключается. А в варианте "Нижняя кнопка нажата" LED на 13 Пине в начале алгоритма включается, включаются ступени и все так зависает, кнопки не реагируют.
Попробуйте так:
Ура! Заработало maksim
Я очень благодарен ВСЕМ за помощь!!!
Попробуйте так:
Пожалуйста, пожалуйста, пожалуйста. Объясните мне что это за фокус? Я не думал что у uint8_t с цифрами от 0 до 4 поблемы. Или это гон из за глобальной перименной с, если да то мне это тоже интерессно почему.
Я особо не вникал в этот вопрос, но когда тип byte с, по какой то причине с-- глючит. Что там происходит я не знаю, ну и на всякий случай сделал с не глобальной....
А все понял. Смотрите:
что бы условие i >= 0 стало не верным i должна стать меньше нуля, а так как i не может быть отрицательной, то условие всегда будет верным и цикл получается вечный.
Поэтому надо объявлять тип char или int8_t.
Ну точно. Блин вот я дал, где глаза то были.
Спасибо за проведённую экспертизу! ;-)
Тогда можно так: