comandare un relè con pulsante e lm35

ciao a tutti, da un po che mi documento su come creare sketch con arduino… Ho una stampante 3d, ho costruito una cassa dove tramite arduino, comando 2 ventole 12v, una che aspiri l’aria (necessaria per stampare in ABS) usando l’lm35 come interruttore e un pulsante (per praticità d’uso), l’altra con un micro presente nella cassa (e pulsante) per far entrare aria. Un passo per volta, prendo lm35, il rele, carico lo sketch tutto ok; implemento il pulsante per attivare la ventola di aspirazione e ottengo (come scritto su sketch): il rele che riceve una lieve alimentazione quando l’lm35 arriva a temperatura e il pulsante attiva il rele. In realta vorrei che la ventola sia indipendente e il pulsante intervenga solo in stato LOW della stessa, ma non ho capito dove sbaglio…

#define RELE 7                // rele collegato al pin digitale 7
#define BUTTON 8              // pin input dove è collegato il pulsante
int  val = 0;                 // si userà val per conservare lo stato del pin di input
int reading = 0;
int sensorPin = A0;
int reley = RELE;


void setup() {
  pinMode(RELE, OUTPUT);       // imposta il pin 7 digitale come output
  pinMode(BUTTON, INPUT);     // imposta il pin 8 digitale come input
}

void loop()  {
  reading = analogRead(sensorPin);
  int celsius = reading / 2;
  if (celsius > 20) {
    digitalWrite(7, HIGH);
  } else {
    digitalWrite(7, LOW);
    delay(500);
  }
  
  val = digitalRead(BUTTON);  // legge il valore dell'input e lo conserva

  // controlla che l'input sia HIGH (pulsante premuto)
  if (val == HIGH) {
    digitalWrite(RELE, HIGH);  //accende il rele
  }
  else {
    digitalWrite(RELE, LOW);   //spegne il rele

  }
}

Ciao,
Il tuo problema è di semplice soluzione pero' permettimi di darti alcuni consigli:
hai una generale confusione nello scrivere il programma: usi delle define per inizializzare variabili che non usi, inizializzi variabili che usi una sola volta, metti dei ritardi solo in un ramo ELSE e non nel suo IF, la conversione della temperatura è farraginosa, nulla di grave in se, ma nel complessivo fa "ombra" al cuore del programma
insomma, ripeto, in generale hai una certa confusione, magari ti farebbe bene prendere un bel respiro e ri-partire da capo sfrondando tutto quello che non serve, magari vedresti piu' facilmente il problema
comunque, dopo il pistolotto iniziale, ti spiego il tuo problema specifico:
tu metti la gestione del pulsante incondizionata, qualunque sia lo stato della temperatura, e quindi sia a temperatura bassa che a temperatura alta il pulsante accende e/o spegne la ventola
devi far eseguire la gestione del pulsante solo se la ventola sarebbe spenta, solo in quel caso il pulsante accenderebbe effettivamente e/o confermerebbe lo spegnimento della ventola

lupin89:
vorrei che la ventola sia indipendente e il pulsante intervenga solo in stato LOW della stessa

Come detto da olio, il problema principale è che l’if che controlla il pulsante viene eseguito sempre, anche quando la ventola dovrebbe restare accesa, per cui di fatto ad ogni ciclo di loop l’uscita viene subito rispenta anche quando il primo if che controlla la temperatura la accende (ecco da dove arriva la leggera tensione).

Il secondo problema non si è ancora presentato, ma immagino che il pulsante non debba essere tenuto costantemente premuto, ma che debba bastare un click per avviare e un altro click per spegnere, e quindi non va considerato il valore attuale del pulsante ma solo le sue variazioni rispetto alla lettura precedente.

Il terzo, derivante dal secondo è stabilire qualche priorità nella logica (se ne possono pensare diverse).

La soluzione, al solito, è scrivere prima una logica funzionante su carta, e solo poi tradurla in istruzioni C.

