Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <LiquidCrystal.h>
- #define SPEED_PIN A6 // Номер ноги для датчика скорости
- #define INJECTOR_PIN A7 // Номер ноги для форсунки
- #define PERIOD 1000000 // Период усреднения текущего расхода и обновления дисплея (микросекунды) - пять секунд
- #define IDLE_STROKE_DURATION 21000 // Суммарное время открытия форсунок (милисекунды) за период на холостом ходу
- #define IDLE_STROKE_HOUR_CONSUMPTION 0.7 // Часовой расход топлива на холостом ходу (литры в час)
- #define TEST_SPEED 60.0 // Контрольная скорость (километры в час) для расчёта коэффициента пробега
- #define TEST_TICKS 84 // Число импульсов с датчика скорости за период на контрольной скорости
- #define HOUR_PERIODS ( 3600000000.0 / PERIOD ) // Число периодов в часу
- #define FUEL_FACTOR ( IDLE_STROKE_HOUR_CONSUMPTION / HOUR_PERIODS / IDLE_STROKE_DURATION ) // Коэффициент расхода топлива (литры) за период
- #define RANGE_FACTOR ( TEST_SPEED / TEST_TICKS / HOUR_PERIODS ) // Коэффициент пробега (километры) за период
- #define CONSUMPTION_FACTOR ( 100.0 * FUEL_FACTOR / RANGE_FACTOR ) // Коэффициент километрового расхода топлива (литры на 100 км)
- #define TICKS_TRESHOLD 1 // Порог (импульсы датчика скорости) за период, выше которого можно считать километровый расход
- #define DURATION_CORR 0 // Поправка при измерении длительности времени открытия одной форсунки (микросекунды)
- #define AVG_LENGTH 10 // Число периодов для усреднения
- #define AVG_REFRESH_TIME 1 // Время в часах, после которого сбрасывается усреднённый километровый расход, если не было сброса по расстоянию (1 час)
- #define AVG_REFRESH_LENGTH 0.1 // Расстояние в километрах, после которого сбрасывается усреднённый километровый расход (100 м)
- #define AVG_REFRESH_PERIODS ( AVG_REFRESH_TIME * HOUR_PERIODS ) // Число периодов между обновлениями среднего расхода
- #define AVG_REFRESH_TICKS ( AVG_REFRESH_LENGTH / RANGE_FACTOR ) // Число импульсов датчика скорости между обновлениями среднего расхода
- // Строковые константы
- #define STR_AVG String(" Cp:")
- #define STR_CUR String("M\xB4\xBD:")
- #define STR_NA String(" \xBD/\xE3")
- #define STR_KMH String("\xBA\xBC/\xC0")
- LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
- unsigned long dur;
- unsigned long dur_t;
- unsigned long t;
- boolean last_injector_state;
- boolean last_speed_state;
- unsigned long total_duration;
- unsigned long total_ticks;
- unsigned long total_avg_duration;
- unsigned long total_avg_ticks;
- unsigned long d_avg_duration;
- unsigned long d_avg_ticks;
- int period_counter;
- // int period_counter2;
- // Структура, описывающая данные для усреднения
- struct consumption_data {
- unsigned int duration;
- word ticks;
- };
- struct consumption_data data[AVG_LENGTH];
- int avg_counter;
- void setup() {
- // Serial.begin(9600);
- lcd.begin(8, 2);
- t = micros() + PERIOD;
- pinMode(INJECTOR_PIN, INPUT);
- pinMode(SPEED_PIN, INPUT);
- last_injector_state = analogRead(INJECTOR_PIN) > 500;
- last_speed_state = analogRead(SPEED_PIN) > 500;
- dur = 0;
- dur_t = micros();
- total_duration = 0;
- total_ticks = 0;
- total_avg_duration = total_duration;
- total_avg_ticks = total_ticks;
- d_avg_duration = total_duration;
- d_avg_ticks = total_ticks;
- // Инициализация данных для усреднения
- for (int i=0; i < AVG_LENGTH; ++i) {
- data[i].duration = 0;
- data[i].ticks = 0;
- }
- period_counter = 0;
- // period_counter2 = 0;
- avg_counter = 0;
- }
- void loop() {
- boolean injector_state = analogRead(INJECTOR_PIN) > 500;
- boolean speed_state = analogRead(SPEED_PIN) > 500;
- unsigned long new_t = micros();
- // Вычисление мгновенных значений
- if (injector_state != last_injector_state) {
- if (injector_state) {
- dur = new_t - dur_t;
- if (dur) dur += DURATION_CORR; // Поправочка
- total_duration += dur;
- } else {
- dur_t = new_t;
- dur = 0;
- }
- last_injector_state = injector_state;
- }
- if (speed_state != last_speed_state) {
- total_ticks++;
- last_speed_state = speed_state;
- }
- // Действия, которые выполняются раз в секунду
- if (new_t >= t) {
- if (!dur) {
- dur = new_t - dur_t;
- if (dur) dur += DURATION_CORR; // Поправочка
- total_duration += dur;
- }
- // Отладочная установка значений
- // if (period_counter2 < AVG_LENGTH * AVG_REFRESH_PERIODS) {
- // total_duration = 100000;
- // total_ticks = 56;
- // } else if (period_counter2 < 2 * AVG_LENGTH * AVG_REFRESH_PERIODS) {
- // total_duration = 20000;
- // total_ticks = 1;
- // } else {
- // total_duration = 100000;
- // total_ticks = 56;
- // }
- d_avg_duration += total_duration;
- d_avg_ticks += total_ticks;
- ++period_counter;
- // ++period_counter2;
- if (d_avg_ticks >= AVG_REFRESH_TICKS || period_counter >= AVG_REFRESH_PERIODS) {
- // Вычисление средних значений
- // total_avg_duration += d_avg_duration - data[avg_counter].duration;
- /// total_avg_ticks += d_avg_ticks - data[avg_counter].ticks;
- data[avg_counter].duration = d_avg_duration;
- data[avg_counter].ticks = d_avg_ticks;
- total_avg_duration = 0;
- total_avg_ticks = 0;
- for (int i=0; i < AVG_LENGTH; i++) {
- total_avg_duration += data[i].duration;
- total_avg_ticks += data[i].ticks;
- }
- period_counter = 0;
- d_avg_duration = 0;
- d_avg_ticks = 0;
- ++avg_counter;
- if (avg_counter >= AVG_LENGTH)
- avg_counter = 0;
- }
- // Конвертация значений в физические единицы и вывод на экран
- String s1, s2, s3;
- unsigned int consumption = 0;
- unsigned int avg_consumption = 0;
- if (total_ticks > TICKS_TRESHOLD) {
- consumption = 10.0 * CONSUMPTION_FACTOR * total_duration / total_ticks;
- }
- if (total_avg_ticks > TICKS_TRESHOLD) {
- avg_consumption = 10.0 * CONSUMPTION_FACTOR * total_avg_duration / total_avg_ticks;
- }
- unsigned int hour_consumption = 10.0 * FUEL_FACTOR * total_duration * HOUR_PERIODS;
- unsigned int spd = RANGE_FACTOR * total_ticks * HOUR_PERIODS;
- s1 = String(total_duration, DEC);
- if (total_ticks > TICKS_TRESHOLD) {
- s1 = STR_CUR + format(consumption);
- // s1 = format(consumption);
- } else {
- s1 = STR_CUR + STR_NA;
- // s1 = "n/a ";
- }
- if (total_avg_ticks > TICKS_TRESHOLD) {
- s2 = STR_AVG + format(avg_consumption);
- // s2 = format(avg_consumption);
- } else {
- s2 = STR_AVG + STR_NA;
- // s2 = "n/a ";
- }
- // s2 = "hr: " + format(hour_consumption);
- // s2 = format(hour_consumption);
- // s3 = "sp: " + String(spd, DEC);
- // s3 = String(spd, DEC);
- // s3 = String(total_ticks, DEC);
- // int iters = 3 - s3.length();
- // int iters = 8 - s3.length();
- // for(int i = 0; i < iters; ++i)
- // s3 = " " + s3;
- // int iters2 = 8 - s1.length();
- // for(int i = 0; i < iters2; ++i)
- // s1 = " " + s1;
- // s3 += STR_KMH;
- lcd.setCursor(0,0);
- lcd.print(s2);
- lcd.setCursor(0,1);
- lcd.print(s1);
- total_duration = 0;
- total_ticks = 0;
- t = new_t + PERIOD;
- }
- }
- String format(unsigned int dec) {
- if (dec > 1000) return String("##.#");
- unsigned int intPart = dec / 10;
- unsigned int fracPart = dec % 10;
- String result = String(intPart, DEC) + "," + String(fracPart, DEC);
- int iters = 4 - result.length();
- for(int i = 0; i < iters; ++i)
- result = " " + result;
- return result;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement