/*
Autores: Alba Sánchez Ibáñez, Lucas Colbert Eastgate
Refatorado e corrigido por Gemini
Este código foi refeito para usar a biblioteca PID_v1.h do Arduino.
A lógica de controle agora é delegada para a biblioteca, tornando o
código mais robusto e fácil de entender.
*/
#include <math.h>
#include <PID_v1.h>
// PINOS
const byte LEDROJO = 3;
const byte LEDVERDE = 5;
const byte THERMISTOR_PIN = A0;
const byte TRANSISTOR_PIN = 6; // PWM Pin para controle de potência
// PERIODOS em milissegundos
const unsigned long PERIODO_TMP_MS = 1000;
const unsigned long PERIODO_MONITOR_MS = 1000;
// VALORES DO TERMISTOR (NTC 10kOhm)
const float THERMISTOR_T0 = 25.0; // Temperatura de referência
const float THERMISTOR_R0 = 10000.0; // Resistência na temperatura de referência
const float THERMISTOR_B = 3950.0; // Constante Beta
const int RESISTOR_DIVISOR = 10000; // Resistor em série com o termistor
//const8ES DE TEMPERATURA
double TMP_REF = 38.0; // Setpoint para a incubadora
const double TMP_MIN = 37.0;
const double TMP_MAX = 39.0;
// VALORES DO CONTROLADOR PID
const float KP = 0.4044;
const float KI = 0.0100;
const float KD = 3.3718;
// VARIÁVEIS DE CONTROLE DO PID
double pid_input;
double pid_output;
// Cria a instância do objeto PID
PID myPID(&pid_input, &pid_output, &TMP_REF, KP, KI, KD, DIRECT);
// CALCULO DE TEMPERATURA (Função Steinhart-Hart)
float val2tmp(int analog_value) {
float resistance = RESISTOR_DIVISOR / ((1023.0 / analog_value) - 1.0);
float celsius = 1.0 / (log(resistance / THERMISTOR_R0) / THERMISTOR_B + 1.0 / (THERMISTOR_T0 + 273.15)) - 273.15;
return celsius;
}
// ESTRUTURAS DE ESTADO
struct Tmp {
unsigned long last_ms;
float val;
};
struct Monitor {
unsigned long last_ms;
};
// --- SETUP DAS TAREFAS ---
void setup_tmp(unsigned long curr_ms, struct Tmp& tmp) {
pinMode(LEDVERDE, OUTPUT);
tmp.last_ms = curr_ms - PERIODO_TMP_MS;
tmp.val = 0;
}
void setup_monitor(unsigned long curr_ms, struct Monitor& mtr) {
Serial.begin(9600);
while (!Serial); // Aguarda a conexão serial
Serial.println(" # > Arduino Control de Temperatura PID 0.4044 0.0100 3.3718");
Serial.println(" # $ - y20 :45 - w4 - l37.0 - l38.0 - l39.0 - tTemperatura - tCalefactor ");
mtr.last_ms = curr_ms - PERIODO_MONITOR_MS;
}
void setup_pid() {
myPID.SetMode(AUTOMATIC);
myPID.SetOutputLimits(0, 255); // Saída PID irá de 0 a 255 (PWM)
}
// --- TAREFAS DE LOOP ---
void tarea_tmp(unsigned long curr_ms, struct Tmp& tmp) {
if (curr_ms - tmp.last_ms >= PERIODO_TMP_MS) {
tmp.last_ms += PERIODO_TMP_MS;
int val = analogRead(THERMISTOR_PIN);
tmp.val = val2tmp(val);
byte est_tmp = (TMP_MIN <= tmp.val && tmp.val <= TMP_MAX) ? HIGH : LOW;
digitalWrite(LEDVERDE, est_tmp);
}
}
void tarea_monitor(unsigned long curr_ms, struct Monitor& mtr, const struct Tmp& tmp, const double& rele_estado) {
if (curr_ms - mtr.last_ms >= PERIODO_MONITOR_MS) {
mtr.last_ms += PERIODO_MONITOR_MS;
if (Serial) {
Serial.print(tmp.val);
Serial.print(" ");
Serial.println(rele_estado);
}
}
}
// --- MAIN ---
Tmp tmp;
Monitor mtr;
void setup() {
unsigned long curr_ms = millis();
pinMode(TRANSISTOR_PIN, OUTPUT);
pinMode(LEDROJO, OUTPUT);
setup_tmp(curr_ms, tmp);
setup_monitor(curr_ms, mtr);
setup_pid();
}
void loop() {
unsigned long curr_ms = millis();
// Tarefa de leitura de temperatura
tarea_tmp(curr_ms, tmp);
// Atualiza a entrada do PID e computa o novo valor de saída
pid_input = tmp.val;
myPID.Compute();
// Aplica a saída do PID para o aquecedor e o LED vermelho (PWM)
analogWrite(TRANSISTOR_PIN, pid_output);
analogWrite(LEDROJO, pid_output);
// Tarefa de monitoramento serial
tarea_monitor(curr_ms, mtr, tmp, pid_output);
}