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...
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 spiegoStefano
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 ![]()
Vinci un karma di incoraggiamento ![]()