Comandare 2 relè con diversi millis

ciao a tutti, partiamo col dire che non so se ho creato il forum nella sezione corretta, vi spiego il mio problema, non riesco a capire come far funzionare con la funzione millis 2 relè per pilotare due ventole che devono stare rispettivamente accese 90 sec e 7 sec, accese in modo alternato, quindi quando una è accesa l'altra deve risultare spenta, tutto questo dovrei fare un ciclo di 3/4 ripetizioni per poi tenerle spente entrambi per 30 minuti, e poi far ripartire tutto il ciclo da capo. vorrei anche implementare delle funzioni if e else che a determinate temperature o umidità (tramite parametro vpd) facciano partire i due relè in modo indipendente sempre con lo stesso ciclo di prima, quindi 90 sec e 7 sec. stavo cercando di scrivere un po' il codice ma non so proprio come fare. allego lo sketch.

#define PIN_1 14     //Pin ESP32 collegato al Pin IN1 del Relè
#define PIN_2 27     //Pin ESP32 collegato al Pin IN2 del Relè 
#define PIN_3 26     //Pin ESP32 collegato al Pin IN3 del Relè 
#define PIN_4 25     //Pin ESP32 collegato al Pin IN4 del Relè 
#define PIN_5 33     //Pin ESP32 collegato al Pin IN5 del Relè
#define PIN_6 32     //Pin ESP32 collegato al Pin IN6 del Relè
#define DHTPIN 13   //Pin ESP32 collegato al Pin Data del DHT22

#define DHTTYPE    DHT22     // DHT 22 (AM2302)

const unsigned long onTimeR1 = 90000;       // 90sec     -- aspiratore on
const unsigned long offTimeR1 = 7000;      //  7sec  -- aspiratore off

const unsigned long onTimeR2 = 7000;        // 7sec     -- estrattore on
const unsigned long offTimeR2 = 90000;        // 90sec -- estrattore off

//const unsigned long onTimeR3 = 1500000;        // 25m     -- HUMIDIFICATOR
//const unsigned long offTimeR3 = 600000;        // 10m

int tAsp = 90000; //tempo aspiratore

int tAsp = LOW;


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


#define CAYENNE_PRINT Serial
#include <CayenneMQTTESP32.h>

#include <Arduino.h>
#include "Ticker.h"
#include <DHT.h>

#ifndef ESP32
#pragma message(THIS EXAMPLE IS FOR ESP32 ONLY!)
#error Select ESP32 board.
#endif

DHT dht(DHTPIN, DHTTYPE);

void setup() {
	pinMode(PIN_1, OUTPUT);
  pinMode(PIN_2, OUTPUT);
  pinMode(PIN_3, OUTPUT);
  pinMode(PIN_4, OUTPUT);
  pinMode(PIN_5, OUTPUT);
  pinMode(PIN_6, OUTPUT);
  Serial.begin(9600);
  Serial.println(F("DHTxx test!"));

  dht.begin();
	Cayenne.begin(username, password, clientID, ssid, wifiPassword);
  Cayenne.virtualWrite(0, digitalRead(PIN_1), "digital_actuator", "d");
  Cayenne.virtualWrite(1, digitalRead(PIN_2), "digital_actuator", "d");
  Cayenne.virtualWrite(2, digitalRead(PIN_3), "digital_actuator", "d");
  Cayenne.virtualWrite(3, digitalRead(PIN_4), "digital_actuator", "d");
  Cayenne.virtualWrite(4, digitalRead(PIN_5), "digital_actuator", "d");
  Cayenne.virtualWrite(5, digitalRead(PIN_6), "digital_actuator", "d");
} 

float humidity;
  // Read temperature as Celsius (the default)
  float temperature;
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f;
  // Check if any reads failed and exit early (to try again).
  // Compute heat index in Fahrenheit (the default)
  float hif;
  // Compute heat index in Celsius (isFahreheit = false)
  float hic;
  float VPsat;
  float VPactual;
  float VPD;

