Modifica sketch per impostare un valore tramite pulsanti

Salve a tutti, io vorrei creare una modifica al mio codice ma non so proprio come arrivare alla soluzione.
Ho iniziato a scrivere un programma per una piastra riscaldante e a una temperatura impostata scatta il relè per evitare che il liquido salga troppo di temperatura. in questo progetto sto usando sensore di temperatura LM35, Arduino uno r3, un monitor lcd 16x2 con modulo i2c e un modulo relè.
Attualmente con il programma che ho scritto funziona tutto solo che imposto tramite pc caricando il valore di temperatura al quale deve scattare il relè. Volevo modificare questa cosa con dei pulsanti, impostati in pullup, per alzare o abbassare il valore di temperatura alla quale il relè deve scattare e far partire il tutto.

#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>

#define I2C_ADDR    0x27 // indirizzo lcd 16x2 i2c
#define BACKLIGHT_PIN     3
#define En_pin  2
#define Rw_pin  1
#define Rs_pin  0
#define D4_pin  4
#define D5_pin  5
#define D6_pin  6
#define D7_pin  7
#define PIN_LM35 A0

//modulo rele
#define PIN_rele1 7
int stato_PIN_rele1;

//libreria lcd cinese
LiquidCrystal_I2C  lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);
//carattere clessidra
byte clessidra[8] = {
  B11111,
  B10001,
  B01010,
  B00100,
  B00100,
  B01110,
  B11111,
  B11111
};
//carattere on
byte on[8] = {
  B00000,
  B00000,
  B00001,
  B00010,
  B10100,
  B01000,
  B00000,
  B00000
};
//carattere off
byte off[8] = {
  B00000,
  B10001,
  B01010,
  B00100,
  B01010,
  B10001,
  B00000,
  B00000
};

void setup() {
 pinMode (PIN_rele1,OUTPUT);
lcd.begin(16,2);
lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
lcd.setBacklight(HIGH);
//creazione carattere
lcd.createChar(0,clessidra);
lcd.createChar(1,on);
lcd.createChar(2,off);
lcd.home();
}

void loop() {
 int valore = analogRead(PIN_LM35);
 //float mV = valore / 1023.0 * 5000;
 //float temperatura = mV / 10;
 float temperatura = valore / 2.046;
 //impostazioni pin rele
   if (temperatura >= 30){
      digitalWrite (PIN_rele1,HIGH);
     (digitalRead(stato_PIN_rele1 == HIGH));
      lcd.setCursor(15,1);
      lcd.write(byte(2));// disegno off
  }else{
      digitalWrite (PIN_rele1,LOW);
      lcd.setCursor(15,1);
      lcd.write(byte(1));  //disegno on}
      }
//impostazioni scritte lcd      
lcd.setCursor(0,0);
lcd.print("Temp:");
lcd.print(temperatura);
lcd.print(" C  ");
//scritta relè1 (scalda) se acceso o spento
lcd.setCursor(14,1);
lcd.print("R");
delay(1000);
}

Benvenuto,
essendo il tuo primo post, nel rispetto del regolamento della sezione Italiana del forum (… punto 13, primo capoverso), ti chiedo cortesemente di presentarti IN QUESTO THREAD (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto) e di leggere con MOLTA attenzione tutto il su citato REGOLAMENTO ... Grazie. :slight_smile:

nid69ita

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione, nessuno ti potrà rispondere, quindi ti consiglio di farla al più presto. :wink:

Zero88Cool:
vorrei creare una modifica al mio codice ma non so proprio come arrivare alla soluzione.

Fondamentalmente è da ripensare il programma in termini di fasi di funzionamento, per lo meno due, una normale e una modifica (selezionate tramite un valore impostato in una variabile), e di condizioni/eventi che fanno passare da una fase all'altra. Ad esempio una logica tipo questa:

SE fase normale:
    SE premuto un tasto:
        visualizza modifica
        reset tempo
        imposta fase modifica
    ALTRIMENTI SE trascorso 1sec:
        reset tempo
        elabora normale
ALTRIMENTI SE fase modifica:
    SE premuto un tasto:
        modifica valore
        visualizza modifica
        reset tempo
    ALTRIMENTI SE trascorsi 5 sec:
        visualizza normale
        imposta fase normale

A questo va aggiunta una logica di riconoscimento degli istanti di pressione dei pulsanti (che si effettua controllando se l'ultima lettura attuale differisce dalla precedente), e lo studio sull'uso della funzione millis per misurare il trascorrere del tempo.

Per quanto riguarda l'hardware, ai pulsanti che chiudono verso massa vanno messi in parallelo dei condensatori da 100nF, così si è a posto con i problemi dei rimbalzi meccanici in chiusura e apertura.

Per la lettura della temperatura la costante 2,046 andrebbe ritoccata in base al valore esatto dei +5V misurati con lo strumento più preciso a disposizione (si può migliorare la precisione di circa un grado).

Grazie dei consigli.

Da domani visto che avrò un po piu di tempo, causa un infortunio al lavoro non grave, vedrò di apportare ulteriori modifiche e di studiare un po di programmazione. Devo dire che come primo progetto con le pochissime conoscenze di Arduino e di programmazione è molto, troppo ambizioso. Io sono fatto cosi se non mi schianto con progetti complessi dopo mi annoio e non continuo. Sicuramente nel giro di pochi giorni non riuscirò a fare tutto, con calma ce la farò.

Il mio obiettivo è quello di scrivere con un programma nel quale ho piu menù:
avvio nel quale tutto è fermo
menù di impostazione temperatura
menù di impostazione di un "miscelatore" acceso o spento
menù di impostazione di un timer, che allo scadere blocca tutto
far partire tutto.

Vedrò sicuramente di rivedere il calcolo della temperatura migliorandolo.

Oggi ho apportato delle modifiche, ma ho riscontrato qualche bug grafico sul display lcd che vedrò di risolvere.

Qui sketch aggiornato

#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>

#define I2C_ADDR    0x27 // indirizzo lcd 16x2 i2c
#define BACKLIGHT_PIN     3
#define En_pin  2
#define Rw_pin  1
#define Rs_pin  0
#define D4_pin  4
#define D5_pin  5
#define D6_pin  6
#define D7_pin  7
#define PIN_LM35 A0

//modulo rele
#define PIN_rele1 7
int stato_PIN_rele1;

//valore temperatura massima
int maxT;

//tasti imput
#define PIN_meno 2
#define PIN_piu 3

//libreria lcd cinese
LiquidCrystal_I2C  lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);

//carattere clessidra
byte clessidra[8] = {
  B11111,
  B10001,
  B01010,
  B00100,
  B00100,
  B01110,
  B11111,
  B11111
};
//carattere on
byte on[8] = {
  B00000,
  B00000,
  B00001,
  B00010,
  B10100,
  B01000,
  B00000,
  B00000
};
//carattere off
byte off[8] = {
  B00000,
  B10001,
  B01010,
  B00100,
  B01010,
  B10001,
  B00000,
  B00000
};

void setup() {
//pin impostati pullup
 pinMode (PIN_meno, INPUT_PULLUP);
 pinMode (PIN_piu, INPUT_PULLUP);
 
 pinMode (PIN_rele1,OUTPUT);
lcd.begin(16,2);
lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
lcd.setBacklight(HIGH);

//creazione carattere
lcd.createChar(0,clessidra);
lcd.createChar(1,on);
lcd.createChar(2,off);
lcd.home();
}

