Официальный сайт компании Arduino по адресу arduino.cc
ШИМ, энкодер, кнопки и EEPROM
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Здравствуйте!
Помогите написать код к моему проекту
Вот суть:
Есть один аналоговый выход, на нем сидит светодиод. Есть энкодер подключенный к плате. И есть, например, десяток кнопок, подключенные к оставшимся ножкам контроллера. Задача следующая: При вращении энкодера значение на выходе меняется от 0 до 255, при выключении питания что бы значение записывалось в EEPROM и при подаче питания значение оставалось таким же. Кнопки: при длительном нажатии, например больше секунды, запоминал текущее значение на выходе а при кратковременном, на ту же кнопку, возвращал из любого значения на то что сохранил.
На этом форуме нашел код для работы с энкодером:
/* ** Энкодер ** Для управлением яркостью LED используется энкодер */ int brightness = 120; // яркость LED, начинаем с половины int fadeAmount = 10; // шаг изменения яркости LED unsigned long currentTime; unsigned long loopTime; const int pin_A = 8; // канал А энкодера на pin 8 const int pin_B = 7; // канал В энкодера на pin 7 unsigned char encoder_A; unsigned char encoder_B; unsigned char encoder_A_prev=0; void setup() { // declare pin 9 to be an output: pinMode(11, OUTPUT); // устанавливаем pin 11 как выход pinMode(pin_A, INPUT); pinMode(pin_B, INPUT); currentTime = millis(); loopTime = currentTime; } void loop() { currentTime = millis(); if(currentTime >= (loopTime + 5)){ // проверяем каждые 5мс (200 Гц) encoder_A = digitalRead(pin_A); // считываем состояние выхода А энкодера encoder_B = digitalRead(pin_B); // считываем состояние выхода А энкодера if((!encoder_A) && (encoder_A_prev)){ // если состояние изменилось с положительного к нулю if(encoder_B) { // выход В в полож. сост., значит вращение по часовой стрелке // увеличиваем яркость, не более чем до 255 if(brightness + fadeAmount <= 255) brightness += fadeAmount; } else { // выход В в 0 сост., значит вращение против часовой стрелки // уменьшаем яркость, но не ниже 0 if(brightness - fadeAmount >= 0) brightness -= fadeAmount; } } encoder_A_prev = encoder_A; // сохраняем значение А для следующего цикла analogWrite(11, brightness); // устанавливаем яркость на 11 ножку loopTime = currentTime; } }
А вот что делать дальше я не знаю.
Есть один момент, после каждого изменения значения на выходе записывать в EEPROM нельзя, крутить будут много и быстро можно убить микросхему. Поэтому выход из положения я вижу так:
Считываем значение из памяти, если совпадает с значением на выходе то ничего не трогаем а если значение изменилось, ждем 5 секунд и перезаписываем значение в EEPROM.
Помогите пожалуйста.
Кнопки при нажатии должны замыкать пин на землю(GND). В примере только 2 кнопки, остальные пишите по аналогии.
Работспособность не проверял, если что не так отпишитесь.
Да работает, спасибо!
Но есть одна проблемка, с вашим кодом светодиод не гаснет полностью, то есть ШИМ не проседает до нуля.
И будет еще одна просьба, не могли бы Вы написать комментарии к коду, я начинающий и мне пока трудно разбираться в исходниках.
И вот теперь когда есть возможность сохранять в память, резко захотелось какое нибуть оповещение о записи, звуковую или помаграть светодиодом, что бы очевиднее было.
Так это не с моим кодом, за яркость светодиода отвечает ваша часть кода я ее не трогал, в 56 строке попробуйте поменять 0 на -10
Коменты добавил в код выше.
Вот еще один момент, не "запоминало" на чем выключилось, то есть "запоминало" но не "вспоминало" при подаче питания (извините за каламбур) решил вопрос так
но в ноль ШИМ так и не становится, пытаюсь выловить багу но не могу
а если в 56 строке выставить -10, то в положении когда должен выключится, он наоборот светит с полной силой!
За коментарии отдельное спасибо!
Итого, вот как выглядит на данный момент
Вот еще один момент, не "запоминало" на чем выключилось, то есть "запоминало" но не "вспоминало" при подаче питания (извините за каламбур) решил вопрос так
В 37 строке происходит тоже самое:
Так что у вас два раза присваивается brightness одно и тоже значение. Может вы просто выключали питание не дождавшись 5 секунд и значение не сохранялось.
По поводу ШИМа - замените кусок кода с 48 по 57 строки включительно вот на этот кусок:
Maksim, огромное Вам спасибо! Все заработало как надо.
А как организовать индикацию записи в память для кнопочек?
А как вы хотите?
Ну даже не знаю, в принципе можно мигнуть светодиодом а можно пискнуть бипером, но я думаю светодиодом нагляднее будет
наверное как то так, начиная с 84 строки
Должен при записи моргнуть два раза.
Ага, я не так выразился, я имел в виду дополнительный светодиод, подключенный к 13 пину (в принципе уже запаян в ардуино) а управляймым светодиодом моргать нельзя. Вобщем я сделал так, все работает. Спасибо!
кстати, в таком случае не нужна последняя строчка:
если ее оставить то светодиод индикации не гас
кстати, в таком случае не нужна последняя строчка:
если ее оставить то светодиод индикации не гас
Так естественно, эта строка была нужна для того, что бы после мигания значиние осталось таким же как и до мигания.
дадада, maksim, я уже понял, а вот как это выглядит http://www.youtube.com/watch?v=4B58Yb4TG5s
очень нужная тема! искал везде в инете, а нашел в итоге у нас на форуме
от себя добавлю, что у меня код заработал только тогдла, когда добавил кусок
Вот у меня такая задачка на дисплей вывожу температуру и влажность с датчика. А энкодером регулирую скорость вращения вентилятора. Температура и влажность выводяться постоянно. Хочу что бы при вращении энкодера выводилась скорость вращения вентилятора в процентах на какоето время а после окончания вращения опять индиицироваллась темература и влажность. Написал код вроде в протеус работает но как то криво (хотя может беда в протеусе) иногда иероглифы начинает выводить а затем пустой дисплей.
Если не сложно глянте код подскажите новичку что улучшить
>serega374
я бы предложил доработать алгоритм
я вижу так:
1) на ЖК экран всегда выводятся все текущие показания - температура, влажность скорость вращения в процентах
2) нажимаем кнопку (короткое нажатие и мигнет светодиод один раз) - показывает текущую скорость вращения в процентах и энкодером меняем её
3) нажимаем кнопку (долгое нажатие и мигает светодиод до тех пор пока кнопка нажата) - идет запись в EEPROM нового значения
Нужная тема. Можно ли оперативно регулировать частоту ШИМ и если можно, то как?
Итак маленько подработал я код. EEPROM и кнопку пока не подключал. Возникла проблема с вычислением процентов от "int encoderValue" Я в начале написал "lcd.print(encoderValue/255*100, 1);" но LCD всегда показывал "0%", потом допер что int целые числа и заменил "volatile int encoderValue = 255;" на "volatile long encoderValue = 255;" LCD стал показывать либо "0%" либо "100%".
Вот хочу спросить у знающих как отобразить мне проценты? Еще вопрос почему ШИМ меняеться с шагом 4 (сейчас на LCD я отображаю непоредственное значение ШИМ и при повороте энкодера на один "щелчок" значение encoderValue изменяеться на 4? И последенее в коде есть переменная "long lastencoderValue = 0;" не могу понять что она занчит? Код я честно признаюсь где-то "спёр" может и тут сильно не пипнайте я только учусь)
Измени логику рассчета - сначала умножь, а потом уже дели.
Где-то уже проскакивало в темах проблема с делением когда все переменные объявлены как целочисленные.
Я бы советовал выкинуть все лишнее из прерывания. Запись нового ШИМ уровня лучше все-таки делать в loop. В прерывании стоит оставлять только если это критично для задачи (сериал или вывод на экран сильно может затормозить программу).
Какой вы используете энкодер? По программе не скажешь что значение скачет по 4. Просто энкодер может быть очень чувствительный.
Вот такой энкодер. Мне это некритично (изменение шим с шагом 4) я думал это в особенностях контролера заложено
Попробуйте отрабатывать каждый 10 ход энкодера (encodervalue от 0 до 2550, а при выводе на ШИМ делите на 10). Можно будет кртуть быстрее.
Попробуйте код с 2 светиками который предлагают китайцы - http://ru.aliexpress.com/item/Free-shipping-KEYES-Rotary-encoder-module-for-arduino-with-demo-code/1743367243.html?spm=2114.031020208.3.2.DvtsZW&ws_ab_test=searchweb201556_1_71_72_73_61_74_75,searchweb201527_4,searchweb201560_9