Ad esempio la seguente è una possibile implementazione. La temperatura ha sempre la priorità, finché la temperatura resta >20° la ventola è accesa e non si può intervenire con il pulsante. Sono da usare alcune variabili “di appoggio” per ricordare lo stato tra un ciclo e l’altro del loop: in particolare dobbiamo sapere se siamo in modo automatico o manuale, e dobbiamo sapere se la lettura precedente del pulsante è diversa da quella attuale, in modo da capire se c’è una variazione. Le scritte rosse sono ovviamente delle if. Si da per scontato che al pulsante sia collegato anche un adeguato condensatore per il debounce e una adeguata resistenza di pull. siccome le variazioni del pulsante, e in particolare gli istanti di pressione, servono in più punti, è molto più comodo effettuare una lettura pulsante preventiva che imposta a true la variabile ‘onPress’ quando il pulsante viene premuto, e poi usare questa variabile nel resto dell’elaborazione.

lupinflow.png

Cosa usi per creare questi diagrammini?

Il solito FidoCadJ. Dico "solito" perché tante altre cose qui sul forum sono fatte con quello, come i disegni dei relé di Brunello. Poi come post-processing con Gimp ritaglio e riduco i colori a 8..16 per avere file .png leggeri da allegare.

grazie per i tuoi consigli, Standardoil, sopratutto

Standardoil:
ri-partire da capo

è quello che ho fatto, specifico meglio che conosco molto poco di arduino, ma l'impegno non manca..

Claudio_FF:
Come detto da olio, il problema principale è che l'if che controlla il pulsante viene eseguito sempre, anche quando la ventola dovrebbe restare accesa .......

ti ringrazio tantissimo perchè è quello che sto cercando di fare.. non capisco come imposto su automatico e manuale. I rele sono quelli a 5v che mettono nello starter kit, ho seguito alcuni video che mostravano come collegare l'lm35 al rele; fatti i collegamenti tutto ok, da li ho pensato di inserire il pulsante.. Le risposte che ho ricevuto sono molto chiare (per chi mastica piu di me), ma mi chiedo, esistono dei video o esempi che riportano una condizione di automatico e manuale? Vorrei comprendere meglio queste funzioni", non sto riuscendo a creare un codice seguendo il diagramma (veramente fantastico).

caso curioso, ora riesco ad accendere il rele con il pulsante ma si è presentato il secondo problema

Claudio_FF:
Il secondo problema non si è ancora presentato, ma immagino che il pulsante non debba essere tenuto costantemente premuto .......

questo è quello che son riuscito a fare oggi :confused:

int reading = 0;
int sensorPin = A0;
int reley = 12;
int stato = LOW;

void setup() {
  pinMode(12, OUTPUT);       // imposta il pin digitale come output
  pinMode(7, INPUT);     // imposta il pin digitale come input
}

void loop()  {
  reading = analogRead(sensorPin);
  int celsius = reading / 2;
  if (celsius > 10) {
    digitalWrite(7, HIGH);
    delay(200);
  } else {
    digitalWrite(7, LOW);
    delay(200);
  }

  int val = digitalRead(7);  // legge il valore dell'input e lo conserva
  if (val =| stato and val == HIGH) {
    digitalWrite(12, HIGH);  //accende il rele
  }
  else {
    digitalWrite(12, LOW);   //spegne il rele
  }
}

risultato: il pulsante alla pressione eccita il rele, al rilascio lo spegne e ignora completamente l'lm35..

>lupin89: Cortesemente, quando “quoti” qualcuno metti poche righe per far capire a cosa ti riferisci e NON tutto il post, cosa del tutto inutile e che … complica solo la vita a chi legge da device mobili. Grazie :slight_smile:

Guglielmo

P.S.: Per questa volta ho “tagliato” io i tuoi “quote” :wink:

Vabbe', grazie per aver seguito un mio suggerimento, ma hai seguito quello meno "pertinente", hai ri-fatto da capo il programma ri-petendo gli errori (per onestà ammetto che non hai ri-petuto tutti gli errori)
hai ancora una variabile inutilizzata
hai ancora la gestione del pulsante indipendente dalla temperatura
la conversione della temperatura è ancora farraginosa
inoltre hai aggiunto una variabile stato che non aggiorni mai e che usi per fare un test che dire strano è poco
insomma mi sembra che tu ci abbia messo poco pensiero, prima di metterti a scrivere codice
ecco... adesso fermati a pensare a quello che ti ho detto, ogni singolo concetto, capiscilo e mettilo in opera
da ultimo,un piccolo scherzo, concedimelo
non ho un video che riporta una condizione di automatico o manuale, ma sono sicuro che tu ne hai a casa almeno un esempio: tutti abbiamo a casa ormai o un termostato o delle valvole termostatiche, ecco il tuo automatico, se invece vuoi un esempio di manuale: alzati dal divano e spegni la luce, ecco fatto l'esempio

