W takim razie zamieszczam:
Kod:
#include <LiquidCrystal.h>
#include <Timers.h>
//lcd and timer objects declaration
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
Timers <4> timer;
//variables for calculating speed
volatile uint16_t impulsCounter = 0;
uint64_t overallImpulsCounter = 0;
uint16_t impulsesPerMeter = 1685;
//variables for calculating fuel comsumption
uint16_t injectorImpulsLength = 0;
uint16_t maxFuelConsumption = 3724; //max fuel cons. equals 37,24 [l/h], this value is multiplied by 100
//variables for calculating distance
uint32_t distanceMeters = 0;
uint8_t distanceHundretMeters = 0;
uint32_t distanceKilometers = 0;
void setup() {
Serial.begin(9600);
//pins declaration
pinMode(2, INPUT_PULLUP); //speedometer impulsator pin
pinMode(3, INPUT_PULLUP); //injectors impulses pin
//start screen
lcd.begin(16,2);
lcd.setCursor(0,0);
lcd.print("ASTRA F X14XE");
delay(3000);
lcd.clear();
//global interrupts
attachInterrupt(digitalPinToInterrupt(2), speedImpulsIncrement, FALLING);
//threads
timer.attach(0,1,measureInjectorImpuls);
timer.attach(1,500,calculateSpeedAndFuelConsumption);
timer.attach(2,1,calculateDistance);
timer.attach(3,1000,displayDistance);
}
//measurment methods
void speedImpulsIncrement() {
impulsCounter++;
}
void measureInjectorImpuls() {
if(digitalRead(3) == LOW)
injectorImpulsLength++;
}
//calculating methods
void calculateSpeedAndFuelConsumption() {
uint8_t speedOfVehicle = 0;
bool motion = false;
uint8_t consumptionPerHour = 0;
uint8_t consumptionPerHour_point = 0;
uint8_t consumptionPer100KM = 0;
uint8_t consumptionPer100KM_point = 0;
Serial.print(injectorImpulsLength);
Serial.print(" ms\t");
noInterrupts();
//calculating speed
speedOfVehicle = impulsCounter * 720 / impulsesPerMeter; //km/h
overallImpulsCounter += impulsCounter;
impulsCounter = 0;
//calculating fuel consumption
consumptionPerHour = maxFuelConsumption * injectorImpulsLength / 5000;
consumptionPer100KM = consumptionPerHour * 100 / speedOfVehicle;
injectorImpulsLength = 0;
interrupts();
Serial.print(speedOfVehicle);
Serial.print(" km/h\t");
consumptionPerHour_point = consumptionPerHour % 10;
consumptionPerHour = consumptionPerHour / 10;
consumptionPer100KM_point = consumptionPer100KM % 10;
consumptionPer100KM = consumptionPer100KM / 10;
if(speedOfVehicle <= 1) {
motion = false;
displayFuelConsumption(motion, consumptionPerHour, consumptionPerHour_point);
} else {
motion = true;
displayFuelConsumption(motion, consumptionPer100KM, consumptionPer100KM_point);
}
displaySpeed(speedOfVehicle);
}
void calculateDistance() {
distanceMeters = overallImpulsCounter * 100 / impulsesPerMeter;
distanceHundretMeters = overallImpulsCounter / impulsesPerMeter;
distanceHundretMeters = distanceHundretMeters % 10;
distanceKilometers = overallImpulsCounter / (impulsesPerMeter * 10);
if(distanceKilometers >= 1) {
timer.updateInterval(1,5000); //calculateDistance interval
timer.updateInterval(2,5000); //displayDistance interval
}
}
void calculateFuelConsumption() {
}
//displaying methods
void displaySpeed(uint8_t speedOfVehicle) {
clearLine(0);
lcd.setCursor(0,0);
lcd.print("SPEED:");
if(speedOfVehicle < 10)
lcd.setCursor(10,0);
else if(speedOfVehicle >=10 && speedOfVehicle < 100)
lcd.setCursor(9,0);
else if(speedOfVehicle >=100 && speedOfVehicle < 1000)
lcd.setCursor(8,0);
lcd.print(speedOfVehicle);
lcd.print(" KM/H");
}
void displayDistance() {
clearLine(1);
lcd.setCursor(0,1);
lcd.print("TRIP:");
if(distanceHundretMeters == 0 && distanceKilometers == 0) {
if(distanceMeters < 10)
lcd.setCursor(13,1);
else if(distanceMeters >=10 && distanceMeters < 100)
lcd.setCursor(12,1);
else if(distanceMeters >=100 && distanceMeters < 1000)
lcd.setCursor(11,1);
lcd.print(distanceMeters);
lcd.print(" M");
}
else {
if(distanceKilometers < 10)
lcd.setCursor(10,1);
else if(distanceKilometers >=10 && distanceKilometers < 100)
lcd.setCursor(9,1);
else if(distanceKilometers >=100 && distanceKilometers < 1000)
lcd.setCursor(8,1);
else if(distanceKilometers >=1000 && distanceKilometers < 10000)
lcd.setCursor(7,1);
lcd.print(distanceKilometers);
lcd.print(".");
lcd.print(distanceHundretMeters);
lcd.print(" KM");
}
}
void displayFuelConsumption(bool motion, uint8_t consumption, uint8_t consumption_point) {
if(motion) {
Serial.print("\t");
Serial.print(consumption);
Serial.print(".");
Serial.print(consumption_point);
Serial.println(" [l/100km]");
} else {
Serial.print("\t");
Serial.print(consumption);
Serial.print(".");
Serial.print(consumption_point);
Serial.println(" [l/h]");
}
}
void clearLine(uint8_t line) {
lcd.setCursor(0,line);
lcd.print(" ");
}
//loop method
void loop() {
timer.process();
}
Mam nadzieje, że jest czytelny
Pozbyłem się wszystkich zmiennych typu float, double. Prędkość zliczam za pomocą przerwań (działa bez zarzutu, mimo że używam funkcji wbudowanych arduino obsugujących przerwania).
Co do spalania, tak wiem, mało dokładnie zliczam czas trwania impulsow, jednak jest to wersja tymczasowa. Bardziej zastanawia mnie dlaczego walnie czasem bubla w stylu (fragment danych wychodzących -> injectorImpulsLength, speedOfVehicle, fuelConsumption) :
23 ms 9 km/h 4.4 [l/100km]
23 ms 10 km/h 4.0 [l/100km]
20 ms 10 km/h 1.0 [l/100km]
22 ms 10 km/h 3.0 [l/100km]
21 ms 11 km/h 1.8 [l/100km]
23 ms 11 km/h 3.6 [l/100km]
Jakby źle wykonywały się obliczenia?