void loop() {
  delay (4000); 
  if (isnan(humidity) || isnan(temperature) || isnan(f)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }
  humidity = dht.readHumidity();
  // Read temperature as Celsius (the default)
  temperature = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  f = dht.readTemperature(false);
  // Compute heat index in Fahrenheit (the default)
  hif = dht.computeHeatIndex(f, humidity, false);
  // Compute heat index in Celsius (isFahreheit = false)
  hic = dht.computeHeatIndex(temperature, humidity, true);
  Cayenne.loop();
  VPsat = 610.7 * 107.5 * temperature / (237.3 + temperature); // Saturation vapor pressure in Pascals
  VPactual = (humidity * VPsat) / 100000.0;  // Actual vapor pressure in Pascals
  VPD = ((100.0 - humidity) /200000.0) * VPsat;  // Vapor Pressure Deficit in Pascals
  Serial.print(F("Humidity: "));
  Serial.print(humidity);
  Serial.print(F("%  Temperature: "));
  Serial.print(temperature);
  Serial.print(F("°C "));
  Serial.print(f);
  Serial.print(F("°F  Heat index: "));
  Serial.print(hic);
  Serial.print(F("°C "));
  Serial.print(hif);
  Serial.println(F("°F"));
  Serial.print(F("VPD: "));
  Serial.print(VPD);
  dt1 = millis() - t1;
    if (dt1 > tAsp)
  
  if  (VPD <= 0.60) digitalWrite (PIN_1, HIGH);
    else
      digitalWrite (PIN_1, LOW);

  if (temperature <= 30) digitalWrite (PIN_1, LOW);
      else 
      digitalWrite (PIN_1, HIGH);
    
}#

Questo è tutto lo sketch, contiene anche delle righe di codice per cayenne mqtt, avevo provato a scrivere un minimo di codice ma non riesco proprio a capire la funzione millis come usarla, ho capito che è un orologio interno, ma oltre a quello niente, avevo messo delle variabili IF per il valore vpd quando supera una certa soglia, che poi vorrebbe attivasse i relè nel modo sopra elencato, 7 secondi uno e 90 l'altro, in modo alternato per 3/4 volte. Grazie

Non, post déplacé.

Emm ... NO ... anzi un bel po' di errori ... :grin:, comunque, buongiorno e benvenuto nella sezione Italiana del forum,

:warning: prima di tutto ti segnalo che, nella sezione in lingua Inglese, si può scrivere SOLO in Inglese ... quindi, per favore, la prossima volta presta più attenzione in quale sezione metti i tuoi post; questa volta esso è stato spostato, da un moderatore della sezione di lingua Inglese, nella sezione di lingua Italiana ... la prossima volta potrebbe venire direttamente eliminato, dopo di che ...

... cortesemente, come prima cosa, leggi attentamente il REGOLAMENTO di detta sezione, (... e, per evitare future possibili discussioni/incomprensioni, prestando molta attenzione al punto 15), dopo di che, come da suddetto regolamento, fai la tua presentazione NELL'APPOSITA DISCUSSIONE spiegando bene quali esperienze hai in elettronica e programmazione, affinché noi possiamo conoscere la tua esperienza ed esprimerci con termini adeguati, infine ...

... come richiesto al punto 7 del succitato regolamento, per favore edita il tuo post qui sopra (quindi NON scrivendo un nuovo post, ma utilizzando il bottone a forma di piccola matita :pencil2: che si trova in basso del tuo post), seleziona la parte di codice e premi l'icona <code/> nella barra degli strumenti per contrassegnarla come codice. Inoltre, così com'è, non è molto leggibile ... assicurati di averlo correttamente indentato nell'IDE prima di inserirlo (questo lo si fa premendo ctrlT su un PC o cmd T su un Mac, sempre all'interno del IDE).

Grazie,

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell’apposita discussione e sistemato il codice come indicato, nel rispetto del regolamento nessuno ti risponderà (eventuali risposte o tuoi ulteriori post, verrebbero temporaneamente nascosti), quindi ti consiglio di farla al più presto. :wink:

Ciao,
secondo me ti conviene creare due funzioni (richiamate continuamente dal loop) che gestiscono ciascuna il suo relé.
Verrà tutto più semplice e pulito che gestire entrambe dal loop.

Prima di tutto, devi togliere quell'orrendo delay (4000); all'inizio del loop(), perché fa fare solo un singolo loop() ogni 4 secondi!

Poi, la classica sintassi per usare millis() è

uint32_t t_fai_questo;
uint32_t t_fai_questaltro;
uint16_t periodo_fai_questo=5000; // Ogni 5 secondi.
uint16_t periodo_fai_questaltro=10000; // Ogni 10 secondi.

loop:
if(millis()-t_fai_questo     > periodo_fai_questo)     {t_fai_questo=millis();     fai_questo();}
if(millis()-t_fai_questaltro > periodo_fai_questaltro) {t_fai_questaltro=millis(); fai_questaltro();}

Quel delay(4000) è per la lettura del sensore dht, stamattina ho provato un po' e sono riuscito a pilotarne uno, devo solo capire come far fare sempre l'opposto all'altro relè, e poi farli spegnere entrambi dopo X tempo, immagino con un'altra funzione millis, però come potrei fare?

?? se il pin del primo rele lo metti a HIGH, l'altro lo metti a LOW e viceversa. Non mi pare complicato. (a meno che non ho capito cosa devi fare)

al post #5 @datman ti ha messo 2 temporizzazioni diverse. Con la prima fai quello che già sei riuscito, con la seconda metti a LOW tutti e due i rele.

Ok grazie, ma dovrei avere in teoria 2 temporizzazioni per relè, più quella per spegnere entrambi, che dovrebbe essere messa dentro una parentesi graffa contenente anche le altre temporizzazioni (divise da altre parentesi graffe) giusto? {{2 temporizzazioni x relè e formula x invertire lo stato del secondo relè} temporizzazione generale per spegnere entrambi} giusto?

Molto semplice imposti il pin (quindi fai una digitaWrite()) invertendo il valore che ti ritorna (digitalRead()) lo stato del pin di cui devi fare l'opposto ... NON ti scrivo il codice ma in pratica:

imposta_stato_del_pin ( ! leggi_stato_altro_pin)

... nota l'operatore di negazione '!' applicato alla lettura dell'altro pin. :wink:

Guglielmo

Se non è chiaro (parrebbe così) il delay(4000) rende impossibile l'uso di millis() per temporizzare le azioni. Se potessimo parlare alla cpu gli stiamo dicendo: cpu esegui per 4 secondi sempre questa istruzione delay.

