#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "MAX30105.h" // Biblioteca MAX3010x
#include "heartRate.h" // Algoritmo de cálculo da frequência cardíaca
MAX30105 particleSensor;
const byte RATE_SIZE = 4; // Aumente este valor para amostras maiores. 4 está bom.
byte rates[RATE_SIZE]; // Array da frequência cardíaca
byte rateSpot = 0;
long lastBeat = 0; // Tempo que o último batimento ocorreu
float beatsPerMinute;
int beatAvg;
// Configurações FIWARE
const char* SSID = "Wokwi-GUEST";
const char* PASSWORD = "";
const char* BROKER_MQTT = "20.55.28.240";
const int BROKER_PORT = 1883;
const char* ID_MQTT = "bpm_030";
const char* TOPICO_PUBLISH = "/TEF/bpm030/attrs";
WiFiClient espClient;
PubSubClient MQTT(espClient);
void conectarWiFi() {
Serial.print("Conectando ao Wi-Fi ");
WiFi.begin(SSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" conectado!");
Serial.print("IP: ");
Serial.println(WiFi.localIP());
}
void conectarMQTT() {
while (!MQTT.connected()) {
Serial.print("Conectando ao MQTT... ");
if (MQTT.connect(ID_MQTT)) {
Serial.println("conectado!");
} else {
Serial.print("falha, rc=");
Serial.print(MQTT.state());
Serial.println(" tentando novamente em 2 segundos");
delay(2000);
}
}
}
// Dimensões do display
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
// Botões
#define BUTTON1 32
#define BUTTON2 33
#define BUTTON3 26
#define BUTTON4 27
// LEDs correspondentes aos botões
#define LED1 12
#define LED2 13
#define LED3 14
#define LED4 15
int buttonState1 = 0;
int buttonState2 = 0;
int buttonState3 = 0;
int buttonState4 = 0;
int bpm;
int spo2;
// Buzzer
#define BUZZER_PIN 25
// Notas musicais
#define NOTE_C4 262
#define NOTE_D4 294
#define NOTE_E4 330
#define NOTE_F4 349
// Criação dos dois barramentos I2C
TwoWire I2C_1 = TwoWire(0);
TwoWire I2C_2 = TwoWire(1);
// Criação dos displays
Adafruit_SSD1306 display1(SCREEN_WIDTH, SCREEN_HEIGHT, &I2C_1, -1); // Display de dados
Adafruit_SSD1306 display2(SCREEN_WIDTH, SCREEN_HEIGHT, &I2C_2, -1); // Display decorativo
// Simulação de dados
bool simular = true;
// Animação (substitua os dados por frames reais)
// Funções de simulação
int lerBPM() {
return simular ? random(65, 100) : 0;
}
int lerSpO2() {
return simular ? random(95, 100) : 0;
}
void setup() {
Serial.begin(115200);
particleSensor.begin(Wire, I2C_SPEED_FAST); // Usa as portas I2C padrão, 400kHz de velocidade
particleSensor.setup(); // Configura o sensor para as configurações padrões
particleSensor.setPulseAmplitudeRed(0x0A); // Liga o LED vermelho para indicar se o sensor está funcionando.
// Conecta Wi-Fi e MQTT
conectarWiFi();
MQTT.setServer(BROKER_MQTT, BROKER_PORT);
// Inicializa os botões
pinMode(BUTTON1, INPUT_PULLUP);
pinMode(BUTTON2, INPUT_PULLUP);
pinMode(BUTTON3, INPUT_PULLUP);
pinMode(BUTTON4, INPUT_PULLUP);
// Inicializa os LEDs
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(LED3, OUTPUT);
pinMode(LED4, OUTPUT);
// Inicializa o buzzer
pinMode(BUZZER_PIN, OUTPUT);
// Inicializa os barramentos I2C
I2C_1.begin(21, 22);
I2C_2.begin(17, 16);
// Inicializa os displays
if (!display1.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("Erro ao iniciar display1");
while (true);
}
if (!display2.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("Erro ao iniciar display2");
while (true);
}
display1.clearDisplay();
display1.setTextSize(4);
display1.setTextColor(SSD1306_WHITE);
display2.clearDisplay();
display2.setTextSize(4);
display2.setTextColor(SSD1306_WHITE);
}
unsigned long lastSendTime = 0;
const long sendInterval = 3000; // Intervalo de 5 segundos (5000 ms)
void loop() {
long irValue = particleSensor.getIR(); // Lê o sensor infravermelho (IR) vai permitir sabermos se o dedo está no sensor ou não
// E também detectar um batimento
if (irValue > 7000) { // Caso seja detectado o dedo
Serial.print(beatAvg);
Serial.println(" BPM");
if (checkForBeat(irValue) == true) // Se um batimento for detectado
{
//Serial.print(beatAvg);
//Serial.println(" BPM");
// Nós sentimos um batimento!
long delta = millis() - lastBeat; // Calcula a duração entre dois batimentos
lastBeat = millis();
beatsPerMinute = 60 / (delta / 1000.0); // Calculando o BPM
if (beatsPerMinute < 255 && beatsPerMinute > 20) // Para calcular a média nós salvamos alguns valores (4) então tiramos a média
{
rates[rateSpot++] = (byte)beatsPerMinute; // Salva esta leitura no array
rateSpot %= RATE_SIZE;
// Pega o valor da média
beatAvg = 0;
for (byte x = 0; x < RATE_SIZE; x++)
beatAvg += rates[x];
beatAvg /= RATE_SIZE;
}
}
}
//if (irValue < 7000) { // Se não for detectado o dedo, informe ao usuário
// beatAvg = 0;
// Serial.println("Por favor, coloque seu dedo.");
//}
// Lê os dados simulados
bpm = beatAvg();
spo2 = lerSpO2();
// Atualiza display 1 com BPM e SpO2
display1.clearDisplay();
display1.setCursor(0, 0);
display1.print("BPM: ");
display1.println(bpm);
//display1.print("SpO2: ");
//display1.print(spo2);
//display1.println("%");
display1.display();
// Atualiza display 2 com animação
display2.clearDisplay();
display2.setCursor(0, 0);
//display2.print("BPM: ");
//display2.println(bpm);
display2.print("SpO2: ");
display2.print(spo2);
display2.println("%");
display2.display();
// Leitura dos botões
buttonState1 = digitalRead(BUTTON1);
buttonState2 = digitalRead(BUTTON2);
buttonState3 = digitalRead(BUTTON3);
buttonState4 = digitalRead(BUTTON4);
// Botões e LEDs
if (buttonState1 == LOW) {
digitalWrite(LED1, HIGH);
tone(BUZZER_PIN, NOTE_C4, 100);
} else {
digitalWrite(LED1, LOW);
}
if (buttonState2 == LOW) {
digitalWrite(LED2, HIGH);
tone(BUZZER_PIN, NOTE_D4, 100);
} else {
digitalWrite(LED2, LOW);
}
if (buttonState3 == LOW) {
digitalWrite(LED3, HIGH);
tone(BUZZER_PIN, NOTE_E4, 100);
} else {
digitalWrite(LED3, LOW);
}
if (buttonState4 == LOW) {
digitalWrite(LED4, HIGH);
tone(BUZZER_PIN, NOTE_F4, 100);
} else {
digitalWrite(LED4, LOW);
}
//MQTT
if (!MQTT.connected()) {
conectarMQTT();
}
MQTT.loop();
// Enviar dados a cada 5 segundos
if (millis() - lastSendTime >= sendInterval) {
lastSendTime = millis(); // Atualiza o tempo de envio
bpm = lerBPM();
spo2 = lerSpO2();
String payload = "b|" + String(bpm) + "|o|" + String(spo2);
MQTT.publish(TOPICO_PUBLISH, payload.c_str());
Serial.println("Dados enviados ao FIWARE:");
Serial.println(payload);
}
}