• Non ci sono risultati.

Scopo del lavoro di tesi è mostrare se sia possibile realizzare un lettore RFID UHF Gen279 utilizzando dispositivi a basso costo e a bassa potenza. Fare riferimento al capitolo 2 per la descrizione e la terminologia dello standard. Essendo un lettore a bassa potenza è pensato per leggere i tag a qualche centimetro di distanza e quindi tale lettore comunica con un tag alla volta. Per raggiungere lo scopo si è tentata l’implementazione dei comandi di Query ed Ack e la ricezione delle risposte del tag a questi comandi. Questa coppia di comandi è fondamentale in quanto permette di ottenere l’EPC del tag interrogato e la loro implementazione è sufficiente a comprendere se il dispositivo possa essere utilizzato o meno come lettore RFID UHF Gen2. Per la realizzazione del lettore è stata selezionata una coppia di schede di sviluppo EM430F6137RF90080 su ciascuna delle quali sono presenti, oltre al microcontrollore CC430F613781, varie porte collegate ai pin del microcontrollore, un connettore per un antenna a 50Ω collegato all'ingresso\uscita RF del microcontrollore e la porta per programmare il microcontrollore ed eseguirne il debug tramite JTAG. È stato utilizzato il debugger MSP-FET 430 UIF82. L’ambiente di sviluppo utilizzato è Code Compose Studio versione 6, il quale offre tutti gli strumenti necessari per programmare il microcontrollore ed eseguire il debug del programma caricato.

79 Vedere il capitolo 2 per la descrizione dello standard 80 http://www.ti.com/tool/em430f6137rf900

81 Vedere capitolo 3 per i successivi riferimenti al microcontollore ad elle sue caratteristiche 82 http://www.ti.com/tool/msp-fet430uif

Come punto di partenza per l’implementazione dello standard la prima operazione che si è tentato di realizzare è stata la trasmissione di un comando di Query. Tale comando è fondamentale in quanto avvia l’inventory round (durante il quale è possibile interrogare i tag ottenendone l’EPC ed accedere alla loro memoria) e stabilisce il formato della risposta dei tag durante tutto l’inventory round. Nella implementazione del comando si è scelto di utilizzare parametri tali rendere il meno oneroso possibile il carico di lavoro del microcontrollore e tali da massimizzare il valore dei tempi massimi che devono essere rispettati. Ci si è dunque posti nella condizione più semplice. È infatti necessario in tale ambito avere un controllo sui tempi di esecuzione in quanto lo standard prevede tempistiche con valori massimi che devono essere rispettate. Un esempio è il comando di Ack che, nella modalità più semplice, deve essere trasmesso al tag entro 250μs dalla trasmissione della risposta ad un comando di Query. Come previsto dallo standard, il lettore utilizza in trasmissione la codifica PIE83 ed una modulazione di ampiezza a due livelli ASK.

Per implementare il comando di Query si è utilizzato:

• TARI=25μs

• PW=TARI/2=12,5μs • RTcal=3 TARI

• TRcal=3 RTcal=9 TARI • Data-0=1 TARI

• Data-1=2 TARI

Con tali scelte è possibile utilizzare in trasmissione un quanto temporale di durata PW=TARI/2=12,5 in quanto tutti gli altri intervalli temporali sono esprimibili come multipli di questa quantità. Si è poi analizzato il microcontrollore al fine di comprendere cosa si potesse realizzare utilizzando le sue risorse hardware e cosa invece si dovesse realizzare a livello firmware.

• Per la trasmissione è stata impostata una frequenza portante pari a 865,7Mhz.

• Si è impostato un data-rate in trasmissione di 80 Kbit/s che è l'inverso del periodo di ciascun bit trasmesso (12,5μs).

• La modulazione di ampiezza è realizzata dal modulo RF del microcontrollore. Si è selezionata una modulazione a 2 livelli trasmettendo una potenza pari a 12 dBm (~15,85mW) per il livello alto e -6dBm (~0,25mW) per quello basso. Profondità di modulazione pari a ~84% e >80% come richiesto dallo standard.

