Aiuto Codice per fade in PWM

Salve a tutti,

sono nuovo nel campo della programmazione e spero che qualcuno possa aiutarmi.
Sono appassionato di ferromodellismo ed ho già sperimentato con successo un regolatore di velocità in PWM. Purtroppo, però, manca di realismo... Vorrei aggiungere al mio regolatore di velocità anche un potenziometro di "fade" in modo tale da decidere in quanto tempo (e quindi in quanto spazio) il treno deve fermarsi o partire.
Ringrazio fin da subito chiunque abbia avuto il tempo di leggere questo post e voglia aiutarmi.

Federico.

PWM-Driver_2_2_Nano.ino (1.65 KB)

Quindi tu vorresti leggere il valore del potenziometro da un minimo ad un massimo e, in funzione del valore, vorresti ? Cambiare di quanto incrementi/decrementi il fade ? ... o cosa ?

Guglielmo

Salve,

Io ho un potenziometro in porta A0 che mi gestisce un segnale PWM variabile da 0 al 100%. Vorrei, con un secondo potenziometro (A1), fare in modo di rallentare la "discesa" della velocità in maniera proporzionale al valore Ohmico.
Quindi, se A1 è 0 Ohm, il cambio di velocià è istantaneo. Se A1 è 10 KiloOhm, il ritado deve essere di 5 secondi.
Ho cercato in giro, ma quasi tutti gli esempi che ho trovato usano la funzione Delay tra un incremento all'altro ma non farebbe al caso mio.

Grazie.

Segnale PWM ? ? ? ... credo tu stia facendo un po' di confusione, il PWM non ha nulla di analogico :wink:

Pin analogico in OUTPUT: NON è un analogico, lo è di nome per far capire che si può, in qualche modo "variare in modo proporzionale" un qualche cosa, ma di analogico NON ha nulla e, in realtà, è solo la generazione di un segnale digitale PWM.
Arduino UNO, MEGA e gli altri modelli basati su MCU AVR NON hanno DAC (Digital to Analog Converter), quindi NON sono in grado di generare veri segnali analogici.

Pin analogico in INPUT: È un vero analogico dato che è connesso ad UN ADC (Analog to Digital Converter) a 10 bit, il che significa che la tensione in ingresso viene trasformata in un numero che va da 0 a 1023.

Chiarito questo tu immagino hai un pin in OUTPUT (e quindi PWM con valore da 0 a 255) che controlla il motore, un pin in INPUT che leggi e regoli il valore del PWM da 0 a 255 (valore che chiameremo X e che indica la "velocità") ed un ulteriore pin in INPUT con il quale vorresti decidere in quanto tempo il pin in OUTPUT passa dal suo valore X a zero.

Ho capito bene ?

Guglielmo

Mi sono spiegato male e chiedo scusa per l'errore.

L'INPUT Analogico in A0 da 0 a 1023, gestisce l'OUTPUT da 0 a 255 sul Pin digitale 9 di Arduino Nano.
Si, il concetto che volevo esprimere è proprio quello.

Federico.

Ok, quindi, tu leggi il secondo potenziometro, ottieni di nuovo un valore che va da 0 a 1023 ed in funzione del valore letto decidi con che "passo" decrementare il valore X della velocità sino a zero. Se decrementi di 1, decrementi lentamente, se decrementi di X, decrementi tutto in un solo colpo e quindi di blocco.

Guglielmo

Esattamente.

Federico.

Fede_ITA:
Esattamente.

Bene ... e quindi ? Devi solo scrivere il codice che svolge questa cosa ... :wink:

Guglielmo

Ah ... se non puoi usare la delay() (... perché nel frattempo dei fare anche altre cose ed il programma non si può bloccare), allora, magari, potresti studiarti come si usa la millis(), prima QUI, poi QUI ed infine leggi anche QUI e QUI :slight_smile:

Guglielmo

Uhm...
Al millis() non ci avevo pensato... Grazie per la dritta! Me lo studio un pò, apporto qualche modifica allo sketch, e poi vediamo come và.
Al massimo correggeremo eventuali errori.

