Tentativo di strumentazione digitale scooter

Si ok ma mischi il costrutto dello switch con quello dell'if, non so se va bene. Poi il tempo = millis(); dovrebbe andare al termine dello switch.

Quindi millis e switch case sono incompatibili? Non c'è verso di conciliare le cose x snellire il codice?

Certo che sono compatibili, però hai mischiato il costrutto (ovvero come si scrive un'istruzione) dello switch con quello dell'if
Dovresti fare così:

// Sketch display con 4 funzioni da implementare nel quadro strumenti del mio scooter

// includo librerie sketch

#include <LiquidCrystal.h>
#include <OneWire.h>
#include <DallasTemperature.h>

// definisco hardware

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
#define BUTTON 13                                 // pin di input a cui è collegato il pulsante  
#define ONE_WIRE_BUS 10                              // pin di input a cui è collegato il sensore temperatura 
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);                // Passaggio oneWire reference alla Dallas Temperature.

// Variabili generali

unsigned long tempo = 0;
int ContatorePulsantePremuto = 0;                   // conta il numero di volte che il pulsante è premuto buttonPushCounter
int StatoPulsante = 0;                              // stato corrente del pulsante
int StatoPulsantePrecedente = 0;                    // stato precedente del pulsante



// variabili lettura numero giri motore

int pin = 8;                                        // imposto il pin D8 come ingresso  per lettura numero giri motore
unsigned long durationhigh;
unsigned long durationlow;
unsigned long durationgiro;
unsigned long giri;
unsigned long giri_prec = 0;

// variabili temperatura

float temperatura = sensors.getTempCByIndex(0);
float temperatura_prec = 0;


// variabili voltmetro

int analogPin = A0;                                 // imposto il pin A0 come ingresso analogico per misura batteria
int lettura = 0;
float voltage;
float voltage_prec = 0;


void setup() {
  tempo = millis();
  lcd.begin(8, 2);                                  //impostiamo il numero di colonne ed il numero di righe di lcd
  pinMode(BUTTON, INPUT);                           // imposta input
  pinMode(pin, INPUT);
  sensors.begin();                                  // avvia libreria DS18B20
  Serial.begin(9600);                               // apre la porta seriale e la inizializza a 9600 bps
  Serial.println("Scaraduino 1.0");                 // messaggio inizializzazione
  lcd.clear();
  lcd.setCursor(1, 0);
  lcd.print("SCARA");
  lcd.setCursor(0, 1);
  lcd.print("DUINO V1");
}

void loop() {

  StatoPulsante = digitalRead(BUTTON);                        // legge il valore del BUTTON e lo conserva
  delay(15);
  if (StatoPulsante != StatoPulsantePrecedente) {             // compara lo stato del pulsante attuale con il precedente
    if (StatoPulsante == HIGH) {                                // se lo stato è cambiato incrementa il contatore

      ContatorePulsantePremuto++;                              // se lo stato corrente è alto, il pulsante è passato da off a on
      if (ContatorePulsantePremuto > 3) {

        // inizializzazione delle variabili

        ContatorePulsantePremuto = 0;
        StatoPulsante = 0;
        StatoPulsantePrecedente = 0;

      }

    }
    StatoPulsantePrecedente = StatoPulsante;                  // salva lo stato corrente nella variabile che indica lo stato precedente per il loop successivo
  }

  switch (ContatorePulsantePremuto) {

    case 1:  // controlla se il pulsante è stato premuto una volta

      durationhigh = pulseIn(pin, HIGH);                    // imposto funzione lettura numero giri
      durationlow = pulseIn(pin, LOW);
      durationgiro = durationhigh + durationlow;
      if (durationhigh > 0 && durationlow > 0) {
        durationgiro = durationhigh + durationlow;
        giri = 60000000 / durationgiro;
        if (abs(giri - giri_prec) > 250) {
          lcd.clear();
          lcd.setCursor(2, 0);
          lcd.print("Giri");
          lcd.setCursor(2, 1);
          lcd.print(giri);

          Serial.println(giri);

          giri_prec = giri;

        }
      }

      break;

     
      case 2:  // controlla se il pulsante è stato premuto due volte
      if ((millis() - tempo) > 500) {
        sensors.requestTemperatures();            // Invia il comando di lettura delle temperatura
        if (abs(temperatura - temperatura_prec) > 1) {
          lcd.clear();
          lcd.setCursor(2, 0);
          lcd.print("Temp");
          lcd.setCursor(0, 1);
          lcd.print(temperatura);
          lcd.setCursor(6, 1);
          lcd.print("\337C""C");

          Serial.print("Temperatura di: ");                    // stampa a video la temperatura
          Serial.print(temperatura);
          Serial.println(" C");

          temperatura_prec = temperatura;

        }
      tempo = millis();
      }
      break;
      
      
      case 3:  // controlla se il pulsante è stato premuto tre volte
      if ((millis() - tempo) > 500) {
        lettura = analogRead(analogPin);
        voltage = (13.3 / 1024) * lettura;                    // 13.75 sono i volts teorici della batteria a pieno carico
        if (abs(voltage - voltage_prec) > 1) {
          lcd.clear();
          lcd.setCursor(2, 0);
          lcd.print("Batt");
          lcd.setCursor(0, 1);
          lcd.print(voltage);
          lcd.setCursor(5, 1);
          lcd.print("V");

          Serial.print(voltage);
          Serial.println("V");

          voltage_prec = voltage;

        }
      tempo = millis();
      }
      break;
   }

}

