Stap 4: codering
Dit is echt het hart van dit project (heh). Stap 3, hebt u de fysieke hartslagmeter, maar nu u beslist wat u zult doen met het apparaat. Het RGB-LCD schild wordt geleverd met 5 programmeerbare knoppen. Voor ons project besloten hebben we op de volgende punten:
- OMHOOG: Neemt een lezen van uw hartslag.
- OMLAAG: Toont het gemiddelde van de laatste 4 lezingen van de hartslag.
- LINKS: Geeft de laatste 4 lezingen.
- RECHTS: Geeft sommige motivatie.
- Selecteer: Verklaart elke knop.
Er zijn drie onderdelen aan de codering:
- Hartslag Sensor data
- Wave Shield audio-uitgang
- Schild van RGB-LCD display & knop indrukt
Nu, laat gaan over de feitelijke code. Wij mazen in principe vrij beschikbare code samen uit de RGB-LCD schild, Wave Shield en Pulse Sensor websites. We hechten ook de twee bestanden die u in .txt formaat nodig zult hebben. Houd er rekening mee dat zal u een bestand van de Pulse Sensor- website , genaamd Interrupt.ino (Breng geen wijzigingen aan dit bestand op enigerlei wijze). Dit bestand wordt uitgevoerd in de achtergrond en doet het zware werk dat gaat in de berekening van uw BPM van de Pulse-Sensor lezingen. Merk op dat dit bestand in dezelfde map als degene die we tonen moet hieronder de code werkt. Het is ook belangrijk het audiobestand om namen te onthouden om de specifieke bestanden. Playcomplete ("file_name.wav") bevat een specifieke bestandsnaam, zult u opmerken. Zodra u het volgende bestand (met de interrupt-bestand in dezelfde map) uploaden bent u goed om te gaan!
<p>// project: interactive heart rate monitor with audio</p><p>// LCD shield libraries #include <Wire.h><wire.h> #include <Adafruit_</wire.h>MCP23017.h></p><p><wire.h><adafruit_mcp23017.h>#include <<adafruit_rgblcdshield.h></adafruit_rgblcdshield.h></adafruit_mcp23017.h></wire.h>Adafruit_RGBLCDShield.h></p><p>#include <Average.h><average.h></average.h></p><p>// waveshield libraries #include <FatReader.h></p><p><fatreader.h>#include <SdReader.h><sdreader.h> #include <avr/pgmspace.h><avr pgmspace.h=""> #include "WaveUtil.h" #include "WaveHC.h"</avr></sdreader.h></fatreader.h></p><p>// objects for audio SdReader card; // This object holds the information for the card FatVolume vol; // This holds the information for the partition on the card FatReader root; // This holds the information for the filesystem on the card FatReader f; // This holds the information for the file we're play WaveHC wave; // This is the only wave (audio) object, since we will only play one at a time</p><p>#define DEBOUNCE 100 // button debouncer, may not be needed</p><p>//============================================================================== // adapted from Adafruit Waveshield website // methods for debugging void sdErrorCheck(void) // checks the SD card { if (!card.errorCode()) return; putstring("\n\rSD I/O error: "); Serial.print(card.errorCode(), HEX); putstring(", "); Serial.println(card.errorData(), HEX); while(1); }</p><p>// adapted from Adafruit rgb lcd shield website // The rgb lcd shield uses the I2C SCL and SDA pins. On classic Arduinos // this is Analog 4 and 5 so you can't use those for analogRead() anymore // However, you can connect other I2C sensors to the I2C bus and share // the I2C bus. Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();</p><p>// These #defines make it easy to set the backlight color #define RED 0x1 #define YELLOW 0x3 #define GREEN 0x2 #define TEAL 0x6 #define BLUE 0x4 #define VIOLET 0x5 #define WHITE 0x7</p><p>//================================================================================ // PULSE SENSOR CODE: adapted from Pulse Sensor website for this project /*</p><p> >> Pulse Sensor Amped 1.2 << This code is for Pulse Sensor Amped by Joel Murphy and Yury Gitman <a href="http://www.pulsesensor.com"> www.pulsesensor.com </a> >>> Pulse Sensor purple wire goes to Analog Pin 0 <<< Pulse Sensor sample aquisition and processing happens in the background via Timer 2 interrupt. 2mS sample rate. PWM on pins 3 and 11 will not work when using this code, because we are using Timer 2! The following variables are automatically updated: Signal : int that holds the analog signal data straight from the sensor. updated every 2mS. IBI : int that holds the time interval between beats. 2mS resolution. BPM : int that holds the heart rate value, derived every beat, from averaging previous 10 IBI values. QS : boolean that is made true whenever Pulse is found and BPM is updated. User must reset. Pulse : boolean that is true when a heartbeat is sensed then false in time with pin13 LED going out. */</p><p>// VARIABLES int pulsePin = 2; // Pulse Sensor purple wire connected to analog pin 2 (rgb lcd shield) int blinkPin = 6; // pin to blink led at each beat</p><p>int fadeRate = 0;</p><p>int heartvals[4]; int h = 0;</p><p>// these variables are volatile because they are used during the interrupt service routine! volatile int BPM; // used to hold the pulse rate volatile int Signal; // holds the incoming raw data volatile int IBI = 600; // holds the time between beats, must be seeded! volatile boolean Pulse = false; // true when pulse wave is high, false when it's low volatile boolean QS = false; // becomes true when Arduoino finds a beat.</p><p>//===============================================================================</p><p>void setup() {</p><p> pinMode( blinkPin, OUTPUT ); // pin that will blink to your heartbeat!</p><p> // Set the output pins for the DAC control. This pins are defined in the library pinMode(2, OUTPUT); pinMode(3, OUTPUT); pinMode(4, OUTPUT); pinMode(5, OUTPUT);</p><p> // enable pull-up resistors on switch pins (analog inputs) digitalWrite(14, HIGH); digitalWrite(15, HIGH); digitalWrite(16, HIGH); digitalWrite(17, HIGH); digitalWrite(18, HIGH); digitalWrite(19, HIGH);</p><p> Serial.begin( 9600 );</p><p> // debugging methods from waveshield website // if (!card.init(true)) { //play with 4 MHz spi if 8MHz isn't working for you if (!card.init()) { //play with 8 MHz spi (default faster!) putstring_nl("Card init. failed!"); // Something went wrong, lets print out why sdErrorCheck(); while(1); // then 'halt' - do nothing! }</p><p> // enable optimize read - some cards may timeout. Disable if you're having problems card.partialBlockRead(true);</p><p> // Now we will look for a FAT partition! uint8_t part; for (part = 0; part < 5; part++) { // we have up to 5 slots to look in if (vol.init(card, part)) break; // we found one, lets bail }</p><p> if (part == 5) { // if we ended up not finding one :( putstring_nl("No valid FAT partition!"); sdErrorCheck(); // Something went wrong, lets print out why while(1); // then 'halt' - do nothing! }</p><p> // Lets tell the user about what we found putstring("Using partition "); Serial.print(part, DEC); putstring(", type is FAT"); Serial.println(vol.fatType(),DEC); // FAT16 or FAT32?</p><p> // Try to open the root directory if (!root.openRoot(vol)) { putstring_nl("Can't open root dir!"); // Something went wrong, while(1); // then 'halt' - do nothing! }</p><p> // secondary file with code for the Pulse Sensor interruptSetup(); // sets up to read Pulse Sensor signal every 2mS // UN-COMMENT THE NEXT LINE IF YOU ARE POWERING The Pulse Sensor AT LOW VOLTAGE, // AND APPLY THAT VOLTAGE TO THE A-REF PIN //analogReference(EXTERNAL); </p><p> // set up for LCD lcd.begin( 16, 2 ); lcd.setBacklight( RED );</p><p> lcd.setCursor( 0, 0 ); lcd.print( "Welcome to your" ); lcd.setCursor( 0, 1 ); lcd.print( "Arduino HRM!" ); playcomplete("intro.wav");</p><p> // lcd.clear();</p><p>} // END OF VOID SETUP</p><p>uint8_t i=0;</p><p>//===============================================================================</p><p>void loop() { uint8_t buttons = lcd.readButtons(); if ( buttons ) { lcd.clear(); lcd.setCursor( 0, 0 );</p><p> if ( buttons & BUTTON_UP ) { heartRate(); } if ( buttons & BUTTON_LEFT ) { playcomplete( "readings.wav" ); lcd.setCursor( 0, 0 ); lcd.print( "Last 4 readings: " ); lcd.setCursor( 0, 1 ); int i; for ( i=0; i<4; i++ ) { lcd.println( heartvals[i] ); } } if ( buttons & BUTTON_RIGHT ) { int randNumber = 0; randNumber = random( 1, 10 ); if ( randNumber == 1 ) { playcomplete("1.wav"); } if ( randNumber == 2 ) { playcomplete("2.wav"); } if ( randNumber == 3 ) { playcomplete("3.wav"); } if ( randNumber == 4 ) { playcomplete("4.wav"); } if ( randNumber == 5 ) { playcomplete("5.wav"); } if ( randNumber == 6 ) { playcomplete("6.wav"); } if ( randNumber == 7 ) { playcomplete("7.wav"); } if ( randNumber == 8 ) { playcomplete("8.wav"); } if ( randNumber == 9 ) { playcomplete("9.wav"); } if ( randNumber == 10 ) { playcomplete("10.wav"); } } if ( buttons & BUTTON_DOWN ) { averageH(); } if ( buttons & BUTTON_SELECT ) { lcd.print( "Select" ); playcomplete( "select.wav" ); } } } // END OF VOID LOOP</p><p>//===============================================================================</p><p>// methods needed for playing .wav files // adapted from waveshield website</p><p>// Plays a full file from beginning to end with no pause. void playcomplete(char *name) { // call our helper to find and play this name playfile(name); while (wave.isplaying) { // do nothing while its playing } // now its done playing }</p><p>void playfile(char *name) { // see if the wave object is currently doing something if (wave.isplaying) {// already playing something, so stop it! wave.stop(); // stop it } // look in the root directory and open the file if (!f.open(root, name)) { putstring("Couldn't open file "); Serial.print(name); return; } // OK read the file and turn it into a wave object if (!wave.create(f)) { putstring_nl("Not a valid WAV"); return; }</p><p> // ok time to play! start playback wave.play(); } //===============================================================================</p><p>// a method called to read and display BPM on lcd on UP button press void heartRate() { int x = 10;</p><p> while ( x != 0 ) { if ( QS == true ){ // Quantified Self flag is true when arduino finds a heartbeat fadeRate = 255; // Set 'fadeRate' Variable to 255 to fade LED with pulse lcd.setCursor( 0, 0 ); lcd.print( "Heart rate: " ); lcd.setCursor( 12, 0 ); lcd.println( BPM ); lcd.setCursor( 0, 1 ); lcd.print( "You are alive!" ); delay( 500 ); QS = false; // reset the Quantified Self flag for next time x--; } } heartvals[h] = BPM ; if ( h < 4 ) { h++; } else if ( h == 4 ) { h = 0; heartvals[h] = BPM ; }</p><p> int i; for ( i=0; i<4; i++ ) { Serial.println( heartvals[i]); } playcomplete( "finished.wav" ); }</p><p>// method to calculate the average of the 4 values in heartvals void averageH() { int average = 0; if ( heartvals[3] == 0 ) { lcd.setCursor( 4, 0 ); lcd.print( "Error..." ); lcd.setCursor( 0, 1 ); lcd.print( "4 values needed" ); } else { playcomplete( "average.wav" ); average = mean( heartvals, 4 ); lcd.setCursor( 0, 0 ); lcd.print( "Average: " ); lcd.setCursor( 9, 0 ); lcd.print( average ); }</p><p>}</p><p>//===============================================================================</p>