#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <math.h>
#define PPG_PIN 34 // Pino do sensor PPG
#define GSR_PIN 35 // Pino do sensor GSR
#define SCL_PIN 26 // Pino SCL para display OLED
#define SDA_PIN 25 // Pino SDA para display OLED
#define BUZZER_PIN 4 // Pino para o buzzer
#define WINDOW_SIZE 5 // Tamanho da janela para o filtro de mediana
#define OLED_RESET -1
Adafruit_SSD1306 display(OLED_RESET);
unsigned long previousMillis = 0;
const long interval = 1000; // Intervalo de aquisição de dados (em milissegundos)
void setup() {
Serial.begin(9600);
pinMode(PPG_PIN, INPUT);
pinMode(GSR_PIN, INPUT);
pinMode(BUZZER_PIN, OUTPUT);
Wire.begin(SDA_PIN, SCL_PIN);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
display.display();
delay(2000);
display.clearDisplay();
}
void loop() {
unsigned long currentMillis = millis();
if(currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
// Aquisição dos dados dos sensores PPG e GSR
int ppgData = analogRead(PPG_PIN);
int gsrData = analogRead(GSR_PIN);
// Imprime os valores lidos dos sensores PPG e GSR
Serial.print("PPG Data: ");
Serial.println(ppgData);
Serial.print("GSR Data: ");
Serial.println(gsrData);
// Processamento dos sinais (filtro de mediana)
int ppgFiltered = medianFilter(ppgData);
int gsrFiltered = medianFilter(gsrData);
// Imprime os valores lidos do medianFilter ppgFiltered e gsrFiltered
Serial.print("PPG Filtered: ");
Serial.println(ppgFiltered);
Serial.print("GSR Filtered: ");
Serial.println(gsrFiltered);
// Extração de características dos sinais
int HR = calculateHeartRate(ppgFiltered);
// Imprime os valores lidos do HR
Serial.print("HR valor: ");
Serial.println(HR);
int stressLevel = calculateStressLevel(gsrFiltered);
// Imprime os valores lidos do stressLevel que é a condutancia
Serial.print("stressLevel valor: ");
Serial.println(stressLevel);
int PRV = calculatePRV(ppgFiltered);
// Imprime os valores lidos do PRV
Serial.print("PRV valor: ");
Serial.println(PRV);
int RR = calculateRR(ppgFiltered);
/*
int bpm = calculateBPM(ppgFiltered);
// Análise e detecção de sonolência
if(isDrowsy(HR, PRV, RR, stressLevel, bpm)) {
// Ativar o buzzer e exibir alerta no display
digitalWrite(BUZZER_PIN, HIGH);
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0,0);
display.println("SONOLENCIA DETECTADA!");
display.display();
delay(10000); // Tempo para o alerta ser exibido
digitalWrite(BUZZER_PIN, LOW);
}
*/
}
}
// Implementação do filtro de mediana
int medianFilter(int data) {
static int window[WINDOW_SIZE]; // Array para armazenar os últimos valores
static int currentIndex = 0; // Índice atual da janela
window[currentIndex] = data; // Adiciona o novo dado à janela
// Incrementa o índice e verifica se ele excedeu o tamanho da janela
currentIndex++;
if (currentIndex >= WINDOW_SIZE) {
currentIndex = 0;
}
// Ordena os valores na janela (usando Bubble Sort para simplificar)
for (int i = 0; i < WINDOW_SIZE - 1; i++) {
for (int j = 0; j < WINDOW_SIZE - i - 1; j++) {
if (window[j] > window[j + 1]) {
// Troca os valores
int temp = window[j];
window[j] = window[j + 1];
window[j + 1] = temp;
}
}
}
// Retorna o valor mediano da janela
return window[WINDOW_SIZE / 2];
}
// Funções para extração de características dos sinais
// Função para calcular a frequência cardíaca (Heart Rate - HR)
int calculateHeartRate(int ppgFiltered) {
// Definir um limiar para detecção de picos
int threshold = 500; // Ajuste conforme necessário
// Inicializar variáveis
int peakCount = 0;
bool aboveThreshold = false;
// Iterar sobre os dados filtrados do sensor PPG
for (int i = 1; i < WINDOW_SIZE; i++) {
// Verificar se o valor atual está acima do limiar
if (ppgFiltered > threshold) {
// Se o valor anterior estiver abaixo do limiar, incrementar contagem de picos
if (!aboveThreshold) {
peakCount++;
aboveThreshold = true;
}
} else {
aboveThreshold = false;
}
}
// Calcular a frequência cardíaca (número de picos por minuto)
int heartRate = (peakCount * 60) / (interval / 1000);
// Retornar a frequência cardíaca calculada
return heartRate;
}
int calculatePRV(int ppgFiltered) {
// Implemente seu código aqui
}
int calculateRR(int ppgData) {
// Implemente seu código aqui
}
/*
int calculateStressLevel(int gsrData) {
// Implemente seu código aqui
}
*/
// Implemente seu código aqui
int calculateStressLevel(int gsrFiltered) {
// Defina os valores mínimo e máximo esperados para a leitura do sensor GSR
const int GSR_MIN = 0;
const int GSR_MAX = 1023; // Valor máximo de leitura do ADC (10 bits)
// Defina os valores mínimo e máximo correspondentes à condutância da pele
const int CONDUCTANCE_MIN = 0; // Ajuste conforme necessário
const int CONDUCTANCE_MAX = 1000; // Ajuste conforme necessário
// Mapeie o valor da leitura do sensor GSR para o intervalo da condutância da pele
int conductance = map(gsrFiltered, GSR_MIN, GSR_MAX, CONDUCTANCE_MIN, CONDUCTANCE_MAX);
// Como uma medida simplificada, o nível de estresse pode ser calculado diretamente
// a partir da condutância da pele
int stressLevel = constrain(conductance, 0, 100); // Ajuste conforme necessário
return stressLevel;
}
int calculateBPM(int ppgData) {
// Implemente seu código aqui
}
// Função para detecção de sonolência
bool isDrowsy(int HR, int PRV, int RR, int stressLevel, int bpm) {
// Implemente seu código aqui
}