// #include <SPI.h>
#include <RotaryEncoder.h> // lib para o encoder.
#include <Wire.h> // permite a comunicação com o I2C.
#include <LiquidCrystal_I2C.h> // lib para o display.
#include <AccelStepper.h> // Permite controlar a variação do motor de passo.
int pwm = 5; // Pino 5 define entre 0 e 5v para controlar a entrada da base do S8050 ajustando a tensão de
int clk = 8; // Pulso de clock. Tem resistor com VCC.
int data = 9; // Pulso de direção. Tem resistor com VCC.
int botao_sw = 11; // Conecta pino ao GND quando o eixo é pressionado. Tem resistor pullup.
const int dir_pino = 12; // Pino de direção do motor.
const int reset_pino = 10;
const int step_pino = 13;
int velocidade_max = 1000; // valor maximo de velocidade do motor.
int velocidade_min = 0; // valor mínimo de velocidade do motor.
float temp_definida = 200; // temperatura de ajuste
float temperatura_lida = 0.0; //
float erro_PID = 0;
float erro_anterior = 0;
float tempo_decorrido, Tempo, tempo_anterior;
float valor_PID = 0;
int botao_apertado = 0;
int menu_ativado = 0;
float ultima_temp_definida = 0;
int disp = 1;
int estado_clk;
int ultimo_estado;
bool estado_dt;
int kp = 40;
int ki = 20;
int kd = 30;
int PID_p = 0;
int PID_i = 0; // valores de PID servem para ajustar o valor de PWM aplicado ao mosfet. Objetivo de manter um valor de temperatura estável.
int PID_d = 0;
float ultimo_kp = 0;
float ultimo_ki = 0; // valores definidos para constantes para ajustar valores de PID?
float ultimo_kd = 0;
int valor_PIDs_fixos = 0;
unsigned long delay_LCD_desejado = 1000;
unsigned long tempo_ant_menu = 0;
float vel_motor = 40;
int velocidade_rotacao = 0;
// Define a stepper and the pins it will use
AccelStepper stepper1(1, step_pino, dir_pino); // (Type of driver: with 2 pins, STEP, DIR)
LiquidCrystal_I2C lcd(0x27, 16, 2);
void setup()
{
stepper1.setMaxSpeed(velocidade_max);
TCCR2B = TCCR2B & B11111000 | 0x03; // pin 3 and 11 PWM frequency of 928.5 Hz
Tempo = millis();
ultimo_estado = (PINB & B00000001); // Detect first state of the encoder
PCICR |= (1 << PCIE0); // enable PCMSK0 scan
PCMSK0 |= (1 << PCINT0); // Set pin D8 trigger an interrupt on state change.
PCMSK0 |= (1 << PCINT1); // Set pin D9 trigger an interrupt on state change.
PCMSK0 |= (1 << PCINT3); // Set pin D11 trigger an interrupt on state change.
pinMode(botao_sw, INPUT_PULLUP);
pinMode(data, INPUT);
pinMode(clk, INPUT);
pinMode(pwm, OUTPUT);
digitalWrite(pwm, HIGH);
pinMode(dir_pino, OUTPUT);
pinMode(reset_pino, OUTPUT);
pinMode(step_pino, OUTPUT);
Serial.begin(9600);
lcd.init();
lcd.backlight();
}
void loop()
{
//digitalWrite(reset_pino, HIGH); // define o pino reset do motor como HIGH
temperatura_lida = medirTemperatura(analogRead(A0)); // le a termperatura baseado na leitura A0
erro_PID = temp_definida - temperatura_lida + 5; // calcula o erro de pid
PID_p = 0.01 * kp * erro_PID; // Calculo do PID (P)
PID_i = 0.01 * PID_i + (ki * erro_PID); // Calculo do PID (I)
// variaveis para calculo do millis
tempo_anterior = Tempo;
Tempo = millis();
tempo_decorrido = (Tempo - tempo_anterior) / 1000;
PID_d = 0.01 * kd * ((erro_PID - erro_anterior) / tempo_decorrido); // Calculo do PID (D)
valor_PID = PID_p + PID_i + PID_d; // Calculo do PID
// Manter valor de PID entre 0 e 255 para pwm
if (valor_PID < 0)
{
valor_PID = 0;
}
else
{
if (valor_PID > 255)
{
valor_PID = 255;
}
}
// definir valor pwm sendo 0 para esquentar e 255 para esfriar
analogWrite(pwm, 255 - valor_PID);
erro_anterior = erro_PID; // armazenar o erro de PID para calculos
// Controle do motor
if (vel_motor > 20 || vel_motor < -20)
{
if (vel_motor > 0)
{
// modifica a velocidade do motor de acordo com o valor no encoder.
digitalWrite(dir_pino, HIGH);
velocidade_rotacao = map(vel_motor, 0, 100, velocidade_min, velocidade_max);
stepper1.setSpeed(velocidade_rotacao);
stepper1.runSpeed();
}
else
{
digitalWrite(dir_pino, LOW);
velocidade_rotacao = map(vel_motor, 0, 100, velocidade_min, velocidade_max);
stepper1.setSpeed(velocidade_rotacao);
stepper1.runSpeed();
}
}
if (menu_ativado == 0)
{
stepper1.setSpeed(velocidade_rotacao);
stepper1.runSpeed();
unsigned long currentTime = millis();
if (currentTime - tempo_ant_menu >= delay_LCD_desejado)
{
lcd.clear();
lcd.setCursor(9, 0);
lcd.print("D:");
lcd.setCursor(11, 0);
lcd.print(temp_definida, 1);
lcd.setCursor(0, 0);
lcd.print("A:");
lcd.setCursor(2, 0);
lcd.print(temperatura_lida, 1);
lcd.setCursor(0, 1);
lcd.print("M:");
lcd.setCursor(2, 1);
lcd.print(vel_motor, 1);
lcd.setCursor(7, 1);
lcd.print("Z:");
lcd.setCursor(9, 1);
lcd.print(valor_PID, 1);
tempo_ant_menu = currentTime;
}
}
else
{
if (menu_ativado == 1)
{
if (temp_definida != ultima_temp_definida || disp)
{
disp = 0;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Set temperature");
lcd.setCursor(0, 1);
lcd.print(temp_definida);
}
ultima_temp_definida = temp_definida;
}
else
{
if (menu_ativado == 2)
{
if (kp != ultimo_kp || disp)
{
disp = 0;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Set P value ");
lcd.setCursor(0, 1);
lcd.print(kp);
}
ultimo_kp = kp;
}
else
{
if (menu_ativado == 3)
{
if (ki != ultimo_ki || disp)
{
disp = 0;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Set I value ");
lcd.setCursor(0, 1);
lcd.print(ki);
}
ultimo_ki = ki;
}
else
{
if (menu_ativado == 4)
{
if (kd != ultimo_kd || disp)
{
disp = 0;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Set D value ");
lcd.setCursor(0, 1);
lcd.print(kd);
}
ultimo_kd = kd;
}
else
{
if (menu_ativado == 5)
{
if (((temperatura_lida > temp_definida) && (temperatura_lida - temp_definida > 6)) || ((temperatura_lida < temp_definida) && (temperatura_lida - temp_definida < -6)))
{
menu_ativado = 0;
Serial.print(temperatura_lida);
Serial.print("\n");
}
}
else
{
if (disp)
{
disp = 0;
lcd.clear();
lcd.setCursor(3, 0);
lcd.print("Executando");
}
}
}
}
}
}
}
}
float medirTemperatura(float x)
{
float y = 0;
y = ((1.697 * pow(10, -9) * pow(x, 4)) - (2.764 * pow(10, -6) * pow(x, 3)) + (0.001467 * pow(x, 2)) - (0.1055 * x) + 29.68);
if (x > 926)
{
y = y + x * 0.01 - 30 / (x * 0.01);
}
else
{
if (x > 840)
{
y = y - x * 0.005;
}
}
return y;
}
// Aperta o botao do encoder. A função ISR começa, independente de onde esteja no código. Depois volta para onde tinha parado.
ISR(PCINT0_vect)
{
stepper1.runSpeed();
if (menu_ativado == 0)
{
estado_clk = (PINB & B00000001);
estado_dt = (PINB & B00000010);
if (estado_clk != ultimo_estado)
{
if (estado_dt != estado_clk)
{
if (vel_motor < 100)
{
vel_motor = vel_motor + 0.5;
}
}
else
{
if (vel_motor > -100)
{
vel_motor = vel_motor - 0.5;
}
}
}
ultimo_estado = estado_clk;
}
else
{
if (menu_ativado == 1)
{
estado_clk = (PINB & B00000001);
estado_dt = (PINB & B00000010);
if (estado_clk != ultimo_estado)
{
if (estado_dt != estado_clk)
{
temp_definida = temp_definida + 0.5;
}
else
{
temp_definida = temp_definida - 0.5;
}
}
ultimo_estado = estado_clk;
}
else
{
if (menu_ativado == 2)
{
estado_clk = (PINB & B00000001);
estado_dt = (PINB & B00000010);
if (estado_clk != ultimo_estado)
{
if (estado_dt != estado_clk)
{
kp = kp + 1;
}
else
{
kp = kp - 1;
}
}
ultimo_estado = estado_clk;
}
else
{
if (menu_ativado == 3)
{
estado_clk = (PINB & B00000001);
estado_dt = (PINB & B00000010);
if (estado_clk != ultimo_estado)
{
if (estado_dt != estado_clk)
{
ki = ki + 1;
}
else
{
ki = ki - 1;
}
}
ultimo_estado = estado_clk;
}
else
{
if (menu_ativado == 4)
{
estado_clk = (PINB & B00000001);
estado_dt = (PINB & B00000010);
if (estado_clk != ultimo_estado)
{
if (estado_dt != estado_clk)
{
kd = kd + 1;
}
else
{
kd = kd - 1;
}
}
ultimo_estado = estado_clk;
}
}
}
}
}
if (PINB & B00001000)
{
botao_apertado = 1;
}
else if (botao_apertado == 1)
{
if (menu_ativado == 4)
{
disp = 1;
menu_ativado = 0;
valor_PIDs_fixos = 1;
botao_apertado = 0;
delay(500);
}
else
{
if (menu_ativado == 3)
{
disp = 1;
menu_ativado = menu_ativado + 1;
botao_apertado = 0;
delay(500);
}
else
{
if (menu_ativado == 2)
{
disp = 1;
menu_ativado = menu_ativado + 1;
botao_apertado = 0;
delay(500);
}
else
{
if (menu_ativado == 1 && valor_PIDs_fixos != 1)
{
disp = 1;
menu_ativado = menu_ativado + 1;
botao_apertado = 0;
delay(500);
}
else
{
if (menu_ativado == 1 && valor_PIDs_fixos == 1)
{
disp = 1;
menu_ativado = 5;
botao_apertado = 0;
delay(500);
}
else
{
if (menu_ativado == 0 && valor_PIDs_fixos != 1)
{
disp = 1;
menu_ativado = menu_ativado + 1;
botao_apertado = 0;
delay(500);
}
else
{
if (menu_ativado == 0 && valor_PIDs_fixos == 1)
{
disp = 1;
menu_ativado = menu_ativado + 1;
botao_apertado = 0;
delay(500);
}
else
{
if (menu_ativado == 5)
{
disp = 1;
menu_ativado = 0;
botao_apertado = 0;
delay(500);
}
}
}
}
}
}
}
}
}
}
ERC Warnings
S8050:OUT: Multi-driven net on pin