Arduino, uscita digitale con duty cycle variabile moooolto lento.

Ciao a tutti,

voglia di sperimentare delle migliorie, i questo caso la regolazione della temperatura. Sto cercando di fare un duty cycle variabile con un'uscita digitale, in pratica ho un valore fisso che deve impostare l'uscita a ON per il tempo di questo valore e a OFF per lo stesso tempo ma per il valore diviso 2. Praticamente vorrei poter tenere a ON l'uscita digitale per "X" secondi

programma. Sto usando il millis() ma non ne esco, se l'ON va bene, l'OFF non riesco a regolarlo.

Ringrazio per l'aiuto :-)

--
Saluti da Drizzt, quello vero! 


www.agidone.altervista.org 
MAI PIU' UN CESSO DI OPEL IN VITA MIA!!!! 
http://www.tappezzeriagraziella.com/
Reply to
Drizzt do'Urden
Loading thread data ...

class myPwm { unsigned long tOn,tOff,lastChange; unsigned pin; public: myPwm ( unsigned p ) { pin = p; }; void SetTOn ( unsigned long t ) { tOn = t; }; void SetTOff ( unsigned long t ) { tOff = t; }; void Setup ( void ) { lastChange = millis(); }; void Loop ( void ); }; void myPwm::Loop ( void ) { bool pinState = digitalRead( pin ); unsigned long nextChange = lastChange+( pinState ? tOn : tOff ); if( millis()>=nextChange ) { lastChange = nextChange; digitalWrite( pin,!pinState ); } }

myPwm led(13);

