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)));
}
Best Bike Speedometer
ReplyDelete