• Molte funzionalità offerte dal gestore di pacchetti presente nel microcontrollore sono state disabilitate perché non utili allo scopo e perché per utilizzare a pieno il gestore di pacchetti è necessario conoscere a priori il numero di byte da trasmettere e ciò in questo ambito non accade. Si è dunque selezionata la modalità “infinite packet length”. Quando la trasmissione viene avviata inizia la trasmissione dei dati all’interno della TXFIFO di lunghezza pari a 64byte a partire dal bit più significativo del primo byte occupato. Per continuare la trasmissione è necessario riempire in corsa la FIFO. Se la FIFO si svuota il trasmettitore si spegne e va in stato di TX_UNDERFLOW, ed il tempo necessario per uscire da tale stato e trasmettere nuovamente è dell’ordine dei 500μs. Per cui è necessario che il trasmettitore abbia continuamente disponibili dati da trasmettere nella FIFO durante un intero inventory round avviato con il comando di Query. Per terminare l’inventory round è sufficiente lasciare che la FIFO si svuoti e quindi che il trasmettitore vada in underflow spegnendosi. • Essendo 12,5μs il quanto temporale utilizzato si è impostato un data rate in trasmissione pari

a 80kbit.

• La codifica PIE non è fornita dal microcontrollore e quindi è stato necessario implementarla in software tramite funzioni che convertono i bit non codificati in bit codificati PIE da inserire nella FIFO per essere trasmessi.

• Il calcolo del CRC5-EPC è stato realizzato in software in quanto il microcontrollore dispone di un modulo per calcolare unicamente il CRC-16.

Per comprendere meglio come è stato implementato il comando di Query è utile analizzare la funzione Query_setting. In funzione dei paramentri del comando di Query passati come argomenti salva in un buffer i dati codificati PIE pronti per essere caricati nella TXFIFO e quindi inviati. Per come è stato configurato il trasmettitore singolo bit trasmesso ha una durata pari a 12,5μs. Per comprendere il funzionamento della funzione vediamone un estratto:

