Светодиодный тахометр
- Войдите на сайт для отправки комментариев
Доброго времени суток! Хочу сделать на мотоцикл тахометр из светодиодов. Прилагаю фотография для наглядности того что примерно я хочу получить. Сегодня пришла UNO3. Подключил к ПК - все видит все мигает. Пока шла плата изучал программирование, написал первый скетч. Конечно же он не компилируется из за ошибок. Прошу помощи, а именно, кому не лень посмотрите мой скетч, он не большой много времени для опытных программистов не отнимет. Укажите мне на мои основные ошибки, и вообще оцените ход мысли, будет ли этот скетч реально считать обороты и зажигать светодиоды. Или может есть проще путь к реализации моей задумки.... Вообщем кто может поможет)))
Еще добавлю что на катушке зажигания на минусовой клемме каждый оборот коленвала(двухтактный двигатель) появляется масса на несколько мс. именно с минусовой клеммы и хочу считывать сигнал.
[code] int kat = 15; int greenLED1 = 1; int greenLED2 = 2; int greenLED3 = 3; int greenLED4 = 4; int greenLED5 = 5; int yellowLED6 = 6; int yellowLED7 = 7; int redLED8 = 8; int PRM = 0; void setup() { // Инициализируем цифровые вход/выход pinmode(kat, INPUT); pinmode(greenLED1, OUTPUT); pinmode(greenLED2, OUTPUT); pinmode(greenLED3, OUTPUT); pinmode(greenLED4, OUTPUT); pinmode(greenLED5, OUTPUT); pinmode(yellowLED6, OUTPUT); pinmode(yellowLED7, OUTPUT); pinmode(redLED8, OUTPUT); } void loop() { if (digitalread(kat)) == HIGH // если на катушке сигнал { unsigned long; } //запускаем отсчет времени if (digitalread(kat)) == HIGH //если на катушке снова сигнал {PRM = 60000000\micros} //обороты равны минуту делим на подсчитанное время между сигналами с катушки if PRM = < 1000 {digitalwrite(greenLED1, HIGH} if 1000 < PRM <= 2000 { digitalwrite(greenLED1, HIGH); digitalwrite(greenLED2, HIGH);} if 2000 < PRM <= 3000 { digitalwrite(greenLED1, HIGH); digitalwrite(greenLED2, HIGH); digtalwrite(greenLED3, HIGH); } if 3000 < PRM <= 4000 { digitalwrite(greenLED1, HIGH); digitalwrite(greenLED2, HIGH); digtalwrite(greenLED3, HIGH); digitalwrite(greenLED4, HIGH); } if 4000 < PRM <= 5000 { digitalwrite(greenLED1, HIGH); digitalwrite(greenLED2, HIGH); digtalwrite(greenLED3, HIGH); digitalwrite(greenLED4, HIGH);} if 5000 < PRM <= 6000 { digitalwrite(greenLED1, HIGH); digitalwrite(greenLED2, HIGH); digtalwrite(greenLED3, HIGH); digitalwrite(greenLED4, HIGH); digitalwrite(greenLED5, HIGH); digitalwrite(yellowLED6, HIGH); } if 6000 < PRM <= 7000 { digitalwrite(greenLED1, HIGH); digitalwrite(greenLED2, HIGH); digtalwrite(greenLED3, HIGH); digitalwrite(greenLED4, HIGH); digitalwrite(greenLED5, HIGH); digitalwrite(yellowLED6, HIGH); digitalwrite(yellowLED7, HIGH); } if 7000 < PRM <= 8000 { digitalwrite(greenLED1, HIGH); digitalwrite(greenLED2, HIGH); digtalwrite(greenLED3, HIGH); digitalwrite(greenLED4, HIGH); digitalwrite(greenLED5, HIGH); digitalwrite(yellowLED6, HIGH); digitalwrite(yellowLED7, HIGH); digitalwrite(redLED8, HIGH); } delay(500); digitalwrite(greenLED1, LOW); digitalwrite(greenLED2, LOW); digtalwrite(greenLED3, LOW); digitalwrite(greenLED4, LOW); digitalwrite(greenLED5, LOW); digitalwrite(yellowLED6, LOW); digitalwrite(yellowLED7, LOW); digitalwrite(redLED8, LOW) } } [/code]
Строки 2-13 и 27 без ошибок.
а сейчас))? больше что то не могу найти пока, да и нашел только грамматические ошибки...
Больше интересно что значит "error: stray '\' in program"
И Еще я так понимаю вот этот кусок у меня выделяет красным так как присвоение значения переменной это не есть выполнение какого то действия? или что тут не так?
Стало получше.
Строки 30 и 32: digitalRead
Строка 31: что это?
Строка 33: что такое \micros?
В строке 36 не хватает );
В строке 98 нет ;
Все
if
(1000 < PRM <= 2000)
приведут к ошибке при работе проги. Надо писать так:if
(
PRM >
1000 && PRM <= 2000)Хорошо ошибки учту и поправлю, спасибо!)
ну а на счет строки 31 и 33 вот тут начитался http://arduino.ru/Reference/Micros
как я понял 31 строка запустит отсчет времени командой
unsigned
long
а 33 строка это я присваиваю к переменно PRM значение равное 60000000 поделить на micros.Вот так правильнее или не в этом дело и я не понял как пользоваться микрос? 60000000 обсчитался, это минута в милисекундах у меня такая)))
Хорошо ошибки учту и поправлю, спасибо!)
ну а на счет строки 31 и 33 вот тут начитался http://arduino.ru/Reference/Micros
как я понял 31 строка запустит отсчет времени командой
unsigned
long
а 33 строка это я присваиваю к переменно PRM значение равное 60000000 поделить на micros.Вот так правильнее или не в этом дело и я не понял как пользоваться микрос? 60000000 обсчитался, это минута в милисекундах у меня такая)))
Unsigned long используется для хранения положительных целых чисел в диапазоне от 0 до 4,294,967,295 (2^32 - 1) изанимает 32 бита (4 байта) в памяти.
micros() это время СО СТАРТА СКЕТЧА в микросекундах. Зачем на него делить?!
if (digitalRead(kat) == LOW) {
long time = micros();
if (digitalRead(kat) == HIGH) {
if (digitalRead(kat) == LOW) {
time = micros() - time;
PRM = 60000000 / time;
}
}
}
Вроде так норм должно быть.
То есть чтобы делить на микрос надо сначало его текущее значение приравнять к переменной? И на катушке у меня никогда на минусовой клемме HIGH не появится так что норм не будет, но я понял ход твоей мысли, при первом сигнале с катушки задать одну переменную а при следующем другую и найти между ними разницу. Так?
Вчера сонный немного ошибся.
int a ;
if (digitalRead(kat) == LOW && a == 0) long time = micros();
if (digitalRead(kat) == HIGH) a =1;
if (digitalRead(kat) == LOW && a == 1) {
time = micros() - time;
PRM = 60000000 / time;
a = 0;
}
HIGH e тебя должен появляться иначе получается что пин "болтается в воздухе" и собирает наводки что преведет к ложным срабатываниям.
Тоесть ты получаешь сигнал LOW с катушки и запоминаешь время, потом получаешь сигнал HIGH чтобы знать что не считываешь время между одним и тем же LOW, и когда снова получаешь LOW вычитаешь из текущего времени время предидущего Low и считаешь сколько оборотов при такой паузе между тактами.
Я правильно понимаю что когда пин 15 будет соединен с землей это будет сигнал LOW? А как на этом же пине получать сигнал HIGH? Там должно появляться 5v?или можно другое напряжение запрограммировать на сигнал HIGH? И еще не совсем понял что такое "а"?
low да когда сигнал близок к нулю, меньше чем 0.4 вольта. High когда сигнал выше 2.4 вольта. Больше 5 вольт подавать на вход нельзя, если высокий уровень с катушки больше 5 вольт для уменьшения нужно использовать резистивный делитель.
Привет всем кто откликнулся (и тем кто еще только собирается) на мой зов помощи новичка) итак мой первый в жизни скетч скомпилировался и я очень рад) получил удовольствие огромное от написания и от разбирательств со всеми скобочками точечками))) кто же мог подумать что деление это не "\" а "/" и прочие как казалось мелочи).... Вообщем ребят посмотрите на код и выразите свое мнение будет ли он работать и есть ли недостатки какие то скрытые от моего неопытного взора. И по возможности дайте ответы:
1)Загрузив скетч в плату он там сохранится даже после потери питания платой? задаю этот вопрос потому что заливал простой скетч мигания светодиодом, все получалось, но после того как отключал от ПК плату и подключал снова скетч не выполнялся.
2)При подаче питания на плату(включаю зажигание на байке) скетч сразу начнет выполняться ?
3)можно ли посмотреть какой скетч залит в плату ?
4)вообщем то ответив на первый вопрос на второй может и не потребуется отвечать но вы поняяли меня надеюсь)
01
я тут подумал, а не так случайно?)
02
int
a ;
03
04
if
(digitalRead(kat) == LOW && a == 0)
long
time = micros();
05
06
if
(digitalRead(kat) == HIGH) a =1;
07
08
if
(digitalRead(kat) == LOW && a == 1) {
09
10
time = micros() -
long
time;
11
12
PRM = 60000000 / time;
13
14
a = 0;
15
16
}
слово long задает тип переменной, в 10 строке оно не нужно.
http://arduino.ru/Reference выучите всё что там есть.
1 - да, скетч находится в энергонезависимой памяти
2 - да
3 - вроде бы да, но сложно и не скетч а Ассемблированый код в котором вы не слова не поймёте.
4 - может потребуется а может и нет, хотя наверно да на 51 процент)))
Спасибо за советы и помощ) все сразу выучить не получится конечно) но я стараюсь) да и учить на практике лучше получается)
Спасибо за советы и помощ) все сразу выучить не получится конечно) но я стараюсь) да и учить на практике лучше получается)
Сам это всё проходил, до сих пор та страница в быстрых закладках))
все проходили) скорей бы пройти уже))
чет ему 36 строка не нравится(
чет ему 36 строка не нравится(
задаешь переменную не там.
32 строка, убери long, и задай переменную вначале со всеми осталными.
Эта ошибка значит что переменная не задекларированна)
все задекларировал)) а без long что плохого будет?) micros не влезет а millis влезет?) и что такое килдык))?
все задекларировал)) а без long что плохого будет?) micros не влезет а millis влезет?) и что такое килдык))?
зачем микросекунды если и с миллисекундами точность достаточно для твооей версии тахометра, при 8000 тысячах оборотов один оборот КВ происходит за 7 милисекунд,
дальше, int рассчитан на макс значение 32 768 соответсвтенно твой скетч начнет неккоректно работать через 32.7 секунды, а лонг хватит на 2,147,483,648 милисекунд или 2147483 секунд.
Килдык значит что вместо того чтобы писать огромный код для каждого промежутка оборотов можно его оптимизировать до 10 строк))
avo74i2, поздравляю с начинанием. Очень неплохо для начала.
А теперь давайте обдумаем ваш вариант. Вы же хотите как на картинке, чтобы светодиодики зажигались по кругу в зависимости от оборотов, так? И ещё один моментик: 3000 оборотов, всяко больше 2000 или даже 1000, так? То есть, если мы проверили и узнали что оборотов больше 5000, то зачем проверять меньшие значения "ранее" (как у вас)?
Предлагаю пойти "обратным счетом" и начинать с больших цифирек, типа такого:
Стоит заметить, что все блоки стали как-бы "одинаковы", что навевает мыслю о "повторяющихся действиях", которые можно запихнуть в цикл.. нет? А давайте попробуем (да и ножки подобраны "подряд", я вам ещё добавил 9 пин..):
Верно? Проверьте. Ну и теперь наглядно видно, что:
1. функция digitalRead() вызывается дважды, только с разным значением уровня, который в обоих случаях есть константа. В "С" есть тернарный оператор "?" который как раз возвращает одно из двух значений и можно с его помощью избавиться от второго вызова ..
2. Переменные level и i изменяют свои значения уменьшением от исходного, и обе они локальны, то есть кроме этого цикла и в общем-то и не нужны в скетче в других функциях .. у МК есть замечательные регистровые команды для таких действий и "С" их тоже умеет делать!
3. У нас есть некий "счетчик цикла" и в "С" есть замечательный цикл "for" как раз для таких повторов, ИТОГО:
Ну вот. Теперь код не содержит большой избыточности, а константы компилятор посчитает и оптимизирует самостоятельно.
Так - лучше? :)
Классно вы всё раззжевали, но мне кажется для ТС сложновато будет))
9 светодиод я вам добавил для того, чтобы отслеживать состояние "мотор выключен вовсе" .. в вашем варианте будет светиться led1.
Ну и ещё давайте внимательно посмотрим на ваш loop().
Вы измеряете период прихода метки за 1 оборот .. и, в то время пока у вас метки ещё нет .. светодиоды будут "переключаться" в странные режимы, ибо переменная RPM обнуляется в начале каждого вызова loop(). А это для вашего скетча - микросекунды.
Вы точно ТАК хотели? А может стоит не "дрочить" светодиоды попусту, а вызывать этот кусок по изменению их состояния только тогда, когда "замер произведен" и что зажигать, а что гасить уже стало понятно ..
Давайте попробуем:
И снова обнаруживаем аж 3 чтения датчика "подряд" .. с разрывом в пару микросекунд (Wiring - большой торомоз, но не спасает!). А если сделать наоборот? Сначала получить значение, а потом уже решать что с ним делать? Типа так:
Так ещё лучше, нет? :)
Ну и напоследок. setup() тоже содержит установку пинов "подряд" .. это тоже можно запихать в цикл и упростить программку. Оставляю как "домашнее задание". Кстати, тогда и переменных потребуется определять меньше.
Ждем окончательный вариант вашего скетча. :)
Очень здорово что вы не поленились все это написать) прочел все это и понял что именно нужно почитать, вечером после работенки придется поучиться )) спасибо , очень полезная инфа с вашей стороны, а иначе как еще научиться так же писать код) ну а на счет контроля выключенного мотора, если светодиоды не горят то он выключен, и на этот случай есть лампочка зарядки) да и когда он заведен я прекрасно слышу )))) поэтому откажусь от этой функции, а чтобы знать что светодиоды исправны в начале при включении зажигания они будут поочередно все зажигаться как контроль типа) надеюсь разберусь что к чему, если что ждите вопросы))
Кстати шаг в 1000 оборотов слишком велик это я сделал просто чтоб затестить скетч, так то я планирую 500 оборотов шаг сделать, и светодиодов будет 14. ножки подряд сделать не получится.
Это не проблема. Заведите массив для хранения номеров ножек и пользуйте их "подряд". Можно сразу, в таком случае хранить не номера ножек а правильные пары {порт, бит} и отказаться от тормозных функций digitalWrite() и digitalRead(). Программа в целом станет ещё и меньше по размеру и легко влезет даже в самую маленькую тиньку.
Всем привет! сегодня собрал тестовую версию тахометра, подключил 5 светодиодов (вместо 14) и вместо катушки на 15 пин воткнул землю через кнопку(чтобы симулировать ее работу). Появились вопросы....вообщем то тыкаю кнопку и светодиоды не зажигаются , скорей всего потому что на смену сигналу LOW не приходит HIGH. вопрос почему?
Как вариант индикации
Чтото я не совсем понял, или ты меня не понял) вот полностью мой код, так понятней будет
на данный момент после загрузки скетча все светодиоды почередно зажигаются но не гаснут, если удаляю 37-44 строки то после запуска скетча они все поочередно загораются гаснут ну и все) что то в этих строках напутал я, все время 7000 оборотов постоянно думает мой тахометр) помогайте искать логическую ошибку)
поставь строку 35 на 45. у тебя вышло что твое условие не вложенное
Понял, теперь гаснут но на кнопку не реагируют)...и еще такой вопрос: почему когла плату отключаю от питания(ЮСБ) и подключив снова начинает выполнятся скетч мигания светодиодом, который был залит изготовителем? а мой пока не залью снова не стартует
А ты кнопку с частотой хотябы 200 тактов в секунду можешь нажимать?
http://arduino.ru/forum/obshchii/prizrachnyi-blink
дошло почему не реагировали на кнопку, digitalRead поменял на analogRead и теперь реакция на кнопку заметна но не такая как хотелось бы...
да мне хотя бы чтоб один-два диода загорались и гасли.... первый вкл при 500 об\мин. это 8 раз в секунду а не 200...да и я специально для этого дела чтобы успевать тыкать добавил нолик к минуте тем самым делю 600000 на милис. но сейчас проблема не в этом, а в том что они либо сразу все мигают, либо все сразу горят либо ваще ни че не происхоит, башка кипит весь день уж с этим вожусь
спасибо что тыкнул куда глядеть, я и сам понял что в этом куске проблема, но вот так и не дошло как ее решить... думаю надо сделать так чтобы если услове не выполняется то следущее не проверялось, а снова проверялось первое пока не станет верным, как этого добиться? делать каждое следущее условие действием предыдущего? или есть какие то другие варианты не с оператором if?
Andy, верно. потому что a=0 стоит в самом начале и сбрасывается КАЖДЫЙ раз. Его надо вынести в глобал и устанавливать один раз по запуску всего скетча. Тогда в процессе работы это будет нормальный флаг изменения состояния конечного автомата. :)
P.S. посмотрел .. в предложенном мною варианте так и прописано. "a" не задается внутри loop().
Подскажите пожалуйста где я могу прочитать про такое выражение : (RPM>level? HIGH : LOW)
искал в учебнике что то не смог найти... смысл как бы вроде понятен но хотелось бы все равно прочесть чтоб оперировать в дальнейшем с легкостью))
Подскажите пожалуйста где я могу прочитать про такое выражение : (RPM>level? HIGH : LOW)
искал в учебнике что то не смог найти... смысл как бы вроде понятен но хотелось бы все равно прочесть чтоб оперировать в дальнейшем с легкостью))
Искать: оператор ? Си
ВИКИ 1 опрераторы в Си
ВИКИ 2 Тернарная условная операция
Странно, что никто не посоветовал изучить ардуиновский встроеный пример, Файл/Примеры/7-дисплей/барГраф. Там в точности алгоритм, который тут как велосипед, изобретается.
Да норм, зато сам поразбирался, почитал, набрался опыта) Сегодня появилось время и пришла мысль вместо кнопки которой я симулировал(неудачно) импульсы катушки зажигания, поставить кулер от компа, дак вот все норм заработало, единствнный минус в том что если резко остановить кулер например на трех тысячах оборотов то светодиоды не погаснут пока не крутнуть его еще до следующего импульса. Как можно решить данный косяк?
Так импульсы надо по другому считать, через прерывание, так точнее будет - attachInterrupt(). Примеры поищите сами, по теме раходомеры или счётчики оборотов, их пруд пруди.
А я вот так считал обороты,довольно точно и никаких глюков, тестировал с помощью NE555
А я вот так считал обороты,довольно точно и никаких глюков, тестировал с помощью NE555
можно увидеть весь код?
А я вот так считал обороты,довольно точно и никаких глюков, тестировал с помощью NE555
можно увидеть весь код?
Да, только он испытывался только в лабораторных условиях.
Привествую, как успехи с тахометром??? Столько всего тут корректировалось, можно увидить финальный скетч пожалуйста, очень захотелось сделать такой тах себе на гонку)