Advertisement
Guest User

Untitled

a guest
Apr 26th, 2017
271
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.76 KB | None | 0 0
  1. #include "PinChangeInterrupt.h" // enables the interrupts at the other pin except the ones at the digital pins 2 and 3
  2. #include <avr/sleep.h>          // enables the sleep function
  3. #include <avr/power.h>          // power management
  4. #include <EEPROMex.h>          // enables some special functions for writing to and reading from EEPROM
  5. #include <EEPROMVar.h>
  6. #include <Wire.h>              // IIC LIBRARY
  7. #include "RTClib.h"            // Real Time Clock Library
  8. #include <math.h>              // enables complex math functions    
  9. #include <LiquidCrystal_I2C.h>
  10. #include <OneWire.h>
  11. #include <DallasTemperature.h>
  12.  
  13. LiquidCrystal_I2C lcd(0x27,20,4);
  14. RTC_DS1307 rtc;
  15. OneWire oneWire(9);
  16. DallasTemperature sensors(&oneWire);
  17.  
  18. // variables declaration
  19. volatile static float vss_pulse_distance = 0.0003816033;  // distance coefficient -- change this according to your measurements (km/pulse)
  20. volatile float LPG_injector_flow;                        // LPG injector flow coef. -- it is calculated at setup() (litres/microseconds)
  21. volatile static float unleadedFlow = 1743e-11;            // gasoline injector flow coef. -- change this according to your measurements (litres/microseconds)
  22.  
  23. byte LPG1, LPG2, LPG3, LPG4, digitLPG, pos = 0;          // LPG_injector_flow = (LPG1 * 1000 + LPG2 * 100 + LPG3 * 10 + LPG4) * 1e-11
  24. volatile unsigned long vss_pulses;                        //keeps how many pulses "passed" from the vss sensor per second
  25. volatile float traveled_distance, traveled_distance2, traveled_distance3, seconds_passed, speed, avg_speed, distance_to_LPGstation;
  26. volatile float used_LPG, used_LPG2, instant_LPG_consumption, avg_LPG_consumption, LPG_in_tank, Full_tank = 49;
  27. volatile float used_Unleaded, used_Unleaded2;
  28. volatile float average_L_100km_Unlead;
  29.  
  30. volatile unsigned long unleadTime1=0, unleadTime2=0, unleadinj_Open_Duration=0;
  31. volatile unsigned long LPG_injector_open_duration = 0, injTime1=0, injTime2=0;
  32. int postemp;
  33. int vss_pin = 2;        // VSS signal input at digital pin 2 (INT0)
  34. int LPG_pin = 3;        // LPG injector signal input at digital pin 3 (INT1)
  35. int ignition_pin = 9;  // ignition signal input
  36. int unleaded_pin = 12;  // Unleaded injector signal input
  37.  
  38.  
  39. boolean buttonState, buttonState2; // variables related to buttons functions
  40. boolean lastButtonState2 = LOW;
  41. long lastDebounceTime = 0, logohold, counter, counter2;
  42. volatile boolean ignition = false;
  43. boolean ignoreRelease = false;
  44. boolean inst_disp = true;
  45. byte menunumber = 0,  menunumbermax = 10; // main menu initial value and maximum value -- see below where the "case:"s are
  46. int h=0, m=0, s, m1; // variables needed for time setting
  47. boolean timeRead = false, displaychange = true;
  48. float thermReading, steinhart; //steinhart - hart equation for thermistors
  49. boolean dots = true;
  50.  
  51. int i=0;
  52.  
  53. void setup()
  54. {
  55.   pinMode(10, INPUT); // Button 1
  56.   //rtc.adjust(DateTime(2017,4,23,16,50,0));
  57.   pinMode(vss_pin, INPUT);
  58.   pinMode(LPG_pin, INPUT);
  59.   pinMode(ignition_pin, INPUT);
  60.   pinMode(unleaded_pin, INPUT);
  61.  
  62.   lcd.begin();
  63.   lcd.clear();
  64.   rtc.begin();
  65.   Serial.begin(9600);
  66.  
  67.   // below recalls the values stored in case of power loss (change of the car battery or take it off for some modifications at the code)
  68.   // So, the system does not loose the measurements when we take it off
  69.   traveled_distance = EEPROM.readFloat(0);
  70.   traveled_distance2 = EEPROM.readFloat (5);
  71.   used_LPG = EEPROM.readFloat (10);
  72.   used_LPG2 = EEPROM.readFloat(15);
  73.   LPG_in_tank = EEPROM.readFloat(20);
  74.   seconds_passed = EEPROM.readFloat(25);
  75.   used_Unleaded = EEPROM.readFloat(30);
  76.   traveled_distance3 = EEPROM.readFloat (35);
  77.   used_Unleaded2 = EEPROM.readFloat(45);
  78.   LPG1 = EEPROM.readByte (40);
  79.   LPG2 = EEPROM.readByte (41);
  80.   LPG3 = EEPROM.readByte (42);
  81.   LPG4 = EEPROM.readByte (43);
  82.   LPG_injector_flow = (LPG1 * 1000 + LPG2 * 100 + LPG3 * 10 + LPG4) * 1e-11;
  83.  
  84.   noInterrupts();
  85.   // set and initialize the TIMER1
  86.   TCCR1A = 0; // set entire TCCR1A register to 0
  87.   TCCR1B = 0; // set entire TCCR1B register to 0
  88.   TCCR1B |= (1 << CS12);//prescaler 256 --> Increment time = 256/16.000.000= 16us
  89.   TIMSK1 |= (1 << TOIE1); // enable Timer1 overflow interrupt
  90.   TCNT1 = 3036; // counter initial value so as to overflow every 1sec: 65536 - 3036 = 62500 * 16us = 1sec (65536 maximum value of the timer)
  91.  
  92.   attachPCINT(digitalPinToPinChangeInterrupt(ignition_pin), ignitionSignal, CHANGE); //enables the ignition signal change detection
  93.  
  94.   interrupts();
  95.   delay(10);
  96. }
  97.  
  98. void loop()
  99. {
  100.   sensors.requestTemperatures();
  101.     // When the ignition switch is turned, executes the next two ifs
  102.   if (ignition == true && digitalRead(9) == LOW) // ignition key turned to OFF
  103.   {
  104.     detachInterrupt(digitalPinToInterrupt(vss_pin)); // disables the interrupts
  105.     detachInterrupt(digitalPinToInterrupt(LPG_pin));
  106.     detachPCINT(digitalPinToPinChangeInterrupt(unleaded_pin));
  107.     delay(50);
  108.     ignition = false; // this variable is necessary in order the code inside this "if" statement to run once
  109.     // when the ignition switched off it stores the values to the EEPROM
  110.     EEPROM.writeFloat (0, traveled_distance);
  111.     EEPROM.writeFloat (5, traveled_distance2);
  112.     EEPROM.writeFloat (10, used_LPG);
  113.     EEPROM.writeFloat (15, used_LPG2);
  114.     EEPROM.writeFloat (20, LPG_in_tank);
  115.     EEPROM.writeFloat (25, seconds_passed);
  116.     EEPROM.writeFloat (30, used_Unleaded);
  117.     EEPROM.writeFloat (35, traveled_distance3);
  118.     EEPROM.writeFloat (45, used_Unleaded2);
  119.      
  120.     sleep_enable(); // enables the sleep mode
  121.     set_sleep_mode(SLEEP_MODE_PWR_DOWN); // set the sleep mode
  122.     cli();
  123.     sleep_bod_disable(); // disables the brown out detector to consume less power while sleeping
  124.     sei();
  125.     sleep_mode(); // microcontroller goes to sleep  
  126.   }
  127.   // when it wakes up continues from here -- also the first time we turn the ignition key to ON starts from here
  128.   if (ignition == true && digitalRead(9) == HIGH) // when the ignition key turned to ON
  129.   {
  130.     ignition = false;   // this variable is needed in order to run once the code inside this if
  131.     logohold = millis(); // this variable is used to hold the LOGO screen on, for 2 sec -- see below
  132.     inst_disp = true;;                                   // writes the display data to the display
  133.  
  134.     attachInterrupt(digitalPinToInterrupt(vss_pin), distance, RISING); // attaches the interrupt which related to the VSS signal
  135.  
  136.     attachPCINT(digitalPinToPinChangeInterrupt(unleaded_pin), UnleadedTime, CHANGE); // petrol injector signal input and interrupt activation
  137.  
  138.     // every 5sec calculates average LPG consumption, remaining distance accordingly to the calculated remaining fuel in tank, average speed and average Unleaded cons.
  139.   }
  140.   if(millis()%5000 < 50)
  141.   {
  142.     avg_LPG_consumption = 100 * used_LPG2/traveled_distance2;
  143.     distance_to_LPGstation = 100 * LPG_in_tank/avg_LPG_consumption;  //remaining distance for LPG
  144.     avg_speed = (traveled_distance3 / seconds_passed)*3600;          //average speed
  145.     average_L_100km_Unlead = 100 * used_Unleaded2/traveled_distance2; //average l/100km for unleaded fuel
  146.   }
  147.  
  148. // For the short and long press function I consulted: http://jmsarduino.blogspot.gr/2009/05/click-for-press-and-hold-for-b.html
  149. // There are many differences though, mainly because I have built a hardware debounce for the buttons
  150.  
  151. ////////// "button 1" functions /////////////////
  152.   buttonState = digitalRead(11);
  153.   if(buttonState==HIGH){
  154.     if(menunumber<6){
  155.       menunumber++;
  156.     }
  157.     else menunumber=0;
  158.   }
  159.   // if (buttonState2 == LOW && lastButtonState2 == HIGH) lastDebounceTime = millis(); //records the time that button1 pressed
  160.  
  161.   // if (buttonState2 == HIGH && lastButtonState2 == LOW)
  162.   // {
  163.   //   if (ignoreRelease == false) // "button 1" SHORT PRESS functions -- on release
  164.   //   {
  165.   //     if (menunumber <= menunumbermax) // changes the display indications backwards
  166.   //     {
  167.   //       if (menunumber == 0) menunumber = menunumbermax;
  168.   //       else menunumber = menunumber - 1;
  169.   //     }
  170.   //   }
  171.   //   else ignoreRelease = false;
  172.   // }
  173.  
  174. // below are the misc screens
  175.   switch (3)
  176.   {
  177.     case 0: // instant speed
  178.       lcd.clear();
  179.       lcd.setCursor(0,0);
  180.       lcd.print(speed,0);
  181.       lcd.setCursor(4, 0);
  182.       lcd.print(F("km/h"));
  183.       Serial.println((String)speed+" km/h");
  184.       delay(10000);
  185.     break;
  186.    
  187.     case 1: // avg speed
  188.       lcd.clear();
  189.       lcd.setCursor(0, 0);
  190.       lcd.print(avg_speed, 0);
  191.       lcd.setCursor(4, 0);
  192.       lcd.print(F("km/h"));
  193.       Serial.println((String)avg_speed+" km/h");
  194.       delay(50000);
  195.     break;
  196.      
  197.     case 2: // traveled distance        
  198.       lcd.clear();
  199.       lcd.setCursor(0,0);
  200.       lcd.print(traveled_distance, 1);
  201.       lcd.print("km");
  202.       Serial.println((String)traveled_distance+" km");
  203.       delay(10000);
  204.     break;
  205.  
  206.     case 3: //RTC and external Temperature
  207.  temp1:    if(inst_disp == true) displaychange = false, inst_disp = false;// these variables ensure that it will not go back to time set immediately
  208.           lcd.clear();
  209.           printTemperature();
  210.           printTime();
  211.           delay(10000);
  212.     break;
  213.    
  214.     case 4: // avg Unleaded consumption
  215.       lcd.clear();
  216.       lcd.setCursor(0,0);
  217.       if(isnan(average_L_100km_Unlead)|| isinf(average_L_100km_Unlead)) lcd.print(F("---"));
  218.       else lcd.print(average_L_100km_Unlead, 1);
  219.       lcd.print(F(" l/100"));
  220.       Serial.println((String)average_L_100km_Unlead+" l/100km");
  221.       delay(10000);
  222.     break;
  223.  
  224.     case 5: //Unleaded Fuel
  225.       lcd.clear();
  226.       lcd.setCursor(0, 0);
  227.       lcd.print(F("Fogyasztas "));
  228.       lcd.print(used_Unleaded,1);
  229.       lcd.print(F(" l"));
  230.       Serial.println("Total unleaded "+(String)used_Unleaded+" l");
  231.       delay(10000);
  232.     break;
  233.   }
  234. }
  235.  
  236. ISR(TIMER1_OVF_vect){ //TIMER1 overflow interrupt -- occurs every 1sec -- it holds the time (in seconds) and also prevents the overflowing of some variables
  237.   instantSpeed();
  238.    
  239.   unleadedConsumption();
  240.   unleadinj_Open_Duration = 0;
  241.    
  242.   seconds_passed++;
  243.   vss_pulses = 0;
  244.    
  245.   TCNT1 = 3036;
  246. }
  247.  
  248. void distance(){// it is called everytime a pulse produced by the VSS sensor
  249.   vss_pulses++;
  250.   traveled_distance += vss_pulse_distance;  // total traveled distance
  251.   traveled_distance2 += vss_pulse_distance; // distance used at average LPG consumption calculations
  252.   traveled_distance3 += vss_pulse_distance; // distance used at average speed calculations
  253.   // we calculate 3 times the same thing in order to reset the distance, the average cons. and average speed independently
  254. }
  255.  
  256. void instantSpeed(){ // current speed
  257.   speed = (vss_pulse_distance * vss_pulses * 3600); // instant speed in km/h
  258. }
  259.  
  260. void UnleadedTime(){// it is called every time a change occurs at the gasoline injector signal and calculates gasoline injector opening time, during the 1sec interval
  261.   if (digitalRead(12) == LOW){
  262.     unleadTime1 = micros();
  263.   }
  264.   if (digitalRead(12) == HIGH){
  265.     unleadTime2 = micros();
  266.   }
  267.   if (unleadTime2 > unleadTime1){
  268.     if ((unleadTime2 - unleadTime1) > 500 && (unleadTime2 - unleadTime1) < 12000){ // some conditions to avoid false readings because of noise
  269.                 // my injectors do not open for longer than 12ms = 12000us (you can change this if you want)
  270.       unleadinj_Open_Duration = unleadinj_Open_Duration + (unleadTime2 - unleadTime1); //total useconds that the gasoline injector opens throughout 1sec                                                                                
  271.     }
  272.   }
  273. }
  274.  
  275. void unleadedConsumption(){
  276.   used_Unleaded = used_Unleaded + (unleadinj_Open_Duration * unleadedFlow);  //total litres of gasoline consumed -- calculated every 1sec
  277.   used_Unleaded2 = used_Unleaded2 + (unleadinj_Open_Duration * unleadedFlow); //this is used in average unleaded consumption calculation
  278. }
  279.  
  280. // ignition signal (sleep - wake up) interrupt routine
  281. void ignitionSignal(){ // this is called everytime the ingintion signal changes -- if the microcontroller is in sleep mode, it will wake up
  282.   ignition = !ignition;
  283. }
  284.  
  285. void printTime(){ // print the time
  286.   DateTime dt = rtc.now();
  287.   lcd.setCursor(5,1);
  288.   lcd.print((String)dt.year()+"."+(String)dt.month()+"."+(String)dt.day());
  289.   lcd.setCursor(7,0);
  290.   lcd.print((String)dt.hour()+":"+(String)dt.minute());
  291.   Serial.println((String)dt.year()+"."+(String)dt.month()+"."+(String)dt.day());
  292.   Serial.println((String)dt.hour()+":"+(String)dt.minute());
  293. }
  294.  
  295. void printTemperature(){ //temperature calcualation
  296.   sensors.requestTemperatures();
  297.   float temp=sensors.getTempCByIndex(0);
  298.   float temp2=sensors.getTempCByIndex(1);
  299.   lcd.setCursor(3,2);
  300.   lcd.print("Belso hom.: ");  lcd.print(temp2,0);
  301.   lcd.setCursor(3,3);
  302.   lcd.print("Kulso hom.: ");  lcd.print(temp,0);
  303.   Serial.println("Inside: "+(String)temp+" Outside: "+(String)temp2);
  304. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement