Спидометр на Arduino
- Войдите на сайт для отправки комментариев
Вс, 17/07/2016 - 13:01
Знаю, что все это неоднократно обсуждалось, но поскольку я новичок, мне это непонятно. Есть геркон, есть магнит на спице колёса, и нужно посчитать сколько раз замкнется геркон за 2 сек. Читал, что нужно использовать прерывания, но у меня что-то не очень получается.
Использовал вот этот код:http://arduino.ru/forum/programmirovanie/podschet-impulsov-za-1-sekundu#comment-87317
Заранее спасибо!
А не проще считать время между замыканиями, а не ждать 2 сек?
А еще лучше не заниматься херней с прерываниями. А просто посчитать количество импульсов (спадов или подьемов) за 2 сек. Да и геркон это механический контакт , так что есть дребезг.
Максим скорость 30км/час или 8,3 м/сек . Если взять колесо 500 мм то его периметр чуть больше 1,5 метра. Так что геркон отработает с частотой максимум 5 Гц.
Считать нужно подъёмы. А как это правильно реализовать, через таймер?
Вот вариант. Но константы надо подбирать по месту.
/ Счет оборотов колеса велосипеда с помощью геркона // ---класс велосчетчик--- class qw_counter/ { public: qw_counter(int pin); int out(); int go(); private: int _pin; // вывод датчика int _N; // сколько циклов loop() надо сделать что бы было 2 сек boolean _P,_P_old ; // состояние изм вывода текущее и старое int _K ; // сколько импульсов произошло на датчике int _K1; // данные на индикацию }; qw_counter::qw_counter(int pin){ _pin= pin; pinMode(_pin, INPUT); _P = digitalRead(_pin); _N = 2000/50; // 2 сек делить на 0.05 сек длит цикла _N = 2000/50; _K =0; } int qw_counter::go(){ _P_old=_P; _P = digitalRead(_pin); if ((_P_old == 0)&&(_P == 1)) _K++; // счет по отпусканию геркона _|- _N--; if (_N != 0) return 1; _N = 2000/50; // 2 сек делить на 0.05 сек длит цикла _K1 = _K; _K = 0 ; return 0; } int qw_counter::out(){ return _K1; } //---- программа ---- qw_counter counter(2);// здесь 2 это нога на которой стоит геркон подкл. на землю void setup() { Serial.begin(9600); } void loop() { delay (50); // 0.05 сек длит цикла if (counter.go() == 0) Serial.println(counter.out()); }Бред. Алгоритм ведь проще пареной репы: случилось замыкание -- запоминаем чего возвращает millis(). Случилось следующее, от текущего millis() отнимаем запомненное. Это время, за которое колесо сделало круг. Делим длину окружности колеса на время, получаем скорость. И подбирать ничего не нужно.
А не могли бы вы это хоть каким-нибудь кусочком кода показать как это делается?
Т.е. _pin это пин к которому подключен вывод геркона?
Вот возьмем резистор 1к Ом.(SMD102) Вот это будет примерно как класс.
А вот уже R1,R2 Это уже представители класса резисторов в 1кOм. Разумеется есть классы резисторов в 2кОма,классы диодов, микросхем.
Вот это строка делает счетчик counter по описанию qw_counter на 2 ноге. Так что _pin это то что внутри, как бы "программная микросхема".
У этой микросхемы есть 2 программные функции.
counter.go() и
counter.out()Первая должна обязательно присутсвовать один раз в цикле loop(). Некий псевдодрайвер.Как2000/50 раз к ней обратились. Так и результат поcounter.out() получили.В принципе подгружаемые библиотеки на классах и постороены. Но народ похоже про это тупо забывает.Объекты нужны, чтобы упростить структуру сложной программы. А у вас простая программа намеренно делается сложной. Еще и имена зубодробительные, чтобы точно не запомнить было, что за что отвечает. Вот этого авангардизма я вообще не понял.
Нафиг в одной строке два действия? Если хотите, чтобы накануне сравнения _N декрементировалась, так и пишите
Только из за дебильных имен выглядит все, как птичья азбука.
А не могли бы вы это хоть каким-нибудь кусочком кода показать как это делается?
класс титановый велосипед StopWatch.
a5021 Вот свистеть не надо. Программа у меня простая.
//---- программа ---- qw_counter counter(2);// здесь 2 это нога на которой стоит геркон подкл. на землю void setup() { Serial.begin(9600); } void loop() { delay (50); // 0.05 сек длит цикла if (counter.go() == 0) Serial.println(counter.out()); }Вот где вы птичий код нашли? А туда куда вы показывали, так это закулисы. Если вы развернете то что в include в .h и .cpp , то мое написание будет ясно как образец лаконичности. Вас убивает, что две команды в одной строке. Но зачем усложнять то просто идет как упрощеный пример. А то можно шифрануть так, что без бухла и консультации со стороны не разбраться.
А туда куда вы показывали, так это закулисы. Если вы развернете то что в include в .h и .cpp , то мое написание будет ясно как образец лаконичности. Вас убивает, что две команды в одной строке. Но зачем усложнять то просто идет как упрощеный пример. А то можно шифрануть так, что без бухла и консультации со стороны не разбраться.
Переведите мне кто-нибудь.
Переведите мне кто-нибудь.
перевожу - он считает, что является автором оригинального стиля форматирования кода.
и, вообще -
delay (50);// 0.05 сек длит циклаТ.е. чтобы узнать скорость м/с нужно длину окружности колёса поделить на noDelay_01.tick?
Denchik200401. Вы в школе (на уроках физики) изучали связь пути, времени и скорости?
Если бы у меня эта физика была... Начнётся только с первого сентября.
V=S/t
вот тебе и вся физика, где V -Скорость S-расстояние t-время
Уточню:
V [км/ч] = S [км] / t [ч] ---> V [км/ч] = 0,001 * S [м] / ( t [c] *(1/3600))
Дальше преобразуйте формулу самостоятельно.
Ну теория это конечно хорошо, но мне бы знать, в вашем решении, Клапауцый, noDelay_01.tick обозначает время между двумя замыкании геркона?
П.с. это и все что мне нужно было знать, формулы эти изучаются во 2-ом классе.
Хотя я был неправ(перечитал код, понял), можно было и повежливее я всё-таки ребёнок!
Цитата:перевожу - он считает, что является автором оригинального стиля форматирования кода.
Берите выше - оригинального стиля программирования в среде Ардуино.
void setup() { } void loop() { delay (50); // 0.05 сек длит цикла // код исполнения }так что команда delay (50); Это нормировка длительности всего цикла loop(). Аналог педали газ-тормоз автомобиля, что бы сделать среднюю длительность цикла. Да и программирование программы становится "горизонтальным". События- обработчик события и псевдо-драйвера.
void setup() { } void loop() { delay (50); // 0.05 сек длит цикла // код исполнения }так что команда delay (50); Это нормировка длительности всего цикла loop(). Аналог педали газ-тормоз автомобиля, что бы сделать среднюю длительность цикла.
ШТА? С каких это пор тупая задержка нормирует длительность всего цикла? Тем более - как-то там "усредняет"? Что будет, если в loop после строчки "код исполнения" вставить код, который выполняется 200 мс? Ваш delay тоже "отнормирует" длительность цикла?
так что команда delay (50); Это нормировка длительности всего цикла loop(). Аналог педали газ-тормоз автомобиля, что бы сделать среднюю длительность цикла. Да и программирование программы становится "горизонтальным". События- обработчик события и псевдо-драйвера.
трамблёр
Вы программируете в привычном стиле, который я называю "вертикальный". Для "вертикального" программирования подразумевается, что loop() это аналог main(). То есть программа решается в один проход цикла loop() сверху - вниз. Понятно что loop() зацикливает программу и она выполняется вновь и вновь.
При "горизонтальном" программировании не ставится задача выполнения программы в один оборот цикла. Здесь важно само фунционирование всей системы, ее выполнение команд и реакция на внешние условия.
Вот представим 2 ситуации. Есть задача и мы ее выполняем и день и ночь . Если нет материала , то сидим ждем пока его не завезут и не идем домой. Это "вертикальное" программирование.
Вторая ситуация . Каждый день после работы (или учебы) мы возвращаемся домой и смотрим, если возможность сделать что то для себя по своему плану. Если есть возможность делаем, нет откладываем на завтра. Здесь 1 проход цикла это один день. В этот день мы должны 1 раз опросить датчики, их проанализировать и дать 1 ответ. 2 раза опрашивать датчик не надо. И если нет условий для выдачи ответа его не давать. Какая длительность цикла в loop() задается в цикле самим программистом. Разумеется никаких циклов и циклических структур при горизонтальном программировании быть не должно, кроме самого loop().
Вы программируете
расскажи нам про трамблёр.
2004.01 -- это дата рождения? Если так, то прости нас всех. На форуме не видно, кому сколько лет.
Обод колеса (шины) имеет длину. Ее можно измерить рулеткой или "сантиметром", которым пользуются любители домашнего шитья. Предположим, что имеется некий небольшой велосипед, где длина окружности колеса равняется одому метру. Дальше мы закпрепляем геркон неподвижно на вилке, а магнит на спицах или ободе. В этом случае, при движении велосипеда, магнит будет замыкать контакты геркона один раз за оборот колеса. Замыкание контактов будет происходить всякий раз, когда велосипед пройдет один метр (длина обода). Если же измерить время, которое проходит между замыканиями геркона, то мы получим вторую величину, необходимую для вычисления скорости. Предположим, что едущий велосипед замыкает геркон через каждые 600 миллисекунд или 0.6 секунды. Разделив длину окружности на время между замыканиями геркона, получим скорость: 1 метр / 0.6 секунды = 1.67 м/с. Скорость обычно считают в км/ч, т.ч. полученное значение нужно умножить на 3600 (секунд в часе) и разделить на 1000 (метров в километре). Скорость нашего воображаемого велосипеда таким образом составит 6 км/ч.
int reedSwitch = 10; // пин, куда присоединен геркон float cLen = 1.0; // длина обода в метрах void setup() { pinMode(reedSwitch, INPUT_PULLUP); // режим входа с подтяжкой к плюсу Serial.begin(9600); // включаем вывод в последовательный порт } void loop() { while (digitalRead(reedSwitch) == HIGH); // ждем, пок геркон не будет замкнут uint32_t Time1 = millis(); // запоминаем время for (;;) { // крутим "вечный" цикл delay(50); // ждем, пока магнит проедет мимо геркона while (digitalRead(reedSwitch) == HIGH); // опять ждем замыкания uint32_t Time2 = millis(); // берем текущее время float rTime = (Time2 - Time1) / 3600000; // находим время полного оборота колеса в долях часа float bikeSpeed = (cLen / 1000) / rTime; // вычисляем скорость в км/ч Serial.print("Скорость равна: "); Serial.print(bikeSpeed); Serial.println(" км/ч."); Time1 = Time2; // запоминаем время для след. вычисления } }Этот код не проверялся в боевых условиях, т.ч. могут быть ляпы, но принцип должен быть примерно такой.
Спасибо вам огромное, это то, что было нужно!
П.с. 2004.01 это дата рождения.
с таким объяснением оно еще как-то выглядит, но это "костыль" своеобразный:), а вдруг скорость очень низкая и геркон не успеет разомкнуться? ну или если ехать больше 45 км/ч с длиной окружности 70 см?почему не проверить размыкание?
Может это и костыль, но для личного использования сойдёт) ну 45км/ч при том что С = 70см это конечно слишком. Велосипеды с такими колесами врятли поедут столько... Но все это уже оффтоп
это не оффтоп, вот ссылка http://bikehike.org/uhod-i-remont/kak-izmerit-diametr-kolesa.html почитай,
наоборот шоссейные колеса больше в диаметре.
Что-то в мониторе порта тишина...
Геркон как подключен?
Я прекрасно знаю, как подавить дребезг на замыкании, как дождаться размыкания и пропустить дребезг на нем, но если бы я это вставил в код, то за деревьями можно было не увидеть леса. Посему, решение тупо вставить задержку было продиктовано желанием сохранить наглядность и читаемость.
Один конец к +5 другой к D10
И получается, что на D10 всегда стоит единица, независимо от того, замкнут геркон или разомкнут. Программа стопориться на первом цикле ожидания (строка 10). Вторым концом геркон должен быть посажен на землю.
Все равно молчит и на gnd и на +3.3 и на +5. Также analogread пробовал, результат 0.
попробовать подключить геркон еще и через светодиодик, чтобы было видно состояние.
т.е. такая цепь. <+5v> r=300 Om +Vd1 <D10> gerkon <GND>
когда геркон замкнут на землю <GND> светодиод Vd1 горит.
a5021 ,согласен, так делать можно, я за то что стоит учесть, что есть условия при которых будет работать неправильно. Так что при желании/необходимости "доработать напильником".
Пробовал при замыкании гори, писал код под замыкание геркона, чтобы если замкнут горел светодиод - работает, но стоит заменить код из digitalWrite на t1 = millis() , так сразу t = ничего
Набросал вот такой код:http://arduino.ru/forum/programmirovanie/millis Н в нем есть одна проблемма с millis(), там все описнно
Покажите ваш код с герконом.
// задаем константы const int buttonPin = 2; // номер входа, подключенный к кнопке const int ledPin = 13; // номер выхода светодиода // переменные int buttonState = 0; // переменная для хранения состояния кнопки int t1; int t2; void setup() { Serial.begin(9600); // инициализируем пин, подключенный к светодиоду, как выход pinMode(ledPin, OUTPUT); // инициализируем пин, подключенный к кнопке, как вход pinMode(buttonPin, INPUT); } void loop(){ // считываем значения с входа кнопки buttonState = digitalRead(buttonPin); // проверяем нажата ли кнопка // если нажата, то buttonState будет HIGH: if (buttonState == HIGH) { // включаем светодиод t1 = millis(); } delay(70); if (buttonState == HIGH) { // включаем светодиод t2 = millis(); } long counter = t2 - t1; if (counter > 0 ) { digitalWrite(ledPin, HIGH); } //Serial.print(counter); }Вот в этом коде проблема с millis()
На комментарии не смотрите, я другой код из под кнопки и светодиода переделывал, а комменты не убрал
millis() -"Количество миллисекунд с момента начала выполнения программы. (unsigned long)"
проверить соответствие типов t1, t2
Теперь он выкидывает цифры 69 70 71... Даже без замыкания геркона
Куда выкидывает? В скетче нигде нет вывода хоть куда-нибудь.
Раскоментируйте 37 строку
Вы чего хотите сделать? Если кнопка нажата, чтобы светодиод загорался?
Чтобы он загорался через 70 мс после того, как нажата кнопка?
Что именно вы хотите изобразить излишне запутанным кодом?
#include <Adafruit_GFX.h> #include <Adafruit_PCD8544.h> Adafruit_PCD8544 display = Adafruit_PCD8544(3, 4, 5, 6, 7); // задаем константы const int buttonPin = 8; // номер входа, подключенный к кнопке const int ledPin = 13; // номер выхода светодиода // переменные int buttonState = 0; // переменная для хранения состояния кнопки unsigned long t1; unsigned long t2; void setup() { Serial.begin(9600); // инициализируем пин, подключенный к светодиоду, как выход pinMode(ledPin, OUTPUT); // инициализируем пин, подключенный к кнопке, как вход pinMode(buttonPin, INPUT); // инициализация и очистка дисплея display.begin(); display.clearDisplay(); display.display(); display.setContrast(50); // установка контраста delay(1000); display.setTextSize(1); // установка размера шрифта display.setTextColor(BLACK); // установка цвета текста display.setCursor(0,0); // установка цвета текста } void loop(){ // считываем значения с входа кнопки buttonState = digitalRead(buttonPin); if (buttonState == LOW) { t1 = millis(); } delay(70); if (buttonState == LOW) { t2 = millis(); } unsigned long counter = t2 - t1; if (counter > 0 ) { digitalWrite(ledPin, HIGH); } Serial.print(counter); display.println(counter); display.display(); }Ну вот как-то так, и все равно беспорядочные числа
я хочу посчитать время между 1 и 2 замыканием геркона