Велоспидометр на ардуино
- Войдите на сайт для отправки комментариев
Сб, 11/08/2018 - 22:13
Подскажите пожалуйста что не так в этом скетче? Проблема в том что иногда он не хочет считать скорость. Геркон цел.
#include <EEPROM.h> //библиотека для работы со внутренней памятью ардуино #include <Wire.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x3F, 16, 2); unsigned long lastturn; //переменные хранения времени float SPEED; //переменная хранения скорости в виде десятичной дроби float DIST; //переменная хранения расстояния в виде десятичной дроби float w_length=2.050; //длина окружности колеса в метрах void setup() { Serial.begin(9600); //открыть порт Wire.begin(0, 2); lcd.begin(); lcd.setCursor(0, 0); // 1 строка lcd.print("Speed:"); lcd.setCursor(0, 1); // 1 строка lcd.print("Distance:"); digitalPinToInterrupt (12); attachInterrupt(12,sens,RISING); //подключить прерывание на 2 пин при повышении сигнала pinMode(14, OUTPUT); //3 пин как выход digitalWrite(14, HIGH); //подать 5 вольт на 3 пин DIST=(float)EEPROM.read(0)/10.0; //вспоминаем пройденное расстояние при запуске системы (деление на 10 нужно для сохранения десятых долей расстояния, см. запись) } void sens() { if (millis()-lastturn > 80) { //защита от случайных измерений (основано на том, что велосипед не будет ехать быстрее 120 кмч) SPEED=w_length/((float)(millis()-lastturn)/1000)*3.6; //расчет скорости, км/ч lastturn=millis(); //запомнить время последнего оборота DIST=DIST+w_length/1000; //прибавляем длину колеса к дистанции при каждом обороте оного } } void loop() { int cel_sp=floor(SPEED); int sot_sp=(((float)cel_sp/1000)-floor((float)cel_sp/1000))*10; int des_sp=(((float)cel_sp/100)-floor((float)cel_sp/100))*10; int ed_sp=(((float)cel_sp/10)-floor((float)cel_sp/10))*10; int dr_sp=(float)(SPEED-floor(SPEED))*10; lcd.setCursor(6, 0); lcd.print(des_sp); lcd.setCursor(7, 0); lcd.print(ed_sp); lcd.setCursor(8, 0); lcd.print("."); lcd.setCursor(9, 0); lcd.print(dr_sp); lcd.setCursor(11, 0); lcd.print("km/h"); int cel_di=floor(DIST); //целые int sot_di=(((float)cel_di/1000)-floor((float)cel_di/1000))*10; //сотни int des_di=(((float)cel_di/100)-floor((float)cel_di/100))*10; //десятки int ed_di=floor(((float)((float)cel_di/10)-floor((float)cel_di/10))*10); //единицы (с точкой) int dr_di=(float)(DIST-floor(DIST))*10; //десятые части lcd.setCursor(9, 1); lcd.print(des_di); lcd.setCursor(10, 1); lcd.print(ed_di); lcd.setCursor(11, 1); lcd.print("."); lcd.setCursor(12, 1); lcd.print(dr_di); lcd.setCursor(13, 1); lcd.print("km"); if ((millis()-lastturn)>2000){ //если сигнала нет больше 2 секунды SPEED=0; //считаем что SPEED 0 EEPROM.write(0,(float)DIST*10.0); //записываем DIST во внутреннюю память. Сделал так хитро, потому что внутренняя память не любит частой перезаписи. Также *10, чтобы сохранить десятую долю } }
Работает на ESP8266 (не спрашивайте почему)
всё-таки почему?
фотографию вашего изобретения покажите?
что значит не хочет? на экране пишет "обиделся, выключаюсь"? или он думает что едет со скоростью 130 км/ч, а вы ему запретили считать?
Думаю, что стандартный прокол - попытка в обработчике обращаться к millis() и проводить вычисления. А так же считывать значения с многобайтовой неволатильной переменной без обеспечения атомарности.
bod9I, после остановки велосипеда сколько раз сохраняется дистанция во внутреннюю память, которая не любит частой перезаписи?
Думаю, что стандартный прокол - попытка в обработчике обращаться к millis().
Поясни, почему нельзя обращаться? Она же вроде только отдает значение внутренней переменной. Я всегда внутри прерывания millis() использоваю, чтоб запомнить момент. Правда, несколько раз миллис вызывать бесполезно, внутри прерывания он не меняется.
Так Вы на строку №24 посмотрите. Там можно вызывать миллис, а можно и не вызывать - там пофиг. Хуже уже не будет.
Поясни, почему нельзя обращаться? Она же вроде только отдает значение внутренней переменной. Я всегда внутри прерывания millis() использоваю, чтоб запомнить момент.
Я не написал, что нельзя. Просто вижу, что товарищ начинает накидывать в обработчик прерывания вычисления, многократное использование millis(). Как правило - вскоре после этого начинается поиск пропавших миллисекунд. Пока он не понимает, что делает - думаю, лучше отказаться от таких приемчиков.