Federico.

Buongiorno,

Ho provato ad inserire il comando millis() all'interno dello sketch e tutto ha smesso di funzionare... Sono sicuro di aver sbagliato qualcosa durante la dichiarazione delle variabili, la posizione dei comandi o il contenuto dell'IF poichè, monostante io modifichi il valore Pot in A0, ottengo sempre 255 in PWM 9 anche se non ottengo errori di sintassi.
Come diceva il mio Prof. di Lettere... "Grammaticalmente perfetto, ma hai scritto una Bibbia di cazzate!"...

Federico

PWM-Driver_2_3_Nano.ino (1.23 KB)

Fede_ITA:
Come diceva il mio Prof. di Lettere... "Grammaticalmente perfetto, ma hai scritto una Bibbia di cazzate!"...

Emmmm ... credo che il tuo professore centrasse esattamente il problema ... ::slight_smile:

Quel codice, anche se sintatticamente corretto (ovvero che non genera errori di sintassi), in realtà ... non serve a nulla !

Allora ... premesso che il programma va riscritto da capo, prima di farlo ti suggerisco di rafforzare un po' le "basi" perché mi sembra che hai alcune grosse lacune ... ::slight_smile:

... potresti cominciare con il leggere attentamente QUESTO proseguire con QUESTO e potresti, ad esempio, comprarti un bel libro come QUESTO che ti chiarirebbe molto le idee.

Dopo di che, una volta rafforzate le "basi", ricomincia a scrivere il codice ma ... "un pezzetto per volta" e mettilo qui dove lo guardiamo, lo commentiamo e lo correggiamo.

Il primo passo che farei e la corretta lettura del primo potenziometro, il salvataggio della velocità impostata e la regolazione della velocità.

Resto in attesa, in questa prima fase, di vedere questo, ma prima, mi raccomando, rafforza le "basi" come detto :wink:

Guglielmo

P.S.: Il codice si può inserire anche dentro i post invece che come allegato, purché, in conformità al regolamento, punto 7, venga racchiuso tra i tag CODE che, in fase di edit, inserisce il bottone </> ... primo a sinistra.

Allora... ho ricominciato tutto da capo.
Questo codice è il mio punto di partenza, sono 2 righe ma funzionano.

// Controllore PWM

  
int mot = 9;                  // PWM collegato al pin digitale 9 
int pot = 0;


void setup() {  
  
  
  pinMode(mot, OUTPUT);       // imposta il pin digitale 9 come output PWM
  pinMode(pot, INPUT);        // imposta il pin analogico come input Potenziometro
}  
  
void loop() {  

  pot = analogRead(A0);
  pot = map (pot, 10, 1023, 0, 255);
    
  analogWrite(mot, pot);      // segnale PWM
}

Perfetto ...
.. un solo appunto, per gli I/O digitali è d'obbligo il pinMode(), in caso di analogRead() ed analogWrite() NON è necessario in quanto le stesse funzioni programmano i pin come servono a loro :wink:

Puoi quindi eliminare quelle due righe dal setup() e vedrai che non cambia nulla :slight_smile:

Ora ... passo successivo, cosa determina se il "treno si deve fermare" ? Un segnale digitale che arriva da qualche sensore posto sui binari ? Tu con un bottone ?

Guglielmo

Perfetto...

Ora, decidiamo che il treno deve fermarsi alla pressione di un pulsante ed il tempo che impiegherà per farlo sarà proporzionale al valore della resistenza in A0.
Nello sketch ho aggiunto, seguendo le indicazioni, un "fade" ed un input digitale "pulsante" in porta 10.
Ovviamente, tutto continua a funzionare come prima, poichè nessuno di questi nuovi elementi entra in gioco.
A questo punto, dovrei aggiungere un blocco IF contenetnte il millis() che, alla pressione del pulsante, fa ciclicamente decelerare il motore.

