GENERATORE DI FORME D’ONDA STRANE CON PIC16F876

6.jpg

Questo che presento è il lavoro che più mi ha divertito rispetto agli altri presenti su questo sito, con un Pic ed un convertitore DA fatto in casa si possono generare segnali con forme d’onda a nostro piacimento, per fare ciò è sufficiente usare tre ruotine che permettono di decidere l’andamento del segnale nel tempo oppure, sempre con esse, modificare una forma d’onda precaricata in eeprom interna al Pic sovrascrivendone parte dei valori. Un bel risultato, quello che avevamo in memoria (non tutti i segnali sono ovviamente possibili creare) appare come d’incanto sullo schermo dell’oscilloscopio, è come se il segnale dalla forma strana fosse passato dalla nostra mente allo strumento. E’ ovvio che tale progetto non ha una grande utilità se non a livello didattico, però è molto divertente generare forme d’onda che la natura non si sognerebbe mai di creare.

IL CONVERTITORE DIGITALE ANALOGICO

Ho deciso di costruirmi uno dei convertitori più semplici e funzionali, una manciata di resistenze ed un operazionale sono sufficienti per farlo funzionare, lo schema del convertire è raffigurato in fig.1.

Un vantaggio di questo convertitore è che esso fa uso di resistenze di solo due valori (uno doppio dell’altro) il che semplifica molto la vita al progettista, io ho scelto 1K e 2K ma valori diversi vanno bene lo stesso a patto di non scendere troppo per non caricare il Pic e di non salire altrettanto per evitare di avvicinarsi troppo alla resistenza d’ingresso dell’operazionale che potrebbe falsare i valori convertiti.

1.JPG

Fig.1

Il funzionamento è il seguente: ad un ogni valore binario presente sugli ingressi b1…b7 corrisponde una tensione all’uscita dell’operazionale, questo ci fa intendere che se fornissimo in maniera sequenziale questi dati numerici al convertitore potremmo ottenere segnali con forme d’onda qualsiasi variabili nel tempo, ed è proprio quello che fa questo sistema, il processore invia al convertitore ciò che noi gli abbiamo preparato in anticipo con il programma, vedremo poi i particolari, per il momento è sufficiente sapere che ad ogni numero binario corrisponde, in maniera univoca, una di tensione analogica del tipo:

                                                                                   [1]

                                                                                      [2]

                                                                                           [3]

E così via.

Ora, seppur gli esempi [1], [2] e [3] riportino valori esatti dobbiamo determinare la relazione che lega il numero binario alla tensione analogica. Per fare ciò occorre semplificare un po’ il circuito di fig1 immaginando che il convertitore sia a 3 bit anziché ad 8 come in fig.2.

2.JPG

Fig.2

Per avere una formula che leghi l’ingresso con l’uscita bisogna mandare alto (Vin) un bit alla volta tenendo gli altri due a zero e applicando alla fine il principio della sovrapposizione degli effetti per avere la relazione complessiva. Iniziamo con mandare alto il bit zero (b0) tenendo gli altri due a zero questa situazione è rappresentata in fig.3.

3.JPG

Fig.3

Si tenda conto che la Vin è uguale per tutti i bit (nel nostro caso, come nella maggior parte dei circuiti digitali, è 5V, ma per la dimostrazione il valore non conta) e che Vout è la tensione analogica di uscita (l’operazionale ha guadagno unitario) inoltre in figura si nota che i bit che sono a zero corrispondono ad una massa.

Il gruppo Vin R6 ed R16 può essere trasformato in un generatore ed una resistenza equivalente di valore:

                                                                                            [4]

Ovvero la tensione vista da R15 verso il generatore è la metà di Vin (R6 ed R16 hanno lo stesso valore).

                                                                                  [5]

Ovvero la resistenza vista da R15 verso il generatore è la metà di una delle due resistenze R6 ed R16 (parallelo di due resistenze di stesso valore).

La nuova situazione è rappresentata in fig.4.

4.JPG

Fig.4

Il gruppo Vin/2, Requivalente, R15 ed R5 può essere trasformato in un generatore ed in una resistenza equivalente di valore:

                                                                                        [6]

Ovvero la tensione vista da R14 verso il generatore è la metà di Vin/2 (partizione della serie R15 Requivalente   con R5).

                           [7]

Ovvero la resistenza vista da R14 verso il generatore è il parallelo della serie Requivalente R15 con R5 (che risulta essere metà di R5).

La nuova situazione è raffigurata in fig.5.

5.JPG

Fig.5

Il gruppo Vin/4, Requivalente_1, R14 ed R4 può essere trasformato in un generatore ed in una resistenza equivalente di valore:

                                                                                        [8]

Ovvero la tensione vista dal ramo Vout verso il generatore è la metà di Vin/4  (partizione della serie R14  Requivalente_1   con R4).

La tensione Vout per b0 = Vin sarà pari quindi a Vin/8, eseguendo lo stesso procedimento per b1 e b2 e applicando il principio della sovrapposizione degli effetti otterremo:

                                                                                  [10]

Che si può trasformare, mettendo in comune Vin  ed 8 in:

         [11]

Ma la quantità in parentesi rappresenta il peso di un numero binario, abbiamo quindi ricavato la relazione che cercavamo, in generale:

                           [12]

Dove N indica il numero delle cifre binarie, che nel nostro esempio è pari a 3 e b2, b1 e b0 sono le cifre binarie che possono assumere due stati, zero ed uno.

Per un numero binario a 8 cifre (1 byte) la relazione sarà:

                                    [13]

Quindi con Vin pari a 5 volt il valore di tensione più piccolo (lo step) che può essere convertito (cifra binaria = 00000001) è:

                                                                                                                                              [14]

Quello più grande (full scala) corrispondente al numero binario 11111111 è:

     [15]

Il convertitore che ho costruito è rappresentato in fig 6, le resistenze più sono precise e più lo è il convertitore, io ne ho usate all’1%. Per quanto riguarda l’operazionale è bene sceglierne uno a basso offset in uscita (del tipo per strumentazione), in ogni caso deve funzionare a tensione singola.

20150324_154422.jpg

PROGRAMMA

Il nostro programma non deve fare altro che scrivere nella memoria eeprom del Pic i valori dei livelli della forma d’onda che si vuole generare e poi mandarli in uscita (porta B) verso il convertitore. La capienza della memoria della PIC16f876 è si 256 byte più che sufficienti per generare segnali periodici piuttosto continui, solo se si amplifica di una certa quantità la scala dei livelli e si allarga quella dei tempi dell’oscilloscopio si notano i gradini della conversione che peraltro potrebbero essere attenuati di molto facendo transitare il segnale attraverso un filtro (cosa che non ho implementato io nel circuito convertitore).

Alla fine del processo di scrittura nella eeprom in ogni cella di memoria risulterà esserci un valore numerico del livello del segnale, subito dopo il programma inizierà a leggere il valore memorizzato dall’indirizzo 0 e lo metterà in uscita per poi incrementare l’indirizzo e fare la stessa cosa  fino al’ultima locazione (256), dopo di che ricomincerà il ciclo azzerando l’indirizzo.

Ci sarà quindi un flusso di dati dal Pic al convertitore che data la loro velocità creeranno un’onda continua, visualizzabile sullo schermo di un oscilloscopio, con andamento periodico.

Si tenga conto che con il processore che ho usato io corredato di un quarzo da 4MHz la massima frequenza ottenibile con segnale sinusoidale è di 300 Hz (generando segnali più complessi può aumentare).

Iniziamo ora ad analizzare le routine che memorizzano il segnale in memoria, la prima che descrivo permette di scrivere solo livelli continui fig. 6.

Fig.6