void Query_setting (unsigned char DR, unsigned char M, unsigned char TRext,

unsigned char sel, unsigned char session, unsigned char target, unsigned char Q,

unsigned char Buf[]){

[...]

if(TRext==0){ //0

zero(&command, querybit);

querybit--;

send_zero(&j,bitBuffer);

}

if(TRext==1){ //1

one(&command, querybit);

querybit--;

send_one(&j,bitBuffer);

[...]

CRC=CRC5EPC(command);

for(i=0;i<5;i++){

//if(CRC&(0b00000001<<i)) send_one(&j,bitBuffer);

if(BIT(CRC,i)) send_one(&j,bitBuffer);

else send_zero(&j,bitBuffer);

}

[...] }

Il codice mostra il modo in cui la funzione query_setting elabora il parametro TRext ed è esemplificativo del modo in cui essa elabora di tutti i parametri del comando Query. Per ogni parametro vengono gestite caso per caso le operazioni da intraprendere in base al valore che esso assume. Command è la stringa di bit che verrà successivamente elaborata dalla funzione CRC5EPC in modo da ottenere il CRC-5 EPC da trasmettere in coda al comando. Command contiene, a partire dal bit più significativo, il codice del comando Query e i bit corrispondenti ai parametri scelti che vengono inseriti in command, con il progredire dell'elaborazione, in forma non codificata. Le funzioni one e zero nel codice precedente inseriscono rispettivamente un uno o uno zero in command alla posizione querybit. Quest'ultima punta alla posizione in cui inserire il successivo bit e viene decrementata di uno ogni volta ne viene inserito uno. Altra operazione che viene eseguita elaborando i parametri è la codifica dei bit di inviare. Ciò avviene tramite la funzioni send_one e send_zero. Esse inseriscono rispettivamente in bitBuffer, che contiene i bit del comando Query in forma codificata, le stringhe di bit corrispondenti ad un uno ed ad uno zero secondo la codifica PIE. L'indice j passato alle due funzioni per indirizzo punta dove inserire il successivo bit in bitBuffer. In particolare per le scelte fatte riguardo sia i valori utilizzati per la codifica PIE che il bit-rate selezionato per il trasmettitore si ha che la trasmissione di un uno è codificata come 1110 e quella di uno zero come 10. Di conseguenza l'inserzione di uno zero codificato comporta un incremento pari a 2 dell'indice j e l'inserzione di un uno codificato comporta invece un incremento di 4 dell'indice j. Configurato in tal modo il trasmettitore si è realizzato un primo firmware per testare se le scelte fatte andassero nella direzione corretta. Il microcontrollore programmato con tale firmware esegue l’invio di un comando di Query alternato con un’onda continua a ciclo continuo. Lo standard prevede che dal momento in cui inizia la trasmissione debba essere trasmessa una portante non modulata per almeno 1500μs, in modo che il Tag si accenda, prima di trasmettere un comando. Dopo la trasmissione di un comando di Query è necessario trasmettere un onda continua per il tempo massimo necessario al tag per terminare di trasmettere la risposta. Il controllo su tali tempi lo si attua considerando che per trasmettere un byte nella FIFO sono necessari 100μs, in quanto la trasmissione di ogni bit impiega 12,5μs. Inoltre è possibile misurare il tempo trascorso tramite polling del numero di byte presenti nella FIFO. Utilizzando un tag avente accessibili i terminali di uscita del demodulatore di ampiezza, si è potuto osservare con un oscilloscopio il comando trasmesso dal trasmettitore e le risposta inviata dal tag.

Testato il corretto funzionamento della trasmissione si è iniziato a pensare come eseguire la ricezione. Il formato della risposta da ricevere dipende dai parametri scelti per il comando di Query ed in particolare si è scelto:

• DR=8

• M=1, quindi si è selezionata la codifica FM0 per la risposta del tag • TRext=1 quindi si è attivato il pilot tone per la risposta del tag

• Sel=All, Session=S0, Target=A in modo che qualsiasi tag che riceve il comando di Query partecipi all’inventory round

• Q=0 in quanto essendo un lettore a bassa potenza non è concepito per interrogare più di un tag alla volta

Per testare la ricezione della risposta da parte del microcontrollore configurato come ricevitore si è realizzato un firmware che configura in tal modo il ricevitore:

• Portante del segnale ricevuto 865,7 Mhz • Banda del filtro di canale 200KHz

• Demodulatore configurato per demodulare un segnale modulato in ampiezza ASK • RXFIFO disabilitata

Illustrazione 28: L’immagine mostra il comando di Query (riquadro rosso) e la risposta del tag (riquadro blu) visualizzate con l'oscilloscopio

• Uscita del demodulatore collegata ad una porta della scheda di sviluppo in modo da poter essere osservata con un oscilloscopio.

In una prima fase l’interesse è stato posto sull’aspetto fisico della ricezione, cioè sulla ricezione e demodulazione del segnale. Successivamente poi si è trattato l’aspetto logico della ricezione, cioè l'estrazione del flusso di bit dal segnale demodulato.

Per gestire l’aspetto fisico della ricezione è stato analizzato il data sheet del microcontrollore, ed in particolare la parte riguardante i registri di controllo della modulo RF configurato come ricevitore. La ricezione fin da subito si è mostrata più ostica da gestire della trasmissione. Sono stati compiuti numerosi test per comprendere quali registri di controllo influissero maggiormente sulla qualità della ricezione in modo da ottimizzare la qualità di ricezione.

I due valori più importanti trovati sono:

• FILTER_LENGTH nel registro AGCTRL0, • CLOSE_IN_RX nel registro FIFO_THR

FILTER_LENGTH stabilisce il confine per decidere se si stia ricevendo un uno o uno zero utilizzando la modulazione ASK. Stabilisce la minima differenza in dB tra due livelli di ampiezza del segnale perché il decisore stabilisca cosa sia un 1 e cosa sia uno 0. Per il corretto funzionamento è stato selezionato il minimo valore possibile pari a 4db. Per i valori più elevati si è visto come non è possibile ricevere la risposta del tag.

CLOSE_IN_RX introduce un’attenuazione in ricezione ed il massimo valore possibile pari a 18dB si è dimostrato quello che maggiormente migliora la qualità di ricezione.

Si è ipotizzato che l’elevata sensibilità in ricezione alle variazioni di questi valori sia causata principalmente dal fatto che trasmettitore e ricevitore operino in una situazione atipica rispetto a quella per cui sono stati progettati.

Infatti i microcontrollori CC430 sono stati progettati per operare nelle seguenti condizioni:

• Distanza trasmettitore e ricevitore sull’ordine dei metri in quanto il ricevitore ha un’elevata sensibilità circa -110dBm e satura per una potenza molto bassa di circa -15dBm.

Introducendo un’attenuazione di 18 dB (massima possibile) e modificando il valore di default di CLOSE_IN_RX, è possibile aumentare il limite di saturazione a discapito della sensibilità ottenendo una sensibilità di -75dBm ed una saturazione di circa +5dBm.

• Il ricevitore riceve direttamente ciò che trasmette il trasmettitore

Qua nessuna delle due condizioni è soddisfatta infatti:

• Ciò che ci interessa ricevere è il segnale backscatterato dal tag e non il comando trasmesso. • A causa della bassa potenza di trasmissione è necessario che il trasmettitore sia ad una

distanza di una decina di centimetri al massimo dal tag perché gli fornisca sufficiente energia

• Il segnale backscatterato dal tag arriva al ricevitore sommandosi all’onda continua emessa dal trasmettitore e complessivamente origina un segnale ricevuto con una bassa profondità di modulazione. È quindi necessario tenere tag e ricevitore ad una distanza massima di qualche centimetro perché venga ricevuta la risposta del tag

• Come conseguenza dei due punti precedenti ricevitore e trasmettitore si trovano ad una distanza massima di 15-20cm.

Da ciò si è ipotizzato come le difficoltà in ricezione siano da ascriversi alla bassa profondità di modulazione della risposta del tag unita al fatto che il ricevitore opera sempre vicino al limite di saturazione. Utilizzando i valori ottimi trovati per i registri di controllo si riesce a ricevere la risposta del tag entro i 10 cm di distanza tra ricevitore e tag seppur con un qualità di ricezione influenzata da posizione e da orientamento del tag. L’entità di questo problema è stata ridotta ma non eliminata con la scelta ottima dei valori dei registri di controllo. Per quanto riguarda il livello logico della ricezione, cioè le operazioni effettuate dopo la demodulazione del segnale ricevuto, si è considerato quale fosse il formato della risposta del tag. In base al preamble ed ai parametri del comando di Query, la risposta del tag ha questo formato:

• Codifica FM0 (M=1)

• Pilot tone abilitato (TRext=1) • DR (Divide Ratio)=8

• Tari=25μs • RTcal=3*TARI

• Symbol rate ~39,5Kbaud

Dato che la codifica FM0 prevede sempre una transizione tra un simbolo ed il successivo ed una transizione a metà simbolo quando si trasmette uno zero si è impostato come data rate del ricevitore il doppio del symbol rate, quindi pari a 79Kbaud. Tra i valori selezionabili con il microcontrollore scelto è stato utilizzato il più vicino pari a 78,949Kbaud. Configurato il data-rate del ricevitore, si è deciso, per gli stessi motivi della trasmissione, di non utilizzare il gestore di pacchetti offerto dal microcontrollore. Il ricevitore così configurato si limita ad interpretare il segnale demodulato in base al data rate selezionato ed a salvare i dati ottenuti un byte alla volta all’interno della RXFIFO costituita 64 byte. Configurato così il ricevitore, si è scritto un firmware per il ricevitore il quale all’avvio apre subito la ricezione. Esso analizza continuamente i dati ricevuti ed appena riconosce l’inizio del preambolo della risposta del tag salva i dati successivi ricevuti in un buffer per un tempo sufficientemente lungo da ricevere tutta la risposta del tag. Analizzando il contenuto del buffer si è notato come il ricevitore così configurato già nel riconoscimento del preambolo della risposta compie errori nella corretta interpretazione del segnale. Si è osservato come ad esempio la violazione v nel preambolo, che dovrebbe essere interpretata come tre bit consecutivi pari a zero viene invece interpretata come una sequenza di quattro zeri. A causa di questo si è ipotizzato che il ricevitore ricevesse con un data-rate troppo elevato, pur essendo il data-rate selezionato in linea con la risposta del tag visualizzata sull’oscilloscopio. Sulla base di questa ipotesi si è abbassato il data rate del ricevitore per osservare se in tal modo ci fosse un miglioramento dell’interpretazione del segnale ricevuto. Per cercare il valore ottimo del data rate si è collegato al lettore un tag operante in condotta e non in aria in modo tale che la ricezione non fosse influenzata da distanza ed orientamento del tag ed eventuali disturbi esterni a radio frequenza. Ciò ha permesso di misurare le prestazioni del lettore al variare del data rate del ricevitore mantenendo stabili le condizioni operative. A partire dall'iniziale data rate pari a 79Kbaud, per il quale si è impostato il data rate ad esso più vicino tra quelli selezionabili pari a 78,949Kbaud, sono state misurate le prestazioni del lettore per data rate di ricezione inferiori riducendo questi ultimi da una misura alla successiva di una quantità corrispondente ad un incremento del periodo di bit pari a 0,125μs. Per ciascuna misura è stato impostato il data rate più prossimo a quello voluto tra quelli impostabili. Sono stati ottenuti i seguenti risultati:

La tabella precedente mostra, al variare del data rate, la percentuale di letture corrette eseguite dell'EPC del tag da parte del lettore. Il valore ottimo del data rate impostato è pari a 72,403 Kbaud per il quale si ottiene il 98,72% di letture corrette. Tale valore è inferiore di 6,546Kbaud (-8,34%) rispetto al valore nominalmente corretto di 78,949 Kbaud. Tale scostamento è di non piccola entità e l’ipotesi fatta che ci ha permesso di trovare una soluzione al problema implicherebbe un grosso scostamento tra il valore effettivo del data rate e quello impostato. Ciò è plausibile anche se improbabile e tale questione meriterebbe ulteriore approfondimento. Una volta ricevuta correttamente la risposta del tag, è necessario estrarre dal flusso di bit ricevuti le informazioni di interesse. Per fare ciò è necessario:

1. Riconoscere il preambolo della risposta del tag in modo che sia noto il bit ricevuto dal quale comincia il contenuto informativo.

2. Eseguire la decodifica FM0 a partire dal bit trovato al punto 1 ricavando i dati di interesse.

La parte del preambolo che si ricerca è quella che viene dopo il pilot tone. Quest'ultimo è pensato per aiutare il ricevitore a sincronizzare il proprio bit rate con quello del segnale ricevuto e non come sequenza da riconoscere.

Da notare che il segnale ricevuto può essere interpretato dal demodulatore in forma diritta oppure in forma rovesciata. Nel secondo caso il segnale ricevuto demodulato osservato sull’oscilloscopio risulta esattamente rovesciato rispetto ciò che ci si aspetterebbe di ricevere, con uno al posto di zero e zero al posto di uno. La causa è probabilmente da ricercarsi nel funzionamento del decisore per la demodulazione di ampiezza integrato sul microcontrollore e del quale però non sono disponibili informazioni sufficienti per comprendere questo fenomeno. Per ovviare al problema è stato implementato il riconoscimento di sequenza del preambolo sia in forma dritta che rovesciata. Vi

Data rate desiderato (Kbaud) Data rate selezionato (Kbaud) Letture corrette

79,000 12,658 78,949 11,23% 78,229 12,783 78,156 15,42% 77,471 12,908 77,560 23,64% 76,728 13,033 76,767 37,39% 75,999 13,158 75,974 54,25% 75,284 13,283 75,378 73,94% 74,582 13,408 74,585 86,31% 73,893 13,533 73,99 95,86% 73,217 13,658 73,196 97,27% 72,553 13,783 72,403 98,72% 71,901 13,908 71,808 96,83% 71,261 14,033 71,213 84,46% 70,631 14,158 70,618 71,98% 70,013 14,283 70,023 48,21% 69,406 14,408 69,428 32,82%

sono due contatori, uno per ciascun tipo di sequenza, e quando uno dei contatori raggiunge un dato valore significa che il preambolo è stato trovato e si esce dal ciclo di ricerca del preambolo. La funzione cerca_RN16, mostrata di seguito, ha lo scopo di riconoscere il preambolo all'interno flusso di bit ricevuti e quindi restituire l'indice del bit a partire dal quale inizia l'RN16 in forma codificata. unsigned long int cerca_RN16 (unsigned int numero_byte){

[...] //ricerco preamble while(1){ while(RXFIFO_bytes()<1); data=ReadSingleReg(RXFIFO); for(j=0;j<8;j++){

if(logic_XOR(((data<<j)&(0b10000000)), preambleBuf[counter])) counter=0; else {

counter++; }

if(logic_XOR(((data<<j)&(0b10000000)), invpreambleBuf[counterinv])) counterinv=0; else { counterinv++; } if(counter>=12) { RN16_found=1; goto RN16; } if(counterinv>=12) { RN16_found=1; goto RN16; }

if(j==7) counter_byte++; //Se conclusa analisi di un byte if(counter_byte>numero_byte) goto RN16;

} }

RN16:

//Mi sposto in avanti di una posizione nella posizione in cui inizia l'RN16 all'interno //dell'ultimo byte analizzato

if(j<7) j++;

posizione_RN16= (unsigned long int) ((data<<8)|j); //Inserisco nella parte bassa posizione bit dell'attuale dato da cui iniziare decodifica se j=0 significa che la lettura dell'attuale byte era conclusa e si comincierà dalla successiva

posizione_RN16&=0x0000FFFF;

if(RN16_found==1) posizione_RN16|=(unsigned long int)(((unsigned long int)(RN16_found))<<16); //Metto ad 1 il LSB dei 16 MSB di posizione RN16 in modo da segnalare che è stato trovato RN16 return posizione_RN16;

}

La ricerca del preamble viene compiuta all'interno di un ciclo da cui si esce solo quando il preamble è stato riconosciuto. Tramite la funzione RXFIFO_bytes, che restituisce i bytes presenti nella

Documenti correlati