if(millis()-t_fai_questo     > periodo_fai_questo)     {t_fai_questo=millis();     fai_questo();}
if(millis()-t_fai_questaltro > periodo_fai_questaltro) {t_fai_questaltro=millis(); fai_que

Vi odio quando scrivete il codice così, sappiatelo. Primo devo scorrere con la barra o con lo shift e la rotella del mouse, per copiarlo viene più difficile da selezionare. Secondo non si capisce nulla e non è un buon esempio di indentazione.

if ( millis() - t_fai_questo > periodo_fai_questo ) {     
    t_fai_questo = millis();
    fai_questo();
}

if ( millis() - t_fai_questaltro > periodo_fai_questaltro) {  
    t_fai_questaltro = millis();
    fai_questaltro();
}

PS: mica va più veloce lo sketch scritto in quel modo e occupa lo stesso spazio in flash.

Ciao.

1 Like

Grazie, avevo pensato che si sarebbe dovuto usare il !, Ma immaginavo con un'altra funzione. Ora provo

Come potrei fare per far leggere il sensore dht ogni x secondi? Sempre con un'altra millis togliendo il delay giusto?

Giusto ... la sequenza che ti ha indicato Maurotec mostra DUE temporizzazioni fatte con millis(), ma tu puoi espandere la cosa al numero di temporizzazioni che vuoi ... dovrai solo avere più variabili di tipo 'unsigned long' (che lui ha chiamato t_fai_xxxxx) per memorizzate l'ultima volta che hai fatto una cosa e più costanti, sempre di tipo 'unsigned long' (che lui ha chiamato periodo_fai_xxxxx) per avere il periodo di esecuzione di ogni singola cosa :slight_smile:

Guglielmo

L'unica cosa è che non ho capito come fare la seconda temporizzazione per spegnere tutto dopo aver fatto 4 cicli con la precedente temporizzazione, per come l'ho scritto io il codice adesso le due temporizzazione vanno in conflitto, dovrei far andare on5sec-off90-on5-off90-on5 e poi off5minuti e on15minuti ad esempio, come faccio a farle coesistere e non interferirsi una con l'altra?

Scusa ma secondo me visto quello che devi fare non è uno o più millis() che ti portano alla soluzione, ma creare un sistema "macchina a stati finiti".
Il tuo sistema può essere solo in uno stato ben determinato in ogni istante. Il passaggio da uno stato all'altro può essere il tempo (dato ma una millis) oppure un cambio nella umidità/temperatura.
Avrai uno stato 1 = periodo di 90 sec accesa una spenta altra;
stato 2 = periodo 7 sec spenta una accesa altra;
qui un contatore che mette stato = 1 per 4 volte, altrimenti lo stato = 3
stato 3 = spente per 30 minuti
questo con un bel switch(stato)
dopo lo switch controlli temperatura/umidità e se necessario rimetti stato a 1 e contatore a 1
link 1
link 2
link 3 (eng)

Qualcosa del genere (preso spunto dal codice del link 3 di majenko)

const byte pinRele1=11;
const byte pinRele2=12;
unsigned long K_TEMPO_CICLO1 =   90000UL; // 90 sec
unsigned long K_TEMPO_CICLO2 =    7000UL; // 7 sec
unsigned long K_TEMPO_PAUSA  = 1800000UL; // 1800 sec 30 min

byte stato = 1; 
byte count = 1;
const byte maxcount = 4;
unsigned long ts; 

void setup()
{ Serial.begin(9600);
  Serial.println("setup");
  pinMode(pinRele1,OUTPUT);
  pinMode(pinRele2,OUTPUT);
}

void loop()
{ Serial.print("count "); Serial.print(count); 
  Serial.print(" - stato "); Serial.println(stato);
  switch(stato)
  { case 1:
      digitalWrite(pinRele1,HIGH);  
      digitalWrite(pinRele2,LOW);  
      ts = millis();    
      stato = 2;        
      break;
    case 2: 
      if(millis() - ts > K_TEMPO_CICLO1) stato = 3;
      break;
    case 3:
      digitalWrite(pinRele1,LOW);  
      digitalWrite(pinRele2,HIGH);  
      ts = millis(); 
      stato = 4;
      break;
    case 4:
      if(millis() - ts > K_TEMPO_CICLO2) stato = 5;
      break;
    case 5:
      count++;
      if(count>maxcount) stato=6; else stato=1;
      break;
    case 6:
      count = 1;
      digitalWrite(pinRele1,LOW);  
      digitalWrite(pinRele2,LOW);  
      stato = 7;  
      ts = millis();    
      break;
    case 7: 
      if(millis() - ts > K_TEMPO_PAUSA) stato = 1;
      break;
  }
  // lettura temperatura ed umidità
  // se necessario cambia lo stato in count=1 e stato=1
}

l'ho provato, funziona per adesso, quindi grazie mille, ora che ho uno spunto e so più o meno come comportarmi con una macchina a stati finiti penso di riuscirci a completare il codice, aggiungendo gli altri stati comprendenti la misurazione di temperatura e umidità. in caso non dovessi riuscire a fare qualcosa tornerò nel forum, magari aggiungerò anche il codice finale una volta completato. grazie mille ancora.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.