Speedometer


Bike speedometer software


//Versiunea 08
//modificat in 12 01 2012
//   CIRCUIT
// Vitezometru
// (Gnd) ---- (R) --------|------- (Reed Switch) ---- (+5v)
//                        |
//                   Digital Pin 11
// pt.ca valoare indicata sa fie cea corecta,
//senzorul trebuie sa fie activat cel putin 300 micosecunde
//
// Voltmetru
// (Gnd) ---- (R2) -------|------- (R1) ---- (Vin)
//                        |
//                      Vout -> Analog Pin 5
//
//
// Termometru
// (Gnd) ---------------LM35----------- (+5v)
//                       |
//                 Analog Pin 0
float temperatura = 0;
//
// includem libraria EEPROM:
#include EEPROM.h
//
// includem libraria pt conectare la LCD:
#include LiquidCrystal.h
//initializam libraria si definim pini de conectare la LCD
//               (RS, EN, D4,D3,D2,D1);
LiquidCrystal lcd(10, 9, 8, 7, 6, 5);

//--------voltmetru-----------
int IntrareVoltmetru = 5;
float vin = 0.0;
float R1 = 15000.0;    // !! valoarea rezistentei R1 !!
float R2 = 1000.0;     // !! valoarea rezistentei R2 !!
float formula = 0;  
//------------------------------------------------------
#define LED 13                   // iesire pentru LED
#define SWITCH 11                // intrare pentru senzor
#define RESET 4                  // intrare butonul reset distanta
int circumferinta = 185;         // circumferinţa în cm
int val = 0;                     // folosit pentru a memora valoarea de intrare
int ValoareaAnterioara = 0;      // folosit pentru a elimina citirea repetata a senzorului in timpul opririi
int debounce = 10;               // Valoarea trebuie crescuta daca este necesar
float rotatii = 1;               // numărul total de rotaţii
float VitezaCurenta = 0;         // viteza curentă în km / h
float VitezaMedie = 0;           // viteza medie de cand am pornit
float VitezaMaxima = 0;          // viteza maxima de cand am pornit

unsigned long revTimer;          // creem un cronometru pentru citirea timpului dintre impulsurii
unsigned long rideTimer;         // cronometru călătorie

boolean activeRiding = false;    // suntem în mişcare?
boolean activityChange = true;   // doar o modalitate de a tine cont de cât timp suntem inactivi
float inactivityTimer;           // millis() la care am început inactivitatea
float activeRidingOffset = 0;    // timpul scăzut din timpul total de mers când se calculează viteza medie
float DistantaParcursa = 0;      // distanţa totală parcursă de cand am pornit
unsigned long DistantaTotala = 0;
unsigned long DistantaMemorata = 0;
int memorare = 0;
//-------------afisare---------------------------
long TimpLcdAnterior = 0;        // pentru actualizare ecran
long LcdInterval = 1000;         // timpul intre afisari
int ecran = 0;                  // ecranul afişat
int ecranMax = 24;              // nr. de ecrane afisate
boolean schimbareEcran = true;    // initial avem un nou ecran
//------------------------------------------------------

