SlideShare a Scribd company logo
0
POLITECNICO DI TORINO
A.A. 2016/2017
Corso di Progettazione di dispositivi
biomedici programmabili
Misuratore della frequenza respiratoria (RR)
basato su NTC
Gruppo 5, LED 7, Tavolo 5
Marta Boscaglia s242462, responsabile progettazione software
Alessio Brondino s242491, responsabile documentazione
Stefano Gabetti s235287, responsabile progettazione hardware
Gabriele Giordano s242511, responsabile progettazione integrata
1
Indice
1. Specifiche di progetto................................................................................................................................ 2
1.1 Opzioni migliorative................................................................................................................................ 2
1.2 Prove di verifica ...................................................................................................................................... 2
2. Schema elettrico ........................................................................................................................................ 4
3. Calcoli di progetto ..................................................................................................................................... 6
3.1 Stima della massima corrente assorbita dal circuito................................................................................ 6
3.2 Dimensionamento del resistore di caduta del led .................................................................................... 6
3.3 Dimensionamento dei resistori di caduta dei led dei display a sette segmenti........................................ 6
3.4 Circuito di condizionamento del sensore NTC........................................................................................ 6
4. Descrizione del Software........................................................................................................................... 8
4.1 Diagramma a blocchi............................................................................................................................... 9
4.2 Flow-chart delle singole routine............................................................................................................ 10
5. Listato completo del codice..................................................................................................................... 17
6. Documentazione delle prove di verifica.................................................................................................. 37
6.1 Verifica del sistema di allarme per la tensione di alimentazione .......................................................... 37
6.2 Verifica della temporizzazione della verifica della tensione di alimentazione ..................................... 38
6.3 Verifica della massima corrente assorbita............................................................................................. 39
6.4 Verifica dell’accuratezza degli estremi di misura ................................................................................. 40
6.5 Verifica del funzionamento del sistema di acquisizione ed elaborazione del segnale e di pilotaggio dei
display ......................................................................................................................................................... 41
6.6 Verifica del funzionamento del deviatore e della misura della frequenza............................................. 42
6.7 Verifica del funzionamento complessivo del dispositivo...................................................................... 44
Appendice A: algoritmo di ricerca del periodo ............................................................................................... 45
2
1.Specifiche di progetto
 Tensione di alimentazione: Val = 5 V ± 150 mV;
 Massima corrente assorbita: Ialmax = 400 mA;
 Verifica della tensione di alimentazione a intervalli di circa 1 s e sistema di allarme con led
rosso:
 Se Val > 4,2 V ± 150 mV led spento
 Se Val < 4,2 V ± 150 mV led acceso fisso
 Misurazione del periodo respiratorio (s) mediante sensore NTC posto al di sotto delle narici;
 Misurazione fornita in uscita su tre display a sette segmenti;
 Frequenza di campionamento 20 Hz, durata dei brani di segnale 12 s;
 Risoluzione 100 ms;
 Accuratezza 300 ms;
 I display permettono di visualizzare valori di periodo respiratorio compresi tra 1 s ± 0,1 s e 8
s ± 0,3 s, valori al di fuori di questo intervallo comportano la visualizzazione sui display del
messaggio d’allarme “888”;
1.1 Opzioni migliorative
 Verifica della tensione di alimentazione con sistema di allarme a due soglie:
 Se Val > 4,8 V ± 150 mV led spento
 Se 4,8 V ± 150 mV > Val > 4,2 V ± 150 mV led lampeggiante
 Se Val > 4,2 V ± 150 mV led acceso fisso
 Possibilità di inserire un dip-switch per visualizzare sui display in alternativa periodo
respiratorio (s) o frequenza respiratoria (atti respiratori/min).
1.2 Prove di verifica
 Verifica del sistema di allarme per la tensione di alimentazione: dopo aver alimentato il
circuito con un alimentatore stabilizzato regolato ad un valore di tensione di 5,0 V ± 0,15 V
ed in grado di erogare una corrente massima di 400 mA, si collega il multimetro in parallelo
all’alimentatore per misurare con accuratezza la tensione di alimentazione. Agendo
sull’alimentatore si fa variare la tensione di alimentazione del circuito partendo da quella
nominale diminuendola progressivamente a passi di 100 mV fino al valore di 3,9 V, dopodiché
si risale sempre a passi di 100 mV fino al valore nominale. Durante la prova si osserva il
cambiamento dello stato del led: il led dovrà essere spento per valori di tensione superiori a
4,8 V ± 0,15 V, lampeggiante per valori di tensione compresi tra 4,8 V ± 0,15 V e 4,2 V ±
0,15 V e acceso fisso per valori inferiori a 4,2 V ± 0,15 V;
 Verifica della temporizzazione della verifica della tensione di alimentazione: lo stato del pin
15 del microcontrollore viene complementato ad ogni verifica della tensione, mediante
3
l’oscilloscopio si osserva lo stato del pin. L’uscita del pin dovrà variare tra un livello logico
alto e un livello logico basso ad intervalli di 1 s ± 0,1 s ed ogni 12 variazioni un livello sarà
mantenuto per un tempo maggiore di quello indicato, perché durante l’elaborazione del
segnale si sospende momentaneamente oltre al campionamento anche il controllo della
tensione per ripartire al termine con uguale temporizzazione per entrambe le operazioni;
 Verifica della massima corrente assorbita: si collega innanzitutto l’amperometro in serie al
circuito. Dopodiché si sostituisce all’uscita del sensore NTC un segnale sinusoidale di
ampiezza 1 Vpp, offset 1,5 V e periodo 20s ottenuto dal generatore di segnali in modo che
siano accesi tutti i segmenti dei display (caso di massima corrente assorbita) e si misura la
corrente assorbita, che dovrà essere inferiore a 400 mA;
 Verifica dell’accuratezza degli estremi di misura: si sostituiscono all’uscita del sensore NTC
segnali sinusoidali di ampiezza 1 Vpp, offset 1,5 V e periodo rispettivamente 0,8 s e 8,4 s
ottenuti dal generatore di segnali: in entrambi i casi dovrà essere visualizzato sui display il
messaggio d’allarme “888”;
 Verifica del funzionamento del sistema di acquisizione ed elaborazione del segnale e di
pilotaggio dei display: si sostituiscono all’uscita del sensore NTC in successione 3 segnali
sinusoidali di ampiezza 1 Vpp, offset 1,5 V e periodi rispettivamente 2 s, 4 s e 6 s ottenuti con
il generatore di segnali. Si osserva il valore del periodo dato in uscita dai display, che deve
essere compatibile con quello dato dal generatore di segnali a meno dell’errore massimo
garantito;
 Verifica del funzionamento del deviatore e della misura della frequenza: selezionando le
stesse forme d’onda della prova precedente e selezionando la visualizzazione della frequenza
mediante il deviatore, per ognuna delle misure dovrà essere visualizzata la frequenza in cicli
al minuto corrispondente al periodo (rispettivamente 30 cicli/min, 15 cicli/min, 10 cicli/min)
a meno dell’errore massimo garantito;
 Verifica del funzionamento complessivo del dispositivo: si collega l’uscita del circuito di
condizionamento del sensore al pin 25 del microcontrollore e si visualizza il segnale in uscita
dal circuito di condizionamento sull’oscilloscopio. Posizionando il sensore al di sotto delle
narici di un soggetto si osserva il valore del periodo respiratorio misurato, che dovrà essere
compatibile con quello visualizzato sull’oscilloscopio.
Firma Committente
_______________________________
Firme Progettisti
________________________________
________________________________
________________________________
________________________________
4
100nF
2.Schema elettrico
5
Il circuito del misuratore di frequenza respiratoria si basa sul funzionamento di un sensore NTC
collegato adeguatamente ad un ingresso del microcontrollore ATmega8. Il microcontrollore riceve in
ingresso sul pin 25 il segnale di tensione in uscita dal circuito di condizionamento del sensore
(realizzato mediante un circuito integrato LM358P), lo elabora opportunamente grazie al firmware
caricato nella sua Program Flash e pilota mediante tre linee di latch-enable (in uscita dai pin 11,12,13)
e quattro linee di segnale (pin 2,3,4,5) tre display a 7 segmenti tramite tre decoder CD4511.
Il microcontrollore esegue anche la verifica della tensione di alimentazione leggendo il valore di
tensione sul pin 24 (corrispondente a metà della tensione di alimentazione). Dopo averlo confrontato
con le soglie impostate il microcontrollore pilota tramite il pin 23 il funzionamento di un led rosso.
Per ogni circuito integrato si è inserito un condensatore di bypass da 100 nF tra il pin di alimentazione
e riferimento di massa.
Mediante un deviatore a due posizioni collegato al pin 16 è possibile selezionare la visualizzazione
sui display del periodo o della frequenza misurati.
6
3.Calcoli di progetto
3.1 Stima della massima corrente assorbita dal circuito
Si suppone un consumo massimo dei componenti del circuito come: 10 mA per ogni segmento acceso
dei display (ID), 10 mA per il led acceso (IL), 10 mA per ognuno degli integrati CD4511 (IC), 10 mA
per l’integrato LM358P (IA) e 20 mA per il microcontrollore ATmega8 (IK).
Da questo risulta una corrente massima:
I 𝑚𝑎𝑥 = I 𝐿 + 22 ∗ I 𝐷 + 3 ∗ I 𝐶 + I 𝐴 + I 𝐾 = 290 𝑚𝐴
Per garantire un discreto margine che assicuri il funzionamento del circuito si dichiara una massima
corrente assorbita di 400 mA.
3.2 Dimensionamento del resistore di caduta del led
Un led rosso ha tensione di soglia nominale VL di circa 1,6 V e assorbe durante il normale
funzionamento una corrente IL di circa 10 mA.
Considerando questi dati il valore del resistore di caduta risulta:
𝑅 =
𝑉𝐴𝐿 − 𝑉𝐿
𝐼𝐿
= 340 Ω
Questo valore non si trova all’interno della serie di resistori con tolleranza 5%. Volendo diminuire il
valore della potenza dissipata si è scelto quindi un resistore da 390 Ω in modo da avere un valore di
corrente inferiore a quello nominale IL.
3.3 Dimensionamento dei resistori di caduta dei led dei display a sette
segmenti
Ogni segmento è un led rosso, per cui ipotizzando gli stessi valori del dimensionamento precedente
si ottiene un valore del resistore di caduta di 340 Ω. In questo caso, volendo ottenere una maggiore
luminosità e dunque una più facile lettura del risultato, si è scelto un resistore da 330 Ω in modo da
ottenere un valore di corrente leggermente maggiore di quella nominale IL.
3.4 Circuito di condizionamento del sensore NTC
7
La dinamica del segnale osservata direttamente all’uscita del sensore è dell’ordine delle decine di
mV, occorre dunque amplificare il segnale in modo da ottenere una dinamica maggiore di almeno un
ordine di grandezza rispetto alla tensione di quantizzazione dell’ADC (10 mV) e minore di quella
d’ingresso dell’ADC (2,56 V). Il circuito di condizionamento così realizzato introduce in uscita un
offset di circa 1,6 V e amplifica di un fattore 10 la dinamica del segnale. Sperimentalmente si è
osservata una dinamica all’uscita del circuito di condizionamento dell’ordine delle centinaia di mV.
8
4.Descrizione del Software
Il firmware è stato realizzato in linguaggio assembler mediante l’ambiente di sviluppo Atmel Studio
7.0 e caricato nella Program Flash del microcontrollore ATmega8 utilizzando la scheda AVR Dragon.
Il programma eseguito dal microcontrollore si suddivide in:
 Campionamento del segnale ricevuto dal sensore NTC e salvataggio nella SRAM ogni 50
ms circa;
 Verifica della tensione di batteria ogni 1000 ms circa;
 Elaborazione del segnale campionato:
- Media mobile su finestre di 4 campioni per ridurre il rumore presente sul segnale e
scrittura dei valori mediati sulla SRAM;
- Algoritmo per la ricerca del periodo del segnale mediato (dettagliato nell’Appendice
A).
 Pilotaggio dei display per fornire in uscita il periodo misurato o la frequenza
