trip computer using Uno

Hello everyone,

I was following this tutorial, trying to make a trip computer for my car. I am using an arduino Uno, and, I am in a very beginner level.

Generally, I understand what the code does, but, the output I get does not make sense to me.

Let me explain. The working principal of the whole project, is to count the pulses you get form the injector harness and the VSS sensor. Those 2, will give you speed and fuel flow rate values. Combining them, you can get instant, average consumption, speed, average speed etc.

Trying it, the result was not what I expected. I want you guys, to take a look at the code, and, if possible, tell me if there is anything wrong with it.

Here is the code I have.

#include <DS1307RTC.h>
#include <FastIO.h>
#include <I2CIO.h>
#include <LCD.h>
#include <Wire.h>              // IIC LIBRARY
#include <LiquidCrystal.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROMex.h>
#include <EEPROMVar.h>

//I2C network adresses for RTC and LCD

#define I2C_ADDR    0x3F;//I2C Adress
#define I2C_ADDR    0x50;//I2C Adress
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); 

//variables declaration

//injector flow l/sec
volatile static long double injector_value = 0.002875166;
//pulses per km
volatile static double pulse_distance = 0.000397545;

volatile unsigned long counter, avg_speed_divider, distance_pulse_count, all_speed_values, all_fuel_consumption_values, temp_distance_pulse_count, injector_pulse_time, temp_injector_pulse_time, injTime1, injTime2, save_number;
volatile unsigned int speed, avg_speed, max_speed=0, fccounter, save_counter, i;
volatile double traveled_distance, display_speed, display_instant_fuel_consumption, display_traveled_distance, injector_open_time, used_fuel, tank_capacity = 40, average_fuel_consumption, instant_fuel_consumption;
volatile boolean to_be_saved;


void setup() { 

lcd.begin(20,4);
lcd.clear();

noInterrupts();

TCCR1A = 0; 
TCCR1B |= ((1 << CS10) | (1 << CS11));
TIMSK1 |= (1 << TOIE1); 
TCNT1 = 3036; 

pinMode(1, INPUT); //Injector
pinMode(2, INPUT);//VSS
pinMode(3, INPUT); //Reset

digitalWrite(1, HIGH);
digitalWrite(2, HIGH);
digitalWrite(3, HIGH);

attachInterrupt(digitalPinToInterrupt(1), injector_count, CHANGE);
attachInterrupt(digitalPinToInterrupt(2), distance_count, FALLING);
//EEPROM.setMemPool(0, 1024);
//loadData();
  
interrupts(); 
  
} 
  
  
void loop() { 
  //reset data
  if (digitalRead(3) == LOW) {
    traveled_distance = 0;
    used_fuel=0;
    all_fuel_consumption_values = 0;
    avg_speed_divider=0;
    
  }
    if(millis()%1000 == 0){
    
    lcd.clear();
    
    
    lcd.setCursor(0,0);
    lcd.print("V");
    lcd.setCursor(2,0);
    lcd.print(display_speed);
    lcd.setCursor(6,0);
    lcd.print("km/h");
    
    lcd.setCursor(0,1);
    lcd.print("DST");
    lcd.setCursor(4,1);
    lcd.print(display_traveled_distance, 1);
    lcd.setCursor(9,1);
    lcd.print("km");
    
    lcd.setCursor(0,2);
    lcd.print("AFC");
    lcd.setCursor(4,2);
    lcd.print(average_fuel_consumption, 1);
    lcd.setCursor(9,2);
    lcd.print("l/100");
    
    lcd.setCursor(14,1);
    lcd.print("SVN");
    lcd.setCursor(18,1);
    lcd.print(save_number);
    
    lcd.setCursor(11,0);
    lcd.print("UF");
    lcd.setCursor(14,0);
    lcd.print(used_fuel, 2);
    lcd.setCursor(19,0);
    lcd.print("L");
    
    lcd.setCursor(0,3);
    lcd.print("IFC");
    lcd.setCursor(4,3);
    lcd.print(display_instant_fuel_consumption, 1);
    lcd.setCursor(8,3);
    if (speed > 3) lcd.print("lt/100");
    else lcd.print("L/h");
    
    lcd.setCursor(12,3);
    lcd.print(tank_capacity);
    lcd.setCursor(18,3);
    lcd.print("lt");
  }
  
} 
  
 // void saveData(){
   // EEPROM.writeInt(0, max_speed);
  }
  
  //void loadData(){
   // EEPROM.readInt(0);
   // max_speed= EEPROM.readInt(0);
   // if (isnan (EEPROM.readInt(0))) max_speed=0;
    
  }
  
  void maxSpeed(){
    if (speed > max_speed) max_speed = speed;
  }
  
  void avgSpeed(){
    all_speed_values += speed;
    avg_speed = all_speed_values / avg_speed_divider;
    
  }
  
  
   void distance_count(){
    distance_pulse_count++;
    traveled_distance += pulse_distance;
    temp_distance_pulse_count++;
    
  }
  
  void injector_count(){
    
    if (digitalRead(1) == LOW) {
    injTime1 = micros();
    }
    else {
    injTime2=micros();
    injector_pulse_time= injector_pulse_time + (injTime2 - injTime1);
    temp_injector_pulse_time = temp_injector_pulse_time + (injTime2 - injTime1);
    digitalWrite(1, HIGH);
    }
  
  }
  
  
  void currentSpeed(){
    if(speed ==0 && distance_pulse_count >20){
      traveled_distance -= pulse_distance * distance_pulse_count;
    }
    speed = pulse_distance* distance_pulse_count *3600;
  }
  
  void fuel_consumption(){
    injector_open_time = ((double)injector_pulse_time / 1000000);
    
    if (speed>3){
      instant_fuel_consumption = (100 * (((injector_open_time * injector_value)*3600)*4)) / speed;
      all_fuel_consumption_values += instant_fuel_consumption;
      average_fuel_consumption = all_fuel_consumption_values / avg_speed_divider;
    }
    else instant_fuel_consumption = ((injector_open_time * injector_value)*3600) * 4;
    
    if(speed ==0 && instant_fuel_consumption >5 || instant_fuel_consumption > 80){
      instant_fuel_consumption = 0;
      injector_open_time = 0;
      
    }
    
    used_fuel += ((injector_open_time * injector_value)*4);
    if (tank_capacity > 0) tank_capacity = 45 - used_fuel;
  }
  
  
  
  