Così gli if sono all'interno dei CASE, non all'esterno.

Meglio ancora infilare lo switch in una funzione e richiamarla ogni 500ms, se serve quando tutto funzionerà!!

Grazie. Domani proverò il codice e poi riportero' l'esito sperando che basti questa modica.

Rileggendo....

       ContatorePulsantePremuto = 0;
        StatoPulsante = 0;
        StatoPulsantePrecedente = 0;

Quando arrivi a contare a 4 lui azzera e non trova lo switch... così:

       ContatorePulsantePremuto = 1;
          //    StatoPulsante = 1;  non serve cambiarlo poichè è letto sopra da button
        StatoPulsantePrecedente = 1;

riparti da 1 e switch ti rimanda al contagiri

concordo, in alcuni punti hai mescolato if e switch in modo non corretto.
hai provato il codice nella versione di cam9500?

fratt:
concordo, in alcuni punti hai mescolato if e switch in modo non corretto.
hai provato il codice nella versione di cam9500?

E già ho fatto una bella macedonia...:slight_smile: Comunque non ho ancora provato il codice, lo testo stasera. A più tardi...

Ciao e grazie!

Dunque ho fatto tante prove, al limite dello sfinimento. Con il codice che segue, leggermente variato senza lo switch case, le cose girano più o meno bene:

void loop()

{

  StatoPulsante = digitalRead(BUTTON);                        // legge il valore del BUTTON e lo conserva
  delay(50);
  if (StatoPulsante != StatoPulsantePrecedente) {             // compara lo stato del pulsante attuale con il precedente
    if (StatoPulsante == HIGH) {                                // se lo stato è cambiato incrementa il contatore
      // se lo stato corrente è alto, il pulsante è passato da off a on
      ContatorePulsantePremuto++;
      delay(50);
      if (ContatorePulsantePremuto > 3) {

        // inizializzazione delle variabili

        ContatorePulsantePremuto = 1;
        StatoPulsante = 1;
        StatoPulsantePrecedente = 1;

      }
      // salva lo stato corrente nella variabile che indica lo stato precedente per il loop successivo

    }
    StatoPulsantePrecedente = StatoPulsante;
  }

  if (ContatorePulsantePremuto == 1) {                    // controlla se il pulsante è stato premuto una volta
    durationhigh = pulseIn(pin, HIGH);                    // imposto funzione lettura numero giri
    durationlow = pulseIn(pin, LOW);
    durationgiro = durationhigh + durationlow;
    if (durationhigh > 0 && durationlow > 0) {
      durationgiro = durationhigh + durationlow;
      giri = 60000000 / durationgiro;
      if ((millis() - tempo) > 1500) {
        
          lcd.clear();
          lcd.setCursor(2, 0);
          lcd.print("Giri");
          lcd.setCursor(2, 1);
          lcd.print(giri);

          Serial.println(giri);

          giri_prec = giri;
          tempo = millis();
        
      }
    }
  }

  if (ContatorePulsantePremuto == 2) {                   // controlla se il pulsante è stato premuto due volte
    sensors.requestTemperatures();                       // Invia il comando di lettura delle temperatura
    if ((millis() - tempo) > 1500) {

      lcd.clear();
      lcd.setCursor(2, 0);
      lcd.print("Temp");
      lcd.setCursor(0, 1);
      lcd.print(temperatura);
      lcd.setCursor(6, 1);
      lcd.print("\337C""C");

      Serial.println(temperatura);
      temperatura_prec = temperatura;

      tempo = millis();
    }
  }

  if (ContatorePulsantePremuto == 3) {                   // controlla se il pulsante è stato premuto tre volte
    lettura = analogRead(analogPin);
    voltage = (13.3 / 1024) * lettura;                    // 13.75 sono i volts teorici della batteria a pieno carico
    if ((millis() - tempo) > 1500) {

      lcd.clear();
      lcd.setCursor(2, 0);
      lcd.print("Batt");
      lcd.setCursor(0, 1);
      lcd.print(voltage);
      lcd.setCursor(5, 1);
      lcd.print("V");

      Serial.println(voltage);
      voltage_prec = voltage;

      tempo = millis();

    }
  }

}

Ho notato che a mandare in pappa il ciclo era la condizione:

if (abs(giri - giri_prec) > 250) {
            
ecc ecc

          }