Il valore immesso nel registro INDIRIZZO_INIZIALE indica l’indirizzo della prima cella di memoria, Il valore immesso nel registro INDIRIZZO_FINALE indica l’indirizzo dell’ultima cella di memoria, Il valore immesso nel registro VALORE (ho poca fantasia J) indica il valore che si vuole scrivere nelle celle indirizzate. Alla fine di queste poche istruzioni c’è la chiamata alla routine di scrittura vera e propria LIVELLO.

Le restanti due routine contengono le stesse istruzioni con le stesse funzioni  di quella appena vista, l’unica cosa che cambia è la chiamata alla routine di scrittura vera e propria che è rispettivamente RAMPA_CRESCENTE e RAMPA_DECRESCENTE, la prima scrive in memoria un livello crescente la seconda un livello decrescente, fig.7 e fig.8.

Fig.7

Fig.8

ESEMPIO

Voglio creare una forma d’onda periodica con il primo semiperiodo triangolare ed il secondo quadrato.

La prima cosa che dobbiamo fare è disegnarla su un pezzo di carta,sulle ordinate scrivo gli indirizzi della eeprom (in decimale che è più umano), ed in ascisse i valori dei livelli (sempre in decimale) fig.9.

Scan.jpg

Fig.9

Il periodo dell’onda è compreso tra l’indirizzo 0 e l’indirizzo 255 e i livelli possono andare da 0 (0V) a 256 (5V), decido che le due semionde giacciano a metà tensione ovvero su 2.5V.

Il periodo sarà diviso in 4, i primi due quarti saranno riservati all’onda triangolare ed i secondi due a quella quadrata.

 La prima semionda, cioè quella triangolare, dovrà partire da 2.5V come deciso, il valore binario (in decimale) corrispondente a quel livello occorre ricavarlo dalla [13]:

                             [16]

Quindi, il valore da immettere nel registro INDIRIZZO_INIZIALE sarà zero (prima cella), quello da immettere nel registro INDIRIZZO_FINALE sarà 32 (un ottavo di periodo) e quello da immettere nel registro VALORE sarà 128.

 La routine  RAMPA_CRESCENTE incrementerà sia l’indirizzo che il valore in maniera lineare fino all’indirizzo finale 32, il valore di tensione che assumerà il segnale alla fine del primo ciclo di scrittura (sulla punta del triangolo) sarà tante volte quanto è stato incrementato l’indirizzo sommate al valore iniziale 128, cioè:

                                                 [17]

Applicando la 13 otteniamo il valore di tensione corrispondente:

                     [18]

La routine con i valori immessi è rappresentata in fig.10.

Fig.10

Ora dobbiamo immettere i valori nella routine che si occupa di far scendere la rampa, essa partirà dal picco (2.5V) appena visto e scenderà fino all’indirizzo 95. Per non sovrascrivere l’indirizzo 32 (già occupato dal valore di picco) occorre far partire il decremento dalla locazione successiva, ovvero 33 (numeri cerchiati in fig.9).

Quindi il valore da immettere nel registro INDIRIZZO_INIZIALE sarà 33, in INDIRIZZO_FINALE 95 (vedere disegno in fig.9) e nel registro VALORE quello appena raggiunto dal picco della rampa crescente ovvero 160. La routine RAMPA_DECRESCENTE incrementerà l’indirizzo della memoria ma diminuirà il valore nel registro VALORE sempre in maniera lineare fino all’indirizzo 95. In questo punto il valore della rampa sarà i 160 raggiunti prima meno tante volte è stato incrementato l’indirizzo, cioè:

                                      [19]

                                     [20]

Il valore di tensione corrispondente a questo numero sarà:

                         [21]

La routine corrispondente è raffigurata in fig.11

Fig.11

Lascio la lettore indagare sulla restante parte del segnale che si ripete in modo analogo. Con questo circuito si possono anche generare forme sinusoidali, basta immettere i livelli corrispondenti in memoria, si tenga conto però che la massima frequenza raggiungibile è 300Hz.

Altre forme d’onda:

20150324_160959.jpg

20150324_212818.jpg

20150324_205300.jpg

20150324_214618.jpg

 

 

Programma

Fabio

HOME