Archivi tag: analogWrite

Arduino – Approfondimenti sulla modulazione di larghezza di impulso (PWM)

Scrivo questo post ad integrazione della lezione: Arduino – lezione 06: modulazione di larghezza di impulso (PWM) che sto utilizzando con i miei studenti di 4′ informatica per illustrare le modulazioni di tipo digitali. L’obiettivo è quello di mostrare sull’oscilloscopio come varia il  Duty Cycle di un’onda quadra su un pin di tipo PWM di Arduino utilizzato per impostare l’intensità luminosa di un LED mediante una regolazione applicata attraverso un trimmer connesso al pin A0 di Arduino.

Oltre alla visualizzazione sull’oscilloscopio si desidera, come riscontro, la stampa sulla Serial Monitor dei seguenti valori:

  • Tensione in input sul pin A0
  • Valore restituito dalla funzione analogRead() – (tra 0 e 1023)
  • Valore restituito dall’analogWrite – (tra 0 e 254)
  • Valore percentuale del Duty Cycle  (tra 0% e 100%)

Il circuito da realizzare con l’indicazione delle connessioni all’oscilloscopio è il seguente:

Sul canale X verrà visualizzata l’onda quadra in uscita dal pin 11 il cui Duty Cycle sarà regolato agendo sul trimmer.

Sul canale Y verrà visualizzata la tensione continua in input sul pin A0, che sarà convertita dal convertitore Analogico Digitale di Arduino in un valore compreso tra 0 e 1023  (risoluzione di 10 bit). Ricordo che tale conversione sarà fatta con l’istruzione analogRead(pin).

Poiché uno degli obiettivi è quello di visualizzare la tensione rilevata sul pin A0, ricordo che tale misurazione viene fatta utilizzando la funzione analogRead(pin) che legge il valore di tensione (compreso tra 0 e 5V) applicato sul piedino analogico ‘pin’ con una risoluzione di 10 bit e la converte in un valore numerico compreso tra 0 e 1023, corrispondente quindi ad un intervallo di 1024 valori, pertanto ogni intervallo corrisponde ad un valore di tensione Vu di:

Per sapere quindi il valore di tensione rilevato (nell’intervallo tra 0V e 5V) sarà sufficiente moltiplicare la tensione unitaria Vu per il valore restituito dalla funzione analogRead(pin), valore quantizzato indicato con Vq compreso tra 0 e 1023:

Sapendo che Vu corrisponde a 4,88 mV

possiamo anche scrivere che:

Questa formula sarà inserita all’interno dello sketch.

Di seguito la schermata dell’oscilloscopio che visualizza la situazione indicata dai dati stampati sulla Serial Monitor:

  • Vmax(2) indica la tensione in ingresso ad A0 (la piccola discrepanza tra valore indicato sull’oscilloscopio e la stampa sulla Serial Monitor dipende dalle approssimazioni di calcolo).
  • Vmax(1) indica il valore di picco della tensione sul pin 11.

La spiegazione del funzionamento dello sketch sono dettagliate nei commenti:

/* Prof. Michele Maffucci
   03.06.2019
 
   Regolazione luminosità LED mediante
   trimmer, si utilizza la funzione map

   Stampa sulla seriale:
   - del valore di tensione sul pin A0
   - del valore restituito dall'analogRead
   - del valore restituito dall'analogWrite
   - del valore del Duty Cycle %
 
   Questo codice è di dominio pubblico 
*/

// pin analogico su cui inviare la tensione analogica (pin A0)
int misura = 0;

// pin a cui è connesso il LED
int pinLed = 11;

// variabile in cui conservare il valore inserito su A0
long val = 0;

// variabile in cui memorizzare il Duty Cycle
int inputVal = 0;

const long VoltRiferimento = 5.0; // valore di riferimento


void setup(){
  Serial.begin(9600);      // inizializzazione della comunicazione seriale
  pinMode(pinLed, OUTPUT); // definizione di ledPin come output
}

void loop(){
  // analogRead leggerà il valore su A0 restituendo un valore tra 0 e 1023
  // per approfondimenti si consulti il link: http://wp.me/p4kwmk-1Qd
  val = analogRead(misura);

  // analogWrite() accetta come secondo parametro (PWM) valori tra 0 e 254
  // pertanto "rimappiamo" i valori letti da analogRead() nell'intervallo
  // tra 0 e 254 usando la funzione map
  // per approfondimenti si consulti il link: http://wp.me/p4kwmk-1Tu
  inputVal = map(val, 0, 1023, 0, 254);
  
  // accendiamo il LED con un valore del Duty Cycle pari a val
  analogWrite(pinLed,inputVal);

  // Tensione inviata sul pin analogico A0.
  // Valore in virgola mobile.

  float volt = (VoltRiferimento/1024.0)*val;

  // visualizzazione il valore della tensione su A0,
  // del valore restituito dalla analogRead,
  // del valore restituito dall'analogWrite
  // e del Duty Cycle %

  // per approfondimenti sull'uso di String si consulti il link: https://www.arduino.cc/reference/en/language/variables/data-types/stringobject/
  
  Serial.println(String("Tensione su A0: ") + volt + "V" + String(";  ") + "analogRead: " + val + String(";  ") + String("Valore analogWrite: ") + inputVal + String("; ") + String("Duty Cycle %: ") + (inputVal/255.0)*100 + String("%;"));
  delay(500); // stampa una strina di valori ogni mezzo secondo
}

Buon Coding a tutti 🙂