corrispondente.
9
4.1 Diagramma a blocchi
var_battery=100
10
4.2 Flow-chart delle singole routine
11
12
13
search_switch
14
15
16
Subroutine di riposta all’interrupt
17
5.Listato completo del codice
Di seguito si riporta l’intero listato del codice in linguaggio assembler caricato nella Program Flash
dell’ATmega8 opportunamente commentato.
; ---- PROGRAMMA ASSEMBLER PER MICROCONTROLLORE ATmega8 ----
;
; - Politecnico di Torino
; - Corso di Laurea Magistrale in Ingegneria Biomedica
; - Esame di Progettazione di Dispositivi Biomedici Programmabili
; - A.A. 2016/2017
; - Progetto: Misuratore di frequenza respiratoria (RR) basato su NTC
; - Autori: Marta Boscaglia, Alessio Brondino, Stefano Gabetti, Gabriele Giordano
;
;
; Definizione dei registri utilizzati
.DEF mp = R16 ; registro di lavoro (generico)
.DEF mp1 = R17 ; registro di lavoro secondario (generico)
.DEF var_sample = R18 ; variabile (tempo di campionamento) decrementata dalla
;subroutine di risposta ad interrupt
.DEF count_sample = R19 ; variabile che conta il numero di campioni di segnale acquisiti
;e successivamente il numero di campioni elaborati
.DEF var_battery = R20 ; variabile (intervallo di controllo batteria) decrementata dalla
;subroutine di risposta ad interrupt
.DEF flag_battery = R21 ; flag utilizzata per determinare lo stato della batteria e
;successivamente in alcune routine del signal processing
.DEF sample1 = R22 ; registro riservato per salvare un campione del brano di segnale
.DEF sample2 = R23 ; registro riservato per salvare un campione del brano di segnale
.DEF sample3 = R24 ; registro riservato per salvare un campione del brano di segnale
.DEF sample4 = R25 ; registro riservato per salvare un campione del brano di segnale
;
; Definizione delle soglie
.EQU th1=0b11110000 ;soglia 2,4 V (flag->1)
.EQU th2=0b11010010 ;soglia 2,1 V (flag->2)
; Vettore di interrupt
rjmp RESET ; Reset Handler
reti ;rjmp EXT_INT0 ; IRQ0 Handler
reti ;rjmp EXT_INT1 ; IRQ1 Handler
reti ;rjmp TIM2_COMP ; Timer2 Compare Handler
reti ;rjmp TIM2_OVF ; Timer2 Overflow Handler
reti ;rjmp TIM1_CAPT ; Timer1 Capture Handler
reti ;rjmp TIM1_COMPA ; Timer1 CompareA Handler
reti ;rjmp TIM1_COMPB ; Timer1 CompareB Handler
reti ;rjmp TIM1_OVF ; Timer1 Overflow Handler
rjmp TIM0_OVF ;Timer0 Overflow Handler
reti ;rjmp SPI_STC ; SPI Transfer Complete Handler
reti ;rjmp USART_RXC ; USART RX Complete Handler
reti ;rjmp USART_UDRE ; UDR Empty Handler
reti ;rjmp USART_TXC ; USART TX Complete Handler
reti ;rjmp ADC_conv ; ADC Conversion Complete Handler
reti ;rjmp EE_RDY ; EEPROM Ready Handler
reti ;rjmp ANA_COMP ; Analog Comparator Handler
reti ;rjmp TWSI ; Two-wire Serial Interface Handler
reti ;rjmp SPM_RDY ; Store Program Memory Ready Handler
; Si sono abilitati solo gli interrupt corrispondenti al power-on reset e all'overflow del
;timer counter 0
;
RESET:
; In questo punto inizia la routine principale del programma
; Si procede innanzitutto alle inizializzazioni dei registri che saranno utilizzati dalle
;routine del programma
18
; Tra questi ci sono quelli relativi alle porte di I/O, all'AD Converter e lo stack pointer
; ---- Inizializzazione dello STACK POINTER
ldi mp,0x04
out SPH,mp
ldi mp,0x5f
out SPL,mp
; Lo stack pointer è stato allocato all'indirizzo corrispondente alla parte
; alta della RAM disponibile, poiché lo stack pointer quando utilizzato viene
; decrementato e successivamente incrementato dopo l'utilizzo.
;
; ---- Inizializzazione di PORTC
ldi mp,0b00000001
;
; Per questa porta di I/O si definisce quali pin sono utilizzati come uscite e quali come
;ingressi.
; I pin che sono usati come uscite, nel nostro caso per pilotare un led, devono
; avere il corrispondente bit nel registro direzione dati (DDR) ad '1'.
; I rimanenti in ingresso devono avere i bit a '0'.
;
out DDRC,mp
; La parola è stata inizialmente scritta nel registro mp e poi successivamente, tramite
;l'istruzione out
; caricata nel Data Direction Register della porta C
; In questo modo è stato definito come uscita il pin 23 del microcontrollore (PC0), tramite
;questo pin sarà pilotato il led.
ldi mp,0x00
out PORTC,mp
; Si scrive il valore zero nella porta C, il led è inizializzato spento.
;
; ---- Inizializzazione di PORTD
ldi mp,0b11101111
out DDRD,mp
; Si abilitano i pin I/O in uscita in DDRD, in questo modo si sono abilitati come uscita i
;pin 2,3,4,5,11,12,13 dell'ATmega8
; PORTD permette di pilotare i display a 7 segmenti, in particolare i primi 4 pin
;(PD0,PD1,PD2,PD3) pilotano le linee A,B,C,D
; che danno in ingresso ai decoder le parole con codifica BCD contenenti il numero da
;visualizzare sul singolo display,
; gli ultimi 3 pin (PD5,PD6,PD7) costituiscono i 3 Latch-Enable che permettono di
;selezionare separatamente ognuno dei 3 decoder
; per scrivere il numero sul display corretto (decine, unità, decimi)
;
; ---- Inizializzazione di PORTB
ldi mp,0b00000010
out DDRB,mp
; E' stato definito come uscita il pin 15 del microcontrollore (PB1)
; tramite questo pin sarà verificata la tempistica del controllo della tensione di batteria
ldi mp,0x00
out PORTB,mp
; Si scrive il valore zero nella porta B
; ---- Inizializzazione del Timer/Counter0
ldi mp,0b00000101
out TCCR0,mp
; Si seleziona per il prescaler passo 1024 (se 1MHz allora 1024us)
; Il contatore sarà quindi incrementato a passi di circa 1ms (1,024ms)
;
ldi mp,246
out TCNT0,mp
; seleziona tempo tra interrupt pari a circa 10ms (10,24ms)
;
ldi mp,0x01
out TIMSK,mp
; abilita l'interrupt in caso di overflow di TCNT0
19
;
ldi var_battery,100
; Si inizializza la variabile var_battery che sarà decrementata dalla subroutine di risposta
;ad interrupt
; In questo modo si ottiene una variabile che raggiungerà il valore 0 dopo circa 1s
;(var_battery = 100 -> 1024 ms),
; permettendoci così di effettuare la verifica dello stato della batteria ad intervalli
;regolari di circa 1000ms come richiesto
;
ldi var_sample,5
; Si inizializza la variabile var_sample che sarà decrementata dalla subroutine di risposta
;ad interrupt (var_sample = 5 -> 51,2 ms)
; In questo modo si ottiene il campionamento del segnale con Tc circa 50 ms (fc circa 20 Hz)
;
ldi count_sample,0
; Inizializza il contatore a 0 (nessun campione acquisito)
;
; ---- Inizializzazione dell'AD Converter
ldi mp,0b11000000
out ADCSRA,mp
; Tramite il registro ADCSRA si decidono le seguenti impostazioni: si abilitano le funzioni
;dell'ADC e lo si avvia,
; non sarà utilizzata la modalità free-running (sia per motivi di consumo energetico, sia
;perché si preferisce avviare le conversioni
; dell'ADC con una temporizzazione nota mediante opportune istruzioni nel codice),
; non si abilitano gli interrupt e si sceglie il passo standard del prescaler
ldi mp, 0b11100001
out ADMUX, mp
; Tramite il registro ADMUX si imposta: tensione di riferimento 2,56 V (riferimento interno
;Vref),
; risultato left adjusted (utilizzando l'High byte contente il risultato si avrà una
;risoluzione su 8 bit -> 256 livelli)
; canale d'ingresso ADC1 (pin 24, PC1)
ldi flag_battery,0
; Si inizializza flag_battery a 0, prima del primo controllo si suppone che la tensione di
;batteria sia a valori ottimali
;
; ---- Inizializzazione del registro Z
ldi ZH, HIGH(Table1*2)
ldi ZL, LOW(Table1*2)
; Il registro Z sarà utilizzato nel corso del programma per contenere gli indirizzi delle
;celle della Program Flash
; in cui è salvata la lookup table. La lookup table permette di convertire il valore del
;periodo respiratorio misurato in campioni
; nel valore del periodo in secondi da dare in uscita sui display
; Si inizializza tale registro in modo che punti alla prima cella della prima riga della
;lookup table
;
; ------ Inizializzazione della SRAM:
clr r27
; clear dell'high byte di X
ldi r26,$60
; Nel programma si utilizzerà il registro X per contenere gli indirizzi delle celle di RAM
; in cui saranno salvati prima i valori dei campioni di segnale e successivamente altri
;valori derivanti dalle routine di
; elaborazione del segnale. Si inizializza il registro X al valore $0060 (primo indirizzo di
;SRAM disponibile)
;
sei
; Mediante questo comando si abilitano gli interrupt a livello di SREG
;
; --------------------------------------- LOOP PRINCIPALE -------------------------------
; Da questo punto inizia il loop infinito che viene eseguito dal microcontrollore
20
;
main_loop:
cpi var_sample,0
brne check_battery_routine
; Se il valore contenuto in var_sample è 0 allora sono passati 50 ms e si procede al
;campionamento del segnale,
; altrimenti si salta alla routine di controllo dello stato della batteria
sir:
ldi var_sample,5
; Si reinizializza var_sample a 5 per contare altri 50ms
;
; ----------------------- CAMPIONAMENTO DEL SEGNALE E SALVATAGGIO IN RAM ---------------
;
ldi mp, 0b11100010
out ADMUX, mp
; Mediante ADMUX si seleziona come canale d'ingresso al convertitore il canale ADC2 (pin 25,
;PC2)
;
; ---- Routine di conversione dell'ADC
;
in mp,ADCSRA
ldi mp1,0b01000000
or mp,mp1
out ADCSRA,mp
; La routine è divisa in due parti:
; nella prima si carica un 1 nel bit 6 di ADCSRA per iniziare la conversione senza
;modificare gli altri bit
;
check_conv_sample:
in mp,ADCSRA
ldi mp1,0b01000000
and mp,mp1
brne check_conv_sample
; nella seconda si attende che la conversione sia finita: si verifica che il valore del bit6
;sia tornato a 0,
; finché questo non avviene il microcontrollore resta all'interno di questa routine di
;controllo
; (questo controllo crea dei tempi di attesa che però sono molto brevi, circa 30us)
;
in mp,ADCH
; Si richiama il risultato della conversione in mp
st X+,mp
; Il valore è salvato nella SRAM e il registro X post-incrementiamo, così da puntare alla
;cella successiva,
; dove si salverà il campione successivo
inc count_sample
; Il contatore del numero di campioni acquisiti si incrementa ogni volta
; Un controllo successivo avvierà la routine di elaborazione del segnale quando il contatore
;avrà raggiunto il valore corrispondente
; alla lunghezza del brano di segnale che si vuole analizzare
;
;------------------------------- CONTROLLO DELLA TENSIONE DI BATTERIA ----------------------
;
check_battery_routine:
cpi var_battery,0
brne signal_processing
; Se non è passato 1 s non si esegue la routine di controllo della batteria e si salta alla
;routine successiva
ldi var_battery,100
; Si reinizializza la variabile di temporizzazione (1 s) per temporizzare il controllo
;successivo
ldi flag_battery,0
; Ogni volta che si effettua il controllo occorre reinizializzare la flag a zero
21
;
ldi mp, 0b11100001
out ADMUX, mp
; Per eseguire il controllo sullo stato della batteria bisogna selezionare il canale ADC1
;(PIN 24, PC1) come ingresso
;
in mp,ADCSRA
ldi mp1,0b01000000
or mp,mp1
out ADCSRA,mp
check_conv_battery:
in mp,ADCSRA
ldi mp1,0b01000000
and mp,mp1
brne check_conv_battery
; La routine che misura la tensione della batteria è identica a quella che rileva il valore
;del campione di segnale
;
in mp,ADCH
; Si legge il valore della tensione misurata
cpi mp,th1
brsh check_battery_voltage_01
ldi flag_battery,1
; Se il valore è inferiore alla prima soglia si modifica la flag e si passa alla verifica
;della 2a soglia,
; altrimenti si salta direttamente alla fine (è inutile verificare la 2a soglia)
cpi mp,th2
brsh check_battery_voltage_01
ldi flag_battery,2
; Se il valore è inferiore alla seconda soglia si modifica ancora la flag
check_battery_voltage_01:
cpi flag_battery,0
brne check_battery_voltage_02
ldi mp,0b00000000
out PORTC,mp
; Se la flag è 0 -> batteria OK, il led resta spento
check_battery_voltage_02:
cpi flag_battery,1
brne check_battery_voltage_03
; Se la flag è 1 -> il valore della tensione è tra le 2 soglie, LED intermittente, occorre
;eseguire il toggle:
in mp,PINC
ldi mp1,0b00000001
and mp,mp1
; si legge il valore del pin che pilota il led (si leggono tutti i pin della porta e si
; mascherano tutti ad eccezione di quello di interesse)
ldi mp1,0b00000001
eor mp,mp1
; eseguendo un or esclusivo tra mp ed mp1 si complementa il bit 0 di mp
out PORTC,mp
; Il valore di mp è messo in uscita (se il led era acceso si spegne e viceversa, si ottiene
;così il lampeggio del led ad intervalli di 1 s)
check_battery_voltage_03:
cpi flag_battery,2
brne signal_processing
ldi mp,0b00000001
out PORTC,mp
; Se la flag è 2 -> il valore della è tensione sotto la seconda soglia, LED acceso fisso
;
;--------------- ELABORAZIONE DEL SEGNALE --------------------
;
signal_processing:
cpi count_sample,255
22
brne main_loop
; Se il numero dei campioni ha raggiunto 255 (si sono registrati circa 12s di segnale)
;allora si procede all'elaborazione
; L'elaborazione del segnale comporta vari passaggi, il primo dei quali è il calcolo della
;media mobile per ridurre il rumore
media_mobile:
; Occorre inizializzare i registri che puntano alla RAM
clr r29
ldi r28,$60
; Il registro Y contiene gli indirizzi delle celle di RAM da cui si leggono i valori dei
;campioni
clr r27
ldi r26,$60
; Il registro X contiene invece gli indirizzi delle celle di RAM dove si scrive il valore
;della media mobile
ld sample1,Y+
dec count_sample
; Al caricamento di ogni campione si decrementa il valore di count_sample, che sarà 0 una
;volta caricati tutti i campioni
ld sample2,Y+
dec count_sample
ld sample3,Y+
dec count_sample
ld sample4,Y+
dec count_sample
average:
ldi mp,0
; Nel registro mp si salva l'eventuale overflow delle somme (poichè si sommano 4 numeri a 8
;bit occorrono 10 bit), mp deve essere inizializzato a 0
add sample1,sample2
brcc sum_sample1_2
; il bit C (Carry) dello status register è quello che indica se è avvenuto overflow nella
;somma, se è avvenuto si aggiunge 1 al termine che salva i riporti
inc mp
clc
; il bit del Carry va riazzerato prima di effettuare la somma successiva, poi si sommano gli
;altri campioni
sum_sample1_2:
add sample1,sample3
brcc sum_sample3
inc mp
clc
sum_sample3:
add sample1,sample4
brcc sum_all4samples
inc mp
clc
; il risultato parziale è ora salvato su due registri in questo modo: 000000XX (mp)
;XXXXXXXX (sample1), questo valore va diviso per 4:
; si può fare eseguendo 2 shift a destra su sample1 e successivamente copiando gli ultimi 2
;bit di mp sui primi 2 di sample1
sum_all4samples:
lsr sample1
lsr sample1
; Il valore di sample1 è stato fatto scorrere verso destra di 2 posti: sample1 --> 00XXXXXX
lsl mp
lsl mp
swap mp
add sample1,mp
; Per ottenere in mp il valore della media si fa scorrere di 2 posti verso sinistra mp -->
;0000XX00,
; poi si invertono le 2 metà di mp (i primi 4 bit con gli ultimi 4) --> XX000000,
23
; infine sommando si vanno a scrivere i 2 bit di riporto di mp nelle posizioni corrette su
;sample1, che dunque contiene il risultato della media
st X+,sample1
; Il valore della media mobile è salvato in RAM sovrascrivendo il campione più vecchio dei 4
;su cui si è eseguita la media
cpi count_sample,0
breq peak_recognition
; Se il numero di campioni è tornato a zero vuol dire che si è eseguita su tutti la media
;mobile e dunque si procede alla routine successiva
mov sample1,sample2
mov sample2,sample3
mov sample3,sample4
ld sample4,Y+
dec count_sample
rjmp average
; Se no si spostano i campioni acquisiti da un registro a quello precedente e si carica un
;nuovo campione nell'ultimo registro riservato ai campioni,
; si è così realizzata una finestra mobile su cui si esegue ogni volta la media, che viene
;sempre riscritta sul campione più vecchio
; Terminata la media mobile si procede con la ricerca del periodo del segnale
peak_recognition:
clr r29
ldi r28,$60
clr r27
ldi r26,$60
; Come in precedenza si utilizza il registro Y per puntare alle celle di RAM da cui si
;leggono i valori (in questo caso dei campioni mediati)
; ed allo stesso modo il registro X per puntare alle celle di RAM su cui si scrive il valore
;di una flag, che assumerà valore 1 se il segnale
; ha andamento decrescente, 0 se crescente
ld sample1,Y+
inc count_sample
search_fall:
ld sample2,Y+
inc count_sample
ldi mp,0
; Si caricano 2 campioni e si usa mp come flag
cp sample1,sample2
brlo check_fall
ldi mp,1
; se sample1>=sample2 la flag diventa 1, indicando così che il segnale ha andamento
;decrescente
check_fall:
st X+,mp
; La flag è sovrascritta sul 1o campione
mov sample1,sample2
; Si sposta il contenuto di sample2 in sample1 per riavviare la verifica sul campione
;successivo
cpi count_sample,255
brne search_fall
; se sono terminati i campioni termina la ricerca di rise/fall
; Ora nella RAM è salvata una successione costituita solo da 1 e 0, che idealmente dovrebbe
;essere un'onda quadra di periodo pari al segnale.
; Misurando dunque la distanza tra due fronti di salita consecutivi si trova il periodo del
;segnale (in realtà l'onda quadra presenta dei "rimbalzi",
; che vanno eliminati per procedere ad una misura corretta)
ldi count_sample,1
; Si re-inizializza count_sample al valore 1 per procedere alla routine successiva
clr r29
ldi r28,$60
; Si inizializza nuovamente il registro Y per puntare alle celle di RAM da cui si leggono i
;valori delle flag
ld sample1,Y+
24
inc count_sample
ldi mp1,0
; mp1 è la flag che ci dà il numero di fronti di salita trovati
ldi sample3,0
ldi sample4,0
; sample3 e sample4 conterranno la posizione dei fronti
search_switch:
ld sample2,Y+
eor sample1,sample2
; or esclusivo tra 2 flag consecutive (nei punti cercati sarà 1)
cpi sample1,1
brne keep_searching
; se l'or non è 1 non ci troviamo su un fronte, ma su un livello
ldi flag_battery,0
; Ora dobbiamo verificare che il fronte sia un vero fronte di salita
; Vanno scartati i fronti di discesa e soprattutto i "rimbalzi" della flag dovuti al rumore
;o alla risoluzione:
; per far questo si verificherà che i 7 valori successivi a quello del fronte di salita
;siano 1 (7*50=350 ms, questo valore è sufficientemente
; lungo per permetterci di scartare i rimbalzi e non troppo da impedire di vedere il primo
;periodo, dato che se T=1s il livello è di circa 500 ms)
; si riutilizza flag_battery (non sono mai contemporaneamente attive l'analisi del segnale e
;la verifica della tensione)
ldi mp,0
; mp è ora utilizzato come contatore
cpi sample2,1
brne anti_bounce1
; con questo controllo su sample2 si scartano i fronti di discesa
movw X,Y
; Ora per verificare che il fronte di salita sia tale si controllano i 7 campioni successivi
; Per puntare agli indirizzi di RAM che li contengono si usa il registro X in modo da non
;modificare il registro Y
find_costant:
inc mp
ld sample1,X+
cpi sample1,1
brne bounce_check
inc flag_battery
; tramite il registro X si carica il primo campione successivo e si esegue la verifica, in
;caso positivo si incrementa flag_battery
bounce_check:
cpi mp,7
brne find_costant
; mp si incrementa ad ogni campione caricato, quando arriva a 7 la verifica è terminata
anti_bounce1:
cpi flag_battery,7
brne save_position
inc mp1
; se flag_battery=7 allora tutti i 7 campioni successivi a quello indicato come probabile
;fronte sono 1 -> si tratta di un vero fronte di salita
; In questo caso si incrementa mp1, che tiene conto del numero di veri fronti di salita
trovati
save_position:
;
cpi mp1,1
brne first_switch
cpi flag_battery,7
brne first_switch
add sample3,count_sample
; Se mp1=1 allora si tratta del primo fronte di salita trovato e si salva dunque la sua
;posizione in sample3
first_switch:
cpi mp1,2
25
brne second_switch
cpi flag_battery,7
brne second_switch
add sample4,count_sample
; Allo stesso modo se mp1=2 è stato trovato il secondo fronte di salita
second_switch:
cpi mp1,2
breq end_search
; Se sono stati trovati 2 fronti di salita allora si interrompe la ricerca senza verificare
;i campioni successivi
keep_searching:
inc count_sample
mov sample1,sample2
; In caso contrario si sposta sample2 in sample1 per far scorrere i campioni prima di
;ripartire
cpi count_sample,248
brne search_switch
; Se non si trova il secondo fronte la ricerca si conclude comunque una volta esauriti i
;campioni (gli ultimi 7 devono essere scartati per
; evitare errori di riconoscimento)
end_search:
sub sample4,sample3
; Si salva in sample4 la distanza tra 2 fronti di salita (tale valore è qui espresso in
;numero di campioni e corrisponde al periodo)
check_max_period:
cpi mp1,2
breq set_display
ldi sample4,255
; Se non è stato trovato il secondo picco la differenza tra sample4 e sample3 ha dato un
;risultato sconosciuto
; Si imposta dunque in sample 4 un valore che comporterà la scrittura del messaggio
;d'allarme di periodo troppo lungo
; Ora si può procedere all'invio tramite le linee di I/O selezionate del valore che sarà
;visualizzato sui display
;----------------------- SCRITTURA DEL RISULTATO SU DISPLAY --------------------
;
set_display:
clr r29
clr r28
; riazzeriamo il registro Y per sicurezza
in mp,PINB
ldi mp1,0b00000100
and mp,mp1
; Dal pin 16 del microcontrollore (PB2) si legge lo stato del dip-switch
cpi mp,0b00000000
brne set_frequenza
set_periodo:
ldi ZH, HIGH(Table1*2)
ldi ZL, LOW(Table1*2)
; Se si legge il valore 0 allora con il deviatore si è selezionata la visualizzazione del
;periodo e dunque si imposta il registro Z
; perchè punti alla Table1
set_frequenza:
cpi mp,0b00000100
brne search_in_lookup_table
ldi ZH, HIGH(Table2*2)
ldi ZL, LOW(Table2*2)
; Se si legge il valore 1 allora con il deviatore si è selezionata la visualizzazione della
;frequenza e dunque si imposta il registro Z
; perchè punti alla Table2
search_in_lookup_table:
lpm mp,Z
; Il primo valore di lookup table è salvato in mp
26
cp mp,sample4
breq found
adiw Zl,4
rjmp search_in_lookup_table
; Si confronta il valore con mp, se sono diversi si salta alla riga successiva (la lookup
;table ha 4 elementi per ogni riga),
; se invece sono uguali allora si è trovata la corrispondenza e si può procedere all'invio
;ai display
found:
adiw Zl,1
lpm mp,Z
adiw Zl,1
; Si incrementa di 1 il valore del low byte di Z, che dunque punta al valore da mettere in
;uscita per le decine
; Si salva questo valore in mp e si incrementa Z per far sì che punti al valore da scrivere
;sulle unità
ldi mp1,0b11100000
or mp1,mp
out PORTD, mp1
; Si mette il numero in binario prelevato dalla lookup table in uscita su PORTD (in questo
;momento i 3 latch sono a 1 ed essendo questi attivi bassi
; nessun valore è ancora inviato in uscita)
ldi mp1,0b01100000
or mp1,mp
out PORTD, mp1
; In questo modo si invia il comando Latch Enable per il controller del display - decine
ldi mp1,15
rcall attendi_le
; Chiamando questa funzione si introducono almeno 15 us di attesa prima di procedere alla
;scrittura del valore delle unità, in modo da non avere problemi
; nel pilotaggio dei display
ldi mp1,0b11100000
eor mp1,mp
out PORTD, mp1
; Vengono resi nuovamente inattivi i LE
lpm mp,Z
adiw Zl,1
; Ora si legge il valore delle unità e si scorre di una casella nella tabella
ldi mp1,0b11100000
or mp1,mp
out PORTD, mp1
ldi mp1,0b10100000
or mp1,mp
out PORTD, mp1
ldi mp1,15
rcall attendi_le
ldi mp1,0b11100000
eor mp1,mp
out PORTD, mp1
; Procedendo allo stesso modo di prima si carica il valore delle unità sull'uscita
;corrispondente, si chiama la routine di attesa e si rendono nuovamente inattivi i Latch
lpm mp,Z
adiw Zl,1
ldi mp1,0b11100000
or mp1,mp
out PORTD, mp1
ldi mp1,0b11000000
or mp1,mp
out PORTD, mp1
ldi mp1,15
; Ripetendo una terza volta il procedimento si carica anche il valore dei decimi sul display
;corrispondente
ldi ZH, HIGH(Table1*2)
27
ldi ZL, LOW(Table1*2)
; Si reinizializza il registro Z, per una nuova ricerca
ldi mp1,0b11100000
eor mp1,mp
out PORTD, mp1
; Si rendono nuovamente inattivi i LE in modo che il numero sia mantenuto sui display
; fino alla comparsa del nuovo valore al termine dell'elaborazione del successivo periodo
clr r27
ldi r26,$60
; Alla fine del signal processing va inizializzato il registro X per riscrivere i dati da 0
ldi var_sample,5
ldi var_battery,100
; Si inizializzano i contatori per evitare che gli interrupt arrivati nel signal processing
;abbiano portato questi a valori non previsti
ldi count_sample,0
; Per registrare un nuovo periodo completo si riporta a 0 count sample
rjmp main_loop
; Terminate tutte le operzioni il programma riparte dall'inizio
;
; ------- Subroutine di risposta all'interrupt ----------
TIM0_OVF:
push mp
in mp,SREG
push mp
; E' fondamentale salvare SREG nello stack per far sì che il rpogramma riparta esattamente
;dal punto in cui era arrivato prima che fosse lanciata
; la richiesta di interrupt, per fare questo si usa il registro mp e dunque occorre prima
;salvare questo nello stack per recuperare il valore corretto
; quando dal questa subroutine il programma ritorna nel main_loop
ldi mp,246
out TCNT0,mp
; E' inizializzata nuovamente la variabile di conteggio del timer counter (10 ms)
dec var_battery
; Si decrementa la variabile di conteggio del ciclo di controllo della batteria (1 s)
dec var_sample
; Si decrementa la variabile di conteggio del ciclo di campionamento (50 ms)
pop mp
out SREG,mp
pop mp
; Ora si richiamano i valori corretti di mp e SREG
reti
;
; -------- Funzione per dare la pausa tra l'accensione di decine, unità e decimi ----------
attendi_le:
dec mp1
cpi mp1,0
brne attendi_le
ret
;
; ---------- LOOKUP TABLE -----------------
; La lookup table Table1 stabilisce una corrispondenza tra il valore del periodo misurato in
;campioni ed il valore in s da visualizzare
.CSEG
Table1:
.DB 0,8,8,8 ; messaggio d'allarme, periodo troppo breve
.DB 1,8,8,8
.DB 2,8,8,8
.DB 3,8,8,8
.DB 4,8,8,8
.DB 5,8,8,8
.DB 6,8,8,8
.DB 7,8,8,8
.DB 8,8,8,8
28
.DB 9,8,8,8
.DB 10,8,8,8
.DB 11,8,8,8
.DB 12,8,8,8
.DB 13,8,8,8
.DB 14,8,8,8
.DB 15,8,8,8
.DB 16,8,8,8
.DB 17,8,8,8
.DB 18,8,8,8
.DB 19,0,1,0
.DB 20,0,1,0 ; T=1 s, primo periodo da rappresentare
.DB 21,0,1,1
.DB 22,0,1,1
.DB 23,0,1,2
.DB 24,0,1,2
.DB 25,0,1,3
.DB 26,0,1,3
.DB 27,0,1,4
.DB 28,0,1,4
.DB 29,0,1,5
.DB 30,0,1,5
.DB 31,0,1,6
.DB 32,0,1,6
.DB 33,0,1,7
.DB 34,0,1,7
.DB 35,0,1,8
.DB 36,0,1,8
.DB 37,0,1,9
.DB 38,0,1,9
.DB 39,0,2,0
.DB 40,0,2,0
.DB 41,0,2,1
.DB 42,0,2,1
.DB 43,0,2,2
.DB 44,0,2,2
.DB 45,0,2,3
.DB 46,0,2,3
.DB 47,0,2,4
.DB 48,0,2,4
.DB 49,0,2,5
.DB 50,0,2,5
.DB 51,0,2,6
.DB 52,0,2,6
.DB 53,0,2,7
.DB 54,0,2,7
.DB 55,0,2,8
.DB 56,0,2,8
.DB 57,0,2,9
.DB 58,0,2,9
.DB 59,0,3,0
.DB 60,0,3,0
.DB 61,0,3,1
.DB 62,0,3,1
.DB 63,0,3,2
.DB 64,0,3,2
.DB 65,0,3,3
.DB 66,0,3,3
.DB 67,0,3,4
.DB 68,0,3,4
.DB 69,0,3,5
.DB 70,0,3,5
.DB 71,0,3,6
29
.DB 72,0,3,6
.DB 73,0,3,7
.DB 74,0,3,7
.DB 75,0,3,8
.DB 76,0,3,8
.DB 77,0,3,9
.DB 78,0,3,9
.DB 79,0,4,0
.DB 80,0,4,0
.DB 81,0,4,1
.DB 82,0,4,1
.DB 83,0,4,2
.DB 84,0,4,2
.DB 85,0,4,3
.DB 86,0,4,3
.DB 87,0,4,4
.DB 88,0,4,4
.DB 89,0,4,5
.DB 90,0,4,5
.DB 91,0,4,6
.DB 92,0,4,6
.DB 93,0,4,7
.DB 94,0,4,7
.DB 95,0,4,8
.DB 96,0,4,8
.DB 97,0,4,9
.DB 98,0,4,9
.DB 99,0,5,0
.DB 100,0,5,0
.DB 101,0,5,1
.DB 102,0,5,1
.DB 103,0,5,2
.DB 104,0,5,2
.DB 105,0,5,3
.DB 106,0,5,3
.DB 107,0,5,4
.DB 108,0,5,4
.DB 109,0,5,5
.DB 110,0,5,5
.DB 111,0,5,6
.DB 112,0,5,6
.DB 113,0,5,7
.DB 114,0,5,7
.DB 115,0,5,8
.DB 116,0,5,8
.DB 117,0,5,9
.DB 118,0,5,9
.DB 119,0,6,0
.DB 120,0,6,0
.DB 121,0,6,1
.DB 122,0,6,1
.DB 123,0,6,2
.DB 124,0,6,2
.DB 125,0,6,3
.DB 126,0,6,3
.DB 127,0,6,4
.DB 128,0,6,4
.DB 129,0,6,5
.DB 130,0,6,5
.DB 131,0,6,6
.DB 132,0,6,6
.DB 133,0,6,7
.DB 134,0,6,7
30
.DB 135,0,6,8
.DB 136,0,6,8
.DB 137,0,6,9
.DB 138,0,6,9
.DB 139,0,7,0
.DB 140,0,7,0
.DB 141,0,7,1
.DB 142,0,7,1
.DB 143,0,7,2
.DB 144,0,7,2
.DB 145,0,7,3
.DB 146,0,7,3
.DB 147,0,7,4
.DB 148,0,7,4
.DB 149,0,7,5
.DB 150,0,7,5
.DB 151,0,7,6
.DB 152,0,7,6
.DB 153,0,7,7
.DB 154,0,7,7
.DB 155,0,7,8
.DB 156,0,7,8
.DB 157,0,7,9
.DB 158,0,7,9
.DB 159,0,8,0
.DB 160,0,8,0
.DB 161,0,8,0
.DB 162,0,8,0 ; messaggio d'allarme, periodo troppo lungo (T > 8 s)
.DB 163,8,8,8
.DB 164,8,8,8
.DB 165,8,8,8
.DB 166,8,8,8
.DB 167,8,8,8
.DB 168,8,8,8
.DB 169,8,8,8
.DB 170,8,8,8
.DB 171,8,8,8
.DB 172,8,8,8
.DB 173,8,8,8
.DB 174,8,8,8
.DB 175,8,8,8
.DB 176,8,8,8
.DB 177,8,8,8
.DB 178,8,8,8
.DB 179,8,8,8
.DB 180,8,8,8
.DB 181,8,8,8
.DB 182,8,8,8
.DB 183,8,8,8
.DB 184,8,8,8
.DB 185,8,8,8
.DB 186,8,8,8
.DB 187,8,8,8
.DB 188,8,8,8
.DB 189,8,8,8
.DB 190,8,8,8
.DB 191,8,8,8
.DB 192,8,8,8
.DB 193,8,8,8
.DB 194,8,8,8
.DB 195,8,8,8
.DB 196,8,8,8
.DB 197,8,8,8
31
.DB 198,8,8,8
.DB 199,8,8,8
.DB 200,8,8,8
.DB 201,8,8,8
.DB 202,8,8,8
.DB 203,8,8,8
.DB 204,8,8,8
.DB 205,8,8,8
.DB 206,8,8,8
.DB 207,8,8,8
.DB 208,8,8,8
.DB 209,8,8,8
.DB 210,8,8,8
.DB 211,8,8,8
.DB 212,8,8,8
.DB 213,8,8,8
.DB 214,8,8,8
.DB 215,8,8,8
.DB 216,8,8,8
.DB 217,8,8,8
.DB 218,8,8,8
.DB 219,8,8,8
.DB 220,8,8,8
.DB 221,8,8,8
.DB 222,8,8,8
.DB 223,8,8,8
.DB 224,8,8,8
.DB 225,8,8,8
.DB 226,8,8,8
.DB 227,8,8,8
.DB 228,8,8,8
.DB 229,8,8,8
.DB 230,8,8,8
.DB 231,8,8,8
.DB 232,8,8,8
.DB 233,8,8,8
.DB 234,8,8,8
.DB 235,8,8,8
.DB 236,8,8,8
.DB 237,8,8,8
.DB 238,8,8,8
.DB 239,8,8,8
.DB 240,8,8,8
.DB 241,8,8,8
.DB 242,8,8,8
.DB 243,8,8,8
.DB 244,8,8,8
.DB 245,8,8,8
.DB 246,8,8,8
.DB 247,8,8,8
.DB 248,8,8,8
.DB 249,8,8,8
.DB 250,8,8,8
.DB 251,8,8,8
.DB 252,8,8,8
.DB 253,8,8,8
.DB 254,8,8,8
.DB 255,8,8,8
; La lookup table Table2 stabilisce una corrispondenza tra il valore del periodo misurato in
;campioni
; ed il valore della frequenza da visualizzare (atti respiratori/min)
Table2:
32
.DB 0,8,8,8 ; messaggio d'allarme, frequenza troppo alta
.DB 1,8,8,8
.DB 2,8,8,8
.DB 3,8,8,8
.DB 4,8,8,8
.DB 5,8,8,8
.DB 6,8,8,8
.DB 7,8,8,8
.DB 8,8,8,8
.DB 9,8,8,8
.DB 10,8,8,8
.DB 11,8,8,8
.DB 12,8,8,8
.DB 13,8,8,8
.DB 14,8,8,8
.DB 15,8,8,8
.DB 16,8,8,8
.DB 17,8,8,8
.DB 18,8,8,8
.DB 19,6,0,0 ; massima frequenza misurabile (60 atti respiratori/min)
.DB 20,6,0,0
.DB 21,5,4,5
.DB 22,5,4,5
.DB 23,5,0,0
.DB 24,5,0,0
.DB 25,4,6,2
.DB 26,4,6,2
.DB 27,4,2,9
.DB 28,4,2,9
.DB 29,4,0,0
.DB 30,4,0,0
.DB 31,3,7,5
.DB 32,3,7,5
.DB 33,3,5,3
.DB 34,3,5,3
.DB 35,3,3,3
.DB 36,3,3,3
.DB 37,3,1,6
.DB 38,3,1,6
.DB 39,3,0,0
.DB 40,3,0,0
.DB 41,2,8,6
.DB 42,2,8,6
.DB 43,2,7,3
.DB 44,2,7,3
.DB 45,2,6,1
.DB 46,2,6,1
.DB 47,2,5,0
.DB 48,2,5,0
.DB 49,2,4,0
.DB 50,2,4,0
.DB 51,2,3,1
.DB 52,2,3,1
.DB 53,2,2,2
.DB 54,2,2,2
.DB 55,2,1,4
.DB 56,2,1,4
.DB 57,2,0,7
.DB 58,2,0,7
.DB 59,2,0,0
.DB 60,2,0,0
.DB 61,1,9,4
.DB 62,1,9,4
33
.DB 63,1,8,8
.DB 64,1,8,8
.DB 65,1,8,2
.DB 66,1,8,2
.DB 67,1,7,6
.DB 68,1,7,6
.DB 69,1,7,1
.DB 70,1,7,1
.DB 71,1,6,7
.DB 72,1,6,7
.DB 73,1,6,2
.DB 74,1,6,2
.DB 75,1,5,8
.DB 76,1,5,8
.DB 77,1,5,4
.DB 78,1,5,4
.DB 79,1,5,0
.DB 80,1,5,0
.DB 81,1,4,6
.DB 82,1,4,6
.DB 83,1,4,3
.DB 84,1,4,3
.DB 85,1,4,0
.DB 86,1,4,0
.DB 87,1,3,6
.DB 88,1,3,6
.DB 89,1,3,3
.DB 90,1,3,3
.DB 91,1,3,0
.DB 92,1,3,0
.DB 93,1,2,8
.DB 94,1,2,8
.DB 95,1,2,5
.DB 96,1,2,5
.DB 97,1,2,2
.DB 98,1,2,2
.DB 99,1,2,0
.DB 100,1,2,0
.DB 101,1,1,8
.DB 102,1,1,8
.DB 103,1,1,5
.DB 104,1,1,5
.DB 105,1,1,3
.DB 106,1,1,3
.DB 107,1,1,1
.DB 108,1,1,1
.DB 109,1,0,9
.DB 110,1,0,9
.DB 111,1,0,7
.DB 112,1,0,7
.DB 113,1,0,5
.DB 114,1,0,5
.DB 115,1,0,3
.DB 116,1,0,3
.DB 117,1,0,2
.DB 118,1,0,2
.DB 119,1,0,0
.DB 120,1,0,0
.DB 121,0,9,8
.DB 122,0,9,8
.DB 123,0,9,7
.DB 124,0,9,7
.DB 125,0,9,5
34
.DB 126,0,9,5
.DB 127,0,9,4
.DB 128,0,9,4
.DB 129,0,9,2
.DB 130,0,9,2
.DB 131,0,9,1
.DB 132,0,9,1
.DB 133,0,9,0
.DB 134,0,9,0
.DB 135,0,8,8
.DB 136,0,8,8
.DB 137,0,8,7
.DB 138,0,8,7
.DB 139,0,8,6
.DB 140,0,8,6
.DB 141,0,8,5
.DB 142,0,8,5
.DB 143,0,8,3
.DB 144,0,8,3
.DB 145,0,8,2
.DB 146,0,8,2
.DB 147,0,8,1
.DB 148,0,8,1
.DB 149,0,8,0
.DB 150,0,8,0
.DB 151,0,7,9
.DB 152,0,7,9
.DB 153,0,7,8
.DB 154,0,7,8
.DB 155,0,7,7
.DB 156,0,7,7
.DB 157,0,7,6
.DB 158,0,7,6
.DB 159,0,7,5
.DB 160,0,7,5
.DB 161,0,7,5
.DB 162,0,7,5 ; massima frequenza misurabile (7,5 atti respiratori/min)
.DB 163,8,8,8
.DB 164,8,8,8
.DB 165,8,8,8
.DB 166,8,8,8
.DB 167,8,8,8
.DB 168,8,8,8
.DB 169,8,8,8
.DB 170,8,8,8
.DB 171,8,8,8
.DB 172,8,8,8
.DB 173,8,8,8
.DB 174,8,8,8
.DB 175,8,8,8
.DB 176,8,8,8
.DB 177,8,8,8
.DB 178,8,8,8
.DB 179,8,8,8
.DB 180,8,8,8
.DB 181,8,8,8
.DB 182,8,8,8
.DB 183,8,8,8
.DB 184,8,8,8
.DB 185,8,8,8
.DB 186,8,8,8
.DB 187,8,8,8
.DB 188,8,8,8
35
.DB 189,8,8,8
.DB 190,8,8,8
.DB 191,8,8,8
.DB 192,8,8,8
.DB 193,8,8,8
.DB 194,8,8,8
.DB 195,8,8,8
.DB 196,8,8,8
.DB 197,8,8,8
.DB 198,8,8,8
.DB 199,8,8,8
.DB 200,8,8,8
.DB 201,8,8,8
.DB 202,8,8,8
.DB 203,8,8,8
.DB 204,8,8,8
.DB 205,8,8,8
.DB 206,8,8,8
.DB 207,8,8,8
.DB 208,8,8,8
.DB 209,8,8,8
.DB 210,8,8,8
.DB 211,8,8,8
.DB 212,8,8,8
.DB 213,8,8,8
.DB 214,8,8,8
.DB 215,8,8,8
.DB 216,8,8,8
.DB 217,8,8,8
.DB 218,8,8,8
.DB 219,8,8,8
.DB 220,8,8,8
.DB 221,8,8,8
.DB 222,8,8,8
.DB 223,8,8,8
.DB 224,8,8,8
.DB 225,8,8,8
.DB 226,8,8,8
.DB 227,8,8,8
.DB 228,8,8,8
.DB 229,8,8,8
.DB 230,8,8,8
.DB 231,8,8,8
.DB 232,8,8,8
.DB 233,8,8,8
.DB 234,8,8,8
.DB 235,8,8,8
.DB 236,8,8,8
.DB 237,8,8,8
.DB 238,8,8,8
.DB 239,8,8,8
.DB 240,8,8,8
.DB 241,8,8,8
.DB 242,8,8,8
.DB 243,8,8,8
.DB 244,8,8,8
.DB 245,8,8,8
.DB 246,8,8,8
.DB 247,8,8,8
.DB 248,8,8,8
.DB 249,8,8,8
.DB 250,8,8,8
.DB 251,8,8,8
36
.DB 252,8,8,8
.DB 253,8,8,8
.DB 254,8,8,8
.DB 255,8,8,8
37
6.Documentazione delle prove di verifica
Le prove di collaudo eseguite in laboratorio hanno dato esito positivo, come dimostrato dalla seguente
documentazione fotografica. Per alcune prove sono riportati commenti e osservazioni per una più
immediata comprensione dei risultati.
6.1 Verifica del sistema di allarme per la tensione di alimentazione
VAL > 4,8 V ± 0,15 V : led spento VAL < 4,2 V ± 0,15 V : led acceso fisso
38
6.2 Verifica della temporizzazione della verifica della tensione di
alimentazione
4,8 V ± 0,15 V > VAL > 4,2 V ± 0,15 V : led lampeggiante, si visualizza sull’oscilloscopio la tensione ai capi
del led, significativa della sua temporizzazione
39
6.3 Verifica della massima corrente assorbita
40
6.4 Verifica dell’accuratezza degli estremi di misura
41
L’incertezza assoluta varia al variare del periodo misurato: questo avviene perché il campionamento
non avviene esattamente ogni 50 ms (fS=20 Hz) come assunto dall’algoritmo per ricavare il periodo,
ma ogni 51,2 ms. All’aumentare del periodo si ha un accumulo dell’errore, per questo motivo
l’accuratezza negli estremi è 0,1 s per periodi di 1 s e 0,3 s per periodi di 8 s. Come accuratezza dello
strumento si è scelta la maggiore delle due, quindi 300 ms.
6.5 Verifica del funzionamento del sistema di acquisizione ed elaborazione
del segnale e di pilotaggio dei display
42
6.6 Verifica del funzionamento del deviatore e della misura della
frequenza
43
44
6.7 Verifica del funzionamento complessivo del dispositivo
Il segnale visualizzato sull’oscilloscopio corrisponde all’uscita del circuito di condizionamento del sensore
NTC quando questo è posto al di sotto delle narici di un soggetto. Il valore del periodo visualizzato sui
display è compatibile con quello ricavabile dalla traccia dell’oscilloscopio
45
Appendice A: algoritmo di ricerca del periodo
Il segnale campionato ha una banda di frequenza dell’ordine delle frazioni di Hz (tipicamente 0,25-
0,5 Hz), per via delle risoluzione richiesta (100 ms) non è possibile campionare il segnale a frequenze
inferiori a 10 Hz. Si è scelta dunque una frequenza di campionamento fS= 20 Hz.
Questo comporta una difficile elaborazione del segnale per via del fatto che la frequenza di
campionamento è circa 40 volte la frequenza di banda.
Per identificare la migliore strategia di ricerca del periodo si sono eseguite simulazioni Matlab del
segnale già campionato a 20 Hz dal microcontrollore. Si è impostato un segnale sinusoidale con
caratteristiche simili a quello presente sull’uscita del sensore: offset di 1,5 V, ampiezza picco-picco
1 V, ampiezza picco-picco del rumore sovrapposto 50 mV, periodi 2s, 4s e 8s. Per simulare
l’acquisizione tramite l’ADC del microcontrollore si è introdotta una discretizzazione su 256 livelli
con tensione di full-range dell’ADC 2,56 V.
Eseguendo la media mobile su finestre di 4 campioni si è osservato un miglioramento del rapporto
segnale rumore, tuttavia il campionamento a frequenza molto maggiore rispetto alla banda del segnale
osservato comporta il fatto che le variazioni lente del segnale in corrispondenza di massimi e minimi
relativi si traducano in tratti di plateau, rendendo impossibile l’identificazione esatta del punto di
massimo o minimo relativo.
Si è dunque pensato di sfruttare i cambi di segno della derivata per ricavare il periodo nel seguente
modo: confrontando il valore di ogni campione Cn con quello precedente Cn-1 e assegnando un valore
1 ad una flag se Cn-1 ≤ Cn e 0 se Cn-1 > Cn .
In questo modo si ottiene un segnale simile ad un’onda quadra ed è possibile trovare il periodo
misurando la distanza tra due fronti di salita. Tuttavia si è osservato come il segnale così modificato
46
presenti dei “rimbalzi” che possono essere interpretati erroneamente come fronti di salita e discesa
successivi portando ad errori nell’identificazione del periodo.
t (s)
t (s)
47
Per risolvere questo problema si è pensato di verificare che i 7 campioni successivi a quello
identificato come fronte di salita corrispondano tutti ad un valore 1 della flag: in questo modo
l’algoritmo non considera i rimbalzi e riesce comunque ad identificare i veri fronti di salita
corrispondenti a periodi significativi (se T=1s, allora l’onda quadra presenta 10 campioni di valore 1
consecutivi ad un vero fronte di salita).
Questo metodo limita però il massimo periodo misurabile, perché occorre che due veri fronti di salita
successivi cadano all’interno della finestra di osservazione: questo si verifica con certezza solo se il
periodo del segnale è inferiore a metà della finestra di osservazione. Un periodo maggiore comporta
il fatto che alcune finestre di osservazione debbano essere scartate. Quando ciò avviene l’algoritmo
produce in uscita sui display un messaggio d’errore, evitando così di comunicare informazioni errate.
Si è scelta una finestra di osservazione della durata di 12 s, accettando la possibilità di avere errori di
riconoscimento per valori di periodo maggiori di 6 s. Si è scelto un periodo massimo misurabile di 8
s, sia perché questo valore è di per sé elevato per una respirazione fisiologica, sia perché fino a questo
valore non si ha una probabilità troppo elevata di scartare misurazioni.
Si riportano di seguito gli script Matlab utilizzati per la simulazione e la realizzazione dei grafici
sopra riportati:
% test_segnale.m
clear all
t (s)
48
close all
clc
t=0:0.05:10;
f=0.125;
phi=1;
for i=1:length(t)
signal(i)=floor((0.5*sin(2*pi*f*t(i)+phi)+1.5)/2.56*256)+5*rand(1);
end
for i=4:length(t)
media_mobile(i-3)=floor((signal(i-3)+signal(i-2)+signal(i-1)+signal(i))/4);
end
media_mobile(length(t)-2)=NaN;
media_mobile(length(t)-1)=NaN;
media_mobile(length(t))=NaN;
figure();
plot(t,signal,t,media_mobile),grid;
title('T= 8s')
xlabel('t (s)')
ylabel('Tensione discretizzata')
legend('segnale','media mobile','Location','best');
% test_picchi.m
clear all
close all
clc
t=0:0.05:10; % campionamento ogni 50 ms (20 Hz)
f=0.5; % frequenza della sinusoide
phi=1; % fase
for i=1:length(t)
signal(i)=floor((0.5*sin(2*pi*f*t(i)+phi)+1.5)/2.56*256)+5*rand(1); %
segnale discretizzato su 256 livelli (8 bit)
end
for i=4:length(t)
media_mobile(i-3)=floor((signal(i-3)+signal(i-2)+signal(i-1)+signal(i))/4);
end
media_mobile(length(t)-2)=signal(length(t)-2);
media_mobile(length(t)-1)=signal(length(t)-1);
media_mobile(length(t))=signal(length(t));
for i=1:length(t)-1
if media_mobile(i)>=media_mobile(i+1)
flag(i)=50;
else
flag(i)=0;
end
end
flag(length(t))=0;
figure();
plot(t,signal,t,media_mobile,t,flag);
title('V_p_p = 1 V; V_o_f_f_s_e_t=1,5 V; V_p_p_,_n_o_i_s_e=50 mV; T = 2 s');
legend('segnale','media mobile','flag');
f1=0.25;
for i=1:length(t)
signal1(i)=floor((0.5*sin(2*pi*f1*t(i)+phi)+1.5)/2.56*256)+5*rand(1);
end
49
for i=4:length(t)
media_mobile1(i-3)=floor((signal1(i-3)+signal1(i-2)+signal1(i-
1)+signal1(i))/4);
end
media_mobile1(length(t)-2)=signal1(length(t)-2);
media_mobile1(length(t)-1)=signal1(length(t)-1);
media_mobile1(length(t))=signal1(length(t));
for i=1:length(t)-1
if media_mobile1(i)>=media_mobile1(i+1)
flag1(i)=50;
else
flag1(i)=0;
end
end
flag1(length(t))=0;
figure();
plot(t,signal1,t,media_mobile1,t,flag1);
title('V_p_p = 1 V; V_o_f_f_s_e_t=1,5 V; V_p_p_,_n_o_i_s_e=50 mV; T =4 s');
legend('segnale','media mobile','flag');
f2=1/8;
for i=1:length(t)
signal2(i)=floor((0.5*sin(2*pi*f2*t(i)+phi)+1.5)/2.56*256+5*rand(1));
end
for i=4:length(t)
media_mobile2(i-3)=floor((signal2(i-3)+signal2(i-2)+signal2(i-
1)+signal2(i))/4);
end
media_mobile2(length(t)-2)=signal2(length(t)-2);
media_mobile2(length(t)-1)=signal2(length(t)-1);
media_mobile2(length(t))=signal2(length(t));
for i=1:length(t)-1
if media_mobile2(i)>=media_mobile2(i+1)
flag2(i)=50;
else
flag2(i)=0;
end
end
flag2(length(t))=0;
figure();
plot(t,signal2,t,media_mobile2,t,flag2);
title('V_p_p = 1 V; V_o_f_f_s_e_t=1,5 V; V_p_p_,_n_o_i_s_e=50 mV; T= 8 s');
legend('segnale','media mobile','flag');

More Related Content

What's hot

ATIPICO POTENTE TASCABILE INDUSTRIAL PLC
ATIPICO POTENTE TASCABILE INDUSTRIAL PLCATIPICO POTENTE TASCABILE INDUSTRIAL PLC
ATIPICO POTENTE TASCABILE INDUSTRIAL PLC
Rémi GUILBERT
 
Radioastronomia amatoriale e radiotelescopi
Radioastronomia amatoriale e radiotelescopiRadioastronomia amatoriale e radiotelescopi
Radioastronomia amatoriale e radiotelescopi
Flavio Falcinelli
 
uNav - Board
uNav - BoarduNav - Board
uNav - Board
Roberto D'Amico
 
Ltc2990 monitoraggio di temperatura, tensione e corrente con i2 c - 2010-11-10
Ltc2990   monitoraggio di temperatura, tensione e corrente con i2 c - 2010-11-10Ltc2990   monitoraggio di temperatura, tensione e corrente con i2 c - 2010-11-10
Ltc2990 monitoraggio di temperatura, tensione e corrente con i2 c - 2010-11-10Ionela
 
Convertitori Digitale-Analogico
Convertitori Digitale-AnalogicoConvertitori Digitale-Analogico
Convertitori Digitale-Analogico
Pasquale Alba
 
Encoder per sistemi robotici, motori & applicazioni OEM - Lika Electronic - E...
Encoder per sistemi robotici, motori & applicazioni OEM - Lika Electronic - E...Encoder per sistemi robotici, motori & applicazioni OEM - Lika Electronic - E...
Encoder per sistemi robotici, motori & applicazioni OEM - Lika Electronic - E...
Lika Electronic
 
Progetto ldc
Progetto ldcProgetto ldc
Progetto ldc
aaa bbbb
 
Candy washing machine_error_code_
Candy washing machine_error_code_Candy washing machine_error_code_
Candy washing machine_error_code_
Domingo Arroyo
 
Timer multifunzione 555
Timer multifunzione 555Timer multifunzione 555
Timer multifunzione 555
Pasquale Alba
 
Attrezzature valsarmento
Attrezzature valsarmentoAttrezzature valsarmento
Attrezzature valsarmentoAndrea Quaranta
 
Crouzet Automation - em4 Guida alla scelta
Crouzet Automation - em4 Guida alla sceltaCrouzet Automation - em4 Guida alla scelta
Crouzet Automation - em4 Guida alla scelta
Crouzet
 
Circuiti logici combinatori registri flip flop
Circuiti logici combinatori registri flip flopCircuiti logici combinatori registri flip flop
Circuiti logici combinatori registri flip flop
Pasquale Alba
 
Conversione A/D
Conversione A/DConversione A/D
Conversione A/D
Pasquale Alba
 
Arduino ai raggi x
Arduino ai raggi xArduino ai raggi x
Arduino ai raggi x
Emanuele Bonanni
 
Progettare con Arduino come un Ingegnere
Progettare con Arduino come un IngegnereProgettare con Arduino come un Ingegnere
Progettare con Arduino come un Ingegnere
Emanuele Bonanni
 
EME ARI VERONA 2010
EME  ARI VERONA  2010EME  ARI VERONA  2010
Aggiornamento mash tun Karstein con SmartPID
Aggiornamento mash tun Karstein con SmartPIDAggiornamento mash tun Karstein con SmartPID
Aggiornamento mash tun Karstein con SmartPID
Arzaman SRL
 
Newsletter Lika Electronic Maggio 2016 IT
Newsletter Lika Electronic Maggio 2016 ITNewsletter Lika Electronic Maggio 2016 IT
Newsletter Lika Electronic Maggio 2016 IT
Lika Electronic
 

What's hot (20)

Attrezzature matera
Attrezzature materaAttrezzature matera
Attrezzature matera
 
ATIPICO POTENTE TASCABILE INDUSTRIAL PLC
ATIPICO POTENTE TASCABILE INDUSTRIAL PLCATIPICO POTENTE TASCABILE INDUSTRIAL PLC
ATIPICO POTENTE TASCABILE INDUSTRIAL PLC
 
Radioastronomia amatoriale e radiotelescopi
Radioastronomia amatoriale e radiotelescopiRadioastronomia amatoriale e radiotelescopi
Radioastronomia amatoriale e radiotelescopi
 
uNav - Board
uNav - BoarduNav - Board
uNav - Board
 
Ltc2990 monitoraggio di temperatura, tensione e corrente con i2 c - 2010-11-10
Ltc2990   monitoraggio di temperatura, tensione e corrente con i2 c - 2010-11-10Ltc2990   monitoraggio di temperatura, tensione e corrente con i2 c - 2010-11-10
Ltc2990 monitoraggio di temperatura, tensione e corrente con i2 c - 2010-11-10
 
Convertitori Digitale-Analogico
Convertitori Digitale-AnalogicoConvertitori Digitale-Analogico
Convertitori Digitale-Analogico
 
Assembly2
Assembly2Assembly2
Assembly2
 
Encoder per sistemi robotici, motori & applicazioni OEM - Lika Electronic - E...
Encoder per sistemi robotici, motori & applicazioni OEM - Lika Electronic - E...Encoder per sistemi robotici, motori & applicazioni OEM - Lika Electronic - E...
Encoder per sistemi robotici, motori & applicazioni OEM - Lika Electronic - E...
 
Progetto ldc
Progetto ldcProgetto ldc
Progetto ldc
 
Candy washing machine_error_code_
Candy washing machine_error_code_Candy washing machine_error_code_
Candy washing machine_error_code_
 
Timer multifunzione 555
Timer multifunzione 555Timer multifunzione 555
Timer multifunzione 555
 
Attrezzature valsarmento
Attrezzature valsarmentoAttrezzature valsarmento
Attrezzature valsarmento
 
Crouzet Automation - em4 Guida alla scelta
Crouzet Automation - em4 Guida alla sceltaCrouzet Automation - em4 Guida alla scelta
Crouzet Automation - em4 Guida alla scelta
 
Circuiti logici combinatori registri flip flop
Circuiti logici combinatori registri flip flopCircuiti logici combinatori registri flip flop
Circuiti logici combinatori registri flip flop
 
Conversione A/D
Conversione A/DConversione A/D
Conversione A/D
 
Arduino ai raggi x
Arduino ai raggi xArduino ai raggi x
Arduino ai raggi x
 
Progettare con Arduino come un Ingegnere
Progettare con Arduino come un IngegnereProgettare con Arduino come un Ingegnere
Progettare con Arduino come un Ingegnere
 
EME ARI VERONA 2010
EME  ARI VERONA  2010EME  ARI VERONA  2010
EME ARI VERONA 2010
 
Aggiornamento mash tun Karstein con SmartPID
Aggiornamento mash tun Karstein con SmartPIDAggiornamento mash tun Karstein con SmartPID
Aggiornamento mash tun Karstein con SmartPID
 
Newsletter Lika Electronic Maggio 2016 IT
Newsletter Lika Electronic Maggio 2016 ITNewsletter Lika Electronic Maggio 2016 IT
Newsletter Lika Electronic Maggio 2016 IT
 

Similar to Relazione pdbp 2016 gruppo 05 brondino gabetti boscaglia giordano

Con display e pulsanti: sensori di temperatura compatti ad infrarossi di ifm ...
Con display e pulsanti: sensori di temperatura compatti ad infrarossi di ifm ...Con display e pulsanti: sensori di temperatura compatti ad infrarossi di ifm ...
Con display e pulsanti: sensori di temperatura compatti ad infrarossi di ifm ...
ifm electronic gmbh
 
Relazione Taratura trasduttore di pressione
Relazione Taratura trasduttore di pressioneRelazione Taratura trasduttore di pressione
Relazione Taratura trasduttore di pressioneStefano Manca
 
Accessori installazione catalogo
Accessori installazione catalogoAccessori installazione catalogo
Workshop arduino
Workshop arduinoWorkshop arduino
Workshop arduino
Flaviano Fior
 
Accessori installazione catalogo
Accessori installazione catalogoAccessori installazione catalogo
Accessori installazione catalogo
Accessori installazione catalogoAccessori installazione catalogo
Catalogo osmosi inversa componenti elettrovalvole sensori 20092015
Catalogo osmosi inversa componenti elettrovalvole sensori 20092015Catalogo osmosi inversa componenti elettrovalvole sensori 20092015
Catalogo osmosi inversa componenti elettrovalvole sensori 20092015
Depuratori Acqua Osmosi Inversa Addolcitori Sinergroup
 
Accessori installazione catalogo
Accessori installazione catalogoAccessori installazione catalogo
Catalogo accessori componenti_installazione_depuratori_acqua_20092015
Catalogo accessori componenti_installazione_depuratori_acqua_20092015Catalogo accessori componenti_installazione_depuratori_acqua_20092015
Catalogo accessori componenti_installazione_depuratori_acqua_20092015
Depuratori Acqua Osmosi Inversa Addolcitori Sinergroup
 
13/10/2017 Sinergroup - Accessori installazione
13/10/2017 Sinergroup - Accessori installazione13/10/2017 Sinergroup - Accessori installazione
13/10/2017 Sinergroup - Accessori installazione
Depuratori Acqua Osmosi Inversa Addolcitori Sinergroup
 
Accessori installazione catalogo
Accessori installazione catalogoAccessori installazione catalogo
Accessori installazione catalogo
Accessori installazione catalogoAccessori installazione catalogo
Accessori installazione catalogo
Accessori installazione catalogoAccessori installazione catalogo
Accessori installazione catalogo
Accessori installazione catalogoAccessori installazione catalogo
Yielding Robot and Rigid Environment - Contact Force Control (IT)
Yielding Robot and Rigid Environment - Contact Force Control (IT)Yielding Robot and Rigid Environment - Contact Force Control (IT)
Yielding Robot and Rigid Environment - Contact Force Control (IT)
EnricoMarinelli3
 
Accessori installazione catalogo
Accessori installazione catalogoAccessori installazione catalogo
Ifm pressure-sensors-pn-brochure-2014-it
Ifm pressure-sensors-pn-brochure-2014-itIfm pressure-sensors-pn-brochure-2014-it
Ifm pressure-sensors-pn-brochure-2014-itifm electronic gmbh
 
Accessori installazione catalogo
Accessori installazione catalogoAccessori installazione catalogo
Accessori installazione catalogo
Accessori installazione catalogo Accessori installazione catalogo
Accessori installazione catalogo
Accessori installazione catalogo Accessori installazione catalogo

Similar to Relazione pdbp 2016 gruppo 05 brondino gabetti boscaglia giordano (20)

Con display e pulsanti: sensori di temperatura compatti ad infrarossi di ifm ...
Con display e pulsanti: sensori di temperatura compatti ad infrarossi di ifm ...Con display e pulsanti: sensori di temperatura compatti ad infrarossi di ifm ...
Con display e pulsanti: sensori di temperatura compatti ad infrarossi di ifm ...
 
Relazione Taratura trasduttore di pressione
Relazione Taratura trasduttore di pressioneRelazione Taratura trasduttore di pressione
Relazione Taratura trasduttore di pressione
 
Accessori installazione catalogo
Accessori installazione catalogoAccessori installazione catalogo
Accessori installazione catalogo
 
Workshop arduino
Workshop arduinoWorkshop arduino
Workshop arduino
 
Accessori installazione catalogo
Accessori installazione catalogoAccessori installazione catalogo
Accessori installazione catalogo
 
Accessori installazione catalogo
Accessori installazione catalogoAccessori installazione catalogo
Accessori installazione catalogo
 
Catalogo osmosi inversa componenti elettrovalvole sensori 20092015
Catalogo osmosi inversa componenti elettrovalvole sensori 20092015Catalogo osmosi inversa componenti elettrovalvole sensori 20092015
Catalogo osmosi inversa componenti elettrovalvole sensori 20092015
 
Accessori installazione catalogo
Accessori installazione catalogoAccessori installazione catalogo
Accessori installazione catalogo
 
Catalogo accessori componenti_installazione_depuratori_acqua_20092015
Catalogo accessori componenti_installazione_depuratori_acqua_20092015Catalogo accessori componenti_installazione_depuratori_acqua_20092015
Catalogo accessori componenti_installazione_depuratori_acqua_20092015
 
13/10/2017 Sinergroup - Accessori installazione
13/10/2017 Sinergroup - Accessori installazione13/10/2017 Sinergroup - Accessori installazione
13/10/2017 Sinergroup - Accessori installazione
 
Accessori installazione catalogo
Accessori installazione catalogoAccessori installazione catalogo
Accessori installazione catalogo
 
Accessori installazione catalogo
Accessori installazione catalogoAccessori installazione catalogo
Accessori installazione catalogo
 
Accessori installazione catalogo
Accessori installazione catalogoAccessori installazione catalogo
Accessori installazione catalogo
 
Accessori installazione catalogo
Accessori installazione catalogoAccessori installazione catalogo
Accessori installazione catalogo
 
Yielding Robot and Rigid Environment - Contact Force Control (IT)
Yielding Robot and Rigid Environment - Contact Force Control (IT)Yielding Robot and Rigid Environment - Contact Force Control (IT)
Yielding Robot and Rigid Environment - Contact Force Control (IT)
 
Accessori installazione catalogo
Accessori installazione catalogoAccessori installazione catalogo
Accessori installazione catalogo
 
Ifm pressure-sensors-pn-brochure-2014-it
Ifm pressure-sensors-pn-brochure-2014-itIfm pressure-sensors-pn-brochure-2014-it
Ifm pressure-sensors-pn-brochure-2014-it
 
Accessori installazione catalogo
Accessori installazione catalogoAccessori installazione catalogo
Accessori installazione catalogo
 
Accessori installazione catalogo
Accessori installazione catalogo Accessori installazione catalogo
Accessori installazione catalogo
 
Accessori installazione catalogo
Accessori installazione catalogo Accessori installazione catalogo
Accessori installazione catalogo
 