void setup() { // put your setup code here, to run once: led.Setup(); led.SetTOn( 1000 ); led.SetTOff( 3000 ); }

void loop() { // put your main code here, to run repeatedly: led.Loop(); }

Reply to
alfio

Il 11/01/2022 16:09, alfio ha scritto:

Ti ringrazio tantissimo per la fiducia :-D ma sto leggendo da 10 minuti ma non ci capisco una mazza, ho provato pure io ad usare myPwm ma non mi faceva funzionare il resto del

come si deve. Ho anche provato ad usare la libreria PID in ON/OFF ma anche con quella

--
Saluti da Drizzt, quello vero! 


www.agidone.altervista.org 
MAI PIU' UN CESSO DI OPEL IN VITA MIA!!!! 
http://www.tappezzeriagraziella.com/
Reply to
Drizzt do'Urden

"Drizzt do'Urden" ha scritto nel messaggio news:srk7ci$gfn$ snipped-for-privacy@gioia.aioe.org...

Il 11/01/2022 16:09, alfio ha scritto:

la prime 21 linee, da "class" fino alla fine della funzione myPwm::Loop(), le copi tali e quali nel tuo programma, e' la definizione di un nuovo tipo di dato.

la riga myPwm led(13); serve per dichiarare una nuova variabile di tipo myPwm, e inizializzarla. per questo esempio ho usato il led integrato, tu la userai per l'uscita che ti serve per esempio: myPwm vapore( 10 ); myPwm pompa( 22 );

il tipo myPwm ha 4 funzioni pubbliche Setup(): non ha parametri, lo devi mettere nel setup di Arduino, serve a

inizializzare i dati interni Loop(): non ha parametri, lo devi mettere nel loop di Arduino, serve per

eseguire l'accensione e spegnimento. SetTOn: imposta il tempo di ON in millisecondi, puoi chiamarlo dove ti pare nel tuo programma. SetTOff: imposta il tempo di OFF in millisecondi, puoi chiamarlo dove ti

pare nel tuo programma.

del

impostarlo come

metti online da qualche parte il codice del tuo programma e vediamo che si puo' fare. mettilo in forma integrale, non tagliare nulla.

Reply to
alfio

"compattamente"!

-- Ho fatto sesso con Control. Domani provo Alt+Del.

Reply to
Archaeopteryx

Il 11/01/2022 16:57, alfio ha scritto:

mio codice, o almeno io non ci riesco.

  /*    * FUNZIOZNAMENTO CONTROLLO MACCHINA CAFFE'

nella lettura del sensore LMT85 * Si usa un display Nextion touch

per quando si spegne la macchinetta * La pompa dell'acqua si attiva col proprio pulsante a doppia azione e con la manopola dell'acqua

  • I dati al display vengono mandati solo ai moduli della pagina selezionata

il timer millis() per non sovracaricare la seriale

  • */

#include

String caffeoff = "9997102102101111102102"; //stringa pulsante caffe che arriva dal Nextion che manda "caffeoff" String caffeon = "9997102102101111110"; //stringa pulsante caffe che arriva dal Nextion che manda "caffeon" String vapoff = "11897112111102102"; //stringa pulsante vapore che arriva dal Nextion che manda "vapoff" String vapon = "11897112111110"; //stringa pulsante vapore che arriva dal Nextion che manda "vapon" String setmeno = "115101116109101110111"; //stringa pulsante +Set Temp che arriva dal Nextion String setpiu = "115101116112105117";//stringa pulsante -Set Temp che arriva dal Nextion String page0 = "1129710310148"; //stringa numero pagina String page1 = "1129710310149";

int page0on = 1; //setta la pagina iniziale a 1, quando si da tensione il Nextion visualizza sempre la pagina 0 int page1on = 0; //variabile di cambio pagina

int statocaffe = 0; //memorizza lo stato del tasto caffe per usarlo nelle comparazioni int statovapore = 0; //memorizza lo stato del tasto vapore per usarlo nelle comparazioni

String a = ""; //variabile dove si memorizza la lettura della seriale dal Nextion String com; //variabile dove viene memorizzata la stringa completa che arriva dal Nextion

int intemperatura = A14; // ingresso sensore temperatura LMT85 int temperatura = 0; //variabile temperatura dopo mappatura int settemp = 0; //temperatura di set int settempvap = 120; //variabile del set fisso della temperatura vapore int settempcaffe = EEPROM.read(0); //variabile modificabile della

int inSwitch = 33; //pin ingresso switch valvola acqua

unsigned long t1, dt; //variabili timer per mandare valori al display unsigned long dim1, dim2; //variabili timer per backlight display

void setup() { Serial.begin(9600); Serial2.begin(9600); //seriale Nextion

pinMode(inSwitch, INPUT); //ingresso switch acqua calda analogReference( INTERNAL2V56 ); //usa il reference di 2.56V per avere

}

void loop() {

// MAPPATURA TEMPERATURA *******************************

temperatura = map(analogRead(intemperatura), 186, 566, 150, 19); //mappa il segnale proveniente dal LMT85

if (statovapore==0) // questo serve alla partenza del micro per

{ settemp = settempcaffe; }

// TERMOSTATO************************

// ***********************************************************

{ digitalWrite (releResistenza, LOW); // ATTENZIONE stati

} // lavora al contrario,

if ((temperatura) > (settemp)) { digitalWrite (releResistenza, HIGH); }

// RICEZIONE STRINGHE DA NEXTION **************************

com = ""; //azzeramento variabile

if (Serial2.available())// in attesa che arrivi un carattere dal Nextion { a=Serial2.read(); }

if(a=="167") //dato inizio stringa da aggiungere nella

{

via alla ricezione della stringa while(start==1) { if (Serial2.available()) { a=Serial2.read();

nella programmazione pulsanti Nextion

{

comando }

else { start=0; // permette di uscire dal ciclo } } } }

stato premuto e siamo sulla pagina 0 { Serial2.print("bt0.val=0"); // manteniamo il pulsante

vapore Serial2.write(0xff); Serial2.write(0xff); Serial2.write(0xff); }

// USO E INTERBLOCCO SWITCH VALVOLA ACQUA***************************

if(statovapore == 0)//verifica che lo stato del vapore sia a zero, vapore NON selezionato { if ((digitalRead(inSwitch)==HIGH) || (statocaffe == 1 ) ) //se

{ digitalWrite(relePompa, LOW); }

else { digitalWrite(relePompa, HIGH); } }

bloccata { digitalWrite(relePompa, HIGH); }

// COMANDI CAFFE' E VAPORE DA DISPLAY****************************

if ((com == caffeon) && (statovapore==0)) { statocaffe=1; digitalWrite(relePompa, LOW); dimming(); //rimanda al ciclo che porta la backlight l 100% }

if (com == caffeoff ) { statocaffe = 0; digitalWrite(relePompa, HIGH); dimming(); //rimanda al ciclo che porta la backlight l 100% }

if (com == vapon ) // se viene premuto il tasto vapore { statovapore=1; // settiamo la variabile corrispondente statocaffe=0; digitalWrite (relePompa, HIGH); //disattiviamo la pompa dell'acqua settemp = settempvap; //settiamo il set temperatura con quello del vapore dimming(); //rimanda al ciclo che porta la backlight l 100% }

{ statovapore=0; //settiamo la sua variabile a 0 //statocaffe = 0; settemp = settempcaffe; //settiamo il set temperatura con

dimming(); //rimanda al ciclo che porta la backlight l 100% }

if (com == page0) // memorizza la pagina 0 su cui stiamo lavorando { page0on = 1;

dimming(); //rimanda al ciclo che porta la backlight l 100% }

if (com == page1) // memorizza la pagina 1 su cui stiamo lavorando { page1on = 1;

dimming(); //rimanda al ciclo che porta la backlight l 100% }

selezionata la pagina relativa { settempcaffe = settempcaffe + 1; EEPROM.write(0, settempcaffe); Serial2.print("settemp.val=" + String (settempcaffe)); // selezionare il modulo numerico scrivendo l'id corrispondente al modulo a cui si vuole inviare Serial2.write(0xff); // bisogna mandare i tre caratteri di fine trasmissione Serial2.write(0xff); Serial2.write(0xff); dimming(); //rimanda al ciclo che porta la backlight l

100% }

selezionata la pagina relativa { settempcaffe = settempcaffe - 1; EEPROM.write(0, settempcaffe); Serial2.print("settemp.val=" + String (settempcaffe)); // selezionare il modulo numerico scrivendo l'id corrispondente al modulo a cui si vuole inviare Serial2.write(0xff); // bisogna mandare i tre caratteri di fine trasmissione Serial2.write(0xff); Serial2.write(0xff); dimming(); //rimanda al ciclo che porta la backlight l

100% }

if (page1on == 1) // manda il valore del set temperatura solo se la

{ Serial2.print("settemp.val=" + String (settempcaffe)); // selezionare il modulo numerico scrivendo l'id corrispondente al modulo a cui si vuole inviare Serial2.write(0xff); // bisogna mandare i tre caratteri di fine trasmissione Serial2.write(0xff); Serial2.write(0xff); }

// AGIORNAMENTO TEMPERATURA SU NEXTION ***************************

pagina 0 { dt = millis() - t1; // aggiorna col timer per non sovracaricare la seriale

if (dt > 500) { Serial2.print("t1.txt=\"" + String(temperatura) + "

*C""\""); // manda la temperatura come stringa e *C come caratteri Serial2.write(0xff); // bisogna mandare i tre caratteri di fine trasmissione Serial2.write(0xff); Serial2.write(0xff); t1=millis(); } if (digitalRead (releResistenza) == HIGH) //se il rele della

{ Serial2.print("t1.bco=63488"); //colore rosso per set temperatura raggiunto Serial2.write(0xff); Serial2.write(0xff); Serial2.write(0xff); }

if (digitalRead (releResistenza) == LOW) //quando la temperatura scende sotto al set e si attiva il rele resistenza torna il colore normale { Serial2.print("t1.bco=1310"); //colore azzurro dello sfondo del display Serial2.write(0xff); Serial2.write(0xff); Serial2.write(0xff); }

}

dim1 = millis() - dim2; // timer per abbassare la backlight se non si premono tasti per il tempo selezionato

if (dim1 > 30000) { Serial2.print("dim=5"); Serial2.write(0xff); Serial2.write(0xff); Serial2.write(0xff); }

}

void dimming() //serve per riportare la retroilluminazione al 100& se si preme un tasto { Serial2.print("dim=100"); Serial2.write(0xff); Serial2.write(0xff); Serial2.write(0xff); dim2=millis(); }

--
Saluti da Drizzt, quello vero! 


www.agidone.altervista.org 
MAI PIU' UN CESSO DI OPEL IN VITA MIA!!!! 
http://www.tappezzeriagraziella.com/
Reply to
Drizzt do'Urden

Il 11/01/2022 23:39, Drizzt do'Urden ha scritto:

Che poi alla fine mi basta anche un semplice proporzionale che commuti

difficile differenziare il tempo ON da quello OFF in base all'errore, una roba tipo questa:

errore = settemp - temperatura; erroreon = errore*kp; erroreoff = erroreon/kpoff; if (erroreon < 0) { erroreon = 0; } if (errore > 50) { errore = 50; } if (erroreoff < 0) { erroreoff = 0; }

if ((temperatura < settemp) && (statoresistenza == 0)) { timer1 = millis() - timer2; digitalWrite(releResistenza, LOW); timer4=millis(); }

if (timer1 > erroreon) { digitalWrite(releResistenza, HIGH); statoresistenza=1; timer3=millis()-timer4; if (timer3 > erroreoff) { statoresistenza=0; timer2=millis(); } }

--
Saluti da Drizzt, quello vero! 


www.agidone.altervista.org 
MAI PIU' UN CESSO DI OPEL IN VITA MIA!!!! 
http://www.tappezzeriagraziella.com/
Reply to
Drizzt do'Urden

fammi capire che tipo di errore, soprattutto in che percentuale su varie impostazioni

Reply to
Franco Af

Il 12/01/2022 20:19, Franco Af ha scritto:

stare ON il 99% e OFF il 1% del tempo impostato, man mano che l'errore

proporzionale. Sto provando anche gli esempi della libreria PID_v1 ma quello on/off

testano gli esempi.

--
Saluti da Drizzt, quello vero! 


www.agidone.altervista.org 
MAI PIU' UN CESSO DI OPEL IN VITA MIA!!!! 
http://www.tappezzeriagraziella.com/
Reply to
Drizzt do'Urden

Il 12/01/2022 20:59, Drizzt do'Urden ha scritto:

-- Saluti da Drizzt, quello vero!

formatting link
MAI PIU' UN CESSO DI OPEL IN VITA MIA!!!!
formatting link

Reply to
Drizzt do'Urden

l'inserimento di myPwm nel tuo codice e' questo:

formatting link

ho modificato la classe myPwm in modo che gestisca l'uscita invertita, e al posto di configurare TON e TOFF ora si imposta periodo e duty cycle. l'inserimento nel tuo codice comporta la copia tale e quale della definizione della classe la dichiarazione della variabile pwmResistenza con parametri il pin e "true" se e' una uscita invertita nella funzione setup() le 2 righe che vedi nel loop la chiamata alla funzione SetDuty() e poi Loop(). non ci dovranno essere altre scritture digitalWrite dell'uscita releResistenza.

non ti resta che giocare con il valore del periodo nella: pwmResistenza.SetPeriod( 5000 ); e con il coefficiente in: pwmResistenza.SetDuty( 5*( settemp-temperatura ) );

il periodo e' in millisecondi il coefficiente dice di quanto cambia in percentuale il duty cycle per ogni grado di differenza tra setpoint e temperatura attuale. in pratica con il valore 5 che vedi adesso, con piu' di 20 gradi di differenza la resistenza e' sempre accesa, con 19 gradi sta 4,75 secondi

accesa e 0,25 spenta, e cosi' via fino a sempre spenta quanto sono uguali o ha superato il setpoint.

nel tuo codice, c'e' solo il while in cui attendi i caratteri da seriale che non mi piace, ma forse non e' un grosso problema, se tutto funziona dovrebbe durare 1_ms * numero_di_caratteri_da_ricevere, e non mi pare che un messaggio del Nextion sia lungo centinaia di caratteri.

prova e facci sapere

Reply to
alfio

Il 12/01/2022 20:59, Drizzt do'Urden ha scritto:

Ma realisticamente che senso ha? Nemmeno una incubatrice ha bisogno una cosa del genere.

Reply to
El_Ciula

Il 12/01/2022 20:59, Drizzt do'Urden ha scritto:

vediamo...

Non vedo variabili macchina in funzione, dobbiamo capire quando crearla

dichiarala fuori dal loop: int mac_in_funz = 0;

Devi impostarla a 1 quando vuoi che la temperatura sia regolata, vedi tu come fare. (metti magari un pulsante di accensione sul display)

if (mac_in_funz == 1){

if (temperatura < (settemp < 5 )) { // quando scende di 5 gradi accendi, oppure regola come vuoi digitalWrite (releResistenza, LOW); } if (temperatura > settemp ) { digitalWrite (releResistenza, HIGH); } }

poi magari, se serve, puoi aggiungere lo spegnimento della resistenza se macchina spenta:

else { digitalWrite (releResistenza, HIGH); }

Fammi capire come vuoi avviare la resistenza.

Reply to
Franco Af

Il 12/01/2022 21:23, Franco Af ha scritto:

un mio errore ...

if (temperatura < (settemp - 5 )) {

Reply to
Franco Af

Il 12/01/2022 21:05, alfio ha scritto:

Caspita, funziona proprio come volevo io, sicuramente non ci sarei mai

non ci riesco, inutile, sono negato per queste cose ma non demordo e

Ora si tratta di provarlo sulla caldaietta e vedere l'effetto che fa.

commutazioni quello meccanico non durerebbe molto. Sto testando anche la comunicazione col Nextion e non sembra influire. Mi sono salvato le tue istruzioni direttamente sullo sketch per non perdere e dimenticare nulla :-)

Per ora un grande grazie, tu e Franco Af siete dei grandi :-)

PS: quanto ci hai messo per scriverlo?

--
Saluti da Drizzt, quello vero! 


www.agidone.altervista.org 
MAI PIU' UN CESSO DI OPEL IN VITA MIA!!!! 
http://www.tappezzeriagraziella.com/
Reply to
Drizzt do'Urden

Il 12/01/2022 21:23, Franco Af ha scritto:

Grazie ancora per l'enorme aiuto che mi avete dato, ora passo alla sperimentazione sul campo :-)

--
Saluti da Drizzt, quello vero! 


www.agidone.altervista.org 
MAI PIU' UN CESSO DI OPEL IN VITA MIA!!!! 
http://www.tappezzeriagraziella.com/
Reply to
Drizzt do'Urden

Il 12/01/2022 23:19, alfio ha scritto:

guarda che non avrei capito nemmeno se lo avessi scritto con i commenti a lato :-D :-D

dal vivo :-)

--
Saluti da Drizzt, quello vero! 


www.agidone.altervista.org 
MAI PIU' UN CESSO DI OPEL IN VITA MIA!!!! 
http://www.tappezzeriagraziella.com/
Reply to
Drizzt do'Urden

Il 13/01/2022 08:44, El_Ciula ha scritto:

formatting link

oppure La Marzocco o Bezzera, tutte marche a me sconosciute fino ad ora :-)

Su questo forum sono veramente competenti e forse alcuni un po esagerati :-D

formatting link

Oggi primi esperimenti e il sistema di regolazione sembra funzionare

vapore e ha mantenuto.

formatting link

--
Saluti da Drizzt, quello vero! 


www.agidone.altervista.org 
MAI PIU' UN CESSO DI OPEL IN VITA MIA!!!! 
http://www.tappezzeriagraziella.com/
Reply to
Drizzt do'Urden

Sta tutto qui:

{ bool pinState = digitalRead (pin);

unsigned long t_nextChange; if (pinState==HIGH) t_nextChange = t_lastChange + tOn; else t_nextChange = t_lastChange + tOff;

if (millis() >= t_nextChange) { t_lastChange = t_nextChange; digitalWrite(pin, !pinState); } }

semplice:

if (acceso==1 && millis()-t_prec>= t_on) { t_prec=millis(); acceso==0; digitalWrite (pin, LOW); } else if (acceso==0 && millis()-t_prec>= t_off) { t_prec=millis(); acceso==1; digitalWrite (pin, HIGH); }

Ringraziamo l'USAC per il gentile contributo. :)

Reply to
LAB

operazioni non facciano ottenere il risultato desiderato:

if (acceso==1 && (millis()-t_prec>= t_on)) { t_prec=millis(); acceso==0; digitalWrite (pin, LOW); } else if (acceso==0 && (millis()-t_prec>= t_off)) { t_prec=millis(); acceso==1; digitalWrite (pin, HIGH); }

Reply to
LAB

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.