lupin89:
non capisco come imposto su automatico e manuale.

Una variabile, magari di tipo bool, chiamata ‘automatico’, impostata inizialmente a true. Quando passi a manuale la imposti a false, quando ripassi ad automatico la riimposti a true. In questo modo per sapere se sei in automatico basta scrivere

if (automatico) ....

questo è quello che son riuscito a fare oggi :confused:

Una prima cosa: hai definito dei nomi di comodo per alcuni pin (sensorPin, reley) ma non per il pulsante. Poi, a parte sensorPin, non li hai mai usati nel programma. Invece hai scritto ogni volta direttamente i numeri dei pin finendo con il confonderti e scrivere sul pin del pulsante invece che su quello del relé. I nomi di comodo servono appunto per non cospargere il codice di numerini facili da sbagliare.

Quindi per prima cosa creiamo dei bei nomi per i pin, maiuscoli per distinguerli dalle variabili, e usiamo sempre questi nel resto del programma:

#define BUTTON  7
#define RELEY   12
#define SENSOR  A0

Poi la condizione:

if (val =| stato and val == HIGH)

non compila neppure, quindi non può essere questo l’ultimo codice provato…

Il diagramma di quello che hai postato è il seguente:

lupinflow2.png

non sto capendo se peggioro o miglioro… comunque ora il rele rimane eccitato con l’lm35, mentre per il pulsante non ci sono ancora arrivato (il rele non rimane eccitato anche se mantengo la pressione sul pulsante)… continuerò a tentare :slight_smile:

#define BUTTON1  7 //puls rosso
#define RELEY 12  //rele vent 1
#define Tpin  A0 // analog pin
float celsius = 0, farhenheit = 0; // temperature variables
float millivolts; //dichiarazione di variabile tensione (float è per i numeri con la virgola)
int sensor;
const int B_LED = 2;
const int V_LED = 3;

int statoPin = LOW;

void setup()
{
  Serial.begin(9600); // inizializza la comunicazione seriale
  // LED
  pinMode(B_LED, OUTPUT);  //stato automatico
  pinMode(V_LED, OUTPUT);  //stato manuale
  pinMode(BUTTON1, INPUT);     // imposta il pin digitale come input pulsante
  pinMode(RELEY, OUTPUT); // imposta il pin digitale come output
}

void loop() {
  sensor = analogRead(Tpin); //lettura valore del sensore LM35 messo sull'ingresso analogico A0
  millivolts = ( sensor / 1023.0) * 5000; //formula per ottenere la tensione di uscita dell'LM35 in millivolts
  celsius = millivolts / 10; // valore espresso in gradi Celsius (l'out del sensore è 10mv per grado)
  farhenheit = celsius * 1.8 + 32; // valore espresso in gradi Farhenheit
  Serial.println(sensor); //stampa su serial monitor del valore restituito dal conv. A/D a 10 bit di Arduino(da 0 a 1024)
  Serial.print(millivolts); //stampa su serial monitor del valore di tensione in millivolts
  Serial.println(" millivolts");
  Serial.print(celsius); Serial.println(" C"); // stampa su serial monitor del valore di temperatura in gradi Celsius
  Serial.print(farhenheit); Serial.println(" F"); //stampa su serial monitor del valore di temperatura in gradi Farhenheit
  // accendi il led
  if (analogRead(Tpin) < 45) {    // 41 corrisponde a 20°C
    analogWrite(V_LED, 255);     
    analogWrite(B_LED, 0);
    digitalWrite(RELEY,LOW);
    delay(50);
  }
  else {
    analogWrite(V_LED, 0);
    analogWrite(B_LED, 255);      
    digitalWrite(RELEY ,HIGH); 
    delay(50);
  }
  {
int pin=digitalRead (BUTTON1);
  if (statoPin == LOW and pin == HIGH) {
         
       digitalWrite(RELEY, HIGH);
       
       delay(1000); 
     }
  }
  }

lupin89:
continuerò a tentare :slight_smile:

Sui led scrivi con analogWrite, che funziona solo sui piedini previsti per il PWM (cioè 3, 5, 6, 9, 10, 11 su un Arduino Uno), quindi non va bene usare analogWrite sul pin 2 (ma sui LED volevi fare una scrittura analogica per regolarne la luminosità?).

