Advertisement
Guest User

Consumption meter

a guest
Dec 24th, 2011
6,865
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <LiquidCrystal.h>
  2.  
  3. #define SPEED_PIN A6 // Номер ноги для датчика скорости
  4. #define INJECTOR_PIN A7 // Номер ноги для форсунки
  5. #define PERIOD 1000000 // Период усреднения текущего расхода и обновления дисплея (микросекунды) - пять секунд
  6.  
  7. #define IDLE_STROKE_DURATION 21000 // Суммарное время открытия форсунок (милисекунды) за период на холостом ходу
  8. #define IDLE_STROKE_HOUR_CONSUMPTION 0.7 // Часовой расход топлива на холостом ходу (литры в час)
  9. #define TEST_SPEED 60.0 // Контрольная скорость (километры в час) для расчёта коэффициента пробега
  10. #define TEST_TICKS 84 // Число импульсов с датчика скорости за период на контрольной скорости
  11.  
  12. #define HOUR_PERIODS ( 3600000000.0 / PERIOD ) // Число периодов в часу
  13. #define FUEL_FACTOR ( IDLE_STROKE_HOUR_CONSUMPTION / HOUR_PERIODS / IDLE_STROKE_DURATION ) // Коэффициент расхода топлива (литры) за период
  14. #define RANGE_FACTOR ( TEST_SPEED / TEST_TICKS / HOUR_PERIODS ) // Коэффициент пробега (километры) за период
  15. #define CONSUMPTION_FACTOR ( 100.0 * FUEL_FACTOR / RANGE_FACTOR ) // Коэффициент километрового расхода топлива (литры на 100 км)
  16.  
  17. #define TICKS_TRESHOLD 1 // Порог (импульсы датчика скорости) за период, выше которого можно считать километровый расход
  18. #define DURATION_CORR 0 // Поправка при измерении длительности времени открытия одной форсунки (микросекунды)
  19. #define AVG_LENGTH 10 // Число периодов для усреднения
  20.  
  21. #define AVG_REFRESH_TIME 1 // Время в часах, после которого сбрасывается усреднённый километровый расход, если не было сброса по расстоянию (1 час)
  22. #define AVG_REFRESH_LENGTH 0.1 // Расстояние в километрах, после которого сбрасывается усреднённый километровый расход (100 м)
  23. #define AVG_REFRESH_PERIODS ( AVG_REFRESH_TIME * HOUR_PERIODS ) // Число периодов между обновлениями среднего расхода
  24. #define AVG_REFRESH_TICKS ( AVG_REFRESH_LENGTH / RANGE_FACTOR ) // Число импульсов датчика скорости между обновлениями среднего расхода
  25.  
  26. // Строковые константы
  27. #define STR_AVG String(" Cp:")
  28. #define STR_CUR String("M\xB4\xBD:")
  29. #define STR_NA String(" \xBD/\xE3")
  30. #define STR_KMH String("\xBA\xBC/\xC0")
  31.  
  32. LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
  33.  
  34. unsigned long dur;
  35. unsigned long dur_t;
  36. unsigned long t;
  37.  
  38. boolean last_injector_state;
  39. boolean last_speed_state;
  40.  
  41. unsigned long total_duration;
  42. unsigned long total_ticks;
  43. unsigned long total_avg_duration;
  44. unsigned long total_avg_ticks;
  45. unsigned long d_avg_duration;
  46. unsigned long d_avg_ticks;
  47. int period_counter;
  48. // int period_counter2;
  49.  
  50. // Структура, описывающая данные для усреднения
  51. struct consumption_data {
  52.   unsigned int duration;
  53.   word ticks;
  54. };
  55.  
  56. struct consumption_data data[AVG_LENGTH];
  57. int avg_counter;
  58.  
  59. void setup() {
  60.   // Serial.begin(9600);
  61.   lcd.begin(8, 2);
  62.   t = micros() + PERIOD;
  63.   pinMode(INJECTOR_PIN, INPUT);
  64.   pinMode(SPEED_PIN, INPUT);
  65.   last_injector_state = analogRead(INJECTOR_PIN) > 500;
  66.   last_speed_state = analogRead(SPEED_PIN) > 500;
  67.  
  68.   dur = 0;
  69.   dur_t = micros();
  70.   total_duration = 0;
  71.   total_ticks = 0;
  72.   total_avg_duration = total_duration;
  73.   total_avg_ticks = total_ticks;
  74.   d_avg_duration = total_duration;
  75.   d_avg_ticks = total_ticks;
  76.  
  77.   // Инициализация данных для усреднения
  78.   for (int i=0; i < AVG_LENGTH; ++i) {
  79.     data[i].duration = 0;
  80.     data[i].ticks = 0;
  81.   }
  82.  
  83.   period_counter = 0;
  84. //  period_counter2 = 0;
  85.   avg_counter = 0;
  86. }
  87.  
  88. void loop() {
  89.   boolean injector_state = analogRead(INJECTOR_PIN) > 500;
  90.   boolean speed_state = analogRead(SPEED_PIN) > 500;
  91.   unsigned long new_t = micros();
  92.  
  93.   // Вычисление мгновенных значений
  94.  
  95.   if (injector_state != last_injector_state) {
  96.     if (injector_state) {
  97.       dur = new_t - dur_t;
  98.       if (dur) dur += DURATION_CORR; // Поправочка
  99.       total_duration += dur;
  100.     } else {
  101.       dur_t = new_t;
  102.       dur = 0;
  103.     }
  104.    
  105.     last_injector_state = injector_state;
  106.   }
  107.  
  108.   if (speed_state != last_speed_state) {
  109.     total_ticks++;
  110.    
  111.     last_speed_state = speed_state;
  112.   }
  113.  
  114.   // Действия, которые выполняются раз в секунду
  115.  
  116.   if (new_t >= t) {
  117.     if (!dur) {
  118.       dur = new_t - dur_t;
  119.       if (dur) dur += DURATION_CORR; // Поправочка
  120.       total_duration += dur;
  121.     }
  122.    
  123.     // Отладочная установка значений
  124.    
  125. //    if (period_counter2 < AVG_LENGTH * AVG_REFRESH_PERIODS) {
  126. //      total_duration = 100000;
  127. //      total_ticks = 56;
  128. //    } else if (period_counter2 < 2 * AVG_LENGTH * AVG_REFRESH_PERIODS) {
  129. //      total_duration = 20000;
  130. //      total_ticks = 1;
  131. //    } else {
  132. //      total_duration = 100000;
  133. //      total_ticks = 56;
  134. //    }
  135.    
  136.     d_avg_duration += total_duration;
  137.     d_avg_ticks += total_ticks;
  138.    
  139.     ++period_counter;
  140. //    ++period_counter2;
  141.    
  142.     if (d_avg_ticks >= AVG_REFRESH_TICKS || period_counter >= AVG_REFRESH_PERIODS) {
  143.       // Вычисление средних значений
  144.      
  145.       // total_avg_duration += d_avg_duration - data[avg_counter].duration;
  146.       /// total_avg_ticks += d_avg_ticks - data[avg_counter].ticks;
  147.      
  148.       data[avg_counter].duration = d_avg_duration;
  149.       data[avg_counter].ticks = d_avg_ticks;
  150.  
  151.       total_avg_duration = 0;
  152.       total_avg_ticks = 0;
  153.      
  154.       for (int i=0; i < AVG_LENGTH; i++) {
  155.         total_avg_duration += data[i].duration;
  156.         total_avg_ticks += data[i].ticks;
  157.       }
  158.      
  159.       period_counter = 0;
  160.       d_avg_duration = 0;
  161.       d_avg_ticks = 0;
  162.  
  163.       ++avg_counter;
  164.       if (avg_counter >= AVG_LENGTH)
  165.         avg_counter = 0;
  166.     }
  167.    
  168.     // Конвертация значений в физические единицы и вывод на экран
  169.  
  170.     String s1, s2, s3;
  171.     unsigned int consumption = 0;
  172.     unsigned int avg_consumption = 0;
  173.    
  174.     if (total_ticks > TICKS_TRESHOLD) {
  175.       consumption = 10.0 * CONSUMPTION_FACTOR * total_duration / total_ticks;
  176.     }
  177.  
  178.     if (total_avg_ticks > TICKS_TRESHOLD) {
  179.       avg_consumption = 10.0 * CONSUMPTION_FACTOR * total_avg_duration / total_avg_ticks;
  180.     }
  181.    
  182.     unsigned int hour_consumption = 10.0 * FUEL_FACTOR * total_duration * HOUR_PERIODS;
  183.     unsigned int spd = RANGE_FACTOR * total_ticks * HOUR_PERIODS;
  184.    
  185.     s1 = String(total_duration, DEC);
  186.  
  187.     if (total_ticks > TICKS_TRESHOLD) {
  188.       s1 = STR_CUR + format(consumption);
  189.       // s1 = format(consumption);
  190.     } else {
  191.       s1 = STR_CUR + STR_NA;
  192.       // s1 = "n/a ";
  193.     }
  194.  
  195.     if (total_avg_ticks > TICKS_TRESHOLD) {
  196.       s2 = STR_AVG + format(avg_consumption);
  197.       // s2 = format(avg_consumption);
  198.     } else {
  199.       s2 = STR_AVG + STR_NA;
  200.       // s2 = "n/a ";
  201.     }
  202.  
  203.     // s2 = "hr: " + format(hour_consumption);
  204.     // s2 = format(hour_consumption);
  205.    
  206.     // s3 = "sp: " + String(spd, DEC);
  207.     // s3 = String(spd, DEC);
  208.     // s3 = String(total_ticks, DEC);
  209.    
  210.     // int iters = 3 - s3.length();
  211.     // int iters = 8 - s3.length();
  212.    
  213.     // for(int i = 0; i < iters; ++i)
  214.     //  s3 = " " + s3;
  215.      
  216.     // int iters2 = 8 - s1.length();
  217.    
  218.     // for(int i = 0; i < iters2; ++i)
  219.     //  s1 = " " + s1;
  220.    
  221.     // s3 += STR_KMH;
  222.    
  223.     lcd.setCursor(0,0);
  224.     lcd.print(s2);
  225.    
  226.     lcd.setCursor(0,1);
  227.     lcd.print(s1);
  228.    
  229.     total_duration = 0;
  230.     total_ticks = 0;
  231.     t = new_t + PERIOD;
  232.   }
  233. }
  234.  
  235. String format(unsigned int dec) {
  236.   if (dec > 1000) return String("##.#");
  237.  
  238.   unsigned int intPart = dec / 10;
  239.   unsigned int fracPart = dec % 10;
  240.   String result = String(intPart, DEC) + "," + String(fracPart, DEC);
  241.  
  242.   int iters = 4 - result.length();  
  243.   for(int i = 0; i < iters; ++i)
  244.     result = " " + result;
  245.  
  246.   return result;
  247. }
Advertisement
Advertisement
Advertisement
RAW Paste Data Copied
Advertisement