Hallo,
ich bin gerade am Bau eines Fitnesstrackers mithilfe von zwei Arduino Nanos, einem OLED-Display, einem GPS (u-blox NEO-6M) und einem Pulsoximeter (MAX30102).
Der Tracker funktioniert soweit, aber leider zeigt mir der Sensor mehr falsche als richtige Werte an. Aufgrund der Speicherkapazität habe ich den einen Arduino nur mit dem MAX30102 verbunden. Dieser gibt die Werte auf anfrage vom anderen Arduino weiter und da werden sie dann auf das OLED übertragen.
Kann mir jemand weiterhelfen, wie ich richtige Werte bekomme?
Hier der Code für den Arduino mit dem Pulsoximeter.
#include <Wire.h>
#include "MAX30105.h"
#include "spo2_algorithm.h"
MAX30105 particleSensor;
#define MAX_BRIGHTNESS 255
char buffer[10] = "00000000";
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
//Arduino Uno doesn't have enough SRAM to store 100 samples of IR led data and red led data in 32-bit format
//To solve this problem, 16-bit MSB of the sampled data will be truncated. Samples become 16-bit data.
uint16_t irBuffer[100]; //infrared LED sensor data
uint16_t redBuffer[100]; //red LED sensor data
#else
uint32_t irBuffer[100]; //infrared LED sensor data
uint32_t redBuffer[100]; //red LED sensor data
#endif
int32_t bufferLength = 100; //data length
int32_t spo2; //SPO2 value
int8_t validSPO2; //indicator to show if the SPO2 calculation is valid
int32_t heartRate; //heart rate value
int8_t validHeartRate; //indicator to show if the heart rate calculation is valid
void setup()
{
Serial.begin(115200); // initialize serial communication at 115200 bits per second:
for(int x=0;x<100;x++){
redBuffer[x]=0;
irBuffer[x]=0;
}
// Initialize sensor
particleSensor.begin(Wire, I2C_SPEED_FAST);
//if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) //Use default I2C port, 400kHz speed
byte ledBrightness = 60; //Options: 0=Off to 255=50mA
byte sampleAverage = 4; //Options: 1, 2, 4, 8, 16, 32
byte ledMode = 2; //Options: 1 = Red only, 2 = Red + IR, 3 = Red + IR + Green
byte sampleRate = 100; //Options: 50, 100, 200, 400, 800, 1000, 1600, 3200
int pulseWidth = 411; //Options: 69, 118, 215, 411
int adcRange = 4096; //Options: 2048, 4096, 8192, 16384
particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange); //Configure sensor with these settings
}
void loop()
{
//calculate heart rate and SpO2 after first 100 samples (first 4 seconds of samples)
maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);
//*/
//dumping the first 25 sets of samples in the memory and shift the last 75 sets of samples to the top
for (byte i = 25; i < 100; i++)
{
redBuffer[i - 25] = redBuffer[i];
irBuffer[i - 25] = irBuffer[i];
}
//take 25 sets of samples before calculating the heart rate.
for (byte i = 75; i < 100; i++)
{
while (particleSensor.available() == false) //do we have new data?
particleSensor.check(); //Check the sensor for new data
redBuffer[i] = particleSensor.getRed();
irBuffer[i] = particleSensor.getIR();
particleSensor.nextSample(); //We're finished with this sample so move to next sample
if(Serial.available()>1){
//if(true){
Serial.read();
Serial.read();
sprintf(buffer, "%4d", heartRate);
Serial.print(buffer);
sprintf(buffer, "%4d", spo2);
Serial.println(buffer);
}
}
//After gathering 25 new samples recalculate HR and SP02
maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);
//}
}
Code von Arduino mit GPS und OLED:
#include "U8glib.h"
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);
//---------------------------------------------------------------------------
#include <SoftwareSerial.h>
#include <Wire.h>
#include <TinyGPS++.h> //1.0.3
#define rxPin 2
#define txPin 5 //unused
SoftwareSerial neogps(rxPin,txPin);
TinyGPSPlus gps;
//---------------------------------------------------------------------------
u8g_uint_t xx = 0;
//---------------------------------------------------------------------------
//Program variables
int day, month, year;
String hour, minute;
int second;
int num_sat;
int speed;
int average_beat;
int SpO2;
char buffer [20] = "00000000";
//String buffer = "00000000";
unsigned long int timeNow = 0;
unsigned long int timePast = 0;
/*******************************************************************************************
* gauge function
* dispay gauge and other gps data on oled
*******************************************************************************************/
void gauge(uint8_t angle) {
//fonts: u8g_font_chikita - u8g_font_04b_03br
// u8g_font_orgv01 - u8g_font_freedoomr10r
u8g.setFont(u8g_font_chikita);
//---------------------------------------------------------------------------
//GESCHWINDIGKEIT
u8g.setFont(u8g_font_chikita);
u8g.setPrintPos(20,6);
u8g.print("km/h");
u8g.setPrintPos(5,6);
u8g.print(speed);
//---------------------------------------------------------------------------
//SATELLITENEMPFANG
u8g.setFont(u8g_font_chikita);
u8g.setPrintPos(95,6);
u8g.print("Sat:");
u8g.setPrintPos(115,6);
u8g.print(num_sat, 5);
//---------------------------------------------------------------------------
//DISTANCE
// u8g.setPrintPos(18,5);
//u8g.print("km");
//---------------------------------------------------------------------------
//UHRZEIT
u8g.setFont(u8g_font_chikita);
u8g.setPrintPos(100, 59);
u8g.print(hour);
if(second%2 == 0)
{u8g.drawStr(105, 59, ":");}
else
{u8g.drawStr(105, 59, " ");}
u8g.setPrintPos(110, 59);
u8g.print(minute);
//u8g.drawStr(90, 65, "00:00");
//---------------------------------------------------------------------------
//DATUM
u8g.setFont(u8g_font_chikita);
u8g.setPrintPos(10,59);
u8g.print(day);
u8g.setPrintPos(15,59);
u8g.print(".");
u8g.setPrintPos(20,59);
u8g.print(month);
u8g.setPrintPos(25,59);
u8g.print(".");
u8g.setPrintPos(30,59);
u8g.print(year);
//---------------------------------------------------------------------------
//HERZFREQUENZ
u8g.setFont(u8g_font_tpssb);
u8g.setPrintPos(40,24);
u8g.print(average_beat);
u8g.setPrintPos(65,24);
u8g.print("bpm");
//---------------------------------------------------------------------------
//BLOOD OXYGEN
u8g.setFont(u8g_font_chikita);
u8g.setPrintPos(51,45);
u8g.print("2");
u8g.setFont(u8g_font_tpssb);
u8g.setPrintPos(30,43);
u8g.print("SpO");
u8g.setPrintPos(60,43);
u8g.print(SpO2);
u8g.setPrintPos(82,43);
u8g.print("%");
//---------------------------------------------------------------------------
}
/*******************************************************************************************
* gauge function
* dispay gauge and other gps data on oled
*******************************************************************************************/
int i = 200;
void setup(void) {
Serial.begin(115200);
neogps.begin(9600);
u8g.setFont(u8g_font_chikita);
u8g.setColorIndex(1);
}
/*******************************************************************************************
* gauge function
* dispay gauge and other gps data on oled
*******************************************************************************************/
void loop(void){
//----------------------------------------------------------
Read_GPS();
Read_Pulsoximeter();
//----------------------------------------------------------
//Display Data on Oled
{
u8g.firstPage();
do {
gauge(xx);
}
while( u8g.nextPage() );
}
//----------------------------------------------------------
}
void Read_GPS(){
//------------------------------------------------------------------
boolean newData = false;
for (unsigned long start = millis(); millis() - start < 1000;)
{
while (neogps.available())
{
if (gps.encode(neogps.read()))
{
newData = true;
break;
}
}
}
//------------------------------------------------------------------
//If newData is true
if(newData == true){
newData = false;
Get_GPS();
}
else {
//no data
}
}
void Get_GPS(){
num_sat = gps.satellites.value();
if (gps.location.isValid() == 1) {
speed = gps.speed.kmph();
//Serial.print("Speed: ");Serial.println(gps_speed);
}
if (gps.time.isValid()){
hour = String(gps.time.hour());
hour = (hour.length() == 1) ? "0"+hour : hour;
minute = String(gps.time.minute());
minute= (minute.length() == 1) ? "0"+minute : minute;
second = gps.time.second();
}
}
//------------------------------------------------------------------
void Read_Pulsoximeter(){
timeNow = millis();
if((timeNow - timePast) > 1000)
{
Serial.print("?");
}
if(Serial.available())
{
readline(Serial.read(), buffer, 20);
//Serial.println(buffer);
average_beat = CharArrToInt(buffer[1], buffer[2], buffer [3]);
SpO2 = CharArrToInt(buffer[5], buffer[6], buffer [7]);
}
}
int readline(int readch, char *buffer, int len)
{
static int pos = 0;
int rpos;
if (readch > 0) {
switch (readch) {
case '\n': // Ignore new-lines
break;
case '\r': // Return on CR
rpos = pos;
pos = 0; // Reset position index ready for next time
return rpos;
default:
if (pos < len-1) {
buffer[pos++] = readch;
buffer[pos] = 0;
}
}
}
// No end of line has been found, so return -1.
return -1;
}
int CharArrToInt(char one, char two, char three){
int number= 0;
if(one<0x30 || one >0x39)one=0x30;
if(two<0x30 || two >0x39)two=0x30;
if(three<0x30 || three >0x39)three=0x30;
number = (one-0x30)*100+(two-0x30)*10+(three-0x30);
return number;
}