void loop() {
 int valore = analogRead(PIN_LM35);
 //float mV = valore / 1023.0 * 5000;
 //float temperatura = mV / 10;
 float temperatura = valore / 2.046;

//valore temperatura massima
 maxT = constrain(maxT,11,100);
   if (digitalRead(PIN_piu)) maxT++;
   if (digitalRead(PIN_meno)) maxT--;
   
 //lcd.setCursor(2,1);
 //lcd.print(maxT);
 

 //impostazioni pin rele
   if (temperatura >= maxT){
      digitalWrite (PIN_rele1,HIGH);
     (digitalRead(stato_PIN_rele1 == HIGH));
      lcd.setCursor(15,1);
      lcd.write(byte(1));// disegno on
  }else{
      digitalWrite (PIN_rele1,LOW);
      lcd.setCursor(15,1);
      lcd.write(byte(2));  //disegno off
      }

//impostazioni scritte lcd      
lcd.setCursor(0,0);
lcd.print("Temp:");
lcd.print(temperatura);
lcd.print(" C  ");

//scritta temperatura massima impostata x il relè
lcd.setCursor(0,1);
lcd.print("maxT:");
lcd.setCursor(5,1);
lcd.print(maxT);

//scritta relè2 miscelatore
lcd.setCursor(11,1);
lcd.print("M");

//scritta relè1 (scalda) se acceso o spento
lcd.setCursor(14,1);
lcd.print("R");
delay(1000);
}

Ho fatto un ulteriore modifica allo sketch, creando degli stati nei quali puoi fare qualcosa.
Piccolo problema riscontrato: non cambia il menu oppure va talmente veloce che arriva in fondo.

Come detto da nid69ita ai pulsanti che chiudono verso massa vanno messi in parallelo dei condensatori da 100nF.

Perdona la mia ignoranza nel campo quindi dovrei aggiungere questo

alla pressione del tasto?

nuovo sketch

#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
//impostazioni lcd
#define I2C_ADDR    0x27 // indirizzo lcd 16x2 i2c
#define BACKLIGHT_PIN     3
#define En_pin  2
#define Rw_pin  1
#define Rs_pin  0
#define D4_pin  4
#define D5_pin  5
#define D6_pin  6
#define D7_pin  7
LiquidCrystal_I2C  lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);

//carattere clessidra
byte clessidra[8] = {
  B11111,
  B10001,
  B01010,
  B00100,
  B00100,
  B01110,
  B11111,
  B11111
};
//carattere on
byte on[8] = {
  B00000,
  B00000,
  B00001,
  B00010,
  B10100,
  B01000,
  B00000,
  B00000
};
//carattere off
byte off[8] = {
  B00000,
  B10001,
  B01010,
  B00100,
  B01010,
  B10001,
  B00000,
  B00000
};
byte next[8] ={
  B00000,
  B00000,
  B10001,
  B11001,
  B11101,
  B11001,
  B10001,
  B00000 
};
//nome dei pin
#define PIN_LM35 A0
#define PIN_meno 2
#define PIN_piu 3
#define PIN_edit 4
#define PIN_start 5
#define PIN_rele1 7
#define PIN_rele2 8
//stato relè temperatura
int stato_PIN_rele1;
// stato relè miscelatore
int stato_PIN_rele2;
//valore temperatura massima
int maxT;
//impostazione x menu
int stato = 0;

void setup() {
 //impostazione pin
 pinMode(PIN_meno,INPUT_PULLUP);
 pinMode(PIN_piu,INPUT_PULLUP);
 pinMode(PIN_edit,INPUT_PULLUP);
 pinMode(PIN_start,INPUT_PULLUP);
 pinMode(PIN_rele1,OUTPUT);
 pinMode(PIN_rele2,OUTPUT);
 //impostazione lcd
 lcd.begin(16,2);
 lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
 lcd.setBacklight(HIGH);
 //creazione carattere
 lcd.createChar(0,clessidra);
 lcd.createChar(1,on);
 lcd.createChar(2,off);
 lcd.createChar(3,next);
 lcd.home();
}

