contatore di km trascorsi Risolto

salve, ho un nuovo problema che sicuramente per voi è ridicolo, ma per me è abbastanza serio :o :o .

ho creato questo codice che mi segna su un lcd 16x2 i giri della ruota in movimento e la velocità istantanea, ma volevo ancora aggiungere i km trascorsi....ho cercato ovunque ma non sono riuscito a capire molto, potreste aiutarmi??

 #include <LiquidCrystal.h>           
 LiquidCrystal lcd(12, 11, 5, 4, 3, 2);  

 #define sensHall A5

 int val;                              
 int rpm = 0 ;                               
 int Kmh = 0 ;                             
 long val_v = 0 ;                            
 int stato1 = LOW ;                       
 int stato2 ;                             
 int contatore = 0 ;                        
 int sens = 75 ;                               
 int nGiri = 2 ;                              
 int millisecondi = 500 ;                     
 int contatorePulsante ;
 int statoPulsante ;
 int statoPulsanteV ;
 int KmPercorsi ;

void setup()
 
{
  
 lcd.begin (16,2) ;

 pinMode (sensHall, INPUT) ;
 pinMode (13,OUTPUT) ;
 
}


void loop() 

{
  
 val = analogRead (sensHall) ;
 
  if ( val < sens )
 stato1 = LOW ;
 
  else
 stato1 = HIGH ;
 

  if ( stato2 != stato1 )
 { 
   
 contatore ++ ;
 stato2 = stato1 ;
 }
 
  if ( millis() - val_v >= millisecondi )
  {
    
 double rps = ((double) contatore / nGiri) / 2.0 * 1000.0 / millisecondi ;
 double rpm = ((double) contatore / nGiri) / 2.0 * 60000.0 / millisecondi ;
 
 Kmh = (rpm * 60.0 * 0.001) ;

 contatore = 0 ;
 
 val_v = millis() ;
 
 lcd.setCursor (0,0) ;
 lcd.print (int(rpm)) ;
 lcd.print (" Giri/min ") ;
 
 lcd.setCursor (0, 1) ;
 lcd.print (Kmh) ;
 lcd.print (" Km/h ") ;

} 
}

Dichiari più volte delle variabili, tipo rpm. Comunque basta che stampi i giri contati per la circonferenza della ruota, no?

si basta fare quello ma il dilemma è come salvare i i giri contati nella eeprom, quindi scriverli e leggerli , poi li moltiplico come dici tu :slight_smile:

Se lo spegnimento è gestito tramite software(Il micro è sempre attivo, ma va in sleep mode) allora ti basterà salvare il dato nell'eeprom solo al verificarsi dell'evento che lo fa entrare in sleep mode. Se invece la gestione dello spegnimento è di tipo "forza bruta" (cioè stacchi l'alimentazione) allora ogni tot devi salvare il dato, dico ogni tot perchè bisogna evitare i cicli continuativi di scrittura dell'eeprom che ha una vita legata strettamente al numero di scritture. Puoi gestire le scritture mediante millis quindi temporizzare (ogni x secondi aggiorno il dato), o meglio aggiornare il dato dell'eeprom con una risoluzione minore di quella adoperata nel software, mi spiego meglio, ho una ruota da 29'' consideriamo abbia una risoluzione di lettura di un giro quindi la risoluzioni in cm è di 231.41cm. Questa sarà la risoluzione che adopererò via software, ma sul eeprom potrei aggiornare il dato per esempio ogni 100 giri quindi avrò una risoluzione di 231.41m. Cosi facendo avrò aggiornamenti della eeprom circa ogni 200m e avrò un "occupazione della memoria nella eeprom minore di quella nel software di ben 100 volte"(tra virgolette perché si parla di una risoluzione del valore numerico non dell'effettiva informazione binaria).

ho provato a fare un contatore di quante volte il sensore di hall (del tipo interruttore magnetico) viene chiuso, e quindi il contatore parte, però non si ferma aggiungendo solo 1, se il sensore rimane chiuso arduino contina a contare all'infinito! ho provato in alcuni modi ma non ho avuto molti risultati....

 int vall = digitalRead (A5);
  
    if (vall ==1)
    
    {
      
    contatorePulsante ++  ;
    delay(50);
     Serial.println (contatorePulsante); 
   

 }

Devi contare i fronti di salita sul pin. Quindi devi tenere traccia dello stato del pin nel precedente ciclo di loop.

scusa l'ignoranza, ma come posso fare?? :o :o :o :o

Devi impostare qualcosa del genere

#define PIN 10

