Realizzare un filtro o un regolatore a virgola fissa
In questa pagina 5
Le note precedenti danno gli ingredienti: formati (Virgola fissa - formati n.m e normalizzazioneIn virgola fissa il processore fa aritmetica sugli interi (con segno) e il fattore di scalacostante per cui si moltiplica un valore reale per ottenere l'intero memorizzato $2^{m}$ resta sottinteso: il formato n.m dice che dei bit disponibili $n$ sono la parte intera (compreso il segno se il numero è con segno, S; nessun segno se U) e $m$ la parte frazionaria. Il valore è $\text{codice}/2^m$. Passare dal formato n.m al decimale, o viceversa, è il calcolo più frequente dell'esame: su 16 bit $\text{valore}=\text{codice}/2^m$, l'intervallo è $[0,2^n)$ (U) oppure $[-2^{n-1},2^{n-1})$ (S), la risoluzione è $2^{-m}$.Virgola fissa - formati n.m e normalizzazione →), scelta e errore (Rappresentare un valore reale in virgola fissa - formato ottimo ed errorePer rappresentare un reale $x$ su $W$ bit a virgola fissa si sceglie il formato che minimizza l'erroresceglie la rappresentazione per cui la differenza tra il valore rappresentato e quello vero è la più piccola possibile: il maggior numero di bit frazionari $m$ compatibile con l'intervallo ($n=W-m$ bit interi, con U se $x\ge0$, con S se $x<0$). Poi $C=\mathrm{round}(x\cdot2^m)$, scritto in esadecimale (per un negativo, in complemento a 2), e l'errore $\varepsilon=\frac{C}{2^m}-x$, positivo se in eccesso, ha modulo $\le2^{-(m+1)}$. Se invece è dato l'errore massimo, i bit minimi si ricavano da $2^{-(m+1)}\le\varepsilon_{max}$.Rappresentare un valore reale in virgola fissa - formato ottimo ed errore →), prodotto e riallineamento (Operazioni in virgola fissa - somma, prodotto e riallineamentoIn virgola fissa il processore opera sugli interi e non sa dov'è la virgola: tocca al programmatore. Regola 1: si sommano solo dati con lo stesso formato (stesso $m$). Regola 2: il prodotto di $n_1.m_1$ per $n_2.m_2$ ha $m_1+m_2$ bit frazionari e il doppio dei bit: va riallineato con uno shift a destra di $m_2$ posizioni (per riportarlo a $m_1$) o preso dalla parte alta. Con la normalizzazione frazionaria $1.15$ il prodotto è $2.30$ e basta uno shift a sinistra di 1 prima di prendere la parte alta. I fattori di scala si scelgono per evitare overflow e perdita di risoluzione.Operazioni in virgola fissa - somma, prodotto e riallineamento →), discretizzazione (Discretizzazione di Eulero e TustinPer realizzare numericamente un filtro o regolatore $F(s)$ si approssima $\frac1s$ con un integratore a tempo discreto. Eulero: $\boxed{s=\dfrac{1-z^{-1}}{T_c}}$ (da $\mathrm{Int}(nT)=\mathrm{Int}((n-1)T)+T,x(n)$). Così $\dfrac{1+s\tau_z}{1+s\tau_p}$ diventa $y(k)=\dfrac{\tau_p}{T_c+\tau_p}y(k-1)+\dfrac{T_c+\tau_z}{T_c+\tau_p}x(k)-\dfrac{\tau_z}{T_c+\tau_p}x(k-1)$. Il passaggio inverso (da algoritmo a $F(s)$) usa $z^{-1}\approx1-sT_c$. L'approssimazione è affidabile solo fino a circa $f_c/10$ (distorsione, warping); Tustin $s=\frac2{T_c}\frac{1-z^{-1}}{1+z^{-1}}$ è più fedele.Discretizzazione di Eulero e Tustin →), quantizzazione (Quantizzazione, fattori di scala e cicli limiteUn algoritmo di filtro o regolatore pensato per un processore ideale va adattato alla realtà: temporizzazionedistribuzione nel tempo delle operazioni di un algoritmo (l'algoritmo nella ISR dell'ADC, durata minore di $T_c$), acquisizione (condizionamento del segnale per sfruttare tutto il fondo scala dell'ADC), fattori di scala (normalizzazione intera o 1.15; evitare overflow), quantizzazione di ingresso, uscita, coefficienti e prodotti (sposta i poli, genera errori a regime e cicli limite). Una frequenza di campionamento troppo alta rende più critica la quantizzazione dei coefficienti: va scelta coerente con la lunghezza di parola.Quantizzazione, fattori di scala e cicli limite →). Qui si mettono insieme su un caso concreto, quello del laboratorio, e su altri due tipici da esame.
Esempio 1: passa-basso su STM32 (laboratorio)
Specifiche: passa-basso del primo ordine con banda 500 Hz, kHz, guadagno 1. Quindi s: il dato va convertito e il calcolo concluso in meno di 20 µs. Con il clock da circa 14 ns ci sono circa 1400 cicli: molti di più di quelli richiesti dal filtro. Si sceglie un IIR del primo ordine (un FIR costerebbe molto di più: Filtri numerici IIR e FIRUn filtro numerico è una equazione alle differenzerelazione che dà il campione di uscita in funzione di campioni di ingresso e di uscita passati $y(k)=\sum_ib_ix(k-i)+\sum_ia_iy(k-i)$. IIR (ricorsivo: qualche $a_i\ne0$) ha risposta impulsiva infinita e bastano pochi termini; FIR (tutti $a_i=0$) è sempre stabile ma richiede molti termini. Il passa-basso IIR del primo ordine $y(k)=b,x(k)+a,y(k-1)$ con $a+b=1$ ha guadagno 1 ed è stabile se $|a|<1$; la risposta al gradino è $y(k)=1-a^{k+1}$. Il filtro analogico equivalente (Eulero) ha $\tau=\dfrac{a,T_c}{1-a}$ e $f_T=\dfrac1{2\pi\tau}$. La media mobile di $N$ campioni è un FIR passa-basso che si assesta in $N$ passi.Filtri numerici IIR e FIR →).
Coefficienti (Eulero). s; (coefficiente di ) e (coefficiente di ), .
Rappresentazione. L'aritmetica del µC è a 32 bit, ma un prodotto richiederebbe un accumulatore a 64 bitregistro che servirebbe per prodotti di dati a 32 bit che non c'è: dati e coefficientii fattori costanti che moltiplicano i campioni nell'algoritmo devono stare su 16 bit ({{uint16_t|tipo C intero senza segno a 16 bit}}). Poiché i numeri sono tutti positivi e minori di 1 si usa 0.16 senza segnoformato in cui il dato è una frazione tra 0 e 1 con 16 bit frazionari con fattore :
Il dato dell'ADC a 12 bit () si allineaporta un dato a 12 bit in una parola a 16 bit con gli MSB o gli LSB coincidenti a sinistra su 16 bit: . La risoluzione numericail passo minimo rappresentabile: 2 elevato a meno m dei coefficienti è : il diagramma di Bode del filtro reale e di quello ideale sono quasi sovrapponibili; resta il troncamentoeliminazione dei bit bassi senza arrotondare implicito nelle moltiplicazioni. 4 dei 16 bit di sono perennemente nulli (l'ADC ha 12 bit, la risoluzione è circa 0,8 mV con FSR 3,3 V).
Prodotto e shift. Il prodotto di due uint16_t (interpretati come interi) è un intero a 32 bit con bit frazionari; per riportarlo a 16 bit frazionari si scartano i 16 bit bassi, cioè shift a destra di 16. Esempio: (0,25) per (0,625) dà ; ✓.
Codice (nella ISRroutine di servizio di una interruzione dell'ADC, con y di tipo {{uint32_t|tipo C intero senza segno a 32 bit}}):
// u: 12 bit; a16, b16: formato 0.16 U; y e yo: formato 0.16 U (0..65535)
y = (a16*yo + b16*(u<<4)) >> 16; // un solo shift: i due prodotti hanno la stessa scala (m = 32)
yo = y;I due prodotti hanno entrambi 32 bit frazionari: si possono sommare prima di fare lo shift (si perde un solo bit di troncamento, invece di due). Poiché e , la somma è al massimo : non va in overflow in 32 bit senza segno. (Nei file del corso i nomi dei coefficienti sono scambiati rispetto a questa nota, ma la struttura è la stessa.)
Esempio 2: coefficienti maggiori di 1 (tema d'esame febbraio 2026)
Algoritmo con in 0.16 U (Q16) e in 4.12 U, calcolo su 32 bit. Si scelgono i formati dei coefficienti per minimizzare l'errore:
- : 0.16 U, (arrotondato);
- : positivo e : 4.12 U, ;
- : negativo, : 5.11 S (segno + 4 bit interi + 11 frazionari), . Allineamento dei prodotti. : bit frazionari, per riportare a 12 (formato di ) si fa . : ; : . Per sommare i due si porta a 11 bit frazionari con (così ha 27 frazionari come ) e poi per ottenere 12 bit frazionari:
y = ((a16*y0) >> 16) + ((((b0_16 >> 1)*x) + (b1_16*x0)) >> 15); // y: 4.12 U
y0 = y; x0 = x;(b1_16 va trattato come intero con segno a 32 bit.) Verifica con il programma: per un gradino unitario () si ottiene (atteso ), (atteso ), ..., (la risposta teorica è : ): gli scostamenti sono errori di arrotondamento. Valore massimo di senza overflow nel calcolo: richiederebbe , ma per la scelta di formato, quindi (fondo scala).
Esempio 3: approssimazione di una funzione (tema d'esame settembre 2026)
Si vuole calcolare , con , , , per ( non esiste in hardware: Architettura del repertorio di istruzioni - RISC, CISC, VLIW e indirizzamentoL'architettura è l'insieme delle risorse visibili al programmatore (istruzioni, modi di indirizzamento). RISC: poche istruzioni semplici, di uguale lunghezza, decodifica cablata, quasi tutte a 1 ciclo; CISC: molte istruzioni complesse, decodifica microprogrammata, più cicli. I DSP sono RISC "potenziati" (MAC, saturazione, barrel shifter, arrotondamento, VLIW, SIMD); i modi di indirizzamento tipici sono immediato, a registro, diretto, indiretto, con auto-incremento, circolare e a bit rovesciati (per la FFT).Architettura del repertorio di istruzioni - RISC, CISC, VLIW e indirizzamento →). Con coefficienti frazionari senza segno 0.16 e arrotondamento: (errore ); (errore ). Se è in 1.15 Uformato senza segno con un bit intero e 15 frazionari: valori tra 0 e 2 (), rad : il valore realmente usato è . Il polinomio con il effettivamente usato dà (il polinomio di Taylor approssima con di errore: è l'errore di troncamento della seriesviluppo di una funzione come somma di potenze di x, non della rappresentazione). Calcolando con , , (tutti in 1.15) e in formato 0.16 si ottiene : errore rispetto a di (arrotondamenti dei prodotti). Questo è l'esempio di come, anche per una funzione non lineare, si lavora con poche moltiplicazioni e shift.
Regole pratiche
- Scrivere il formato di ogni variabile in un commento (e nei nomi, per esempio
a_q16). - Controllare, prima di ogni somma, che i due addendi abbiano lo stesso numero di bit frazionari; se no, shift.
- Usare un accumulatore a 32 bit per i prodotti di dati a 16 bit e fare un solo shift dopo aver sommato prodotti con la stessa scala.
- Verificare l'assenza di overflow nel caso peggiore (ingresso a fondo scala, somma dei moduli dei coefficienti).
- Verificare la risposta con una simulazione (per esempio in Python o con il debugger sul µC) confrontandola con il calcolo in virgola mobile.
Errori comuni
- Moltiplicare due
uint16_tinuint16_t: il prodotto va in overflow; serve convertire inuint32_tprima del prodotto. - Shiftare di troppo o troppo poco dopo il prodotto (conta quanti bit frazionari ha il risultato).
- Dimenticare il segno: un prodotto con un negativo va fatto con interi con segno.
- Allineare a destra il dato a 12 bit e poi trattarlo come se fosse 0.16 U.
Versione ripasso
- Passa-basso STM32: Hz, kHz: , (0.16 U); ;
y=(a*yo+b*(u<<4))>>16(: nessun overflow in 32 bit). - Prodotto: bit frazionari; shift a destra per tornare a ; sommare prodotti con la stessa scala e poi un solo shift.
- : 0.16 U
0xCCCD, 4.12 U0xC333, 5.11 S0xA000;y=((a*y0)>>16)+((((b0>>1)*x)+(b1*x0))>>15). - : , (0.16 U); in 1.15 U .
- Regole: commentare i formati, controllare le scale prima delle somme, verificare overflow e simulare.
- Errori: prodotto in 16 bit; shift sbagliati; segno ignorato; dato a 12 bit non riallineato (Quantizzazione, fattori di scala e cicli limiteUn algoritmo di filtro o regolatore pensato per un processore ideale va adattato alla realtà: temporizzazionedistribuzione nel tempo delle operazioni di un algoritmo (l'algoritmo nella ISR dell'ADC, durata minore di $T_c$), acquisizione (condizionamento del segnale per sfruttare tutto il fondo scala dell'ADC), fattori di scala (normalizzazione intera o 1.15; evitare overflow), quantizzazione di ingresso, uscita, coefficienti e prodotti (sposta i poli, genera errori a regime e cicli limite). Una frequenza di campionamento troppo alta rende più critica la quantizzazione dei coefficienti: va scelta coerente con la lunghezza di parola.Quantizzazione, fattori di scala e cicli limite →).
Esercizi su questo argomento
- Esercizio 3 · calcolo di y = a·x + b e di un polinomio in virgola fissa a 32 bit (temi d'esame gennaio 2026 e settembre 2026)
- Esercizio 19 · realizzazione in C di un filtro con coefficienti maggiori di 1 a virgola fissa (tema d'esame febbraio 2026)
- Esercizio 20 · regolatore PI in C per il controllo PWM di un motore, valore del duty-cycle e risoluzione (tema d'esame gennaio 2023)
- Esercizio 22 · filtro numerico a 8 bit, coefficienti, prodotti parziali ed errore di troncamento (esercizi del 4 dicembre 2020)
Teoria collegata
- Architettura del repertorio di istruzioni - RISC, CISC, VLIW e indirizzamento
- Formulario - elettronica industriale
- Linguaggio C per i microcontrollori - puntatori, tipi e operatori
- Microcontrollori STM32 - clock, timer, ADC e codice HAL
- PWM e ADC - ritardo di risposta e sincronizzazione
- Regolatori PI e PID digitali
- Virgola fissa - formati n.m e normalizzazione