cioè alla fine del ciclo, dopo la terza funzione, se non si verifica la condizione programmata,
il ciclo non si riavvia. Tolta quella e lasciata solo la condizione if millis() il ciclo ha ripreso a girare.

Restano dei ma. Il display aggiornandosi ogni 1500ms sfarfalla un pò. Idee? Inoltre a volte bisogna pigiare più di una volta sul pulsante per ciclare, oppure bisogna pigiare con fermezza e più a lungo. Come mai? Devo prevedere dei delay per il pulsante?

Grazie

1500ms equivalgono a 1 secondo e mezzo... strano che sfarfalli con un intervallo così lungo...

e strano anche che quell'if mandi in crisi il loop...

dovrei provare di persona il codice per rendermi conto di cosa succede...

Ciao, immagino ogni 1.5sec. si veda l'lcd.clear(). Dovresti far fare l'lcd.clear() solo quando cambia il ContatorePulsantePremuto aggiungendo unContatorePulsantePremuto_old per confronto.
Quindi se ContatorePulsantePremuto !=ContatorePulsantePremuto -> lcd.clear() altrimenti stampa solo il valore dei giri o temperatura.... non so se mi spiego

Stefano

cam9500:
Ciao, immagino ogni 1.5sec. si veda l'lcd.clear(). Dovresti far fare l'lcd.clear() solo quando cambia il ContatorePulsantePremuto aggiungendo unContatorePulsantePremuto_old per confronto.
Quindi se ContatorePulsantePremuto !=ContatorePulsantePremuto -> lcd.clear() altrimenti stampa solo il valore dei giri o temperatura.... non so se mi spiego

Stefano

mh ok, ho fatto così:

void loop()

{

  StatoPulsante = digitalRead(BUTTON);                        // legge il valore del BUTTON e lo conserva
  delay(50);
  if (StatoPulsante != StatoPulsantePrecedente) {             // compara lo stato del pulsante attuale con il precedente
    lcd.clear();
    if (StatoPulsante == HIGH) {                                // se lo stato è cambiato incrementa il contatore
      // se lo stato corrente è alto, il pulsante è passato da off a on
      ContatorePulsantePremuto++;
      if (ContatorePulsantePremuto > 3) {

        // inizializzazione delle variabili

        ContatorePulsantePremuto = 1;
        StatoPulsante = 1;
        StatoPulsantePrecedente = 1;

      }

in effetti va meglio. grazie

Ah, bravo, ancora meglio: risparmi una variabile rispetto a quanto ti ho detto io ed ottieni lo stesso risultato.

Ragazzi, siccome ho quasi ultimato il codice, vorrei inserire una bella frase in stile open source per indicare che lo sketch è copiabile e modificabile da chiunque. Avete delle frasi con roba del genere da passarmi?

Grazie

Ragazzi mi serve confrontare la variabile giri con un range di valori, cosi da avere un risultato a cifre tonde. Cioè vorrei ad esempio che se la lettura dei numeri dei giri fosse compresa tra 500 e 1000, sul display venga stampato 1000, se invece fosse compresa tra 1000 e 1500 , sul display venga stampato 1500 e così via fino a 10500.

Ho scritto questo:

 if (giri >= 500 && giri <= 1000) { 
lcd.setCursor(2, 1);
lcd.print("1000");
}
 
if (giri >= 1001 && giri <= 1500) { 
lcd.setCursor(2, 1);
lcd.print("1500");
}
 
if (giri >= 1501 && giri <= 2000) { 
lcd.setCursor(2, 1);
lcd.print("2000");
}
 
if (giri >= 2001 && giri <= 2500) { 
lcd.setCursor(2, 1);
lcd.print("2500");
}

Ma Arduino con questo blocco di if è come se bloccasse il programma e non riesco a switchare tra i case che mi restituiscono le altre funzioni. Ho un dubbio. ma dopo il primo if, devo usare solo else?

Grazie

Quel che hai scritto è corretto, il problema è altrove.

Cioè? Se hai modo potresti spiegarmi?

Non lo so, ma quest'ultimo pezzo di codice che hai postato non può bloccare il programma, non essendoci nessun ciclo. E poi comunque mi sembra scritto correttamente, dovrebbe fare quello che intendi.

Ok grazie.

Ragazzi finalmente ho qualcosa di concreto su cui lavorare! Grazie a tutti quelli che mi hanno sopportato e supportato!

Link al video: Video prova progetto!

A bloccarmi per qualche giorno, pensate,è stata l'alimentazione a batteria ( una 9V usata che ho tolto dalla sveglia) che evidentemente non era sufficiente ed Arduino non funzionava bene. Ho fatto la prova col pc e tutto è andato come doveva andare.

E vai!

Ohhh bene: qualcosa di concreto aiuta ad andare avanti !!

Immagino la soddisfazione di vedere i giri che cambiano ad ogni accelerata..... mi ricordo il contagiri a led di tanti anni fa :smiley:

Vinci un karma di incoraggiamento :wink: