// Configuración Blynk
#define BLYNK_TEMPLATE_ID "TMPL2TNl1Gnuu"
#define BLYNK_TEMPLATE_NAME "A4 Telemed"
#define BLYNK_AUTH_TOKEN "sAxmoWtggtivhwqiLxZzaHwcVJ7K_dpk"
// Configuración WiFi
char ssid[] = "IZZI-632E";
char pass[] = "y9pze3yf";
// LIBRERÍAS
#include <WiFi.h>
#include <BlynkSimpleEsp32.h>
#include <Wire.h>
#include "MAX30105.h"
#include "spo2_algorithm.h"
#include "DHT.h"
// Configuración sensores
MAX30105 particleSensor;
#define DHTPIN 4
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
// Variables globales
uint32_t irBuffer[100]; // Buffer para datos IR
uint32_t redBuffer[100]; // Buffer para datos rojo
int32_t spo2; // Valor de SpO2
int8_t validSPO2; // Indicador de validez SpO2
int32_t heartRate; // Frecuencia cardíaca
int8_t validHeartRate; // Indicador de validez FC
float temperature;
unsigned long lastUpdate = 0;
const long updateInterval = 1000; // Actualizar cada segundo
void setup() {
Serial.begin(115200);
// Iniciar Blynk
Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
// Iniciar sensor DHT
dht.begin();
// Iniciar sensor MAX30102
Wire.begin();
if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) {
Serial.println("MAX30102 no encontrado");
while (1);
}
// Configurar sensor MAX30102
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
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);
Serial.println("Sistema listo. Coloque su dedo en el sensor...");
}
void loop() {
Blynk.run(); // Mantener conexión Blynk
if (millis() - lastUpdate >= updateInterval) {
lastUpdate = millis();
// Leer temperatura
temperature = dht.readTemperature();
// Tomar muestras del sensor óptico
for (byte i = 0; i < 100; i++) {
while (!particleSensor.available()) {
particleSensor.check();
}
redBuffer[i] = particleSensor.getRed();
irBuffer[i] = particleSensor.getIR();
particleSensor.nextSample();
}
// Calcular SpO2 y frecuencia cardíaca
maxim_heart_rate_and_oxygen_saturation(irBuffer, 100, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);
// Mostrar datos por Serial
displayData();
// Enviar datos a Blynk
sendToBlynk();
}
}
void displayData() {
Serial.println("\n--- Mediciones ---");
// Temperatura
if (!isnan(temperature)) {
Serial.print("Temperatura: ");
Serial.print(temperature);
Serial.println(" °C");
} else {
Serial.println("Error lectura temperatura");
}
// SpO2
Serial.print("SpO2: ");
if (validSPO2) {
Serial.print(spo2);
Serial.println("%");
} else {
Serial.println("No válido");
}
// Frecuencia cardíaca
Serial.print("Frecuencia Cardíaca: ");
if (validHeartRate) {
Serial.print(heartRate);
Serial.println(" BPM");
} else {
Serial.println("No válida");
}
Serial.println("------------------");
}
void sendToBlynk() {
// Enviar temperatura
if (!isnan(temperature)) {
Blynk.virtualWrite(V1, temperature);
}
// Enviar SpO2
if (validSPO2) {
Blynk.virtualWrite(V0, spo2);
}
// Enviar frecuencia cardíaca
if (validHeartRate) {
Blynk.virtualWrite(V2, heartRate);
}
}