ISR(TIMER1_OVF_vect) { 
    counter++;
    
    if (temp_injector_pulse_time <800 && temp_distance_pulse_count ==0 && to_be_saved ==1) saveData();
    if (save_counter > 45 && speed ==0 && to_be_saved ==1 ) saveData();
    temp_injector_pulse_time=0;
    temp_distance_pulse_count =0;
    
    if(counter>3){ 
      
      currentSpeed();
      fuel_consumption();
      
      if (instant_fuel_consumption >0.3) to_be_saved=1;
     
      if (speed >3) {
       avg_speed_divider++;
       avgSpeed();
       maxSpeed();
     }
      save_counter++;
      distance_pulse_count = 0;
      counter = 0;
      injector_pulse_time=0;
      
      display_instant_fuel_consumption = instant_fuel_consumption;
      display_traveled_distance = traveled_distance;
      display_speed = speed;
  } 
    TCNT1 = 3036; 
  }

Best regards,

Kostas

Trying it, the result was not what I expected.

You should read the forum guide. It will help you give the information needed for us to help you if we can. Not just about posting code in code tags, it also advises not to say things like the above, but instead to explain what you did expect and what actually you actually got.

Thanks. I will do that.

The thing that confused me the most was the awkward speed values I was getting. To be accurate, they were jumping form 50 to 500 and when the car stopped, the value was at 3, without getting to 0 as it should.

Also, it maybe seems like a noob question, but, I can't understand why he declares that into the void_setup

digitalWrite(1, HIGH);
digitalWrite(2, HIGH);
digitalWrite(3, HIGH);

And also, why he uses FALLING, and CHANGE in the same section.

attachInterrupt(digitalPinToInterrupt(1), injector_count, CHANGE);
attachInterrupt(digitalPinToInterrupt(2), distance_count, FALLING);

Would it help if I attached the circuit schematic?

Would it help if I attached the circuit schematic?

If you read the forum guide, you would not need to ask that question...

I will read the code to see if I can spot anything.

Setting a pin with pinMode(x, INPUT); and then digitalWrite(x, HIGH); is a hang-over from early versions of the Arduino language. It is equivalent to pinMode(x, INPUT_PULLUP); in newer versions of the language.

Using CHANGE and FALLING in the same section is normal and ok. They are different interrupt pins for different sensors. Understanding how to interpret the signals from the different sensors may make it clear why those values were used.

Here is the schematic for the circuit. The connections are straight forward. I use 2 voltage regulators, in order to protect the board from the voltages of both the vss and the injector. (LCD is connected on an I2C bus.)

Both the injectors and the vss produce a square wave pulse. The difference, as I 've read, is that the injector line is always at 12V and when the injector opens the voltage drops to 0.


Voltage regulators are not a suitable component for this purpose. You should use voltage dividers, plus some over-voltage protection for the Arduino inputs, such as Zenner diodes. Alternatively, you could use opto-isolators.

Could you elaborate? Could the regulator affect the results of the measurements?

Yes, very much so.
Those regulators don't have the required capacitors, so are likely to oscillate, which in turn will seriously mess with your measurements.
There are several ways to connect to these higher voltage signals. Optocouplers, voltage divider or a diode and pull-up resistor can all do the job. Which one is most suitable depends on the precise nature of the signal.

Thank you for your answer. At the moment, I have none of the above, so I tried the most easy solution I could think. I found a circuit of a voltage divider, with 2 resistors, which I did on the breadboard. The results were good. The voltage is exactly half... Yea, I know, not the brightest thing to do... but.... it worked.

The problem is, that although the signal is changing, I get no readings at the moment on the lcd. I am sure that the cable which I intersected to get is the signal is the correct one, but... no results

update*
After removing the digitalWrite(2, HIGH); part, the speedometer seems to work just fine. And more accurate than I expected.