Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Manufacturing Technology >> Productieproces

Van KY-039 tot hartslag

Componenten en benodigdheden

Arduino UNO
× 1
KY-039 hartslagsensor
× 1
Jumperdraden (algemeen)
× 1

Over dit project

In de set van 37 sensoren voor Arduino , er is een hartslagsensor. De naam belooft teveel. Mensen hebben de neiging om te denken dat het een digitaal nummer geeft via I2C of iets dergelijks, een nummer dat de hartslag is. Wat de sensor levert, is slechts een "analoge" waarde van 0 tot 1023, die aangeeft hoeveel infrarood licht de lichtsensor ontvangt, of eigenlijk hoeveel iets de lichtsensor in de schaduw stelt . Hoe hoger de waarde, hoe minder infrarood licht.

Kortom:plaats je vinger tussen de IR led en de lichttransistor van de sensor. Je hartslag verwijdt de bloedvaten in je vinger, waardoor de IR wordt gefilterd. Hierdoor ontstaat een pulserend signaal.

In dit project beschrijf ik hoe dit signaal wordt omgezet in een hartslag van bijvoorbeeld 66 BPM (beats per minute).

De eenvoudige stappen

Als u zojuist de waarden van de KY-039-sensor leest en plot, krijgt u zoiets als dit:

De waarden zijn gehele waarden. Niet erg nauwkeurig. Bereken in plaats daarvan een gemiddelde van een aantal van hen en plot het gemiddelde. Je krijgt dit:

Hier kun je de hartslag van het hart al zien. Krijg het tijdsverschil tussen elke significante stijging van de puls. Daaruit kun je de hartslag in BPM berekenen.

(Het kleine zigzagpatroon in de afbeelding hierboven is te wijten aan kunstlicht, 50 Hz, nog iets waar je mee te maken hebt.)

Stappen uitgelegd

Hier is een simpele code om gewoon uit te voeren wat je leest van de KY-039-sensor:

// Pulse Monitor Test Scriptint sensorPin =0;void setup() { Serial.begin(9600);}void loop (){ while(1) { Serial.print(analogRead(sensorPin)); Serieel.print('\n'); }}  

Wat je zou kunnen krijgen is zoiets als dit:

Aangezien dit een bijschrift is van het seriële monitorvenster dat de seriële uitvoer van uw Arduino op 9600 baud leest, wordt het hele proces getimed door de Serial.print() functie, die een snelheid instelt voor het lezen en plotten van de waarden. Hoe dan ook, de curve is erg gekarteld, omdat hij varieert tussen 360 en 383 en alleen gehele waarden heeft.

Gladmaken

Om een ​​vloeiendere output te krijgen, neemt u gemiddeld 20 laatste metingen van de sensor. Hier is hoe ik het doe. Ik definieer een constante die aangeeft hoeveel metingen ik wil:

#define samp_siz 20 

Dan heb ik een array met dat aantal metingen:

int leest[samp_siz];  

Voor elke nieuwe lezing trek ik de oudste lezing af van een som en voeg ik de nieuwste lezing toe aan de som. In de array vervang ik de oudste lezing door de nieuwste lezing.

 lezer =analogRead (sensorPin); // lees de sensorsom -=leest [ptr]; // trek de oudste lezing af van de som +=lezer; // voeg de nieuwste lezing toe aan de som reads[ptr] =reader; // sla de nieuwste meting op in de array last =float (sum) / samp_siz; // bereken nu het gemiddelde ptr++; // update de index voor de array, hebben ptr %=samp_siz; // het herstart op 0 wanneer nodig 

Met een arraygrootte van 20 en een baudrate van 9600 in de seriële monitor, zou ik een plot als volgt kunnen krijgen:

Hier zie je de werkelijke hartslag als een steile stijgende curve. Maar je ziet ook een klein zigzagpatroon. De kleinere zigzag komt van mijn keukenlamp, drie LED-lampen die de kamer verlichten. Het lichtnet in mijn huis is 240 V, 50 Hz AC. Dus 50 keer per seconde stijgt de lichtintensiteit, blijkbaar ook in de IR-band. Ik zou die ruis van 50 Hz graag wegwerken. Het zou moeten werken als ik gedurende een periode van 20 ms waarden van de sensor aflees en een gemiddelde van alle waarden neem. Eens kijken...

 n =0; start =millis(); lezer =0.; do { reader +=analogRead (sensorPin); // lees en voeg waarden toe... n++; nu =millis(); } while (nu  

Met dit fragment neem ik de sensormetingen op in brokken van 20 ms, waardoor de 50 Hz-flikkering die wordt veroorzaakt door kunstlicht, wordt geëgaliseerd. Als je in een land met 60 Hz woont, gebruik dan 16,67 ms chunks. Of 16667 µs.

Omdat ik de curve al in secties van 20 ms gladstrijk, heb ik de array die ik eerder heb gebruikt niet echt nodig, maar omdat hij er is en gemakkelijk kan worden aangepast, laat ik hem daar. En het gebruik van een arraygrootte van 5 lijkt de laatste vervelende ruis te compenseren. Dit is wat ik nu heb:

Het laatste wat ik moet doen, is een deel van het herhalende patroon herkennen. Omdat de stijgende helling regelmatiger is, ga ik ervoor. Merk op hoe de waarden van de y-as in alle grafieken heel verschillend zijn. Ik kan echt niet alleen vertrouwen op absolute waarden. Ik kan alleen vertrouwen op het stijgen en dalen van de curve. Wiskundigen zouden het hebben over de afgeleide. Ik ben tevreden als ik n . vind opeenvolgende stijgende waarden, waarbij n zou een handige instelbare waarde kunnen zijn. Ik begin met 5. Hiervoor heb ik de rise_threshold constante gedefinieerd in de code. Als ik 5 opeenvolgende stijgende waarden vind, weet ik dat ik aan de onderkant van de curve naar boven sta. Ik neem de tijd. Ik wacht op een dalende curve, dan wacht ik op de volgende 5 stijgende waarden en noteer de tijd. Vervolgens print ik de bijbehorende BPM.

Ik heb een test gedaan en geteld hoe veel opeenvolgend stijgend waarden daar zijn in de kromme en gevonden uit daar waren tussen 10 en 15. Dus als Ik tel naar 5, Ik zal de meeste zeker weet Ik heb gevonden de begin van de hartslag.

Omdat ik pas na elke hartslag print, zal er niet veel worden afgedrukt. Er is meer tijd voor het uitlezen van de sensor. Ik kan meer hoogfrequent geluid opvangen, wat ik niet zal zien, omdat de plotter niet aan staat. Laten we eens kijken hoe het werkt.

De laatste code

#define samp_siz 4#define rise_threshold 5// Pulse Monitor Test Scriptint sensorPin =0;void setup() { Serial.begin(9600);}void loop (){ float reads[samp_siz], sum; lange int nu, ptr; float laatste, lezer, start; float eerste, tweede, derde, voor, print_value; bool stijgt; int stijging_telling; int n; lange int last_beat; voor (int i =0; i  before) { rise_count++; if (!rising &&rise_count> rise_threshold) { // Ok, we hebben een stijgende curve gedetecteerd, wat impliceert een hartslag. // Noteer de tijd sinds de laatste slag, houd de twee vorige // tijden bij (eerste, tweede, derde) om een ​​gewogen gemiddelde te krijgen. // De stijgende vlag voorkomt dat we dezelfde stijging detecteren // meer dan eenmaal stijgen =waar; eerste =millis () - laatste_slag; last_beat =millis(); // Bereken het gewogen gemiddelde van de hartslag // volgens de drie laatste slagen print_value =60000. / (0,4 * eerste + 0,3 * tweede + 0,3 * derde); Serial.print(print_value); Serieel.print('\n'); derde =tweede; tweede =eerste; } } else { // Ok, de curve daalt stijgend =false; stijging_count =0; } voor =laatste; ptr++; ptr %=samp_grootte; }}  

Het werkt best goed. Hier is een video.

Merk op dat de kleine RX-led op de Arduino synchroon met mijn hart knippert. Simpelweg omdat wanneer er een hartslag is, de snelheid wordt berekend en afgedrukt naar de serie, die de led knippert. Wanneer de vinger een beetje beweegt, zullen er foutlezingen zijn.

Verdere ontwikkeling

Op dit moment wordt de afgedrukte snelheid berekend op basis van de laatste drie beats. Maar het zou passender kunnen zijn om het te berekenen op basis van bijvoorbeeld een periode van 15 s. Ik zou 15 opeenvolgende snelheidswaarden kunnen opslaan, het gemiddelde kunnen berekenen, dan de vijf waarden die het verst van het gemiddelde liggen weglaten en een nieuw gemiddelde berekenen. Dit zou vrijwel een betrouwbare en stabiele meting van de hartslag opleveren.

Ik heb de sensor alleen op mijn vrouw en op mij getest. Elke stap in het verbeteren van het signaal heb ik gemaakt op basis van de vorige metingen. Iemand anders kan een ander soort hartslag hebben die een ander gevormde curve veroorzaakt, die een andere benadering nodig heeft om de beat te vinden. Misschien is het de dalende curve die gemakkelijker te herkennen is. Of helemaal bovenaan. En wat gebeurt er als de puls 180 - 200 BPM is? Het vinden van de stijgende curve is misschien lastiger.

Code

  • Definitieve versie
Definitieve versieC/C++
Het programma leest de hartslag en drukt de snelheid af in het seriële venster.
#define samp_siz 4#define rise_threshold 4// Pulse Monitor Test Scriptint sensorPin =0;void setup() { Serial.begin(9600);}void loop (){ float leest [samp_siz], som; lange int nu, ptr; float laatste, lezer, start; float eerste, tweede, derde, voor, print_value; bool stijgt; int stijging_telling; int n; lange int last_beat; voor (int i =0; i  before) { rise_count++; if (!rising &&rise_count> rise_threshold) { // Ok, we hebben een stijgende curve gedetecteerd, wat impliceert een hartslag. // Noteer de tijd sinds de laatste slag, houd de twee vorige // tijden bij (eerste, tweede, derde) om een ​​gewogen gemiddelde te krijgen. // De stijgende vlag voorkomt dat we dezelfde stijging meer dan eens detecteren. stijgend =waar; eerste =millis() - laatste_slag; last_beat =millis(); // Bereken het gewogen gemiddelde van de hartslag // volgens de drie laatste slagen print_value =60000. / (0,4 * eerste + 0,3 * tweede + 0,3 * derde); Serial.print(print_value); Serieel.print('\n'); derde =tweede; tweede =eerste; } } else { // Ok, de curve daalt stijgend =false; stijging_count =0; } voor =laatste; ptr++; ptr %=samp_grootte; }} 

Schema's


Productieproces

  1. Kleursensor – Werking en toepassingen
  2. OPT3007 ultradunne omgevingslichtsensor
  3. Werking en toepassingen van de omgevingslichtsensor
  4. Sensorgegevens streamen van een ppDAQC Pi-plaat met InitialState
  5. Raspberry Pi temperatuur- en lichtsensor
  6. Zonne-opritverlichting naar MSP430 draadloos sensorknooppunt
  7. Spraak- en sms-lichtsensor met Raspberry Pi en Twilio
  8. Windows 10 IoT Core – Hartslagpulsen lezen
  9. Raspberry Pi-lichtsensor:een eenvoudige LDR-zelfstudie
  10. Digitale lichtsensor
  11. Hartslagmeter op afstand