Konstruera en billig pulsoximeter med standardkomponenter
Bidraget med av DigiKeys nordamerikanska redaktörer
2020-08-13
Pulsoximetri mäter den perifera syremättnaden (SpO2), vilket återspeglar hur effektivt hjärtlungsystemet förser kroppen med syrerikt blod. Idrottare använder SpO2 -mätningar för att mäta sin ansträngningsnivå under träning, men dessa mätningar har fått större betydelse under COVID-19-pandemin. Sjukvårdspersonal ser efter en minskning av SpO2 som ett tidigt varningstecken på skador på lungvävnad orsakade av SARS-CoV-2 viruset som orsakar COVID-19.
För drabbade personer med lindriga symtom som uppmanas att hålla sig i karantän hemma, kan en billig pulsoximeter göra det lättare att mäta infektionens förlopp och ge den förvarning som krävs för att eskalera vården.
Artikeln diskuterar kortfattat symptomen på COVID-19 och behovet av SpO2-övervakning. Den visar sedan hur utvecklare kan använda en digital signalstyrningsenhet (DSC) från Microchip Technology och några ytterligare enheter för att konstruera en billig pulsoximeter som kan ge hemanvändare en tidig förvarning om symptom som tyder på långt gången COVID-19-infektion.
COVID-19 och behovet av att mäta nivåer av syremättnad
COVID-19 har en stor mängd symptom till följd av de skadliga effekterna av viruset SARS-CoV-2. Ett särskilt oroväckande symtom för sjukvården är skador på lungvävnaden, som leder till en försämrad andning och syreupptagning. Även om läkare använder individuella röntgenbilder av bröstkorgen och datortomografi (CT) för att bekräfta detta stadium av COVID-19, använder de rutinmässigt SpO2-mätningar som en tidig indikering.
SpO2-mätning är ett icke-invasivt alternativ till mätning av arteriell syremättnad (SaO2) som bestäms direkt genom att analysera blodgasnivåerna i prover från en artär hos patienten. Även om vissa tillstånd kan kräva direkt mätning av arteriella blodgaser har SpO2 visat sig ge en tillförlitlig uppskattning av SaO2. Kanske viktigast av allt är att den kan utföras lika tillförlitligt i hemmet som i kliniska miljöer med optiska pulsoximetrar.
Optiska pulsoximetrar mäter SpO2 genom att utnyttja skillnaderna i ljusabsorption mellan syrefritt hemoglobin (Hb) och syrehaltigt hemoglobin (HbO2). Hemoglobin, som finns i röda blodkroppar, bildar snabbt en reversibel bindning med upp till fyra syremolekyler i de syrerika lungorna. I detta tillstånd som HbO2 absorberar molekylen mer ljus vid 940 nm än vid 660 nm (figur 1).
Figur 1: Pulsoximetri utnyttjar skillnaderna i absorptionsspektrum mellan syresatta (HbO2) och syrefria (Hb) blodkroppar. (Bildkälla: Wikipedia)
När de röda blodkropparna som bär HbO2 passerar till periferin, där syrepartialtrycket - trycket för en enskild gaskomponent i en gasblandning - är lägre, minskar hemoglobins affinitet för syre och HbO2 börjar avlasta sina syremolekyler och blir så småningom till Hb. I detta syrefattiga tillstånd förändras molekylens ljusabsorptionsspektrum och de absorberar mer ljus vid 660 nm än vid 940 nm.
Eftersom HbO2 blir Hb när syrepartialtrycket är lågt kan SpO2 bestämmas med den enkla formeln:
SpO2 = HbO2/(HbO2+Hb)
De relativa koncentrationerna av Hb och HbO2 i blodet kan i sin tur bestämmas genom att mäta ljusabsorptionen vid 660 nm och 940 nm våglängd.
Pulsoximetrar utnyttjar förhållandet mellan blodets syrepartialtryck, hemoglobins syrebelastning och skillnader i ljusabsorption för att ge tillförlitliga mätningar av SpO2.
Viktiga delsystem i en typisk pulsoximeter
En typisk konstruktion av en pulsoximeter består av tre stora delsystem:
- Ett delsystem för ljusleverans med analoga omkopplare och drivrutiner samt lysdioder (LED) med röda (660 nm) och infraröda (IR) (950 nm) våglängder. Vissa system innehåller även gröna (530 nm) ljuskällor för användning med fotopletysmografimetoder (PPG) som bestämmer hjärtfrekvensen genom att övervaka volymförändringar i hudens blodkärl.
- Ett delsystem för ljusdetektering med en fotodiod, en signalbehandlingskedja och en analog-till-digitalomvandlare (ADC).
- En DSC eller mikrokontroller för att samordna delsystemen för ljustillförsel och detektion samt för att beräkna SpO2 från mätdata.
Även om dessa grundläggande delsystem finns i alla pulsoximetrar kan implementationen av dem variera avsevärt. I transmissiva pulsoximetrar placeras fotodioden på motsatt sida av användarens finger eller örsnibben från lysdioderna. Vanliga enheter som kläms fast på fingret kombinerar röda lysdioder, infraröda lysdioder och valfria gröna lysdioder på ena sidan av klämman med en fotodiod på den andra. I reflekterande pulsoximetrar placeras fotodioden och lysdioderna på samma sida av huden med en optisk barriär mellan dem för att minska artefakter. SFH7060 från OSRAM är ett exempel på en enhet för reflektionsmätning med lysdioder och en fotodiod i en enda kapsling på 7,2 x 2,5 x 0,9 mm.
Oavsett om de använder dessa optiska paket för transmissiva eller reflekterande metoder, behöver konstruktörerna relativt få ytterligare komponenter för att konstruera en billig pulsoximeter som kan ge hemanvändare information som visar om de behöver utvärderas ytterligare av sjukvårdspersonal. I en exempelkonstruktion som bygger på DSC:n DSPIC33FJ128GP802 från Microchip Technology används mikrokontrollerns inbyggda kringutrustning för att styra belysningen av huden med röda och infraröda lysdioder och för att digitalisera den behandlade utsignalen från fotodioden (figur 2).
Figur 2: En typisk konstruktion av en pulsoximeter kombinerar delsystem för lysdiodsbelysning och behandling av fotodiodens signal med en mikrokontroller som används för att styra tidpunkten för belysningen och datainsamlingen. (Bildkälla: Microchip Technology)
Konstruktioner av pulsoximetrar bygger vanligtvis på en enda fotodiod med en bred spektral responskurva för att fånga upp den överförda eller reflekterade signalen oberoende av belysningskällan. För att se till att den mottagna signalen motsvarar just röda eller infraröda våglängder, kan man med hjälp av hård- eller mjukvarulogik endast visa den röda eller infraröda belysningskällan vid en viss tidpunkt och växla mellan de två källorna för att slutföra en sekvens av mätningar.
Implementering av en billig hårdvarudesign för pulsoximetrar
I den här konstruktionen använder DSC:n den externa digital-till-analog-omvandlaren MCP4728 från Microchip Technology för att ställa in separata MBT2222-transistorer på den nivå som behövs för att driva varje lysdiod med den önskade intensiteten. För att tidsbestämma den exakta "på"-sekvensen för varje lysdiod använder DSC två av sina PWM-utgångar (pulsbreddsmodulering) för att styra den analoga omkopplaren ADG884 från Analog Devices (figur 3).
Figur 3: En analog omkopplare, som drivs av växelvisa signaler för röda och infraröda kanaler från den digitala styrenheten, ger ström till röda lysdioder och infraröda lysdioder. (Bildkälla: Microchip Technology)
För att behandla fotodiodens utgång tillhandahåller en enda MCP6002 från Microchip Technology ett par operationsförstärkare som behövs för att genomföra en grundläggande signalbehandlingskedja i två steg. I det första steget används operationsförstärkaren MCP6002, konfigurerad som en transimpedansförstärkare, för att omvandla fotodiodens strömutgång till en spänningssignal. Efter ett högpassfilter för att minska bruset ger den andra operationsförstärkaren i MCP6002 den förstärkning och den justering av DC-offset som behövs för att optimera den behandlade signalens svängningar i hela intervallet för den ADC som är inbyggd i DSC (figur 4).
Figur 4: En signalbehandlingskedja i två steg som behandlar fotodiodens utgång för leverans till den digitala styrenhetens inbyggda ADC. (Bildkälla: Microchip Technology)
Vid användning använder DSC:n sina PWM-utgångar och ADC-ingångar för att synkronisera lysdiodsbelysningen och ADC:ns digitalisering av den behandlade utsignalen från fotodioden. Här samordnas varje period av alternerande röd belysning och infraröd belysning med signalinsamling och omvandling. Ytterligare en ADC-sampling sker när de båda lysdioderna är avstängda för att mäta omgivningsljuset som sedan används för att optimera lysdiodernas intensitet och SpO2-mätningen. Resultatet är en noga kontrollerad sekvens av händelser som samordnar lysdiodsbelysningen och ADC:ns digitalisering för att samla in det röda våglängdsresultat för Hb, samla in omgivningens ljus och slutligen samla in resultaten av de infraröda våglängderna för HbO2 (figur 5).
Figur 5: Den billiga pulsoximeterns funktion beror på den digitala signalstyrningens förmåga att hantera den exakta tidpunkten för de sekvenser för belysning och datainsamling som krävs för att samla in mätningar för bestämning av SpO2. (Bildkälla: Microchip Technology)
Implementering av en avbrottsdriven mjukvarulösning
Microchip tillhandahåller ett paket med firmware för pulsoximetrar med ett exempelprogram som visar hur DSC:n används för att utföra dessa sekvenser för belysningskontroll och dataomvandling. Här implementerar programmet en avbrottsdriven metod med hjälp av ett par av DSC:ns timers - Timer2 och Timer3 - för att tidsbestämma de separata "på"-sekvenserna för den infraröda lysdioden respektive den röda lysdioden. Varje timer ger i sin tur tidsbasen för två av DSC:s OC-moduler (utgångskomparering), OC1 och OC2, som används för att styra de analoga omkopplarna för den infraröda lysdioden respektive den röda lysdioden.
Som visas i lista 1 initialiserar programvaran först Timer2 och Timer3 för att ställa in den önskade perioden för belysningscykeln och aktivera avbrott. Som en del av initialiseringssekvensen kopplas OC1- och OC2-modulerna till separata utgångsstift med hjälp av DSC:ns RP-funktion (flyttbara stift). Initialiseringssekvensen ställer sedan in belysningens arbetscykel och väljer den tillhörande timern som tidsbas.
Kopiera
//*********************************************************************************************************
// Initialize Timer 2 - IR light
//*********************************************************************************************************
T2CON = 0x0020; // Stop 16-bit Timer2, 1:64(40MhzFosc) Prescale, Internal clock (Fosc/2)
TMR2 = 0x00; // Clear timer register
PR2 = 1250; // Load the period value, OCxRS <= PRx, 4ms period = (1/(Fosc/2))*1000*64*PR2 = (1/(40000000/2))*1000*64*1250
IPC1bits.T2IP = 2; // Set Timer2 Interrupt Priority Level
IFS0bits.T2IF = 0; // Clear Timer2 Interrupt Flag
IEC0bits.T2IE = 1; // Enable Timer2 Interrupt
//*********************************************************************************************************
// Initialize Timer 3 - Red light
//*********************************************************************************************************
T3CON = 0x0020; // Stop 16-bit Timer3, 1:64(40MhzFosc) Prescale, Internal clock (Fosc/2)
TMR3 = 0x00; // Clear timer register
PR3 = 1250; // Load the period value, OCxRS <= PRx, 4ms period = (1/(Fosc/2))*1000*64*PR2 = (1/(40000000/2))*1000*64*1250
IPC2bits.T3IP = 2; // Set Timer3 Interrupt Priority Level
IFS0bits.T3IF = 0; // Clear Timer3 Interrupt Flag
IEC0bits.T3IE = 1; // Enable Timer3 Interrupt
//*********************************************************************************************************
// Initialize Output Compare 1 module in Continuous Pulse mode, OC1 controls IR LED switch
//*********************************************************************************************************
RPOR6bits.RP13R = 0b10010; // RP13/RB13 tied to OC1 (IR)
OC1CONbits.OCM = 0b000; // Disable Output Compare 1 Module
OC1R = 0; // Write the duty cycle for the first PWM pulse, 24=8MHzFosc(50us), 30=40MHzFosc(50us), 600=40MHzFosc(1ms)
OC1RS = duty_cycle; // Write the duty cycle for the second PWM pulse, OCxRS <= PRx, 499=8MHzFosc(1ms), 623=40MHzFosc(1ms), 1246=40MHzFoc,2msPeriod, 4984=40MHzFoc,8msPeriod, 280=450us D/C@40MHzFoc,2msPeriod,switch
OC1CONbits.OCTSEL = 0; // Select Timer 2 as output compare time base
//*********************************************************************************************************
// Initialize Output Compare 2 module in Continuous Pulse mode, OC2 controls Red LED switch
//*********************************************************************************************************
RPOR6bits.RP12R = 0b10011; // RP12/RB12 tied to OC2 (Red)
OC2CONbits.OCM = 0b000; // Disable Output Compare 2 Module
OC2R = 0; // Write the duty cycle for the first PWM pulse, 24=8MHzFosc, 30=40MHzFosc, 600=40MHzFosc(1ms)
OC2RS = duty_cycle; // Write the duty cycle for the second PWM pulse, OCxRS <= PRx, 499=8MHzFosc(1ms), 623=40MHzFosc(1ms), 1246=40MHzFoc,2msPeriod, 4984=40MHzFoc,8msPeriod, 280=450us D/C@40MHzFoc,2msPeriod,switch
OC2CONbits.OCTSEL = 1; // Select Timer 3 as output compare time base
Lista 1: Huvudrutinen från Microchip Technologys paket med exempelkod som använder en kort initialiseringssekvens för att ställa in den digitala signalstyrningens timers och moduler för utgångskomparering som är hjärtat i den här billiga pulsoximeterlösningen. (Kodkälla: Microchip Technology)
Detta tillvägagångssätt drar nytta av DSC-arkitekturens association för varje timeravbrott till en specifik ISR-ingångspunkt (Interrupt Service Routine). När exempelvis, den röda LED-kanalens Timer3-avbrott inträffar utför DSC:n funktionen vid ingångspunkten _T3Interrupt. När Timer3 för den röda lysdioden löper ut inträffar således två samordnade hårdvaru- och mjukvaruhändelser:
- OC2 genererar en kontinuerlig puls till den analoga omkopplaren och tänder den röda lysdioden
- DSC börjar utföra ISR _T3Interrupt (lista 2)
Kopiera
void __attribute__((__interrupt__, no_auto_psv)) _T3Interrupt(void) //Read Red DC & AC signals from AN0 & AN1
{
int delay;
unsigned char i;
Read_ADC_Red = 1;
CH0_ADRES_Red_sum = 0;
CH1_ADRES_Red_sum = 0;
for (delay=0; delay<200; delay++); //2000=delayed 256us before read ADC
// LATBbits.LATB14 = 1; // for debugging
for (i=0; i<oversampling_number; i++)
{
//Acquires Red-DC from Channel0 (AN0)
AD1CHS0bits.CH0SA = 0x00; // Select AN0
AD1CON1bits.SAMP = 1; // Begin sampling
while(!AD1CON1bits.DONE); // Waiting for ADC completed
AD1CON1bits.DONE = 0; // Clear conversion done status bit
CH0_ADRES_Red_sum = CH0_ADRES_Red_sum + ADC1BUF0; // Read ADC result
//Acquires Red-AC from Channel1 (AN1)
AD1CHS0bits.CH0SA = 0x01; // Select AN1
AD1CON1bits.SAMP = 1; // Begin sampling
while(!AD1CON1bits.DONE); // Waiting for ADC completed
AD1CON1bits.DONE = 0; // Clear conversion done status bit
CH1_ADRES_Red_sum = CH1_ADRES_Red_sum + ADC1BUF0; // Read ADC result
}
CH0_ADRES_Red = CH0_ADRES_Red_sum / oversampling_number;
FIR_input_Red[0] = CH1_ADRES_Red_sum / oversampling_number;
#ifdef Sleep_Enabled
if (CH0_ADRES_Red<=74 && CH1_ADRES_Red>=4000) //if spo2 probe is not connected, 74=60mV, 4000=3.2V
{
goto_sleep = 1;
}
else if (CH0_ADRES_Red > Finger_Present_Threshold) //if no finger present then goto sleep
{
goto_sleep = 1;
}
else
#endif
{
// LATBbits.LATB14 = 0; // for debugging
for (delay=0; delay<500; delay++); //1000=delayed 256us before read ADC
// LATBbits.LATB14 = 1; // for debugging
//Acquires Red-DC baseline from Channel0 (AN0)
AD1CHS0bits.CH0SA = 0x00; // Select AN0
AD1CON1bits.SAMP = 1; // Begin sampling
while(!AD1CON1bits.DONE); // Waiting for ADC completed
AD1CON1bits.DONE = 0; // Clear conversion done status bit
Baseline_ambient = ADC1BUF0;
Baseline_Upper_Limit = Baseline_ambient + DCVppHigh;
Baseline_Lower_Limit = Baseline_ambient + DCVppLow;
Meter_State = Calibrate_Red();
}
// LATBbits.LATB14 = 0; // for debugging
OC2RS = duty_cycle; // Write Duty Cycle value for next PWM cycle
IFS0bits.T3IF = 0; // Clear Timer3 Interrupt Flag
}
Lista 2: Timer3 ISR som ingår i Microchip Technologys paket med exempelkod samlar in mätningar från den röda lysdiodsbelysningen och mätningar av omgivningsljuset, medan Timer2 ISR endast behöver samla in mätningar från den infraröda belysningen. (Kodkälla: Microchip Technology)
Som visas i lista 2 läser ISR _T3Interrupt den röda baslinjenivån (Red-DC) från ADC-kanal 0 (AN0) och den röda dynamiska nivån (Red-AC) från ADC-kanal 1 (AN1). Om utvecklaren väljer att inkludera en definition för Sleep_Enabled följer den kompilerade ISR-koden upp datainsamlingen med en kontroll för att se om processorn ska gå in i viloläge. Standardkonfigurationen av Microchips programpaket innehåller ett #define for Sleep_Enabled, så variabeln goto_sleep kommer att ställas in om den optiska givaren inte är ansluten eller om användarens finger inte är närvarande.
Efter denna kontroll av givarens status tar ISR prover av den omgivande ljusnivån och använder detta uppdaterade värde för att flytta gränserna för baslinjens fönster i enlighet med detta. Med hjälp av dessa justerade gränser ökar eller minskar funktionen Calibrate_Red() DAC-utgången för den röda lysdiodsdrivrutinen så att ljusstyrkan hålls mellan Baseline_Lower_Limit och Baseline_Upper_Limit.
I avbrottsrutinen för timer T2 används samma grundläggande konstruktionsmönster med undantag för kontrollen av sleep_enabled och mätning av omgivningsljusets nivå.
När timern, utgångskompareringen och ISR:erna är på plats utför exempelprogramvarans huvudrutin en kort initialiseringssekvens och startar Timer2 och Timer3. Då går koden in i huvudslingan och väntar på data som behandlas av ISR:erna. När röda och infraröda data blir tillgängliga bearbetas dessa värden av ett digitalt FIR-filter (finite impulse response), som slutligen anropar rutiner för att beräkna SpO2 och hjärtfrekvens (lista 3).
Kopiera
//********** Enable OC1 & OC2 ouputs for IR & Red LED's on/off switch **********
OC2CONbits.OCM = 0b101; // Select the Output Compare 2 mode, Turn on Red LED
T3CONbits.TON = 1; // Start Timer3
for (delay=0; delay<2200; delay++);
OC1CONbits.OCM = 0b101; // Select the Output Compare 1 mode, Turn on IR LED
T2CONbits.TON = 1; // Start Timer2
goto_sleep = 0;
first_reading = 0;
while (1)
{
if (goto_sleep)
{
[lines clipped]
Sleep(); // Put MCU into sleep
Nop();
}
}
//--------- Main State Machine starts here ---------
if (RedReady && IRReady)
{
RedReady = 0;
IRReady = 0;
// LATBbits.LATB14 = 1; //for debugging
FIR(1, &FIR_output_IR[0], &FIR_input_IR[0], &BandpassIRFilter);
FIR(1, &FIR_output_Red[0], &FIR_input_Red[0], &BandpassRedFilter);
CH1_ADRES_IR = FIR_output_IR[0];
CH1_ADRES_Red = FIR_output_Red[0];
[lines clipped]
if (Detection_Done)
{
//Max & Min are all found. Calculate SpO2 & Pulse Rate
SpO2_Calculation(); //calculate SpO2
Pulse_Rate_Calculation(); //calculate pulse rate
[lines clipped]
}
/*****************************************************************************
* Function Name: SpO2_Calculation()
* Specification: Calculate the %SpO2
*****************************************************************************/
void SpO2_Calculation (void)
{
double Ratio_temp;
IR_Vpp1 = fabs(IR_Max - IR_Min);
Red_Vpp1 = fabs(Red_Max - Red_Min);
IR_Vpp2 = fabs(IR_Max2 - IR_Min2);
Red_Vpp2 = fabs(Red_Max2 - Red_Min2);
IR_Vpp = (IR_Vpp1 + IR_Vpp2) / 2;
Red_Vpp = (Red_Vpp1 + Red_Vpp2) / 2;
IR_Vrms = IR_Vpp / sqrt(8);
Red_Vrms = Red_Vpp / sqrt(8);
// SpO2 = log10(Red_Vrms) / log10(IR_Vrms) * 100;
// if (SpO2 > 100)
// {
// SpO2 = 100;
// }
// Using lookup table to calculate SpO2
Ratio = (Red_Vrms/CH0_ADRES_Red) / (IR_Vrms/CH0_ADRES_IR);
Lista 3: Detta utdrag från huvudrutinen i Microchip Technologys paket med exempelkod visar hur koden initialiserar timer-modulerna och modulerna för utgångskomparering och går in i en ändlös slinga, beräknar SpO2 och hjärtfrekvens när mätningar finns tillgängliga, eller sätter processorn i energisnålt viloläge när sensorfunktionerna går offline. (Kodkälla: Microchip Technology)
För SpO2 omvandlar funktionen SpO2_Calculation() pulsamplituderna (Vpp) för de röda och IR-signalerna till Vrms-värden. Med hjälp av dessa värden genererar funktionen en proportion och använder en uppslagstabell (visas inte i lista 3) för att omvandla proportionen till ett specifikt SpO2-värde. Typiskt sett är denna uppslagstabell hämtad från flera empiriska mätningar. Pulse_Rate_Calculation() använder tiden för mätningen mellan topparna för att bestämma hjärtfrekvensen.
Optimeringsalternativ för SpO2-utformning
Även om konstruktionen som beskrivs i artikeln är en effektiv lösning för en billig pulsoximeter kan övriga enheter optimeras ytterligare. En utvecklare kan exempelvis utesluta den externa dubbla operationsförstärkaren MCP6002 genom att använda de inbyggda operationsförstärkarna i DSC:n DSPIC33CK64MP102 från Microchip Technology.
Vid implementeringen av av denna modifierade konstruktion av pulsoximetern måste dock utvecklarna skriva om vissa viktiga delar av det tidigare beskrivna mjukvarupaketet för att ta hänsyn till vissa skillnader i DSC:n.
DSC:n DSPIC33CK64MP102 tillhandahåller exempelvis en uppsättning timer-moduler för flera användningar, istället för funktionen Timer2/Timer3 i DSC:n DSPIC33FJ128GP802, vilket innebär att utvecklare måste tillhandahålla en egen lösning för vissa av de funktioner som beskrivs i de listor som ingår i artikeln. Trots detta är principerna för användningen desamma och utvecklare kan, åtminstone, använda de designmönster som visas i programvarupaketet från Microchip Technology för att vägleda sin egen skräddarsydda programvarudesign.
Slutsats
Mätning av syremättnad i blodet är en viktig indikering för andningsfunktionen och har blivit ett viktigt verktyg för att hantera hälsan under pandemin COVID-19. Med hjälp av enkla optiska metoder ger pulsoximetrar tillförlitliga uppskattningar av perifer syremättnad (SpO2), vilket uppfyller ett särskilt behov av prisvärda lösningar för hälsoövervakning under pandemin.
Som framgår är en DSC i kombination med några få grundläggande komponenter en effektiv hårdvarubas för att implementera en billig pulsoximeter som på ett tillförlitligt sätt kan leverera SpO2-mätningar som kan indikera ett behov för användaren att söka ytterligare medicinsk vård för en pågående COVID-19-infektion.
Disclaimer: The opinions, beliefs, and viewpoints expressed by the various authors and/or forum participants on this website do not necessarily reflect the opinions, beliefs, and viewpoints of DigiKey or official policies of DigiKey.




