Мигаем светодиодом с таймером по прерыванию
- Войдите на сайт для отправки комментариев
Может не совсем верно озаглавил, но что первое пришло в голову - то и написал.
В общем суть такая:
Есть (будет) код, который заставляет светодиоды мигать в определённый момент времени (которое, кстати тоже постоянно изменяется).
По нажатию на кнопку, которая будет висеть на 2-м пине (пин прерывания №0) должно засекаться время (timer) от последнего нажатия (прерывания) и цикл мигания должен начинаться с самого начала, причём этот цикл должен быть равен предыдущему измерению времени между нажатиями (прерываниями).
Наверное написал полную чушь, т.к. сложно объяснить идею в пару строк.
Другими словами, это будет вращающийся круг, как колесо велосипеда или мотоцикла и светодиоды должны загораться и гаснуть к примеру только в часовых точках механических часов (смотрите рисунок).
Светодиодов будет к примеру 6, т.е. каждый будет мигать ровна 2 раза за один цикл.
Вот что набросал для начала:
#include <Wire.h> int ledState = LOW; // этой переменной устанавливаем состояние светодиода long previousMillis = 0; // храним время последнего переключения светодиода long interval = 100; // интервал между включение/выключением светодиода (0,1 секунда) void setup() { Serial.begin(9600); pinMode(13, OUTPUT); pinMode(12, OUTPUT); pinMode(11, OUTPUT); pinMode(10, OUTPUT); pinMode(9, OUTPUT); //Digital Pin 2 Set As An Interrupt attachInterrupt(0, fan_interrupt, RISING); // по прирыванию запускаем fan_interrupt } void loop() { Serial.print(digitalRead(2)); // смотрим как отрабатывает кнопка или геркон } void cikl() { // Тут нужно заставить мигать светодиоды в определённый момент времени // и так, что-бы цикл после прерывания начинался заново с новым временем, // рассчитанным в функции прерывания. Т.е. 6 светодиодов должны загореться с временем // равным interval/6 (для мигания светодиодов в различных местах конструкции) или interval/2 (для мигания в часовых точках циферблата), вроде так, но не уверен // так же нужно обойтись без delay, т.к. иногда светодиоды должны будут загораться одновременно // если светодиод не горит, то зажигаем, и наоборот if (ledState == LOW) ledState = HIGH; else ledState = LOW; // устанавливаем состояния выхода, чтобы включить или выключить светодиод digitalWrite(13, ledState); // } } void fan_interrupt() { interval = (millis() - time_last); // рассчитываем время между нажатиями кнопки или замыканиями геркона time_last = millis(); // в качестве последнего значения времени присваиваем текущее cikl(); // запускаем цикл мигания светодиодов }
То есть у нас есть время Tx , равное времени, прошедшему с момента старта устройства, или с момента последнего нажатия на кнопку. После нажатия на кнопку, мы берём это время Tх и что с ним делаем? То, что отсчёт начинается заново, абсолютно понятно. Но что мы делаем со значением Tx, куда и как применяем?
Время Tx = время с момента последнего нажатия на кнопку.
Дальше это время разбиваем на 6 частей, т.к. в конструкции будет 6 независимых светодиодов, и используя уже "урезанное" время добиваемся загорания и гашения светодиодов в определённой позиции, для вырисовывания определённой картинки (точки, короткие полоски, штрих-пунктир)
Если взять за основу циферблат часов, то светодиоды будут стоять на местах 12 часов, 2, 4, 6, 8 и 10.
Это необходимо, т.к. скорость вращения круга будет меняться.
Учитывая, что скорость предыдущего оборота ~ равняется текущему (в большинстве случаев).
Именно из-за этого и решил привязаться к времени между нажатиями кнопки или замыкания геркона (скорее всего геркон поставлю, т.к. надёжнее) .
Время Тх = время от старта устройства до первого нажатия на кнопку, а уже потом от предпоследнего, до последнего нажатия на кнопку.
А, писать на спицах лисапеда, увы, мой друг, не мудрено? Это что-ли? Или там на лопастях вентилятора? Так если это, то готовые проекты есть наверняка, зачем изобретать велосипед для велосипеда? Не стесняйтесь пользоваться плодами чужих трудов.
Да, что-то вроде того должно получиться.
Можно и на спицах велосипеда и на вентилятор.
Тут немного другая штука (но суть на 100% такая же) - ветряк, ременная передача на диск, где вся эта электроника и будет висеть.
Бегло просмотрел гугл:
http://www.instructables.com/id/RGBike-POV-Open-project/
http://habrahabr.ru/post/151042/
Но всё без исходников.
Если есть на примете похожие проекты с исходниками, подкиньте пожалуйста.
И лучше датчик Холла использовать вместо геркона. Хотя если обороты небольшие, то можно и геркон.
Опенсорц - http://hacknmod.com/hack/open-source-bicycle-pov-display-pictures-animation/
Искать следует по "bike bicycle led arduino pov"
Спасибо!)
Есть 2 датчика хола (http://www.ebay.com/itm/NEW-Hall-element-switch-For-Magnetic-Detect-Ardu...) Но он даже неодимовый магнит улавливает вплотную, как увеличить его чувствительность?
Там вверху есть кнопка "Number steps", ежели её нажать, то увидите и сорцы и описание. А также есть кнопка Download PDF, в котором всё сразу.
Увеличить чувствительность... Ну, самое простое, заменить датчик на более чутьёвый (чёрная такая штучка с тремя ножками в прорези платы). Или изменить коэффициент усиления у ОУ, там ведь мелкосхема ОУ, насколько я понимаю, стоит? Вот с нею можно ещё разобраться. Что, кстати, за мелкосхема?
Да это ОУ LM393, буду подбирать сопротивление из того, что имеется в наличии.
Да это ОУ LM393, буду подбирать сопротивление из того, что имеется в наличии.
Для начала определите схему включения, она либо как усилитель включена, либо как компаратор. Скорее второе, так как в этом случае она срабатывает от разницы напряжений между входами равной микровольтам. При этом на выходе формируется уровень почти равный уровню питания.
Посмотрел даташит, в нём она заявлена как компаратор, такшта вопрос вообще снимается. Смотрите куда там этот датчик подключен, если в цепи есть сопротивление, то попробуйте его просто закоротить для проверки работоспособности устройства.
на схеме есть место для подстроечного резистора, но вместо него стоит резистор на 100кОм, при его закорачивании, датчик не работает (сигнала на выходе нет)
Надо смотреть, куда он там стоит. Тут, по слухам, у датчиков Холла по выходу открытый коллектор. Так что это может быть нагрузочный резистор, который, если закоротить, превратит датчик в неработающее устройство либо на время КЗ, либо навсегда.
Моя вина, как-то ваще не подумал уточнить. В общем тут посмотрите - http://carnovato.ru/princip-raboty-shema-datchika-holla-skutere/
А тут схемы включения: https://www.google.ru/search?q=подключение+датчика+холла
Датчик хола и дальше работает исправно.
Для нормальной работы взял более можный магнит.
Теперь возник вопрос, как запустить на исполнение другую функцию если нет вращения к примеру 10 секунд.
Пока в коде написал условие, если время между прерыванием более 1 секунды то светодиоды мигают по кругу.
Но при отсутствии ветра вращения может не быть и несколько часов.
Т.е. нужно заменить эту часть кода
на функцию, которая будет запускаться при бездействии более 10 секунд.
На данный момент код выглядит так:
Я сам новичок, поэтому могу ошибаться, но мне кажется, что для хранения значений таймера (millis) следует использовать unsigned long, а не просто long.
7 строка:
long previousMillis = 0;
заменить на:
unsigned long previousMillis = 0;
Лично я все переменные, которые используются для вычислений времени с помощью millis, сделал бы unsigned long. Во избежание ошибок. А то у вас там и float, и long, и unsigned long, так лучше не делать, как мне кажется.
Конкретно по вопросу - я его не понял, увы, но насколько понял, настолько и отвечу:
Конкретно по вопросу - я его не понял, увы, но насколько понял, настолько и отвечу:
нолик дорисуй для 10 секунд :)
Конкретно по вопросу - я его не понял, увы, но насколько понял, настолько и отвечу:
нолик дорисуй для 10 секунд :)
А это мысль!
Спасибо, типы переменных подправлю.
Конкретно по вопросу - я его не понял, увы, но насколько понял, настолько и отвечу:
Да, объяснил я конечно не очень понятно.
Можно было и так сделать, но переменная interval при отсутствии ветра может и не изменяться в течении нескольких часов. Т.к. нет ветра - нет вращения, нет вращения - датчик хола не даёт сигнал на прерывание, где и рассчитывается переменная interval.
Отсюда и вопрос, можно ли отсчитать 10 секунд при отсутствии сигнала с датчика хола более 10 секунд?
Спасибо, типы переменных подправлю.
Конкретно по вопросу - я его не понял, увы, но насколько понял, настолько и отвечу:
Да, объяснил я конечно не очень понятно.
Можно было и так сделать, но переменная interval при отсутствии ветра может и не изменяться в течении нескольких часов. Т.к. нет ветра - нет вращения, нет вращения - датчик хола не даёт сигнал на прерывание, где и рассчитывается переменная interval.
Отсюда и вопрос, можно ли отсчитать 10 секунд при отсутствии сигнала с датчика хола более 10 секунд?
Так введите второй счётчик, который растёт постоянно, а в те моменты, когда Холл посылает имульс и ваше прерывание срабатывает - обнуляйте его. Таким образом, пока имульсы есть, счётчик никогда не достигнет предельного значения, после которого запутстися ваша функция.
А ещё в микроконтроллерах есть таймер, который может сам отсчитывать время и, по достижению указанного значения, генерировать прерывание, в которое можете засунуть свою подпрограмму.
Тоже была такая идея, но обнулять millis() вроде как нельзя...
Про встроеный таймер почитаю.
Зачем нам миллис обнулять? Нам надо, чтобы миллис-превмиллис было <10000 тогда, когда лопасти крутятся. Этого достаточно вполне.
Што нам для этого надо? Праааальн - в ISR добавить строку prevmillis=millis(). Ну то есть в void fan_interrupt().
Но тогда код перестанет работать, да? Верно. А кто сказал, что превмиллисов может быть только 1? Сделайте себе второй превмиллис, назовите его как хотите и пользуйтесь на здоровье.
Тоже была такая идея, но обнулять millis() вроде как нельзя...
Про встроеный таймер почитаю.
зачем вам обнулять милис? вам не достаточно брать значение милис когда еще все крутилось? и проверять каждый раз не достигла ли милис которая сейчас в разнице с сохраненой 10 секунд?