• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Niedokładność pomiarowa - problem z odczytywaniem impulsow
#26
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 Smile
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?
 
Odpowiedź
  


Wiadomości w tym wątku
RE: Niedokładność pomiarowa - problem z odczytywaniem impulsow - przez qbic - 17-08-2018, 19:20

Skocz do:


Przeglądający: 3 gości