Per il resto, più che tentare ripeto che prima bisogna fare un disegno che funziona su carta seguendo le frecce col dito, e poi lo si può tradurre in codice.

diciamo che, dove mi sono "ispirato" riportava analogWrite e non capivo perché (quindi ho lasciato, ora correggo anche se..). Non ho ancora le capacita di tradurre un diagramma in istruzioni, non riesco a impartirle (x ora). Alla luce di ciò, prendo il tuo primo diagramma e vedo se trovo il modo.. :slight_smile:

posso consigliare (è l'ultima volta) una cosa?
molla la questione automatico manuale, molla i led colorati e le altre belle cavolate che vai in giro a raccattare col copia-incolla alla disperata
torna al tuo primo programma e fai l'unica modifica che serve: bada al pulsante se e solo se lo LM35 NON accende la ventola
visto che tu hai un IF che accende e un ELSE che spegne, in che ramo devi lavorare?
va' che se non ne esci così ti metto nel girone degli ingannieri........

in ELSE, o dove lo stato del rele è LOW. credo

non credere, FAI, e fai da te pensando a quello che fai: smetti di copiare in maniera incontrollata

Questa è una logica molto più semplice. Prevede che inizialmente vi sia una variabile ‘stato’ inizializzata a zero, e una variabile ‘manuale’ inizializzata a false. Ad ogni pressione la variabile ‘manuale’ cambia di livello. Il relé è acceso se temperatura elevata oppure se manuale == true.

lupinflow3.png

lo sketch l’ho fatto prima del post, grazie >Claudio_FF

#define BUTTON  7
#define RELEY   12
#define temPin  A0
int stato = 0;

float celsius = 0, farhenheit = 0; // temperature variables
float millivolts; //dichiarazione di variabile tensione (float è per i numeri con la virgola)
int sensor;

const int B_LED = 2;
const int V_LED = 3;

void setup() {
  pinMode(B_LED, OUTPUT);   //stato automatico
  pinMode(V_LED, OUTPUT);   //stato manuale
  pinMode(BUTTON, INPUT);   // imposta il pin digitale come input pulsante
  pinMode(RELEY, OUTPUT);   // imposta il pin digitale come output
  Serial.begin (9600);
}

void loop() {
  sensor = analogRead(temPin); //lettura valore del sensore LM35 messo sull'ingresso analogico A0
  millivolts = ( sensor / 1023.0) * 5000; //formula per ottenere la tensione di uscita dell'LM35 in millivolts
  celsius = millivolts / 10; // valore espresso in gradi Celsius (l'out del sensore è 10mv per grado)
  farhenheit = celsius * 1.8 + 32; // valore espresso in gradi Farhenheit
  Serial.println(sensor); //stampa su serial monitor del valore restituito dal conv. A/D a 10 bit di Arduino(da 0 a 1024)
  Serial.print(millivolts); //stampa su serial monitor del valore di tensione in millivolts
  Serial.println(" millivolts");
  Serial.print(celsius); Serial.println(" C"); // stampa su serial monitor del valore di temperatura in gradi Celsius
  Serial.print(farhenheit); Serial.println(" F"); //stampa su serial monitor del valore di temperatura in gradi Farhenheit

  // vnetola temperatura

  if (digitalRead(BUTTON) == HIGH) {
    stato = !stato;
    delay(200);
   }
  if (analogRead(farhenheit) > 90 and stato == LOW) {    // 41 corrisponde a 20°C
    digitalWrite(V_LED, LOW);
    digitalWrite(B_LED, HIGH);
    digitalWrite(RELEY, HIGH);
    
  }delay(500);
  if (analogRead(farhenheit) < 40){
    digitalWrite(B_LED, LOW);
     }
     if (stato == HIGH and (temPin) < 46) {
    digitalWrite(RELEY, stato);
    digitalWrite(V_LED, stato);
    digitalWrite(B_LED, 0);
   } else {
    digitalWrite(RELEY, stato);
    digitalWrite(V_LED, stato);
    digitalWrite(B_LED, 0);
   }
}

ok io sono arrivato sin qui, ad problemi sul valore della temperatura, se imposto 50° e la temperatura percepita dal sensore è nella fascia impostata il rele accende e spegne. grazie per l’aiuto

non capisco: se inserisco /.../ tra //temp e la penultima graffa il pulsante funziona, le tolgo per far leggere al loop il resto il pulsante non lo legge :o :o

#define BUTTON 7
#define RELEY 12
#define TEMPIN A0

float celsius = 0, farhenheit = 0; // temperature variables
float millivolts; //dichiarazione di variabile tensione (float è per i numeri con la virgola)
int sensor;
int man = 0; //stato pulsante
int pul = 0; //valore lettura pulsante
int aut = 0; //stato temp
int val = 0; //valore lettura temp
void setup() {
  pinMode(RELEY, OUTPUT);
  pinMode(BUTTON, INPUT);
  Serial.begin(9600);
}

void loop() {


  sensor = analogRead(TEMPIN); //lettura valore del sensore LM35 messo sull'ingresso analogico A0
  millivolts = ( sensor / 1023.0) * 5000; //formula per ottenere la tensione di uscita dell'LM35 in millivolts
  celsius = millivolts / 10; // valore espresso in gradi Celsius (l'out del sensore è 10mv per grado)
  farhenheit = celsius * 1.8 + 32; // valore espresso in gradi Farhenheit
  Serial.println(sensor); //stampa su serial monitor del valore restituito dal conv. A/D a 10 bit di Arduino(da 0 a 1024)
  Serial.print(millivolts); //stampa su serial monitor del valore di tensione in millivolts
  Serial.println(" millivolts");
  Serial.print(celsius); Serial.println(" C"); // stampa su serial monitor del valore di temperatura in gradi Celsius
  Serial.print(farhenheit); Serial.println(" F");
  delay(500);

  if (digitalRead(BUTTON)) {
    pul = !pul;  // cambia stato pulsante
    delay(200);
  }
  if (pul == HIGH and man == 0) {
    digitalWrite (RELEY, HIGH);
  } else {
    digitalWrite (RELEY, LOW);
  }

  val = analogRead(TEMPIN);  //leggi temp
  if (val > 45) {
    (aut = !aut); // cambia stato lett temp
    if (aut == HIGH);
    digitalWrite (RELEY, HIGH);
  } else {
    digitalWrite(RELEY, LOW);
  }
}

ditemi qualcosa :cry:
grazie a tutti per la pazienza

Non è che non lo legge. Continui a comandare lo stesso relé da due if diverse che fanno cose diverse, e la seconda annulla i comandi della prima.

Il relé va comandato in un solo punto, come da schema post #15.

Metto qua il codice (che segue lo schema #15) solo da completare...

//--------definizioni nomi di comodo

#define  BUTTON  7
#define  RELEY   12
#define  TEMPIN  A0

//--------variabili di lavoro permanenti

uint8_t stato = 0;
bool    manuale = false;

//--------

void setup() 
{
    pinMode(BUTTON, INPUT);
    pinMode(RELEY, OUTPUT);
    Serial.begin (9600);
}

//--------

void loop() 
{
    // lettura pulsante, alla pressione (HIGH) viene
    // variato lo stato della variabile manuale

    uint8_t lettura = digitalRead(BUTTON);

    if ((0 == stato) && (HIGH == lettura))      // se pressione
    {
        stato = 1;
        manuale = !manuale;
    }
    else if ((1 == stato) && (LOW == lettura))  // se rilascio
    {
        stato = 0;
    }

    // lettura temperatura e conversioni. NOTA: per aumentare
    // la precisione al valore 5000 va sostituito il valore
    // della Vcc letta con un preciso tester digitale quando il
    // circuito e` alimentato con l'alimentatore definitivo.

    uint16_t sensor = analogRead(TEMPIN);
    float millivolts = (float)sensor / 1023. * 5000.;
    float celsius = millivolts / 10.;
    float farhenheit = (celsius * 1.8) + 32.;

    Serial.println(sensor);
    Serial.print(millivolts);
    Serial.println(" millivolts");
    Serial.print(celsius); 
    Serial.println(" C");
    Serial.print(farhenheit); 
    Serial.println(" F");


    /* completare qui con la gestione relé */


    delay(200);  // Rallenta il loop a circa 5 cicli al secondo
                 // e agisce da debounce per il pulsante
}

lupin89:
ditemi qualcosa :cry:
grazie a tutti per la pazienza

io qualcosa te lo ho detto, due volte
Non ci sarà una terza, adesso la palla è a te