void setup() {
  // declaram pinii de interfata
  pinMode(LED, OUTPUT);            // LED este o ieşire,
  pinMode(SWITCH, INPUT);          // si SWITCH este intrare
  pinMode(IntrareVoltmetru, INPUT);// intrare masura tensiune
  pinMode(RESET, INPUT);           // RESET este intrare
  analogReference(INTERNAL);       // Folosim referinta interna de 1.1V
  // setam numarul de coloane şi rânduri pe LCD
  lcd.begin(20, 2);              
  lcd.clear();
  lcd.setCursor(6, 0);
  lcd.print("ATENTIE");
  lcd.setCursor(2, 1);
  lcd.print("puneti-va casca!");
  delay(2000);
  lcd.clear();
  // citire distanta totala din EEPROM
  DistantaMemorata = (EEPROM.read(10) * 65536) + (EEPROM.read(11) * 256) + (EEPROM.read(12));
  DistantaTotala = DistantaMemorata;
  //-----------voltmetru--------------------
  formula = ((1.1/1023)/(R2/(R1+R2)));
  //----------------------------------------
  revTimer = millis();            // Start cronometru puls
  rideTimer = millis();           // start cronometru călătorie
}
void loop(){
  //-----------resetare distanta------------
  if (digitalRead(RESET) == LOW) {  
    EEPROMclear();             //memoram valorile in eeprom
    delay(500);
    DistantaTotala = 0;
    DistantaMemorata = 0;
    DistantaParcursa = 0;
    lcd.setCursor(0, 0);
    lcd.print("  Distanta          ");
    lcd.setCursor(0, 1);
    lcd.print("           Resetata ");
    delay(2000);
    lcd.clear();
    ecran = 0;    // începe de la capăt cu afisarea
  }
  //----------------------------------------
  if(activityChange) {
    inactivityTimer = millis();
    activityChange = false;
  }
  else {
    if(activityChange) {
      activeRidingOffset += millis() - inactivityTimer;
      activityChange = false;
    }
  }
  val=digitalRead(SWITCH);         // citeşte valoarea de intrare şi memoreaz-o.
  if (val==HIGH) {                 // verifica dacă intrare este "HIGH" (magnetu-l este in raza senzorului)
    digitalWrite(LED, HIGH);       // "aprinde" LED-ul
    ValoareaAnterioara = HIGH;     // permite următoarul "impuls" pentru a fi numărat
  }
  else {
    digitalWrite(LED, LOW);        // Stinge led-ul
    if (ValoareaAnterioara != LOW && millis() - revTimer > debounce) { // daca...
      pulse();                    // inseamna ca ne miscam
    }
    ValoareaAnterioara = LOW;     // în cazul în care magnetul este în raza de acţiune a senzorului in timpul stationarii.
  }
  if(millis()-revTimer > 2000) { // daca a trecut prea mult timp de la ultimul impuls,
    VitezaCurenta = 0;           //  inseamna ca stam pe loc
    if(activeRiding) {
      activityChange = true;
      activeRiding = false;
    }
  }
  //----------Memorare distanta---------------
  if(millis()-revTimer > 10000) { // daca a trecut prea mult timp de la ultimul impuls,
    if  (memorare == 1)  {        // si memorarea este activata
      EEPROMwrite();              //memoram distanta in eeprom
      delay(500);
      lcd.setCursor(0, 0);
      lcd.print("  Distanta          ");
      lcd.setCursor(0, 1);
      lcd.print("           Salvata  ");
      delay(2000);
      lcd.clear();
      memorare = 0;  //setam memorarea 0 pt a preveni scriierea repetata
      ecran = 0;    // începe de la capăt cu afisarea
    }
  }
  //----------Afisare Rezultate-------------
  unsigned long TimpLcdActual = millis();
  if(TimpLcdActual - TimpLcdAnterior > LcdInterval)   // memoram ultima data cand am afisat
  {
    TimpLcdAnterior = TimpLcdActual;
    ecran++;
    if (ecran > ecranMax) ecran = 0;  // toate ecranele afisate ? => începe de la capăt
    schimbareEcran = true;

    if (schimbareEcran)   // actualizare numai în cazul în care ecranul se schimbă.
    {
      schimbareEcran = false; // resetare pentru urmatoarea schimbare
      switch(ecran)
      {
      case 0:
        DisTotala();
        break;
      case 1:
        DisTotala();
        break;
      case 2:
        DisTotala();
        break;
      case 3:
        DisTotala();
        break;
      case 4:
        DisTotala();
        break;
      case 5:
        VitMedie();
        break;
      case 6:
        VitMedie();
        break;
      case 7:
        VitMedie();
        break;
      case 8:
        VitMedie();
        break;
      case 9:
        VitMedie();
        break;
      case 10:
        VitMaxima();
        break;
      case 11:
        VitMaxima();
        break;
      case 12:
        VitMaxima();
        break;
      case 13:
        VitMaxima();
        break;
      case 14:
        VitMaxima();
        break;
      case 15:
        Temp();
        break;
      case 16:
        x();
        break;
      case 17:
        x();
        break;
      case 18:
        x();
        break;
      case 19:
        x();
        break;
      case 20:
        volt();
        break;
      case 21:
        x();
        break;
      case 22:
        x();
        break;
      case 23:
        x();
        break;
      case 24:
        x();
        break;
      default:
        break;
      }
    }
  }
  //------------------------------------------------------
}
void pulse() {
  memorare = 1;  //activam memorarea pt urmatoarea oprire
  rotatii++;     // incrementam nr. de rotatii

  DistantaParcursa = (float) circumferinta * rotatii / 100000;// distata in KM

  DistantaTotala = DistantaMemorata + DistantaParcursa;

  VitezaCurenta = (float) (millis() - revTimer)*0.001;   // Convertim timpul trecut din milisecunde in secunde
  VitezaCurenta = circumferinta/VitezaCurenta;           // V = d/t: Circumferinta rotii / timp trecut
  VitezaCurenta = VitezaCurenta*0.036;                   // Km/h Conversion: 1 cm/s = 0.01 m/s * 3600 s/hr  = 0.036 Km/h

  if (VitezaMaxima < VitezaCurenta) {
    VitezaMaxima = VitezaCurenta;
  }
  // calculam timpul de cand am pornit din care scadem stationarile
  unsigned long activeRidingMillis = millis() - rideTimer - activeRidingOffset;
  float activeRidingHours = (float) activeRidingMillis / 1000/60/60;  // transformam in ore
  VitezaMedie = DistantaParcursa / activeRidingHours;                 //viteza medie = distanta parcursa/timp

  revTimer = millis();       // memoram momentul actual pt. a calcula viteza data viitoare

  if(!activeRiding) {
    activityChange = true;
    activeRiding = true;
  }
}
void DisTotala() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(VitezaCurenta,0);
  lcd.print("Kmh");
  lcd.setCursor(10, 0);
  lcd.print(DistantaParcursa);
  lcd.print("km");
  lcd.setCursor(0, 1);
  lcd.print("DistTot:");
  lcd.setCursor(10, 1);
  lcd.print(DistantaTotala);
  lcd.print("Km");
}
void VitMedie() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(VitezaCurenta,0);
  lcd.print("Kmh");
  lcd.setCursor(10, 0);
  lcd.print(DistantaParcursa);
  lcd.print("km");
  lcd.setCursor(0, 1);
  lcd.print("V.Medie:");
  lcd.setCursor(10, 1);
  lcd.print(VitezaMedie,1);
  lcd.print("Kmh");
}
void VitMaxima() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(VitezaCurenta,0);
  lcd.print("Kmh");
  lcd.setCursor(10, 0);
  lcd.print(DistantaParcursa);
  lcd.print("km");
  lcd.setCursor(0, 1);
  lcd.print("V.Maxima:");
  lcd.setCursor(10, 1);
  lcd.print(VitezaMaxima,1);
  lcd.print("Kmh");
}
void Temp() {
  temperatura = (1.1*analogRead(0)*100/1024);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(VitezaCurenta,0);
  lcd.print("Kmh");
  lcd.setCursor(10, 0);
  lcd.print(DistantaParcursa);
  lcd.print("km");
  lcd.setCursor(0, 1);
  lcd.print("Temp:");
  lcd.setCursor(10, 1);
  lcd.print(temperatura,1);
  lcd.print((char)223);  // scrie caracterul pt. grade celsius
  lcd.print("C");
}
void volt() {
  //-----------voltmetru-------------------
  // citim valoarea de pe intrarea analogica si calculam tensiunea
  vin = ((analogRead(IntrareVoltmetru) * formula) + 0.6);  // adaugam caderea de tensiune pe dioda
  //----------------------------------------
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print(VitezaCurenta,0);
  lcd.print("Kmh");
  lcd.setCursor(10, 0);
  lcd.print(DistantaParcursa);
  lcd.print("km");
  lcd.setCursor(0, 1);
  lcd.print("Tensiune:");
  lcd.setCursor(10, 1);
  lcd.print(vin,1);
  lcd.print("V");
}
void x() {
  lcd.setCursor(0, 0);
  lcd.print("                    ");
  lcd.setCursor(0, 0);
  lcd.print(VitezaCurenta,0);
  lcd.print("Kmh");
  lcd.setCursor(10, 0);
  lcd.print(DistantaParcursa);
  lcd.print("km ");
}

void EEPROMwrite()  {      // Memorarea distantei
  // memoreaza variabilele in EEPROM
  EEPROM.write(10, byte((DistantaTotala & 16711680)/65536));
  EEPROM.write(11, byte((DistantaTotala & 65280)/256));
  EEPROM.write(12, byte((DistantaTotala & 255)));
}
void EEPROMclear()  {      // Stergerea distantei
    EEPROM.write(10, byte((0 & 16711680)/65536));
    EEPROM.write(11, byte((0 & 65280)/256));
    EEPROM.write(12, byte((0 & 255)));
}

1 comment :