void loop() {

 switch(stato){
  //menu di inizio
  case 0:
 //impostazione scritte lcd
  lcd.clear();
  lcd.setCursor(3,0);
  lcd.print("Premi Edit");
  lcd.setCursor(2,1);
  lcd.print("per iniziare");
  if (digitalRead(PIN_edit)){
    stato = 1;
    }
   break;
//menu maxT 
  case 1:
  //scritte lcd
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Imp. maxT");
  lcd.setCursor(0,1);
  lcd.write(byte(3));
  lcd.setCursor(1,1);
  lcd.print("next");
  lcd.setCursor(6,1);
  lcd.print("T+ T- T:");
  lcd.setCursor(14,1);
  lcd.print(maxT);
   //valore temperatura massima
  maxT = constrain(maxT,11,100);
   if (digitalRead(PIN_piu)) maxT++;
   if (digitalRead(PIN_meno)) maxT--;
   if (digitalRead(PIN_edit)){
    stato = 2;
    delay(300);
   }
  break;
//menu miscelatore
  case 2:
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Imp. Miscelatore");
  lcd.setCursor(0,1);
  lcd.write(byte(3));
  lcd.setCursor(1,1);
  lcd.print("next");
  lcd.setCursor(7,1);
  lcd.print("M  M");
  lcd.setCursor(8,1);
  lcd.write(byte(1));
  lcd.setCursor(11,1);
  lcd.write(byte(2));
  //lettura tasto
  if (digitalRead(PIN_piu)){
    (digitalWrite(stato_PIN_rele2, HIGH));
   }
  if (digitalRead(PIN_meno)){
    (digitalWrite(stato_PIN_rele2, LOW));
   }
  if (digitalRead(PIN_edit)){
    stato = 3;
    delay(300);
   }
  break;
//menu timer
  case 3:
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Imp. Timer");
  lcd.setCursor(0,1);
  lcd.write(byte(3));
  lcd.setCursor(1,1);
  lcd.print("next");
  lcd.setCursor(6,1);
  lcd.print("T+ T-");
  //lettura tasto
  if (digitalRead(PIN_edit)){
    stato = 4;
    delay(300);
    }
  break;
//start o menu impostazioni
  case 4:
  lcd.clear();
  lcd.setCursor(0,1);
  lcd.write(byte(3));
  lcd.setCursor(1,1);
  lcd.print("Start");
  lcd.setCursor(8,1);
  lcd.print("+Imp");
    if (digitalRead(PIN_edit)){
    stato = 5;
    }
    if (digitalRead(PIN_piu)){
    stato = 1;
    delay(300);
    }
  break;
//schermata finale del programma in funzione
  case 5:
  int valore = analogRead(PIN_LM35);
 //float mV = valore / 1023.0 * 5000;
 //float temperatura = mV / 10;
 float temperatura = valore / 2.046;
 
 //impostazioni pin rele
   if (temperatura >= maxT){
      digitalWrite (PIN_rele1,HIGH);
     (digitalRead(stato_PIN_rele1 == HIGH));
      lcd.setCursor(15,1);
      lcd.write(byte(1));// disegno on
  }else{
      digitalWrite (PIN_rele1,LOW);
      lcd.setCursor(15,1);
      lcd.write(byte(2));  //disegno off
      }
   //impostazioni scritte lcd      
  lcd.setCursor(0,0);
  lcd.print("Temp:");
  lcd.print(temperatura);
  lcd.print(" C  ");

  //scritta temperatura massima impostata x il relè
  lcd.setCursor(0,1);
  lcd.print("maxT:");
  lcd.setCursor(5,1);
  lcd.print(maxT);

  //scritta relè2 miscelatore
  lcd.setCursor(11,1);
  lcd.print("M");

  //scritta relè1 (scalda) se acceso o spento
  lcd.setCursor(14,1);
  lcd.print("R");
  delay(1000);   
  break;
  
  }
}

Zero88Cool:
Ho fatto un ulteriore modifica allo sketch, creando degli stati nei quali puoi fare qualcosa.

Impostazione logica perfetta (diversi stati/situazioni mutuamente esclusivi in cui compiere azioni al verificarsi di eventi/condizioni).

Piccolo problema riscontrato: non cambia il menu oppure va talmente veloce che arriva in fondo.

Gli ingressi sono configurati come PULLUP, quindi a pulsanti non premuti il livello letto con digitalRead vale 1 (HIGH). Le condizioni che hai scritto nel programma risultano sempre vere a pulsanti NON premuti e false a pulsanti premuti.

Perdona la mia ignoranza nel campo quindi dovrei aggiungere questo

In parallelo ai pulsanti, si.