#include <PID_v1.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define CONFIG_MODE_INTERRUPT_PIN 2
#define SENSOR_PIN 12
#define KP_PIN 3
#define KI_PIN 4
#define KD_PIN 5
#define TARGET_PIN 6
#define MIN_DUTY_CYCLE_PIN 7
#define DUTY_CYCLE_OUTPUT_PIN 0
#define PWM_BYPASS_PIN 7
#define INTAKE_ENABLE_PIN 5
#define EXAUST_ENABLE_PIN 6
#define BOOT_LED_PIN 13
#define DUTY_CYCLE_REFERENCE_DEADZONE 5
#define MAX_DUTY_CYCLE_REFERENCE 170
#define SENSOR_MIN 0
#define SENSOR_MAX 100
#define SETPOINT_MIN 25
#define SETPOINT_MAX 40
#define BOOT_SECONDS 10
#define EXAUST_BOOT_DELAY 5
double setpoint, sensor_input, pid_output;
float kp = 0, ki = 0, kd = 0; //Inicializa-se o PID desativado
int duty_cycle_reference, max_duty_cycle_set;
volatile bool config_mode = false;
OneWire sensor_bus(SENSOR_PIN);
DallasTemperature Sensor(&sensor_bus);
PID pid_control(&sensor_input, &pid_output, &setpoint, kp, ki, kd, DIRECT);
void setup() {
Sensor.begin();
Sensor.setResolution(9);
pid_control.SetMode(AUTOMATIC);
kp = analogRead(KP_PIN) / 100.0;
ki = analogRead(KI_PIN) / 100.0;
kd = analogRead(KD_PIN) / 100.0;
pid_control.SetTunings(kp, ki, kd);
pinMode(BOOT_LED_PIN, OUTPUT);
pinMode(INTAKE_ENABLE_PIN, OUTPUT);
pinMode(EXAUST_ENABLE_PIN, OUTPUT);
pinMode(PWM_BYPASS_PIN, OUTPUT);
pinMode(CONFIG_MODE_INTERRUPT_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(CONFIG_MODE_INTERRUPT_PIN), change_config_status, CHANGE);
config_mode = digitalRead(CONFIG_MODE_INTERRUPT_PIN);
Serial.begin(9600);
// Startup do sistema de resfriamento (quebra de inercia)
digitalWrite(BOOT_LED_PIN, HIGH);
set_pwm_duty_cycle(0);
for (int boot_counter = 0; boot_counter < BOOT_SECONDS; boot_counter++) {
digitalWrite(INTAKE_ENABLE_PIN, HIGH);
if (boot_counter >= EXAUST_BOOT_DELAY) {
digitalWrite(EXAUST_ENABLE_PIN, HIGH);
if (config_mode) { Serial.print("* Boot Intake/Exaust !\n"); }
}
else {
digitalWrite(EXAUST_ENABLE_PIN, LOW);
if (config_mode) { Serial.print("* Boot Intake !\n"); }
}
delay(1000);
}
}
void loop() {
digitalWrite(BOOT_LED_PIN, LOW);
digitalWrite(INTAKE_ENABLE_PIN, HIGH);
digitalWrite(EXAUST_ENABLE_PIN, HIGH);
setpoint = map(analogRead(TARGET_PIN), 0, 1023, SETPOINT_MIN, SETPOINT_MAX);
max_duty_cycle_set = map(analogRead(MIN_DUTY_CYCLE_PIN), 0, 1023, 0, MAX_DUTY_CYCLE_REFERENCE);
if (config_mode) {
kp = analogRead(KP_PIN) / 100.0;
ki = analogRead(KI_PIN) / 100.0;
kd = analogRead(KD_PIN) / 100.0;
pid_control.SetTunings(kp, ki, kd);
}
Sensor.requestTemperatures();
sensor_input = constrain(Sensor.getTempCByIndex(0), SENSOR_MIN, SENSOR_MAX);
pid_control.Compute();
duty_cycle_reference = min(pid_output, max_duty_cycle_set);
set_pwm_duty_cycle(duty_cycle_reference);
if (config_mode) {
Serial.print("* Sensor:");
Serial.print(sensor_input);
Serial.print(" Setpoint:");
Serial.print(setpoint);
Serial.print(" Kp:");
Serial.print(kp);
Serial.print(" Ki:");
Serial.print(ki);
Serial.print(" Kd:");
Serial.print(kd);
Serial.print(" PID_out:");
Serial.print(pid_output);
Serial.print(" Max_out:");
Serial.print(max_duty_cycle_set);
Serial.print(" Output:");
Serial.print(duty_cycle_reference);
Serial.print(" !\n");
}
delay(500);
}
void change_config_status() {
config_mode = digitalRead(CONFIG_MODE_INTERRUPT_PIN);
}
void set_pwm_duty_cycle(int analog_value) {
if (analog_value <= DUTY_CYCLE_REFERENCE_DEADZONE) {
digitalWrite(PWM_BYPASS_PIN, LOW);
analogWrite(DUTY_CYCLE_OUTPUT_PIN, 0);
return;
}
digitalWrite(PWM_BYPASS_PIN, HIGH);
analogWrite(DUTY_CYCLE_OUTPUT_PIN, analog_value);
}