/* Devido a problemas com o sensor DS18B20 (O qual está em Beta atualmente(11/02/2024)) presente no Wokwi substitui pelo NTC.
Isso causou com que uma parte da programação tratasse apenas do tratamento de dados do NTC
O sistema possui um sistema de transferência de dados para o Thingspeak em Https,
O micro SD foi adaptado para armazenar a média dos ultimos dados registrados,
assim mesmo que não seja transmitido ele será guardado para possíveis emergências.
*/
// Incluir bibliotecas
#include <WiFi.h>
#include <DHT.h>
#include <ThingSpeak.h>
#include <MPU6050_tockn.h>
//#include <SD.h>
//----------------------------------------------------------------------------------------
// Definicoes e constantes
unsigned long tempo;
int unstable = 1; // usei o tipo inteiro para que o ThingSpeaky interpretasse sem erros
const char* SSIDName = "Wokwi-GUEST"; // nome da rede WiFi
const char* SSIDPass = ""; // senha da rede WiFI
const int BPM_PIN = 25;
const int numLeiturasBPM_Oximetro = 10;
int leiturasBPM[numLeiturasBPM_Oximetro];
int indiceAtualBPM = 0;
long sumBPM = 0;
long sumOxi = 0;
const int DHT_PIN = 15; // terminal do sensor de temperatura e umidade
const int NTC_PIN = 34; // terminal do sensor NTC
//INPORTANTE Tentamos implementar um salvamento de dados para o Micro SD
//Porém, o código se tornou instável. No dia 12/06 o código funcionava entretanto no dia 13/06
// já apresentava erros de referência a biblioteca SD.h então optamos por deixar ideia no código
// e trabalhar nela posteriormente.
//const int SD_CS_PIN = 5; // terminal CS do Micro SD
//String dados = " ";
unsigned long myChannelNumber = 2561174; // numero do canal no ThingSpeak
const char* myWriteAPIKey = "EPWPBHR0IMT5BJSZ"; // APIKey do ThingSpeak
// Constantes para cálculo do NTC
const float R0 = 10000; // Resistor de 10kΩ
const float T0_NTC = 298.15; // Temperatura de referência (25ºC em Kelvin)
const float BETA = 3950; // Constante beta do termistor NTC
const float R_REF = 10000; // Resistor de 10kΩ em série com o NTC
// Variaveis globais e objetos
DHT dhtSensor(DHT_PIN, DHT22); // instancia o objeto dhtSensor a partir da classe DHT
float temperaturaExterna; // variavel para guardar o valor da temperatura em Celsius
float temperaturaInterna; // variavel para guardar o valor da temperatura do NTC
WiFiClient client; // instancia o objeto client a partir da classe WiFiClient
int httpCode; // variavel para guardar o codigo de retorno HTTP do ThingSpeak
// Definição de pino de leitura do MPU6050
MPU6050 mpu6050(Wire);
// Setup
void setup() {
Serial.begin(115200);
// Inicializa comunicação com MPU6050
Wire.begin();
mpu6050.begin();
mpu6050.calcGyroOffsets(true);
//Define pino de BPM
randomSeed(analogRead(BPM_PIN)); // Inicializa o gerador de números aleatórios
// Inicializa o cliente ThingSpeak
ThingSpeak.begin(client);
Serial.print("Conectando-se ao Wi-Fi");
WiFi.begin(SSIDName, SSIDPass); // inicializa WiFi
while (WiFi.status() != WL_CONNECTED) { // repete enquanto nao estabelece conexao
delay(100);
Serial.print(".");
}
Serial.println();
Serial.println("Conectado!");
Serial.print("IP: ");
Serial.println(WiFi.localIP()); // imprime o endereco IP
}
// Inicializa o SD card
// if (!SD.begin(SD_CS_PIN)) {
// Serial.println("Erro ao inicializar o cartão SD!");
// return;
// }
// Serial.println("Cartão SD inicializado com sucesso.");
//}
// Função para calcular a temperatura do NTC
float calcularTemperaturaNTC(int adcValue) {
float Vout = adcValue * (3.3 / 4095.0);
float R_ntc = R_REF / ((3.3 / Vout) - 1.0);
float temperatura = (1.0 / ((log(R_ntc / R0) / BETA) + (1.0 / T0_NTC))) - 273.15; // Convertendo Kelvin para Celsius
return temperatura;
}
// Função para salvar dados no Micro SD
//void salvarNoSD(String dados) {
// File file = SD.open("/dados.txt", FILE_APPEND);
// if (file) {
// file.println(dados);
// file.close();
// Serial.println("Dados salvos no SD.");
// } else {
// Serial.println("Erro ao abrir o arquivo no SD.");
//}
//}
// Loop
void loop() {
//Coleta dados do sensor de BPM
//IMPORTANTE
//Criei essa adaptação técnica (gambiarra) para conseguir lidar com a falta do sensor de
//batimentos cardíacos no Wokwi. No código contendo um sensor real, será necessário utilizar um algoritmo FIFO
//apenas para fins de estudo adotei essa medida, os outros sensores estão funcionando sem essa adaptação
// Gera 10 valores aleatórios e soma-os
for (int i = 0; i < numLeiturasBPM_Oximetro; i++) {
int BPMrandomValue = random(60, 150); // Gera um valor aleatório entre 60 e 180
sumBPM += BPMrandomValue; // Adiciona o valor à soma
int OxiRandomValue = random(90, 100);
sumOxi += OxiRandomValue;
delay(500); // Atraso para simular a leitura de dados
}
// Calcula a média
float averageBPMRead = sumBPM / float(numLeiturasBPM_Oximetro);
float averageOxiRead = sumOxi / float(numLeiturasBPM_Oximetro);
// Exibe a média na porta serial
Serial.print("Média dos Batimentos: ");
Serial.println(averageBPMRead);
Serial.print("Média do percentual de oxigenação do sangue: ");
Serial.println(averageOxiRead);
if(averageOxiRead < 95){
Serial.print("A oxigenação está muito baixa, procure Ajuda! ");
}else{
Serial.print("A oxigenação está adequada. ");
}
//Transmissão para dashboard
httpCode = ThingSpeak.writeField(myChannelNumber, 5, averageOxiRead, myWriteAPIKey);
averageOxiRead = 0;
sumOxi = 0;
httpCode = ThingSpeak.writeField(myChannelNumber, 3, averageBPMRead, myWriteAPIKey);
averageBPMRead = 0;
sumBPM = 0;
// Coleta de dados do MPU6050
mpu6050.update();
float workAngleX = mpu6050.getAngleX();
float workAngleY = mpu6050.getAngleY();
Serial.print("Graus X: ");
Serial.println(workAngleX);
Serial.print("Graus Y: ");
Serial.println(workAngleY);
// Coleta dados da temperatura externa
float temperaturaExterna = dhtSensor.readTemperature();
// Verifica se a leitura do sensor DHT22 foi bem-sucedida
if (isnan(temperaturaExterna)) {
Serial.println("Erro ao ler o sensor DHT22!");
} else {
Serial.print("Temperatura Externa: ");
Serial.println(temperaturaExterna);
}
// Coleta dados da temperatura interna do NTC
int adcValue = analogRead(NTC_PIN);
float temperaturaInterna = calcularTemperaturaNTC(adcValue);
// Verifica se a leitura do sensor NTC foi bem-sucedida
if (temperaturaInterna < -40 || temperaturaInterna > 150) { // Faixa de temperatura geralmente válida para um NTC
Serial.println("Erro ao ler o sensor NTC!");
} else {
Serial.print("Temperatura do NTC: ");
Serial.println(temperaturaInterna);
}
// Determina se o sistema está instável com base nos ângulos
if ((workAngleX >= 90 || workAngleX <= -90) || (workAngleY >= 90 || workAngleY <= -90)) {
unstable = 1;
Serial.print("O operador está em uma inclinação preoucupante ");
} else {
unstable = 0;
Serial.print("O operador está equilibrado ");
}
// Enviar instabilidade ao ThingSpeak
httpCode = ThingSpeak.writeField(myChannelNumber, 4, unstable, myWriteAPIKey);
if (httpCode == 200) {
Serial.println("Instabilidade enviada com sucesso.");
} else {
Serial.println("Erro ao enviar instabilidade. Código HTTP: " + String(httpCode));
}
// Enviar dados ao ThingSpeak somente se ambos os sensores fornecerem leituras válidas
if (!isnan(temperaturaExterna) && (temperaturaInterna >= -40 && temperaturaInterna <= 150)) {
// Write value to Field 1 of a ThingSpeak Channel
int httpCode = ThingSpeak.writeField(myChannelNumber, 1, temperaturaExterna, myWriteAPIKey);
// Write value to Field 2 of a ThingSpeak Channel
httpCode = ThingSpeak.writeField(myChannelNumber, 2, temperaturaInterna, myWriteAPIKey);
if (httpCode == 200) {
Serial.println("Channel write successful.");
} else {
Serial.println("Problem writing to channel. HTTP error code " + String(httpCode));
}
} else {
Serial.println("Dados não enviados ao ThingSpeak devido a leituras inválidas.");
}
// Cria string de dados para salvar no SD
// dados = "Temp Externa: " + String(temperaturaExterna) + ", Temp NTC: " + String(temperaturaInterna) + ", Graus X: " + String(workAngleX) + ", Graus Y: " + String(workAngleY) + ", Instabilidade: " + String(unstable) + ", BPM: " String(BPMRead);
//salvarNoSD(dados);
// O ThingSpeak trabalha com uma média de atualização de 15 segundos
delay(1000);
}