Хоть и старая тема, но всё равно отпишусь
По-моему проще и надежней всего сделать так:
для одновременной реализации спидометра и одометра (первый - как следствие второго) нужно 3-4 переменных, задействовать одно внешнее прерывание и еще 3 переменных для формирования простых отрезков времени:
PHP код:
unsigned long cur_ms = 0; //переменная для отслеживания натикавших миллисекунд с момента пуска МК
unsigned long prev_ms = 0; //переменная для вычисления отрезков времени
int ms = 0; //сам отрезок времени
unsigned long m; //одометр, значение, по-идее, считывается из EEPROM при включении и потом туда же записывается при выключении МК
unsigned long m_temp = 0; //переменная для вычисления пройденного пути за отрезок времени
int speed = 0; //переменная для хранения скорости
void setup() {
pinMode(20, INPUT);
digitalWrite(20, HIGH);
attachInterrupt(3, odom, RISING);
}
void odom() {
m++;
}
void loop() {
cur_ms = millis(); //сколько прошло мс с момента включения
ms = cur_ms - prev_ms; //сколько прошло мс с последнего срабатывания расчета
if (ms > 500) {
prev_ms = cur_ms; //ставим метку когда было срабатывание
speed = (m - m_temp) * 3600 / ms; //вычисляем скорость км в час по кол-ву пройденных метров за отрезок времени ms
m_temp = m; //ставим метку когда было вычисление
ms=0; //обнуляем отрезок времени
}
}
или если без одометра (т.е. не сохранять/извлекать из eeprom), то чуть проще:
PHP код:
unsigned long cur_ms = 0; //переменная для отслеживания натикавших миллисекунд с момента пуска МК
unsigned long prev_ms = 0; //переменная для вычисления отрезков времени
int ms = 0; //сам отрезок времени
int m = 0; //пройденное расстояние
int speed = 0; //переменная для хранения скорости
void setup() {
pinMode(20, INPUT); //включаем 20й порт на Ардуино Мега2560 на чтение
digitalWrite(20, HIGH); //включаем подтягивающий резистор
attachInterrupt(3, odom, RISING); //включаем внешнее прерывание
}
void odom() {
m++; //добавляем 1 при каждом срабатывании
}
void loop() {
cur_ms = millis(); //сколько прошло мс с момента включения
ms = cur_ms - prev_ms; //сколько прошло мс с последнего расчета
if (ms > 500) {
prev_ms = cur_ms; //ставим метку когда было срабатывание
speed = m * 3600 / ms; //вычисляем скорость км в час по кол-ву пройденных метров за отрезок времени ms
m = 0; //обнуляем пройденное расстояние
ms=0; //обнуляем отрезок времени
}
}
Множитель при вычислении скорости подбираем под свою "систему".
Если учесть, что на каждые 1,5 метра приходится примерно 5 срабатываний, а точность на скорости ниже 20км/ч не важна, то отрезки можно делать по 500мс и будет достаточно.
На 54км/ч, т.е. 15м/с - это 50 срабатываний в секунду. А при отрезке 500мс - 25 срабатываний. Т.е. может произойти 24-25 срабатываний (отклонение всегда в меньшую сторону, если нет дребезга) и погрешность будет -2,16..0 км/ч. С увеличением скорости точность увеличивается.
С учетом того, что редкий зверь разгоняется за 5с до сотни, грубо говоря за 0,5с можно добавить не более 10км/ч (а большинство машин и 5км/ч вряд-ли добавят).
ЗЫ: а можно включить прерывание по изменению ( attachInterrupt(3, odom, CHANGE); ) и тогда точность будет в 2 раза выше