#define OVERFLOWFIRSTCOUNTER 100
#define DIAMETER 73.66
#define GIRTH (DIAMETER * 3.14)

bool previous = false;
unsigned int firstCounter = 0;
unsigned long secondCounter = 0;
double kmp = 0;

void setup() {
  //Leggo il valore di secondCounter dalla EEPROM
}

void loop() {
  if(digitalRead(PIN) == HIGH) {
    if(previous == false) {//Se il valore precedente è LOW
      previous = true;//Aggiorno il valore precedente con HIGH
      if(++firstCounter == OVERFLOWFIRSTCOUNTER) {//Incremento il primo contatore e verifico che sia arrivato al valore di aggiornamento
        firstCounter = 0;//Ripristino il primo contatore
        secondCounter++;//Incremento il secondo contatore
        //Aggiorno il valore di secondCounter nel EEPROM
      }
    }
  } else previous = false;//Ripristino lo stato precedente a LOW
  kmp = (firstCounter + secondCounter * 100) * GIRTH;//Calcolo la distanza percorsa
}

WOW, non so proprio come ringraziarti!!!! provo ad inserirlo subito nel mio codice grazie mille :slight_smile: :slight_smile: ti faccio poi sapere se funziona

eccolo, anche se è un pò lentuccio ma il funzionamento c'è!!

 #include <LiquidCrystal.h>           
 LiquidCrystal lcd(13, 12, 11, 10, 9, 8); 

 #define sensHall A5
 #define contatoreMax 100
 #define distanzaGiro 0.001
 
 bool precedente = false ;
 float  kmp = 0 ; 

 int val;                             
 int rpm = 0 ;                               
 float Kmh = 0 ;                             
 long val_v = 0 ;                           
 int stato1 = LOW ;                       
 int stato2 ;                             
 int contatore = 0 ;                       
 int sens = 75 ;                               
 int nGiri = 2 ;                             
 int millisecondi = 500 ;
 unsigned int primoContatore = 0 ;
 unsigned long secondoContatore = 0 ;
 

void setup()
 
{
 
 
 lcd.begin (16,2) ;

 pinMode (sensHall, INPUT) ;
 
 
}


void loop()

{
  
  
 
 val = analogRead (sensHall) ;
 
  if ( val < sens )
 stato1 = LOW ;
 
  else
 stato1 = HIGH ;
 

  if ( stato2 != stato1 )
 {
   
 contatore ++ ;
 stato2 = stato1 ;
 }
 
  if ( millis() - val_v >= millisecondi )
  {
   
 double rps = ((double) contatore / nGiri) / 2.0 * 1000.0 / millisecondi ;
 double rpm = ((double) contatore / nGiri) / 2.0 * 60000.0 / millisecondi ;
 
 Kmh = (rpm * 60.0 * distanzaGiro) ;

 contatore = 0 ;
 
 val_v = millis() ;
 
 lcd.setCursor (0, 1) ;
 lcd.print (Kmh) ;
 lcd.print (" KM/H ") ;
 

 }
 
  
    if(digitalRead (sensHall) == HIGH)
  {
    if(precedente == false)
   { precedente = true ;
   
     if (++ primoContatore == contatoreMax)
    { primoContatore = 0 ;
      secondoContatore ++ ;
    }
   }
  }
   else precedente = false ;
   kmp = (primoContatore + secondoContatore * 100) * distanzaGiro ;
  
   lcd.setCursor (0,0) ;
 lcd.print ((kmp)) ;
 lcd.print (" KM FATTI ") ;
 
 
}

E via ai consigli:
-Pulisci il codice e rendi più leggibile il codice, so che il Wiring non è Python ma le indentature rendono il codice più facile da leggere, le righe vuote dovrebbero separare gruppi di operazioni diverse tra loro, non essere disposte a caso.
-Dichiara le variabili all'inizio della funzione oppure prima del Setup() se sono globali, ok questa è una regola del C che è stata superata nel Wiring ma è comunque un buona regola per scrivere codice, si evitano dichiarazioni ripetitive e si ha ben chiaro cosa serve e cosa no.
-Evita le costanti e ripiega sulle definizioni del preprocessore, non ha senso ad ogni ciclo di loop ricalcolare 2.0 * 1000.0, questa non cambierà mai, per di più l'operazione è tra due float e non int quindi un operazione parecchio onerosa per un piccolo AVR.
-Utilizza unsigned con senso, se contatore può essere positivo sarebbe comodo dichiararlo come unsigned cosi si raddoppiano i valori possibili.
-Utilizza i tipi piu consoni, se hai bisogno di un int non usare un float, se hai bisogno di un bool non usare un int.