Tesina esame di stato 2015 TASTIERA ELETTRONICA CONTROLLATA DA UN MICROPROCESSORE Marchi Michele, Sidibe David 5aeln Indice Descrizione progetto pag. 1 Schema a blocchi pag. 2 Schema elettrico pag. 3 o Micro dsPIC33FJ128MC706A pag. 4 o Alimentazione pag. 6 o Pulsanti pag. 6 o DAC MCP4822 pag. 7 Amplificatore LM386 pag. 10 Software pag. 10 Conclusioni pag. 14 Descrizione progetto Il nostro obiettivo era quello di realizzare una tastiera elettronica controllata da un microprocessore e composta da due ottave, più precisamente la quarta e la quinta. Un'ottava è un intervallo di 8 note (do, re, mi, fa, sol, la, si, do) più 5 semitoni (diesis), posizionate a diverse frequenze nella scala musicale. Nel nostro caso, per motivi di spazio, abbiamo dovuto tralasciare l’ ultimo Do di entrambe le ottave, in modo da ottenere 7 note e 5 semitoni per ottava. La nostra risulta quindi una tastiera composta da 14 note più 10 semitoni. Per quanto riguarda le frequenze attribuite a ciascuna nota, si è stabilito che la nota La della quarta ottava corrisponda ad una frequenza di 440 Hz, mentre per calcolare la frequenza delle altre note si usa la seguente formula: fnota = 440 * 2n/12 (dove n è la distanza della nota scelta dalla nota La della quarta ottava) Se ad esempio volessimo ricavare la frequenza della nota Fa# della quarta ottava la formula risulterebbe: fnota= 440 * 2-3/12 = 369,99 Hz Di seguito uno schema riportante le frequenze delle 13 note della quarta ottava: Pag. 1 Schema a blocchi TASTI I tasti rappresentano il nostro sistema di input. Premendoli, sceglieremo quale nota verrà suonata. MICRO CONTROLLORE DAC AMPLIFI CATORE I segnali dei tasti premuti verranno acquisiti dal micro e in seguito verranno creati e rielaborati i campioni digitali della nota scelta. Conversione del segnale digitale in ingresso in un segnale analogico. Amplificazione del segnale analogico (regolazione volume). Le casse (speakers) emetteranno le note scelte. Pag. 2 Schema elettrico Pag. 3 Micro dsPIC33FJ128MC706A 3.3V D3 1N4148 SMD R26 10K R27 JP1 C25 .1uF 1 2 3 4 5 3.3V 100 C26 1nF HEADER 5 39 47 48 40 RD0 RD1 RD2 RD3 RD4 RD5 RD6 RD7 RD8 RD9 RD10 RD11 46 49 50 51 52 53 54 55 42 43 44 45 PWM1L/RE0 PWM1H/RE1 PWM2L/RE2 PWM2H/RE3 PWM3L/RE4 PWM3H/RE5 PWM4L/RE6 PWM4H/RE7 C1RX/RF0 C1TX/RF1 U1RX/SDI1/RF2 U1TX/SDO1/RF3 U2RX/SDA2/CN17/RF4 U2TX/SCL2/CN18/RF5 U1RTS/SCK1/INT0/RF6 OSC1/CLKIN/RC12 PGED2/SOSCI/T4CK/CN1/RC13 PGEC2/SOSCO/T1CK/CN0/RC14 OSC2/CLKO/RC15 SCL1/RG2 SDA1/RG3 SCK2/CN8/RG6 SDI2/CN9/RG7 SDO2/CN10/RG8 SS2/CN11/RG9 OC1/RD0 OC2/RD1 OC3/RD2 OC4/RD3 OC5/IC5/CN13/RD4 OC6/IC6/CN14/RD5 OC7/CN15/RD6 OC8/UPDN/CN16/RD7 IC1/FLTA/INT1/RD8 IC2/U1CTS/FLTB/INT2/RD9 IC3/INT3/RD10 IC4/INT4/RD11 9 25 41 dsPIC33FJ128MC706A 18 17 RB7 RB6 60 61 62 63 64 1 2 3 RE0 RE1 RE2 RE3 RE4 RE5 RE6 RE7 58 59 34 33 31 32 35 RF0 RF1 RF2 RF3 RF4 RF5 RF6 37 36 4 5 6 8 RG2 RG3 RG6 RG7 RG8 RG9 Vcap/Vddcore RC12 RC13 RC14 RC15 PGED1/AN7/RB7 PGEC1/AN6/OCFA/RB6 PGED3/AN0/Vref +/CN2/RB0 PGEC3/AN1/Vref -/CN3/RB1 AN2/SS1/CN4/RB2 AN3/INDX/CN5/RB3 AN4/QEA/IC7/CN6/RB4 AN5/QEB/IC8/CN7/RB5 U2CTS/AN8/RB8 AN9/RB9 TMS/AN12/RB10 TDI/AN13/RB11 TCK/AN12/RB12 TDI/AN13/RB13 U2RTS/AN14/RB14 AN15/OCFB/CN12/RB15 Vss Vss Vss RD0 RD1 RD2 RD3 RD4 RD5 RD6 RD7 RD8 RD9 RD10 RD11 16 15 14 13 12 11 21 22 23 24 27 28 29 30 AVss RC12 RC13 RC14 RC15 RB0 RB1 RB2 RB3 RB4 RB5 RB8 RB9 RB10 RB11 RB12 RB13 RB14 RB15 20 RB0 RB1 RB2 RB3 RB4 RB5 RB8 RB9 RB10 RB11 RB12 RB13 RB14 RB15 MCLR 56 U? 7 C? .1uF 19 C? .1uF AVdd C? .1uF 10 26 38 57 C? .1uF Vdd Vdd Vdd Vdd C? .1uF PROGRAMMAZIONE E DEBUG C? 10uF Il pic da noi utilizzato necessita di una tensione di alimentazione di 3.3V, abbiamo quindi dovuto convertire i 5V tramite l' LM1117. Caratteristiche principali: Architettura Velocità CPU Tipo di memoria Memoria programmabile RAM 16-bit 40 MIPS Flash 128 KB 16,384 KB Piedini totali 64 RE0 RE1 RE2 RE3 RE4 RE5 RE6 RE7 RF0 RF1 RF2 RF3 RF4 RF5 RF6 RG2 RG3 RG6 RG7 RG8 RG9 Timers 9 x 16-bit 4 x 32-bit Comunicazione digitale periferica 2-SPI Pag. 4 Il pic che abbiamo utilizzato fa parte della famiglia dei DSC (Digital Signal Controller). I membri di tale famiglia integrano delle innovative caratteristiche riducendo contemporaneamente i consumi, e sono inoltre molto più veloci dei vecchi micro. In particolare, il nostro pic è molto veloce nelle risposte degli interrupt e offre periferiche di comando come il PWM o il watchdogs molto precise, anche se noi non le abbiamo utilizzate. I pic della famiglia DSC sono utilizzati in una vasta gamma di applicazioni, ma la maggior parte sono utilizzati per il controllo del motore, conversione di potenza e applicazioni di elaborazione di un sensore. Attualmente i DSC vengono commercializzati come le tecnologie verdi per il loro potenziale di ridurre il consumo energetico nei motori elettrici e alimentatori. La struttura dell' integrato è davvero ridotta, 12 mm x 12 mm, con un totale di 64 piedini. Date le sue piccolissime dimensioni ci siamo dovuti fornire di un adattatore per la nostra basetta a mille fori. Porte utilizzate: Abbiamo utilizzato tutti ingressi digitali per la lettura dei tasti: Da RB0 a RB5 Da RB8 a RB15 Da RD0 a RD7 RC12 e RC15 Per programmare il pic e per effettuare il debug con l’ ICD3 abbiamo utilizzato le seguenti porte: RB6 e RB7, corrispondenti a PGEC1 e PGED1 Per la comunicazione SPI con il Dac abbiamo utilizzato le seguenti porte: RF6 per il segnale del clock RF3 comunicazione SDI RE5 per il chip set RG5 per il latch del DAC Non abbiamo utilizzato l’ oscillatore al quarzo perché l oscillatore interno è sufficientemente veloce. Sul piedino MCLR abbiamo inserito un circuito di precauzione con un diodo 1N4148, una resistenza R26 e un condensatore C25. Questi componenti sono necessari per prevenire eventuali sovratensioni provenienti dal piedino 1 dello zoccolo di programmazione, che potrebbero influenzare l' alimentazione del circuito. Pag. 5 Alimentazione Per far fronte al range di funzionamento del nostro micro compreso tra 3 e 3.6V abbiamo dovuto utilizzare l' LM1117. Esso si tratta di un regolatore di tensione grazie al quale possiamo diminuire la tensione in entrata Vin, nel nostro caso 5V, ad un valore Vout a scelta tra 1.8V, 2.5V, 2.85V, 3.3V o 5V. La Vref applicata al resistore R1 è di 1.25V, come suggerito dal datasheet, e genera una corrente costante I1. In seguito la corrente I1 attraversa il resistore R2 e possiamo così, attraverso la regolazione dei due resistori impostare la Vout ad un valore desiderato. Nel nostro caso per trasformare la Vin da 5V a 3.3V abbiamo impostato R1 a 110 Ω e R2 a 180Ω. Sostituendo tali valori alla formula di seguito riportata, e tenendo presente che la Iadj è tendente a 0, si nota come Vout = 3.3: Vref (1+ Pulsanti VCC SW8 SW PUSHBUTTON R32 10K DO I segnali digitali provvenienti dall' alimentazione a 3.3V passano attraverso i tasti e successivamente su una resistenza di pull-down da 10k per garantire l' ingresso logico del pic. Il valore delle resistenze di ciascun pulsante è stato impostato a 10k poiché, anche se venissero premute più note insieme, la somma di tutte le correnti deve stare entro certi limiti per evitare il danneggiamento del micro. Pag. 6 DAC MCP4822 Cenni riguardanti i DAC: Il Digital to Analog Converter (DAC) è un componente elettronico in grado di produrre in uscita un determinato livello di tensione o di corrente, in funzione di un valore numerico al suo ingresso. Una larga diffusione ad uso domestico dei DAC si ha nei riproduttori digitali di suoni, nel controllo dell'apertura del diaframma nelle macchine fotografiche, nei controlli digitali (volume, luminosità) dei televisori e in tutte quelle situazioni nelle quali un'informazione numerica deve controllare una grandezza di tipo analogico. Una delle caratteristiche da tenere maggiormente in considerazione nei DAC è la risoluzione. Si passa dagli 8 bit (256 livelli di tensione) dei DAC più semplici (telecomandi ecc.), ai 12 bit per i controlli di precisione (strumenti di misura, multimetri, oscilloscopi), ai 16 bit per i riproduttori musicali ad alta fedeltà, fino ad arrivare al DVD, con i suoi 24 bit di risoluzione. All'aumentare della risoluzione corrisponde però un maggior numero di elaborazioni per ottenere la tensione d'uscita; in altre parole, più è elevata la risoluzione del DAC e più la sua elaborazione ne risulterà rallentata. Nel nostro caso abbiamo utilizzato il DAC MCP4822 per convertire i dati della sinusoide in uscita del pic in un segnale analogico. pag. 7 Le principali caratteristiche del nostro DAC sono: n° bit: 12 bit Vref: 2,048 V Tensione di alimentazione: 2.7 - 5.5 V INL: ± 2 LSB DNL: ± 0.2 LSB Il massimo errore di quantizzazione, secondo la seguente formula, è di circa 0.00025. dove N= Il valore dell' LSB, cioè del bit meno significativo, è di 0.5mV, ovvero il valore del quanto. L' MCP4822 presenta un errore di offset di circa ±0.02%, ossia potremmo trovare un errore di più o meno 1.024mV. Altri parametri da tenere in considerazione sono gli errori di INL e DNL. L' INL è il massimo spostamento tra la caratteristica della curva reale e quello della retta ideale, mentre il DNL è la massima variazione rispetto alla variazione ideale al cambio del bit meno significativo. L' INL e il DNL devono essere compresi tra eper garantire la monotonia della mia funzione. IL settling time, il tempo di assestamento, è un altro parametro importante e descrive il tempo necessario alla Vo per mantenersi in una frazione del valore finale. Nel nostro caso corrisponde a 4.5 µs. pag. 8 Il tipo di interfaccia che abbiamo utilizzato è la SPI (Serial Peripheral Interface). Questa connessione presenta un master, ovvero il micro, e uno o più slave, nel nostro caso solamente uno ossia il dac, collegati tra di loro attraverso 4 segnali: o SCK (Serial Clock): clock seriale che scandisce gli istanti di emissione e di lettura dei bit sulle linee di dati. È un segnale emesso dal master ed è quindi quest'ultimo a richiedere di volta in volta la trasmissione di un segnale. o SDI (Serial Data Input): linea attraverso cui il dispositivo (master o slave) riceve il dato seriale emesso dalla controparte. o SDO (Serial Data Output): linea di output di dato. o CS(Chip Select): emesso dal master per scegliere con quale dispositivo slave vuole comunicare. Il bus di dati è di tipo seriale sincrono e la trasmissione e ricezione può avvenire contemporaneamente. pag. 9 Amplificatore LM386 Questo componente è un circuito integrato con un operazionale al suo interno. All' uscita del dac c' è un condensatore di accoppiamento da 1uF per collegarsi al circuito in figura. Questo componente è stato usato per amplificare la piccola tensione che troviamo in uscita al dac. Allo schema fornito dal datasheet sono stati sostituiti vari componenti essenzialmente per una questione di disponibilità del materiale. Ad esempio è stato cambiato il condensatore sul piedino numero 8 con uno più piccolo da 1uF poiché con il valore imposto in precedenza produceva troppa distorsione. Il condensatore posto di seguito alla resistenza sul piedino 5 è stato invece sostituito da uno da 100nF mentre l' ultimo condensatore da 250uF è stato sostituito da uno da 220 uF. Software IL caricamento del software nel PIC dal PC avviene tramite un programmatore esterno, come ad esempio il Pick-it o l ICD3. L interfaccia software invece viene fornita dalla Microchip stessa: MPLAB X infatti, oltre a permettere lo sviluppo del software, offre anche la possibilità di lanciare il debug, ossia di eseguire le istruzioni una alla volta per individuare eventuali errori nel funzionamento del software. La parte principale del programma scritto in linguaggio C è su un file chiamato main. Al programma principale è stato necessario includere delle librerie di intestazione, in cui sono dichiarate le funzioni standard di input/output del C. #include #include #include <xc.h> <stdio.h> <string.h> #include #include #include <math.h> <stdbool.h> <stddef.h> pag. 10 #include #include #include #include #include #include #include <stdint.h> "Spi.h" "Rout.h" "Menu.h" "tglPin.h" "Tast.h" "Main.h" All' inizio del programma vengono impostati I vari parametri dell' oscillatore interno, nel nostro caso viene configurato a 40 MHz. La frequenza a cui opera il dispositivo è: Fcy = Sono stati poi impostati i vari bit per la configurazione di N1 del prescaler, N2 del postscaler e l' M, il moltiplicatore del PLL. Fosc = Fn , La frequenza nominale è di 7.37KHz. Per prima cosa è stata creata una funzione per la lettura dei tasti attraverso uno switch. Nel primo stato viene presupposto che nessun tasto sia premuto, successivamente invece, nel secondo stato, viene inserita un' attesa dell' antirimbalzo. A questo punto se un tasto viene premuto viene ritenuto valido. Per finire è presente la decodifica e la lettura del tasto per sapere quale tasto è stato premuto, il quale viene messo all' interno di una variabile. Sono stati poi inizializzati dei prototipi delle funzioni dei due timer: void Init_Timer6( void ); void Init_Timer8(void); CONTROLLI // TIMER A 2 ms // TIMER IN FREE RUNNING PER INTERVALLO IL PRIMO TIMER void Init_Timer6( void ) { T6CON=0; // IL TIMER viene RESETTATO IFS2bits.T6IF = 0; // viene resettato l interrupt del timer1 IPC11bits.T6IP = 2; // priorità dell' interrupt di livello 3 TMR6= 0x0000; PR6 = 40000; // periodo del registro Timer1 = 1ms IEC2bits.T6IE = 1; // Abilita interrupt del Timer6 T6CONbits.TON = 1; // Abilita il conteggio del Timer6 } pag. 11 Queste impostazioni servono per la gestione dei tempi con la comunicazione con lo slave, ovvero il dac. Il timer 8 lo abbiamo invece utilizzato per una semplice divisione tra la frequenza di del clock fissata a 40 MHz e la frequenza di campionamento fissata a 22kHz. void Init_Timer8( void ) { T8CON=0; IFS3bits.T8IF=0; TMR8= 0x0000; PR8=TIMER8LOAD; IEC3bits.T8IE = 1; T8CONbits.TON = 1; // TIMER RESET // // Abilita interrupt del Timer8 // Abilita il conteggio del Timer8 } In seguito questi interrupt vengono gestiti attraverso la SIR (service interrupt routine) in generale, l'utente deve azzerare il flag interrupt posto nell' adeguato registro IFSx per la fonte di interrupt che SIR gestisce. In caso contrario, il SIR sarà attivato di nuovo dopo l'uscita dalla routine. Quindi il SIR controlla soltanto le interruzioni del programma. Il SIR invece per l' interrupt del timer8 sostanzialmente permette di avere una struttura per le note con il valori di ogni nota e il numero di campioni. IFS3bits.T8IF = 0; tglPin(); Acc=0l; nSum=1; for(i=0; i < NUMNOTE;i++) { if (Note[i].Enabled) { k=Note[i].Index; l=Note[i].Limit; data=Note[i].Camp[k++]; if (k >=l) k=0; Note[i].Index=k; //reset timer Acc+=(long)data; nSum++; pag. 12 // Aggiunge alla variabile a sinistra il valore a destra } } data =(int) (Acc / nSum); LoadDac(data + 2047); } Da qui si è deciso che ogni singola nota avrà un numero massimo di 200 campioni e la frequenza di campionamento per rispettare il teorema di Shennon è stata fissata a 22Khz, cioè almeno il doppio della F massima. Poi è stata inizializzata la tabella per le note attraverso un ciclo for in cui viene fatta una semplice divisione tra la frequenza di campionamento e la frequenza di ogni singola nota. Così abbiamo trovato i campioni per ogni nota. Viene creato poi l' angolo di 2π pari a 360° comprendente il primo semicerchio positivo e il secondo semicerchio negativo. Adesso c' è un piccolo step riguardante l'angolo: viene fatta una semplice divisione tra l'angolo giro completo e i campioni trovati prima per ogni nota. Successivamente viene controllato se il numero di campioni per nota non supera il numero 200, precedentemente fissato per il numero massimo di campioni, così attraverso un altro ciclo for inizio a ricostruire i vari valori della sinusoide che voglio comporre per le varie note. È da ricordare che il dac è a 12 bit quindi ho 4096 livelli possibili da assumere per la sinusoide. Quindi vengono utilizzati 2048 valori per la parte positiva e 2048 per la parte negativa. for (i=0;i < NUMNOTE;i++) { Nstep=(int) (((float) FCAMP / (float)tabNote[i]) + 0.5 ); // CAMPIONI PER NOTA StepAngolo=(2.0 * pi) / (float) Nstep; //360°/campioni Angolo=0; if ( Nstep < STEPNOTE) { for (k=0; k < Nstep;k++) { tmp=(float) MAXDAC * sin(Angolo); Note[i].Camp[k]=(int) tmp; Angolo+=StepAngolo; // Aggiunge alla variabile a sinistra il valore a destra } Note[i].Limit=Nstep; Note[i].Index=0; Note[i].Enabled=false; } } } pag. 13 CONCLUSIONI La scheda realizzata funziona correttamente ed è stata testata per quanto riguarda gli ingressi digitali e l' uscita del dac. Il pic inoltre è stato correttamente programmato con l' ICD3 . Durante l esperienza sono emerse alcune difficoltà riguardanti le resistenze di pulldown che hanno un maggior consumo di corrente. Ma tutto sommato sono la stessa cosa per questo tipo di applicazioni. Inoltre sono state apportate alcune modifiche esterne riguardanti la tensione di alimentazione per i tasti. Inizialmente erano stati portati due fili esterni attraverso un header, in seguito però per motivi di spazio sono stati spostati attraverso un bus di cavi. pag. 14