Relazione pdbp 2016 gruppo 05 brondino gabetti boscaglia giordano

  • 1. 0 POLITECNICO DI TORINO A.A. 2016/2017 Corso di Progettazione di dispositivi biomedici programmabili Misuratore della frequenza respiratoria (RR) basato su NTC Gruppo 5, LED 7, Tavolo 5 Marta Boscaglia s242462, responsabile progettazione software Alessio Brondino s242491, responsabile documentazione Stefano Gabetti s235287, responsabile progettazione hardware Gabriele Giordano s242511, responsabile progettazione integrata
  • 2. 1 Indice 1. Specifiche di progetto................................................................................................................................ 2 1.1 Opzioni migliorative................................................................................................................................ 2 1.2 Prove di verifica ...................................................................................................................................... 2 2. Schema elettrico ........................................................................................................................................ 4 3. Calcoli di progetto ..................................................................................................................................... 6 3.1 Stima della massima corrente assorbita dal circuito................................................................................ 6 3.2 Dimensionamento del resistore di caduta del led .................................................................................... 6 3.3 Dimensionamento dei resistori di caduta dei led dei display a sette segmenti........................................ 6 3.4 Circuito di condizionamento del sensore NTC........................................................................................ 6 4. Descrizione del Software........................................................................................................................... 8 4.1 Diagramma a blocchi............................................................................................................................... 9 4.2 Flow-chart delle singole routine............................................................................................................ 10 5. Listato completo del codice..................................................................................................................... 17 6. Documentazione delle prove di verifica.................................................................................................. 37 6.1 Verifica del sistema di allarme per la tensione di alimentazione .......................................................... 37 6.2 Verifica della temporizzazione della verifica della tensione di alimentazione ..................................... 38 6.3 Verifica della massima corrente assorbita............................................................................................. 39 6.4 Verifica dell’accuratezza degli estremi di misura ................................................................................. 40 6.5 Verifica del funzionamento del sistema di acquisizione ed elaborazione del segnale e di pilotaggio dei display ......................................................................................................................................................... 41 6.6 Verifica del funzionamento del deviatore e della misura della frequenza............................................. 42 6.7 Verifica del funzionamento complessivo del dispositivo...................................................................... 44 Appendice A: algoritmo di ricerca del periodo ............................................................................................... 45
  • 3. 2 1.Specifiche di progetto  Tensione di alimentazione: Val = 5 V ± 150 mV;  Massima corrente assorbita: Ialmax = 400 mA;  Verifica della tensione di alimentazione a intervalli di circa 1 s e sistema di allarme con led rosso:  Se Val > 4,2 V ± 150 mV led spento  Se Val < 4,2 V ± 150 mV led acceso fisso  Misurazione del periodo respiratorio (s) mediante sensore NTC posto al di sotto delle narici;  Misurazione fornita in uscita su tre display a sette segmenti;  Frequenza di campionamento 20 Hz, durata dei brani di segnale 12 s;  Risoluzione 100 ms;  Accuratezza 300 ms;  I display permettono di visualizzare valori di periodo respiratorio compresi tra 1 s ± 0,1 s e 8 s ± 0,3 s, valori al di fuori di questo intervallo comportano la visualizzazione sui display del messaggio d’allarme “888”; 1.1 Opzioni migliorative  Verifica della tensione di alimentazione con sistema di allarme a due soglie:  Se Val > 4,8 V ± 150 mV led spento  Se 4,8 V ± 150 mV > Val > 4,2 V ± 150 mV led lampeggiante  Se Val > 4,2 V ± 150 mV led acceso fisso  Possibilità di inserire un dip-switch per visualizzare sui display in alternativa periodo respiratorio (s) o frequenza respiratoria (atti respiratori/min). 1.2 Prove di verifica  Verifica del sistema di allarme per la tensione di alimentazione: dopo aver alimentato il circuito con un alimentatore stabilizzato regolato ad un valore di tensione di 5,0 V ± 0,15 V ed in grado di erogare una corrente massima di 400 mA, si collega il multimetro in parallelo all’alimentatore per misurare con accuratezza la tensione di alimentazione. Agendo sull’alimentatore si fa variare la tensione di alimentazione del circuito partendo da quella nominale diminuendola progressivamente a passi di 100 mV fino al valore di 3,9 V, dopodiché si risale sempre a passi di 100 mV fino al valore nominale. Durante la prova si osserva il cambiamento dello stato del led: il led dovrà essere spento per valori di tensione superiori a 4,8 V ± 0,15 V, lampeggiante per valori di tensione compresi tra 4,8 V ± 0,15 V e 4,2 V ± 0,15 V e acceso fisso per valori inferiori a 4,2 V ± 0,15 V;  Verifica della temporizzazione della verifica della tensione di alimentazione: lo stato del pin 15 del microcontrollore viene complementato ad ogni verifica della tensione, mediante
  • 4. 3 l’oscilloscopio si osserva lo stato del pin. L’uscita del pin dovrà variare tra un livello logico alto e un livello logico basso ad intervalli di 1 s ± 0,1 s ed ogni 12 variazioni un livello sarà mantenuto per un tempo maggiore di quello indicato, perché durante l’elaborazione del segnale si sospende momentaneamente oltre al campionamento anche il controllo della tensione per ripartire al termine con uguale temporizzazione per entrambe le operazioni;  Verifica della massima corrente assorbita: si collega innanzitutto l’amperometro in serie al circuito. Dopodiché si sostituisce all’uscita del sensore NTC un segnale sinusoidale di ampiezza 1 Vpp, offset 1,5 V e periodo 20s ottenuto dal generatore di segnali in modo che siano accesi tutti i segmenti dei display (caso di massima corrente assorbita) e si misura la corrente assorbita, che dovrà essere inferiore a 400 mA;  Verifica dell’accuratezza degli estremi di misura: si sostituiscono all’uscita del sensore NTC segnali sinusoidali di ampiezza 1 Vpp, offset 1,5 V e periodo rispettivamente 0,8 s e 8,4 s ottenuti dal generatore di segnali: in entrambi i casi dovrà essere visualizzato sui display il messaggio d’allarme “888”;  Verifica del funzionamento del sistema di acquisizione ed elaborazione del segnale e di pilotaggio dei display: si sostituiscono all’uscita del sensore NTC in successione 3 segnali sinusoidali di ampiezza 1 Vpp, offset 1,5 V e periodi rispettivamente 2 s, 4 s e 6 s ottenuti con il generatore di segnali. Si osserva il valore del periodo dato in uscita dai display, che deve essere compatibile con quello dato dal generatore di segnali a meno dell’errore massimo garantito;  Verifica del funzionamento del deviatore e della misura della frequenza: selezionando le stesse forme d’onda della prova precedente e selezionando la visualizzazione della frequenza mediante il deviatore, per ognuna delle misure dovrà essere visualizzata la frequenza in cicli al minuto corrispondente al periodo (rispettivamente 30 cicli/min, 15 cicli/min, 10 cicli/min) a meno dell’errore massimo garantito;  Verifica del funzionamento complessivo del dispositivo: si collega l’uscita del circuito di condizionamento del sensore al pin 25 del microcontrollore e si visualizza il segnale in uscita dal circuito di condizionamento sull’oscilloscopio. Posizionando il sensore al di sotto delle narici di un soggetto si osserva il valore del periodo respiratorio misurato, che dovrà essere compatibile con quello visualizzato sull’oscilloscopio. Firma Committente _______________________________ Firme Progettisti ________________________________ ________________________________ ________________________________ ________________________________
  • 6. 5 Il circuito del misuratore di frequenza respiratoria si basa sul funzionamento di un sensore NTC collegato adeguatamente ad un ingresso del microcontrollore ATmega8. Il microcontrollore riceve in ingresso sul pin 25 il segnale di tensione in uscita dal circuito di condizionamento del sensore (realizzato mediante un circuito integrato LM358P), lo elabora opportunamente grazie al firmware caricato nella sua Program Flash e pilota mediante tre linee di latch-enable (in uscita dai pin 11,12,13) e quattro linee di segnale (pin 2,3,4,5) tre display a 7 segmenti tramite tre decoder CD4511. Il microcontrollore esegue anche la verifica della tensione di alimentazione leggendo il valore di tensione sul pin 24 (corrispondente a metà della tensione di alimentazione). Dopo averlo confrontato con le soglie impostate il microcontrollore pilota tramite il pin 23 il funzionamento di un led rosso. Per ogni circuito integrato si è inserito un condensatore di bypass da 100 nF tra il pin di alimentazione e riferimento di massa. Mediante un deviatore a due posizioni collegato al pin 16 è possibile selezionare la visualizzazione sui display del periodo o della frequenza misurati.
  • 7. 6 3.Calcoli di progetto 3.1 Stima della massima corrente assorbita dal circuito Si suppone un consumo massimo dei componenti del circuito come: 10 mA per ogni segmento acceso dei display (ID), 10 mA per il led acceso (IL), 10 mA per ognuno degli integrati CD4511 (IC), 10 mA per l’integrato LM358P (IA) e 20 mA per il microcontrollore ATmega8 (IK). Da questo risulta una corrente massima: I 𝑚𝑎𝑥 = I 𝐿 + 22 ∗ I 𝐷 + 3 ∗ I 𝐶 + I 𝐴 + I 𝐾 = 290 𝑚𝐴 Per garantire un discreto margine che assicuri il funzionamento del circuito si dichiara una massima corrente assorbita di 400 mA. 3.2 Dimensionamento del resistore di caduta del led Un led rosso ha tensione di soglia nominale VL di circa 1,6 V e assorbe durante il normale funzionamento una corrente IL di circa 10 mA. Considerando questi dati il valore del resistore di caduta risulta: 𝑅 = 𝑉𝐴𝐿 − 𝑉𝐿 𝐼𝐿 = 340 Ω Questo valore non si trova all’interno della serie di resistori con tolleranza 5%. Volendo diminuire il valore della potenza dissipata si è scelto quindi un resistore da 390 Ω in modo da avere un valore di corrente inferiore a quello nominale IL. 3.3 Dimensionamento dei resistori di caduta dei led dei display a sette segmenti Ogni segmento è un led rosso, per cui ipotizzando gli stessi valori del dimensionamento precedente si ottiene un valore del resistore di caduta di 340 Ω. In questo caso, volendo ottenere una maggiore luminosità e dunque una più facile lettura del risultato, si è scelto un resistore da 330 Ω in modo da ottenere un valore di corrente leggermente maggiore di quella nominale IL. 3.4 Circuito di condizionamento del sensore NTC
  • 8. 7 La dinamica del segnale osservata direttamente all’uscita del sensore è dell’ordine delle decine di mV, occorre dunque amplificare il segnale in modo da ottenere una dinamica maggiore di almeno un ordine di grandezza rispetto alla tensione di quantizzazione dell’ADC (10 mV) e minore di quella d’ingresso dell’ADC (2,56 V). Il circuito di condizionamento così realizzato introduce in uscita un offset di circa 1,6 V e amplifica di un fattore 10 la dinamica del segnale. Sperimentalmente si è osservata una dinamica all’uscita del circuito di condizionamento dell’ordine delle centinaia di mV.
  • 9. 8 4.Descrizione del Software Il firmware è stato realizzato in linguaggio assembler mediante l’ambiente di sviluppo Atmel Studio 7.0 e caricato nella Program Flash del microcontrollore ATmega8 utilizzando la scheda AVR Dragon. Il programma eseguito dal microcontrollore si suddivide in:  Campionamento del segnale ricevuto dal sensore NTC e salvataggio nella SRAM ogni 50 ms circa;  Verifica della tensione di batteria ogni 1000 ms circa;  Elaborazione del segnale campionato: - Media mobile su finestre di 4 campioni per ridurre il rumore presente sul segnale e scrittura dei valori mediati sulla SRAM; - Algoritmo per la ricerca del periodo del segnale mediato (dettagliato nell’Appendice A).  Pilotaggio dei display per fornire in uscita il periodo misurato o la frequenza corrispondente.
  • 10. 9 4.1 Diagramma a blocchi var_battery=100
  • 11. 10 4.2 Flow-chart delle singole routine
  • 12. 11
  • 13. 12
  • 15. 14
  • 16. 15
  • 17. 16 Subroutine di riposta all’interrupt
  • 18. 17 5.Listato completo del codice Di seguito si riporta l’intero listato del codice in linguaggio assembler caricato nella Program Flash dell’ATmega8 opportunamente commentato. ; ---- PROGRAMMA ASSEMBLER PER MICROCONTROLLORE ATmega8 ---- ; ; - Politecnico di Torino ; - Corso di Laurea Magistrale in Ingegneria Biomedica ; - Esame di Progettazione di Dispositivi Biomedici Programmabili ; - A.A. 2016/2017 ; - Progetto: Misuratore di frequenza respiratoria (RR) basato su NTC ; - Autori: Marta Boscaglia, Alessio Brondino, Stefano Gabetti, Gabriele Giordano ; ; ; Definizione dei registri utilizzati .DEF mp = R16 ; registro di lavoro (generico) .DEF mp1 = R17 ; registro di lavoro secondario (generico) .DEF var_sample = R18 ; variabile (tempo di campionamento) decrementata dalla ;subroutine di risposta ad interrupt .DEF count_sample = R19 ; variabile che conta il numero di campioni di segnale acquisiti ;e successivamente il numero di campioni elaborati .DEF var_battery = R20 ; variabile (intervallo di controllo batteria) decrementata dalla ;subroutine di risposta ad interrupt .DEF flag_battery = R21 ; flag utilizzata per determinare lo stato della batteria e ;successivamente in alcune routine del signal processing .DEF sample1 = R22 ; registro riservato per salvare un campione del brano di segnale .DEF sample2 = R23 ; registro riservato per salvare un campione del brano di segnale .DEF sample3 = R24 ; registro riservato per salvare un campione del brano di segnale .DEF sample4 = R25 ; registro riservato per salvare un campione del brano di segnale ; ; Definizione delle soglie .EQU th1=0b11110000 ;soglia 2,4 V (flag->1) .EQU th2=0b11010010 ;soglia 2,1 V (flag->2) ; Vettore di interrupt rjmp RESET ; Reset Handler reti ;rjmp EXT_INT0 ; IRQ0 Handler reti ;rjmp EXT_INT1 ; IRQ1 Handler reti ;rjmp TIM2_COMP ; Timer2 Compare Handler reti ;rjmp TIM2_OVF ; Timer2 Overflow Handler reti ;rjmp TIM1_CAPT ; Timer1 Capture Handler reti ;rjmp TIM1_COMPA ; Timer1 CompareA Handler reti ;rjmp TIM1_COMPB ; Timer1 CompareB Handler reti ;rjmp TIM1_OVF ; Timer1 Overflow Handler rjmp TIM0_OVF ;Timer0 Overflow Handler reti ;rjmp SPI_STC ; SPI Transfer Complete Handler reti ;rjmp USART_RXC ; USART RX Complete Handler reti ;rjmp USART_UDRE ; UDR Empty Handler reti ;rjmp USART_TXC ; USART TX Complete Handler reti ;rjmp ADC_conv ; ADC Conversion Complete Handler reti ;rjmp EE_RDY ; EEPROM Ready Handler reti ;rjmp ANA_COMP ; Analog Comparator Handler reti ;rjmp TWSI ; Two-wire Serial Interface Handler reti ;rjmp SPM_RDY ; Store Program Memory Ready Handler ; Si sono abilitati solo gli interrupt corrispondenti al power-on reset e all'overflow del ;timer counter 0 ; RESET: ; In questo punto inizia la routine principale del programma ; Si procede innanzitutto alle inizializzazioni dei registri che saranno utilizzati dalle ;routine del programma
  • 19. 18 ; Tra questi ci sono quelli relativi alle porte di I/O, all'AD Converter e lo stack pointer ; ---- Inizializzazione dello STACK POINTER ldi mp,0x04 out SPH,mp ldi mp,0x5f out SPL,mp ; Lo stack pointer è stato allocato all'indirizzo corrispondente alla parte ; alta della RAM disponibile, poiché lo stack pointer quando utilizzato viene ; decrementato e successivamente incrementato dopo l'utilizzo. ; ; ---- Inizializzazione di PORTC ldi mp,0b00000001 ; ; Per questa porta di I/O si definisce quali pin sono utilizzati come uscite e quali come ;ingressi. ; I pin che sono usati come uscite, nel nostro caso per pilotare un led, devono ; avere il corrispondente bit nel registro direzione dati (DDR) ad '1'. ; I rimanenti in ingresso devono avere i bit a '0'. ; out DDRC,mp ; La parola è stata inizialmente scritta nel registro mp e poi successivamente, tramite ;l'istruzione out ; caricata nel Data Direction Register della porta C ; In questo modo è stato definito come uscita il pin 23 del microcontrollore (PC0), tramite ;questo pin sarà pilotato il led. ldi mp,0x00 out PORTC,mp ; Si scrive il valore zero nella porta C, il led è inizializzato spento. ; ; ---- Inizializzazione di PORTD ldi mp,0b11101111 out DDRD,mp ; Si abilitano i pin I/O in uscita in DDRD, in questo modo si sono abilitati come uscita i ;pin 2,3,4,5,11,12,13 dell'ATmega8 ; PORTD permette di pilotare i display a 7 segmenti, in particolare i primi 4 pin ;(PD0,PD1,PD2,PD3) pilotano le linee A,B,C,D ; che danno in ingresso ai decoder le parole con codifica BCD contenenti il numero da ;visualizzare sul singolo display, ; gli ultimi 3 pin (PD5,PD6,PD7) costituiscono i 3 Latch-Enable che permettono di ;selezionare separatamente ognuno dei 3 decoder ; per scrivere il numero sul display corretto (decine, unità, decimi) ; ; ---- Inizializzazione di PORTB ldi mp,0b00000010 out DDRB,mp ; E' stato definito come uscita il pin 15 del microcontrollore (PB1) ; tramite questo pin sarà verificata la tempistica del controllo della tensione di batteria ldi mp,0x00 out PORTB,mp ; Si scrive il valore zero nella porta B ; ---- Inizializzazione del Timer/Counter0 ldi mp,0b00000101 out TCCR0,mp ; Si seleziona per il prescaler passo 1024 (se 1MHz allora 1024us) ; Il contatore sarà quindi incrementato a passi di circa 1ms (1,024ms) ; ldi mp,246 out TCNT0,mp ; seleziona tempo tra interrupt pari a circa 10ms (10,24ms) ; ldi mp,0x01 out TIMSK,mp ; abilita l'interrupt in caso di overflow di TCNT0
  • 20. 19 ; ldi var_battery,100 ; Si inizializza la variabile var_battery che sarà decrementata dalla subroutine di risposta ;ad interrupt ; In questo modo si ottiene una variabile che raggiungerà il valore 0 dopo circa 1s ;(var_battery = 100 -> 1024 ms), ; permettendoci così di effettuare la verifica dello stato della batteria ad intervalli ;regolari di circa 1000ms come richiesto ; ldi var_sample,5 ; Si inizializza la variabile var_sample che sarà decrementata dalla subroutine di risposta ;ad interrupt (var_sample = 5 -> 51,2 ms) ; In questo modo si ottiene il campionamento del segnale con Tc circa 50 ms (fc circa 20 Hz) ; ldi count_sample,0 ; Inizializza il contatore a 0 (nessun campione acquisito) ; ; ---- Inizializzazione dell'AD Converter ldi mp,0b11000000 out ADCSRA,mp ; Tramite il registro ADCSRA si decidono le seguenti impostazioni: si abilitano le funzioni ;dell'ADC e lo si avvia, ; non sarà utilizzata la modalità free-running (sia per motivi di consumo energetico, sia ;perché si preferisce avviare le conversioni ; dell'ADC con una temporizzazione nota mediante opportune istruzioni nel codice), ; non si abilitano gli interrupt e si sceglie il passo standard del prescaler ldi mp, 0b11100001 out ADMUX, mp ; Tramite il registro ADMUX si imposta: tensione di riferimento 2,56 V (riferimento interno ;Vref), ; risultato left adjusted (utilizzando l'High byte contente il risultato si avrà una ;risoluzione su 8 bit -> 256 livelli) ; canale d'ingresso ADC1 (pin 24, PC1) ldi flag_battery,0 ; Si inizializza flag_battery a 0, prima del primo controllo si suppone che la tensione di ;batteria sia a valori ottimali ; ; ---- Inizializzazione del registro Z ldi ZH, HIGH(Table1*2) ldi ZL, LOW(Table1*2) ; Il registro Z sarà utilizzato nel corso del programma per contenere gli indirizzi delle ;celle della Program Flash ; in cui è salvata la lookup table. La lookup table permette di convertire il valore del ;periodo respiratorio misurato in campioni ; nel valore del periodo in secondi da dare in uscita sui display ; Si inizializza tale registro in modo che punti alla prima cella della prima riga della ;lookup table ; ; ------ Inizializzazione della SRAM: clr r27 ; clear dell'high byte di X ldi r26,$60 ; Nel programma si utilizzerà il registro X per contenere gli indirizzi delle celle di RAM ; in cui saranno salvati prima i valori dei campioni di segnale e successivamente altri ;valori derivanti dalle routine di ; elaborazione del segnale. Si inizializza il registro X al valore $0060 (primo indirizzo di ;SRAM disponibile) ; sei ; Mediante questo comando si abilitano gli interrupt a livello di SREG ; ; --------------------------------------- LOOP PRINCIPALE ------------------------------- ; Da questo punto inizia il loop infinito che viene eseguito dal microcontrollore
  • 21. 20 ; main_loop: cpi var_sample,0 brne check_battery_routine ; Se il valore contenuto in var_sample è 0 allora sono passati 50 ms e si procede al ;campionamento del segnale, ; altrimenti si salta alla routine di controllo dello stato della batteria sir: ldi var_sample,5 ; Si reinizializza var_sample a 5 per contare altri 50ms ; ; ----------------------- CAMPIONAMENTO DEL SEGNALE E SALVATAGGIO IN RAM --------------- ; ldi mp, 0b11100010 out ADMUX, mp ; Mediante ADMUX si seleziona come canale d'ingresso al convertitore il canale ADC2 (pin 25, ;PC2) ; ; ---- Routine di conversione dell'ADC ; in mp,ADCSRA ldi mp1,0b01000000 or mp,mp1 out ADCSRA,mp ; La routine è divisa in due parti: ; nella prima si carica un 1 nel bit 6 di ADCSRA per iniziare la conversione senza ;modificare gli altri bit ; check_conv_sample: in mp,ADCSRA ldi mp1,0b01000000 and mp,mp1 brne check_conv_sample ; nella seconda si attende che la conversione sia finita: si verifica che il valore del bit6 ;sia tornato a 0, ; finché questo non avviene il microcontrollore resta all'interno di questa routine di ;controllo ; (questo controllo crea dei tempi di attesa che però sono molto brevi, circa 30us) ; in mp,ADCH ; Si richiama il risultato della conversione in mp st X+,mp ; Il valore è salvato nella SRAM e il registro X post-incrementiamo, così da puntare alla ;cella successiva, ; dove si salverà il campione successivo inc count_sample ; Il contatore del numero di campioni acquisiti si incrementa ogni volta ; Un controllo successivo avvierà la routine di elaborazione del segnale quando il contatore ;avrà raggiunto il valore corrispondente ; alla lunghezza del brano di segnale che si vuole analizzare ; ;------------------------------- CONTROLLO DELLA TENSIONE DI BATTERIA ---------------------- ; check_battery_routine: cpi var_battery,0 brne signal_processing ; Se non è passato 1 s non si esegue la routine di controllo della batteria e si salta alla ;routine successiva ldi var_battery,100 ; Si reinizializza la variabile di temporizzazione (1 s) per temporizzare il controllo ;successivo ldi flag_battery,0 ; Ogni volta che si effettua il controllo occorre reinizializzare la flag a zero
  • 22. 21 ; ldi mp, 0b11100001 out ADMUX, mp ; Per eseguire il controllo sullo stato della batteria bisogna selezionare il canale ADC1 ;(PIN 24, PC1) come ingresso ; in mp,ADCSRA ldi mp1,0b01000000 or mp,mp1 out ADCSRA,mp check_conv_battery: in mp,ADCSRA ldi mp1,0b01000000 and mp,mp1 brne check_conv_battery ; La routine che misura la tensione della batteria è identica a quella che rileva il valore ;del campione di segnale ; in mp,ADCH ; Si legge il valore della tensione misurata cpi mp,th1 brsh check_battery_voltage_01 ldi flag_battery,1 ; Se il valore è inferiore alla prima soglia si modifica la flag e si passa alla verifica ;della 2a soglia, ; altrimenti si salta direttamente alla fine (è inutile verificare la 2a soglia) cpi mp,th2 brsh check_battery_voltage_01 ldi flag_battery,2 ; Se il valore è inferiore alla seconda soglia si modifica ancora la flag check_battery_voltage_01: cpi flag_battery,0 brne check_battery_voltage_02 ldi mp,0b00000000 out PORTC,mp ; Se la flag è 0 -> batteria OK, il led resta spento check_battery_voltage_02: cpi flag_battery,1 brne check_battery_voltage_03 ; Se la flag è 1 -> il valore della tensione è tra le 2 soglie, LED intermittente, occorre ;eseguire il toggle: in mp,PINC ldi mp1,0b00000001 and mp,mp1 ; si legge il valore del pin che pilota il led (si leggono tutti i pin della porta e si ; mascherano tutti ad eccezione di quello di interesse) ldi mp1,0b00000001 eor mp,mp1 ; eseguendo un or esclusivo tra mp ed mp1 si complementa il bit 0 di mp out PORTC,mp ; Il valore di mp è messo in uscita (se il led era acceso si spegne e viceversa, si ottiene ;così il lampeggio del led ad intervalli di 1 s) check_battery_voltage_03: cpi flag_battery,2 brne signal_processing ldi mp,0b00000001 out PORTC,mp ; Se la flag è 2 -> il valore della è tensione sotto la seconda soglia, LED acceso fisso ; ;--------------- ELABORAZIONE DEL SEGNALE -------------------- ; signal_processing: cpi count_sample,255
  • 23. 22 brne main_loop ; Se il numero dei campioni ha raggiunto 255 (si sono registrati circa 12s di segnale) ;allora si procede all'elaborazione ; L'elaborazione del segnale comporta vari passaggi, il primo dei quali è il calcolo della ;media mobile per ridurre il rumore media_mobile: ; Occorre inizializzare i registri che puntano alla RAM clr r29 ldi r28,$60 ; Il registro Y contiene gli indirizzi delle celle di RAM da cui si leggono i valori dei ;campioni clr r27 ldi r26,$60 ; Il registro X contiene invece gli indirizzi delle celle di RAM dove si scrive il valore ;della media mobile ld sample1,Y+ dec count_sample ; Al caricamento di ogni campione si decrementa il valore di count_sample, che sarà 0 una ;volta caricati tutti i campioni ld sample2,Y+ dec count_sample ld sample3,Y+ dec count_sample ld sample4,Y+ dec count_sample average: ldi mp,0 ; Nel registro mp si salva l'eventuale overflow delle somme (poichè si sommano 4 numeri a 8 ;bit occorrono 10 bit), mp deve essere inizializzato a 0 add sample1,sample2 brcc sum_sample1_2 ; il bit C (Carry) dello status register è quello che indica se è avvenuto overflow nella ;somma, se è avvenuto si aggiunge 1 al termine che salva i riporti inc mp clc ; il bit del Carry va riazzerato prima di effettuare la somma successiva, poi si sommano gli ;altri campioni sum_sample1_2: add sample1,sample3 brcc sum_sample3 inc mp clc sum_sample3: add sample1,sample4 brcc sum_all4samples inc mp clc ; il risultato parziale è ora salvato su due registri in questo modo: 000000XX (mp) ;XXXXXXXX (sample1), questo valore va diviso per 4: ; si può fare eseguendo 2 shift a destra su sample1 e successivamente copiando gli ultimi 2 ;bit di mp sui primi 2 di sample1 sum_all4samples: lsr sample1 lsr sample1 ; Il valore di sample1 è stato fatto scorrere verso destra di 2 posti: sample1 --> 00XXXXXX lsl mp lsl mp swap mp add sample1,mp ; Per ottenere in mp il valore della media si fa scorrere di 2 posti verso sinistra mp --> ;0000XX00, ; poi si invertono le 2 metà di mp (i primi 4 bit con gli ultimi 4) --> XX000000,
  • 24. 23 ; infine sommando si vanno a scrivere i 2 bit di riporto di mp nelle posizioni corrette su ;sample1, che dunque contiene il risultato della media st X+,sample1 ; Il valore della media mobile è salvato in RAM sovrascrivendo il campione più vecchio dei 4 ;su cui si è eseguita la media cpi count_sample,0 breq peak_recognition ; Se il numero di campioni è tornato a zero vuol dire che si è eseguita su tutti la media ;mobile e dunque si procede alla routine successiva mov sample1,sample2 mov sample2,sample3 mov sample3,sample4 ld sample4,Y+ dec count_sample rjmp average ; Se no si spostano i campioni acquisiti da un registro a quello precedente e si carica un ;nuovo campione nell'ultimo registro riservato ai campioni, ; si è così realizzata una finestra mobile su cui si esegue ogni volta la media, che viene ;sempre riscritta sul campione più vecchio ; Terminata la media mobile si procede con la ricerca del periodo del segnale peak_recognition: clr r29 ldi r28,$60 clr r27 ldi r26,$60 ; Come in precedenza si utilizza il registro Y per puntare alle celle di RAM da cui si ;leggono i valori (in questo caso dei campioni mediati) ; ed allo stesso modo il registro X per puntare alle celle di RAM su cui si scrive il valore ;di una flag, che assumerà valore 1 se il segnale ; ha andamento decrescente, 0 se crescente ld sample1,Y+ inc count_sample search_fall: ld sample2,Y+ inc count_sample ldi mp,0 ; Si caricano 2 campioni e si usa mp come flag cp sample1,sample2 brlo check_fall ldi mp,1 ; se sample1>=sample2 la flag diventa 1, indicando così che il segnale ha andamento ;decrescente check_fall: st X+,mp ; La flag è sovrascritta sul 1o campione mov sample1,sample2 ; Si sposta il contenuto di sample2 in sample1 per riavviare la verifica sul campione ;successivo cpi count_sample,255 brne search_fall ; se sono terminati i campioni termina la ricerca di rise/fall ; Ora nella RAM è salvata una successione costituita solo da 1 e 0, che idealmente dovrebbe ;essere un'onda quadra di periodo pari al segnale. ; Misurando dunque la distanza tra due fronti di salita consecutivi si trova il periodo del ;segnale (in realtà l'onda quadra presenta dei "rimbalzi", ; che vanno eliminati per procedere ad una misura corretta) ldi count_sample,1 ; Si re-inizializza count_sample al valore 1 per procedere alla routine successiva clr r29 ldi r28,$60 ; Si inizializza nuovamente il registro Y per puntare alle celle di RAM da cui si leggono i ;valori delle flag ld sample1,Y+
  • 25. 24 inc count_sample ldi mp1,0 ; mp1 è la flag che ci dà il numero di fronti di salita trovati ldi sample3,0 ldi sample4,0 ; sample3 e sample4 conterranno la posizione dei fronti search_switch: ld sample2,Y+ eor sample1,sample2 ; or esclusivo tra 2 flag consecutive (nei punti cercati sarà 1) cpi sample1,1 brne keep_searching ; se l'or non è 1 non ci troviamo su un fronte, ma su un livello ldi flag_battery,0 ; Ora dobbiamo verificare che il fronte sia un vero fronte di salita ; Vanno scartati i fronti di discesa e soprattutto i "rimbalzi" della flag dovuti al rumore ;o alla risoluzione: ; per far questo si verificherà che i 7 valori successivi a quello del fronte di salita ;siano 1 (7*50=350 ms, questo valore è sufficientemente ; lungo per permetterci di scartare i rimbalzi e non troppo da impedire di vedere il primo ;periodo, dato che se T=1s il livello è di circa 500 ms) ; si riutilizza flag_battery (non sono mai contemporaneamente attive l'analisi del segnale e ;la verifica della tensione) ldi mp,0 ; mp è ora utilizzato come contatore cpi sample2,1 brne anti_bounce1 ; con questo controllo su sample2 si scartano i fronti di discesa movw X,Y ; Ora per verificare che il fronte di salita sia tale si controllano i 7 campioni successivi ; Per puntare agli indirizzi di RAM che li contengono si usa il registro X in modo da non ;modificare il registro Y find_costant: inc mp ld sample1,X+ cpi sample1,1 brne bounce_check inc flag_battery ; tramite il registro X si carica il primo campione successivo e si esegue la verifica, in ;caso positivo si incrementa flag_battery bounce_check: cpi mp,7 brne find_costant ; mp si incrementa ad ogni campione caricato, quando arriva a 7 la verifica è terminata anti_bounce1: cpi flag_battery,7 brne save_position inc mp1 ; se flag_battery=7 allora tutti i 7 campioni successivi a quello indicato come probabile ;fronte sono 1 -> si tratta di un vero fronte di salita ; In questo caso si incrementa mp1, che tiene conto del numero di veri fronti di salita trovati save_position: ; cpi mp1,1 brne first_switch cpi flag_battery,7 brne first_switch add sample3,count_sample ; Se mp1=1 allora si tratta del primo fronte di salita trovato e si salva dunque la sua ;posizione in sample3 first_switch: cpi mp1,2
  • 26. 25 brne second_switch cpi flag_battery,7 brne second_switch add sample4,count_sample ; Allo stesso modo se mp1=2 è stato trovato il secondo fronte di salita second_switch: cpi mp1,2 breq end_search ; Se sono stati trovati 2 fronti di salita allora si interrompe la ricerca senza verificare ;i campioni successivi keep_searching: inc count_sample mov sample1,sample2 ; In caso contrario si sposta sample2 in sample1 per far scorrere i campioni prima di ;ripartire cpi count_sample,248 brne search_switch ; Se non si trova il secondo fronte la ricerca si conclude comunque una volta esauriti i ;campioni (gli ultimi 7 devono essere scartati per ; evitare errori di riconoscimento) end_search: sub sample4,sample3 ; Si salva in sample4 la distanza tra 2 fronti di salita (tale valore è qui espresso in ;numero di campioni e corrisponde al periodo) check_max_period: cpi mp1,2 breq set_display ldi sample4,255 ; Se non è stato trovato il secondo picco la differenza tra sample4 e sample3 ha dato un ;risultato sconosciuto ; Si imposta dunque in sample 4 un valore che comporterà la scrittura del messaggio ;d'allarme di periodo troppo lungo ; Ora si può procedere all'invio tramite le linee di I/O selezionate del valore che sarà ;visualizzato sui display ;----------------------- SCRITTURA DEL RISULTATO SU DISPLAY -------------------- ; set_display: clr r29 clr r28 ; riazzeriamo il registro Y per sicurezza in mp,PINB ldi mp1,0b00000100 and mp,mp1 ; Dal pin 16 del microcontrollore (PB2) si legge lo stato del dip-switch cpi mp,0b00000000 brne set_frequenza set_periodo: ldi ZH, HIGH(Table1*2) ldi ZL, LOW(Table1*2) ; Se si legge il valore 0 allora con il deviatore si è selezionata la visualizzazione del ;periodo e dunque si imposta il registro Z ; perchè punti alla Table1 set_frequenza: cpi mp,0b00000100 brne search_in_lookup_table ldi ZH, HIGH(Table2*2) ldi ZL, LOW(Table2*2) ; Se si legge il valore 1 allora con il deviatore si è selezionata la visualizzazione della ;frequenza e dunque si imposta il registro Z ; perchè punti alla Table2 search_in_lookup_table: lpm mp,Z ; Il primo valore di lookup table è salvato in mp
  • 27. 26 cp mp,sample4 breq found adiw Zl,4 rjmp search_in_lookup_table ; Si confronta il valore con mp, se sono diversi si salta alla riga successiva (la lookup ;table ha 4 elementi per ogni riga), ; se invece sono uguali allora si è trovata la corrispondenza e si può procedere all'invio ;ai display found: adiw Zl,1 lpm mp,Z adiw Zl,1 ; Si incrementa di 1 il valore del low byte di Z, che dunque punta al valore da mettere in ;uscita per le decine ; Si salva questo valore in mp e si incrementa Z per far sì che punti al valore da scrivere ;sulle unità ldi mp1,0b11100000 or mp1,mp out PORTD, mp1 ; Si mette il numero in binario prelevato dalla lookup table in uscita su PORTD (in questo ;momento i 3 latch sono a 1 ed essendo questi attivi bassi ; nessun valore è ancora inviato in uscita) ldi mp1,0b01100000 or mp1,mp out PORTD, mp1 ; In questo modo si invia il comando Latch Enable per il controller del display - decine ldi mp1,15 rcall attendi_le ; Chiamando questa funzione si introducono almeno 15 us di attesa prima di procedere alla ;scrittura del valore delle unità, in modo da non avere problemi ; nel pilotaggio dei display ldi mp1,0b11100000 eor mp1,mp out PORTD, mp1 ; Vengono resi nuovamente inattivi i LE lpm mp,Z adiw Zl,1 ; Ora si legge il valore delle unità e si scorre di una casella nella tabella ldi mp1,0b11100000 or mp1,mp out PORTD, mp1 ldi mp1,0b10100000 or mp1,mp out PORTD, mp1 ldi mp1,15 rcall attendi_le ldi mp1,0b11100000 eor mp1,mp out PORTD, mp1 ; Procedendo allo stesso modo di prima si carica il valore delle unità sull'uscita ;corrispondente, si chiama la routine di attesa e si rendono nuovamente inattivi i Latch lpm mp,Z adiw Zl,1 ldi mp1,0b11100000 or mp1,mp out PORTD, mp1 ldi mp1,0b11000000 or mp1,mp out PORTD, mp1 ldi mp1,15 ; Ripetendo una terza volta il procedimento si carica anche il valore dei decimi sul display ;corrispondente ldi ZH, HIGH(Table1*2)
  • 28. 27 ldi ZL, LOW(Table1*2) ; Si reinizializza il registro Z, per una nuova ricerca ldi mp1,0b11100000 eor mp1,mp out PORTD, mp1 ; Si rendono nuovamente inattivi i LE in modo che il numero sia mantenuto sui display ; fino alla comparsa del nuovo valore al termine dell'elaborazione del successivo periodo clr r27 ldi r26,$60 ; Alla fine del signal processing va inizializzato il registro X per riscrivere i dati da 0 ldi var_sample,5 ldi var_battery,100 ; Si inizializzano i contatori per evitare che gli interrupt arrivati nel signal processing ;abbiano portato questi a valori non previsti ldi count_sample,0 ; Per registrare un nuovo periodo completo si riporta a 0 count sample rjmp main_loop ; Terminate tutte le operzioni il programma riparte dall'inizio ; ; ------- Subroutine di risposta all'interrupt ---------- TIM0_OVF: push mp in mp,SREG push mp ; E' fondamentale salvare SREG nello stack per far sì che il rpogramma riparta esattamente ;dal punto in cui era arrivato prima che fosse lanciata ; la richiesta di interrupt, per fare questo si usa il registro mp e dunque occorre prima ;salvare questo nello stack per recuperare il valore corretto ; quando dal questa subroutine il programma ritorna nel main_loop ldi mp,246 out TCNT0,mp ; E' inizializzata nuovamente la variabile di conteggio del timer counter (10 ms) dec var_battery ; Si decrementa la variabile di conteggio del ciclo di controllo della batteria (1 s) dec var_sample ; Si decrementa la variabile di conteggio del ciclo di campionamento (50 ms) pop mp out SREG,mp pop mp ; Ora si richiamano i valori corretti di mp e SREG reti ; ; -------- Funzione per dare la pausa tra l'accensione di decine, unità e decimi ---------- attendi_le: dec mp1 cpi mp1,0 brne attendi_le ret ; ; ---------- LOOKUP TABLE ----------------- ; La lookup table Table1 stabilisce una corrispondenza tra il valore del periodo misurato in ;campioni ed il valore in s da visualizzare .CSEG Table1: .DB 0,8,8,8 ; messaggio d'allarme, periodo troppo breve .DB 1,8,8,8 .DB 2,8,8,8 .DB 3,8,8,8 .DB 4,8,8,8 .DB 5,8,8,8 .DB 6,8,8,8 .DB 7,8,8,8 .DB 8,8,8,8
  • 29. 28 .DB 9,8,8,8 .DB 10,8,8,8 .DB 11,8,8,8 .DB 12,8,8,8 .DB 13,8,8,8 .DB 14,8,8,8 .DB 15,8,8,8 .DB 16,8,8,8 .DB 17,8,8,8 .DB 18,8,8,8 .DB 19,0,1,0 .DB 20,0,1,0 ; T=1 s, primo periodo da rappresentare .DB 21,0,1,1 .DB 22,0,1,1 .DB 23,0,1,2 .DB 24,0,1,2 .DB 25,0,1,3 .DB 26,0,1,3 .DB 27,0,1,4 .DB 28,0,1,4 .DB 29,0,1,5 .DB 30,0,1,5 .DB 31,0,1,6 .DB 32,0,1,6 .DB 33,0,1,7 .DB 34,0,1,7 .DB 35,0,1,8 .DB 36,0,1,8 .DB 37,0,1,9 .DB 38,0,1,9 .DB 39,0,2,0 .DB 40,0,2,0 .DB 41,0,2,1 .DB 42,0,2,1 .DB 43,0,2,2 .DB 44,0,2,2 .DB 45,0,2,3 .DB 46,0,2,3 .DB 47,0,2,4 .DB 48,0,2,4 .DB 49,0,2,5 .DB 50,0,2,5 .DB 51,0,2,6 .DB 52,0,2,6 .DB 53,0,2,7 .DB 54,0,2,7 .DB 55,0,2,8 .DB 56,0,2,8 .DB 57,0,2,9 .DB 58,0,2,9 .DB 59,0,3,0 .DB 60,0,3,0 .DB 61,0,3,1 .DB 62,0,3,1 .DB 63,0,3,2 .DB 64,0,3,2 .DB 65,0,3,3 .DB 66,0,3,3 .DB 67,0,3,4 .DB 68,0,3,4 .DB 69,0,3,5 .DB 70,0,3,5 .DB 71,0,3,6
  • 30. 29 .DB 72,0,3,6 .DB 73,0,3,7 .DB 74,0,3,7 .DB 75,0,3,8 .DB 76,0,3,8 .DB 77,0,3,9 .DB 78,0,3,9 .DB 79,0,4,0 .DB 80,0,4,0 .DB 81,0,4,1 .DB 82,0,4,1 .DB 83,0,4,2 .DB 84,0,4,2 .DB 85,0,4,3 .DB 86,0,4,3 .DB 87,0,4,4 .DB 88,0,4,4 .DB 89,0,4,5 .DB 90,0,4,5 .DB 91,0,4,6 .DB 92,0,4,6 .DB 93,0,4,7 .DB 94,0,4,7 .DB 95,0,4,8 .DB 96,0,4,8 .DB 97,0,4,9 .DB 98,0,4,9 .DB 99,0,5,0 .DB 100,0,5,0 .DB 101,0,5,1 .DB 102,0,5,1 .DB 103,0,5,2 .DB 104,0,5,2 .DB 105,0,5,3 .DB 106,0,5,3 .DB 107,0,5,4 .DB 108,0,5,4 .DB 109,0,5,5 .DB 110,0,5,5 .DB 111,0,5,6 .DB 112,0,5,6 .DB 113,0,5,7 .DB 114,0,5,7 .DB 115,0,5,8 .DB 116,0,5,8 .DB 117,0,5,9 .DB 118,0,5,9 .DB 119,0,6,0 .DB 120,0,6,0 .DB 121,0,6,1 .DB 122,0,6,1 .DB 123,0,6,2 .DB 124,0,6,2 .DB 125,0,6,3 .DB 126,0,6,3 .DB 127,0,6,4 .DB 128,0,6,4 .DB 129,0,6,5 .DB 130,0,6,5 .DB 131,0,6,6 .DB 132,0,6,6 .DB 133,0,6,7 .DB 134,0,6,7
  • 31. 30 .DB 135,0,6,8 .DB 136,0,6,8 .DB 137,0,6,9 .DB 138,0,6,9 .DB 139,0,7,0 .DB 140,0,7,0 .DB 141,0,7,1 .DB 142,0,7,1 .DB 143,0,7,2 .DB 144,0,7,2 .DB 145,0,7,3 .DB 146,0,7,3 .DB 147,0,7,4 .DB 148,0,7,4 .DB 149,0,7,5 .DB 150,0,7,5 .DB 151,0,7,6 .DB 152,0,7,6 .DB 153,0,7,7 .DB 154,0,7,7 .DB 155,0,7,8 .DB 156,0,7,8 .DB 157,0,7,9 .DB 158,0,7,9 .DB 159,0,8,0 .DB 160,0,8,0 .DB 161,0,8,0 .DB 162,0,8,0 ; messaggio d'allarme, periodo troppo lungo (T > 8 s) .DB 163,8,8,8 .DB 164,8,8,8 .DB 165,8,8,8 .DB 166,8,8,8 .DB 167,8,8,8 .DB 168,8,8,8 .DB 169,8,8,8 .DB 170,8,8,8 .DB 171,8,8,8 .DB 172,8,8,8 .DB 173,8,8,8 .DB 174,8,8,8 .DB 175,8,8,8 .DB 176,8,8,8 .DB 177,8,8,8 .DB 178,8,8,8 .DB 179,8,8,8 .DB 180,8,8,8 .DB 181,8,8,8 .DB 182,8,8,8 .DB 183,8,8,8 .DB 184,8,8,8 .DB 185,8,8,8 .DB 186,8,8,8 .DB 187,8,8,8 .DB 188,8,8,8 .DB 189,8,8,8 .DB 190,8,8,8 .DB 191,8,8,8 .DB 192,8,8,8 .DB 193,8,8,8 .DB 194,8,8,8 .DB 195,8,8,8 .DB 196,8,8,8 .DB 197,8,8,8
  • 32. 31 .DB 198,8,8,8 .DB 199,8,8,8 .DB 200,8,8,8 .DB 201,8,8,8 .DB 202,8,8,8 .DB 203,8,8,8 .DB 204,8,8,8 .DB 205,8,8,8 .DB 206,8,8,8 .DB 207,8,8,8 .DB 208,8,8,8 .DB 209,8,8,8 .DB 210,8,8,8 .DB 211,8,8,8 .DB 212,8,8,8 .DB 213,8,8,8 .DB 214,8,8,8 .DB 215,8,8,8 .DB 216,8,8,8 .DB 217,8,8,8 .DB 218,8,8,8 .DB 219,8,8,8 .DB 220,8,8,8 .DB 221,8,8,8 .DB 222,8,8,8 .DB 223,8,8,8 .DB 224,8,8,8 .DB 225,8,8,8 .DB 226,8,8,8 .DB 227,8,8,8 .DB 228,8,8,8 .DB 229,8,8,8 .DB 230,8,8,8 .DB 231,8,8,8 .DB 232,8,8,8 .DB 233,8,8,8 .DB 234,8,8,8 .DB 235,8,8,8 .DB 236,8,8,8 .DB 237,8,8,8 .DB 238,8,8,8 .DB 239,8,8,8 .DB 240,8,8,8 .DB 241,8,8,8 .DB 242,8,8,8 .DB 243,8,8,8 .DB 244,8,8,8 .DB 245,8,8,8 .DB 246,8,8,8 .DB 247,8,8,8 .DB 248,8,8,8 .DB 249,8,8,8 .DB 250,8,8,8 .DB 251,8,8,8 .DB 252,8,8,8 .DB 253,8,8,8 .DB 254,8,8,8 .DB 255,8,8,8 ; La lookup table Table2 stabilisce una corrispondenza tra il valore del periodo misurato in ;campioni ; ed il valore della frequenza da visualizzare (atti respiratori/min) Table2:
  • 33. 32 .DB 0,8,8,8 ; messaggio d'allarme, frequenza troppo alta .DB 1,8,8,8 .DB 2,8,8,8 .DB 3,8,8,8 .DB 4,8,8,8 .DB 5,8,8,8 .DB 6,8,8,8 .DB 7,8,8,8 .DB 8,8,8,8 .DB 9,8,8,8 .DB 10,8,8,8 .DB 11,8,8,8 .DB 12,8,8,8 .DB 13,8,8,8 .DB 14,8,8,8 .DB 15,8,8,8 .DB 16,8,8,8 .DB 17,8,8,8 .DB 18,8,8,8 .DB 19,6,0,0 ; massima frequenza misurabile (60 atti respiratori/min) .DB 20,6,0,0 .DB 21,5,4,5 .DB 22,5,4,5 .DB 23,5,0,0 .DB 24,5,0,0 .DB 25,4,6,2 .DB 26,4,6,2 .DB 27,4,2,9 .DB 28,4,2,9 .DB 29,4,0,0 .DB 30,4,0,0 .DB 31,3,7,5 .DB 32,3,7,5 .DB 33,3,5,3 .DB 34,3,5,3 .DB 35,3,3,3 .DB 36,3,3,3 .DB 37,3,1,6 .DB 38,3,1,6 .DB 39,3,0,0 .DB 40,3,0,0 .DB 41,2,8,6 .DB 42,2,8,6 .DB 43,2,7,3 .DB 44,2,7,3 .DB 45,2,6,1 .DB 46,2,6,1 .DB 47,2,5,0 .DB 48,2,5,0 .DB 49,2,4,0 .DB 50,2,4,0 .DB 51,2,3,1 .DB 52,2,3,1 .DB 53,2,2,2 .DB 54,2,2,2 .DB 55,2,1,4 .DB 56,2,1,4 .DB 57,2,0,7 .DB 58,2,0,7 .DB 59,2,0,0 .DB 60,2,0,0 .DB 61,1,9,4 .DB 62,1,9,4
  • 34. 33 .DB 63,1,8,8 .DB 64,1,8,8 .DB 65,1,8,2 .DB 66,1,8,2 .DB 67,1,7,6 .DB 68,1,7,6 .DB 69,1,7,1 .DB 70,1,7,1 .DB 71,1,6,7 .DB 72,1,6,7 .DB 73,1,6,2 .DB 74,1,6,2 .DB 75,1,5,8 .DB 76,1,5,8 .DB 77,1,5,4 .DB 78,1,5,4 .DB 79,1,5,0 .DB 80,1,5,0 .DB 81,1,4,6 .DB 82,1,4,6 .DB 83,1,4,3 .DB 84,1,4,3 .DB 85,1,4,0 .DB 86,1,4,0 .DB 87,1,3,6 .DB 88,1,3,6 .DB 89,1,3,3 .DB 90,1,3,3 .DB 91,1,3,0 .DB 92,1,3,0 .DB 93,1,2,8 .DB 94,1,2,8 .DB 95,1,2,5 .DB 96,1,2,5 .DB 97,1,2,2 .DB 98,1,2,2 .DB 99,1,2,0 .DB 100,1,2,0 .DB 101,1,1,8 .DB 102,1,1,8 .DB 103,1,1,5 .DB 104,1,1,5 .DB 105,1,1,3 .DB 106,1,1,3 .DB 107,1,1,1 .DB 108,1,1,1 .DB 109,1,0,9 .DB 110,1,0,9 .DB 111,1,0,7 .DB 112,1,0,7 .DB 113,1,0,5 .DB 114,1,0,5 .DB 115,1,0,3 .DB 116,1,0,3 .DB 117,1,0,2 .DB 118,1,0,2 .DB 119,1,0,0 .DB 120,1,0,0 .DB 121,0,9,8 .DB 122,0,9,8 .DB 123,0,9,7 .DB 124,0,9,7 .DB 125,0,9,5
  • 35. 34 .DB 126,0,9,5 .DB 127,0,9,4 .DB 128,0,9,4 .DB 129,0,9,2 .DB 130,0,9,2 .DB 131,0,9,1 .DB 132,0,9,1 .DB 133,0,9,0 .DB 134,0,9,0 .DB 135,0,8,8 .DB 136,0,8,8 .DB 137,0,8,7 .DB 138,0,8,7 .DB 139,0,8,6 .DB 140,0,8,6 .DB 141,0,8,5 .DB 142,0,8,5 .DB 143,0,8,3 .DB 144,0,8,3 .DB 145,0,8,2 .DB 146,0,8,2 .DB 147,0,8,1 .DB 148,0,8,1 .DB 149,0,8,0 .DB 150,0,8,0 .DB 151,0,7,9 .DB 152,0,7,9 .DB 153,0,7,8 .DB 154,0,7,8 .DB 155,0,7,7 .DB 156,0,7,7 .DB 157,0,7,6 .DB 158,0,7,6 .DB 159,0,7,5 .DB 160,0,7,5 .DB 161,0,7,5 .DB 162,0,7,5 ; massima frequenza misurabile (7,5 atti respiratori/min) .DB 163,8,8,8 .DB 164,8,8,8 .DB 165,8,8,8 .DB 166,8,8,8 .DB 167,8,8,8 .DB 168,8,8,8 .DB 169,8,8,8 .DB 170,8,8,8 .DB 171,8,8,8 .DB 172,8,8,8 .DB 173,8,8,8 .DB 174,8,8,8 .DB 175,8,8,8 .DB 176,8,8,8 .DB 177,8,8,8 .DB 178,8,8,8 .DB 179,8,8,8 .DB 180,8,8,8 .DB 181,8,8,8 .DB 182,8,8,8 .DB 183,8,8,8 .DB 184,8,8,8 .DB 185,8,8,8 .DB 186,8,8,8 .DB 187,8,8,8 .DB 188,8,8,8
  • 36. 35 .DB 189,8,8,8 .DB 190,8,8,8 .DB 191,8,8,8 .DB 192,8,8,8 .DB 193,8,8,8 .DB 194,8,8,8 .DB 195,8,8,8 .DB 196,8,8,8 .DB 197,8,8,8 .DB 198,8,8,8 .DB 199,8,8,8 .DB 200,8,8,8 .DB 201,8,8,8 .DB 202,8,8,8 .DB 203,8,8,8 .DB 204,8,8,8 .DB 205,8,8,8 .DB 206,8,8,8 .DB 207,8,8,8 .DB 208,8,8,8 .DB 209,8,8,8 .DB 210,8,8,8 .DB 211,8,8,8 .DB 212,8,8,8 .DB 213,8,8,8 .DB 214,8,8,8 .DB 215,8,8,8 .DB 216,8,8,8 .DB 217,8,8,8 .DB 218,8,8,8 .DB 219,8,8,8 .DB 220,8,8,8 .DB 221,8,8,8 .DB 222,8,8,8 .DB 223,8,8,8 .DB 224,8,8,8 .DB 225,8,8,8 .DB 226,8,8,8 .DB 227,8,8,8 .DB 228,8,8,8 .DB 229,8,8,8 .DB 230,8,8,8 .DB 231,8,8,8 .DB 232,8,8,8 .DB 233,8,8,8 .DB 234,8,8,8 .DB 235,8,8,8 .DB 236,8,8,8 .DB 237,8,8,8 .DB 238,8,8,8 .DB 239,8,8,8 .DB 240,8,8,8 .DB 241,8,8,8 .DB 242,8,8,8 .DB 243,8,8,8 .DB 244,8,8,8 .DB 245,8,8,8 .DB 246,8,8,8 .DB 247,8,8,8 .DB 248,8,8,8 .DB 249,8,8,8 .DB 250,8,8,8 .DB 251,8,8,8
  • 37. 36 .DB 252,8,8,8 .DB 253,8,8,8 .DB 254,8,8,8 .DB 255,8,8,8
  • 38. 37 6.Documentazione delle prove di verifica Le prove di collaudo eseguite in laboratorio hanno dato esito positivo, come dimostrato dalla seguente documentazione fotografica. Per alcune prove sono riportati commenti e osservazioni per una più immediata comprensione dei risultati. 6.1 Verifica del sistema di allarme per la tensione di alimentazione VAL > 4,8 V ± 0,15 V : led spento VAL < 4,2 V ± 0,15 V : led acceso fisso
  • 39. 38 6.2 Verifica della temporizzazione della verifica della tensione di alimentazione 4,8 V ± 0,15 V > VAL > 4,2 V ± 0,15 V : led lampeggiante, si visualizza sull’oscilloscopio la tensione ai capi del led, significativa della sua temporizzazione
  • 40. 39 6.3 Verifica della massima corrente assorbita
  • 41. 40 6.4 Verifica dell’accuratezza degli estremi di misura
  • 42. 41 L’incertezza assoluta varia al variare del periodo misurato: questo avviene perché il campionamento non avviene esattamente ogni 50 ms (fS=20 Hz) come assunto dall’algoritmo per ricavare il periodo, ma ogni 51,2 ms. All’aumentare del periodo si ha un accumulo dell’errore, per questo motivo l’accuratezza negli estremi è 0,1 s per periodi di 1 s e 0,3 s per periodi di 8 s. Come accuratezza dello strumento si è scelta la maggiore delle due, quindi 300 ms. 6.5 Verifica del funzionamento del sistema di acquisizione ed elaborazione del segnale e di pilotaggio dei display
  • 43. 42 6.6 Verifica del funzionamento del deviatore e della misura della frequenza
  • 44. 43
  • 45. 44 6.7 Verifica del funzionamento complessivo del dispositivo Il segnale visualizzato sull’oscilloscopio corrisponde all’uscita del circuito di condizionamento del sensore NTC quando questo è posto al di sotto delle narici di un soggetto. Il valore del periodo visualizzato sui display è compatibile con quello ricavabile dalla traccia dell’oscilloscopio
  • 46. 45 Appendice A: algoritmo di ricerca del periodo Il segnale campionato ha una banda di frequenza dell’ordine delle frazioni di Hz (tipicamente 0,25- 0,5 Hz), per via delle risoluzione richiesta (100 ms) non è possibile campionare il segnale a frequenze inferiori a 10 Hz. Si è scelta dunque una frequenza di campionamento fS= 20 Hz. Questo comporta una difficile elaborazione del segnale per via del fatto che la frequenza di campionamento è circa 40 volte la frequenza di banda. Per identificare la migliore strategia di ricerca del periodo si sono eseguite simulazioni Matlab del segnale già campionato a 20 Hz dal microcontrollore. Si è impostato un segnale sinusoidale con caratteristiche simili a quello presente sull’uscita del sensore: offset di 1,5 V, ampiezza picco-picco 1 V, ampiezza picco-picco del rumore sovrapposto 50 mV, periodi 2s, 4s e 8s. Per simulare l’acquisizione tramite l’ADC del microcontrollore si è introdotta una discretizzazione su 256 livelli con tensione di full-range dell’ADC 2,56 V. Eseguendo la media mobile su finestre di 4 campioni si è osservato un miglioramento del rapporto segnale rumore, tuttavia il campionamento a frequenza molto maggiore rispetto alla banda del segnale osservato comporta il fatto che le variazioni lente del segnale in corrispondenza di massimi e minimi relativi si traducano in tratti di plateau, rendendo impossibile l’identificazione esatta del punto di massimo o minimo relativo. Si è dunque pensato di sfruttare i cambi di segno della derivata per ricavare il periodo nel seguente modo: confrontando il valore di ogni campione Cn con quello precedente Cn-1 e assegnando un valore 1 ad una flag se Cn-1 ≤ Cn e 0 se Cn-1 > Cn . In questo modo si ottiene un segnale simile ad un’onda quadra ed è possibile trovare il periodo misurando la distanza tra due fronti di salita. Tuttavia si è osservato come il segnale così modificato
  • 47. 46 presenti dei “rimbalzi” che possono essere interpretati erroneamente come fronti di salita e discesa successivi portando ad errori nell’identificazione del periodo. t (s) t (s)
  • 48. 47 Per risolvere questo problema si è pensato di verificare che i 7 campioni successivi a quello identificato come fronte di salita corrispondano tutti ad un valore 1 della flag: in questo modo l’algoritmo non considera i rimbalzi e riesce comunque ad identificare i veri fronti di salita corrispondenti a periodi significativi (se T=1s, allora l’onda quadra presenta 10 campioni di valore 1 consecutivi ad un vero fronte di salita). Questo metodo limita però il massimo periodo misurabile, perché occorre che due veri fronti di salita successivi cadano all’interno della finestra di osservazione: questo si verifica con certezza solo se il periodo del segnale è inferiore a metà della finestra di osservazione. Un periodo maggiore comporta il fatto che alcune finestre di osservazione debbano essere scartate. Quando ciò avviene l’algoritmo produce in uscita sui display un messaggio d’errore, evitando così di comunicare informazioni errate. Si è scelta una finestra di osservazione della durata di 12 s, accettando la possibilità di avere errori di riconoscimento per valori di periodo maggiori di 6 s. Si è scelto un periodo massimo misurabile di 8 s, sia perché questo valore è di per sé elevato per una respirazione fisiologica, sia perché fino a questo valore non si ha una probabilità troppo elevata di scartare misurazioni. Si riportano di seguito gli script Matlab utilizzati per la simulazione e la realizzazione dei grafici sopra riportati: % test_segnale.m clear all t (s)
  • 49. 48 close all clc t=0:0.05:10; f=0.125; phi=1; for i=1:length(t) signal(i)=floor((0.5*sin(2*pi*f*t(i)+phi)+1.5)/2.56*256)+5*rand(1); end for i=4:length(t) media_mobile(i-3)=floor((signal(i-3)+signal(i-2)+signal(i-1)+signal(i))/4); end media_mobile(length(t)-2)=NaN; media_mobile(length(t)-1)=NaN; media_mobile(length(t))=NaN; figure(); plot(t,signal,t,media_mobile),grid; title('T= 8s') xlabel('t (s)') ylabel('Tensione discretizzata') legend('segnale','media mobile','Location','best'); % test_picchi.m clear all close all clc t=0:0.05:10; % campionamento ogni 50 ms (20 Hz) f=0.5; % frequenza della sinusoide phi=1; % fase for i=1:length(t) signal(i)=floor((0.5*sin(2*pi*f*t(i)+phi)+1.5)/2.56*256)+5*rand(1); % segnale discretizzato su 256 livelli (8 bit) end for i=4:length(t) media_mobile(i-3)=floor((signal(i-3)+signal(i-2)+signal(i-1)+signal(i))/4); end media_mobile(length(t)-2)=signal(length(t)-2); media_mobile(length(t)-1)=signal(length(t)-1); media_mobile(length(t))=signal(length(t)); for i=1:length(t)-1 if media_mobile(i)>=media_mobile(i+1) flag(i)=50; else flag(i)=0; end end flag(length(t))=0; figure(); plot(t,signal,t,media_mobile,t,flag); title('V_p_p = 1 V; V_o_f_f_s_e_t=1,5 V; V_p_p_,_n_o_i_s_e=50 mV; T = 2 s'); legend('segnale','media mobile','flag'); f1=0.25; for i=1:length(t) signal1(i)=floor((0.5*sin(2*pi*f1*t(i)+phi)+1.5)/2.56*256)+5*rand(1); end
  • 50. 49 for i=4:length(t) media_mobile1(i-3)=floor((signal1(i-3)+signal1(i-2)+signal1(i- 1)+signal1(i))/4); end media_mobile1(length(t)-2)=signal1(length(t)-2); media_mobile1(length(t)-1)=signal1(length(t)-1); media_mobile1(length(t))=signal1(length(t)); for i=1:length(t)-1 if media_mobile1(i)>=media_mobile1(i+1) flag1(i)=50; else flag1(i)=0; end end flag1(length(t))=0; figure(); plot(t,signal1,t,media_mobile1,t,flag1); title('V_p_p = 1 V; V_o_f_f_s_e_t=1,5 V; V_p_p_,_n_o_i_s_e=50 mV; T =4 s'); legend('segnale','media mobile','flag'); f2=1/8; for i=1:length(t) signal2(i)=floor((0.5*sin(2*pi*f2*t(i)+phi)+1.5)/2.56*256+5*rand(1)); end for i=4:length(t) media_mobile2(i-3)=floor((signal2(i-3)+signal2(i-2)+signal2(i- 1)+signal2(i))/4); end media_mobile2(length(t)-2)=signal2(length(t)-2); media_mobile2(length(t)-1)=signal2(length(t)-1); media_mobile2(length(t))=signal2(length(t)); for i=1:length(t)-1 if media_mobile2(i)>=media_mobile2(i+1) flag2(i)=50; else flag2(i)=0; end end flag2(length(t))=0; figure(); plot(t,signal2,t,media_mobile2,t,flag2); title('V_p_p = 1 V; V_o_f_f_s_e_t=1,5 V; V_p_p_,_n_o_i_s_e=50 mV; T= 8 s'); legend('segnale','media mobile','flag');