// Controllore PWM

  
const int pulsante = 10;            // dichiarazione del pin collegato al Pulsante
const int mot = 9;                  // PWM collegato al pin digitale 9 
int pot = 0;
int fade = 0;
int statopulsante = 0;

void setup() {  
  
  pinMode(pulsante, INPUT);        // pin dichiarato come input      
  
  
}  
  
void loop() {  
  statopulsante = digitalRead(pulsante);
  fade = analogRead(A1);                 // lettura potenziometro "Fade"
  pot = analogRead(A0);                  // lettura potenziometro collegato al PWM
  pot = map (pot, 10, 1023, 0, 255);     
    
    if (statopulsante == HIGH) {
                                         // manca il blocco IF contenente millis()
    } else {
  
  analogWrite(mot, pot);                 // segnale PWM
}
}

Bene ...
... allora, ricorda che un pulsante "ideale", come quello che disegni su uno schema, quando lo premi si chiude e quando lo lasci si apre, tutto in modo perfetto, ma, come sempre, la "realtà" è ben diversa e qualsiasi contatto meccanico che si chiude e si apre, nella realtà provoca dei "rimbalzi".

Se guardi con un oscilloscopio la chiusura/apertura di un contatto scoprirai che fa ...

... occorre quindi prevedere quello che si chiama "debouncing" o, ad ogni pressione/chiusura del bottone/interruttore Arduino, in realtà, leggerà N chiusure ed aperture "a raffica" :smiley:

Per il "debouncing" esistono tecniche HW e tecniche SW ... approfondisci l'argomento su Google e poi decidi quale delle due tecniche vuoi usare perché la cosa, ovviamente, ha un impatto sul SW che scrivi :wink:

Dopo di che andiamo avanti ... :smiley:

Guglielmo

OK...
credo mi sia più facile aggiungere un condensatore al pulsante che scrivere del codice... :smiley:

Fede_ITA:
OK...
credo mi sia più facile aggiungere un condensatore al pulsante che scrivere del codice...

Concordo ... :smiley: :smiley: :smiley:

A questo punto, nel loop() dovrai verificare la pressione del bottone e se premuto memorizzare la cosa in una flag (... così da ricordati che è stato premuto, altrimenti ti tocca stare con dito sul bottone :smiley: :smiley: :smiley:).

Sempre nel loop() avrai un IF che verifica lo stato di questa flag e, se la trova attiva ... dovra portare a zero la velocità con un passo o con un tempo proporzinale al valore del potenziometro :wink:

Come sempre ... un passo alla volta, mi raccomando :slight_smile:

Guglielmo

Esattamente,

ho trovato un solo esempio di flag "dichiarato" :-\ e non capisco perché lo abbiano messo sia prima del void setup che all'interno dello stesso... Comunque sia, mia ignoranza a parte, questo è il risultato:

// Controllore PWM

 
const int pulsante = 10;            // dichiarazione del pin collegato al Pulsante
const int mot = 9;                  // PWM collegato al pin digitale 9 
int pot = 0;
int fade = 0;
int statopulsante = 0;
int flag = 0;                            // <-------

void setup() {  
 
 pinMode(pulsante, INPUT);        // pin dichiarato come input      
 int flag = 0;                          // <-------
 
}  
 
void loop() {  
 statopulsante = digitalRead(pulsante);
 fade = analogRead(A1);                 // lettura potenziometro "Fade"
 pot = analogRead(A0);                  // lettura potenziometro collegato al PWM
 pot = map (pot, 10, 1023, 0, 255);     
   
   if (statopulsante == HIGH) {
     if (flag == 0) {}                  //  <--------  manca il millis()
   } else {
 
 analogWrite(mot, pot);                 // segnale PWM
}
}

Chiedo scusa, non ho molta esperienza di Forum...

>Fede_ITA: ti ricordo che in conformità al regolamento, punto 7, devi editare il tuo post (in basso a destra del post, bottone More -> Modify) e racchiudere il codice all'interno dei tag CODE (... sono quelli che in edit inserisce il bottone fatto così: </>, tutto a sinistra). Grazie :slight_smile:

Guglielmo