antiworldx
Excluido
Busca informacion sobre la ecuacion de diferencias de la funcion pid (proporcional integrativo derivativo)
Follow along with the video below to see how to install our site as a web app on your home screen.
Nota: This feature currently requires accessing the site using the built-in Safari browser.
// Programa: Controlador Fuzzy PI LM35
#include <16F877.H>
#device adc = 10 // Utilizar A/D de 10 bits
#fuses NOWDT, XT, NOPUT, NOPROTECT, NODEBUG, NOBROWNOUT, NOLVP, NOCPD, NOWRT
#use delay(clock = 4000000) // Define clock de 4MHz
#priority timer0, ext // Define enterrupcion como priodidad
#include <LCD.C>
#use fast_io(a)
#use fast_io(b)
#use fast_io(c)
#use fast_io(d)
#use fast_io(e)
int temp_ref = 26; // Temperatura de referencia
// *** Interrupção que garante um tempo de amostragem de 1 segundo ***
#int_timer0
void trata_tmr0()
{
static int cont_timer0; // Variável de contagem para o timer 0
set_timer0(131); // Inicializa o timer no valor 131
cont_timer0++; // Incrementa a variável de contagem em uma unidade
if (cont_timer0 == 125) // Ocorreram 125 interrupções (1s)?
{
float temp; // Temperatura
float erro; // Erro da temperatura
static float erro_anterior; // Erro anterior da temperatura
static float out_fuzzy_anterior; // Saída anterior do controlador Fuzzy PI
boolean control_on = 1; // Variável que diz o estado do sistema de controle
cont_timer0 = 0; // Zera a variável de contagem
set_ADC_channel(0); // Seleciona o canal AN0 para conversão
delay_us(20); // Espera 20 microsegundos
temp = read_adc(); // Lê o valor no conversor A/D
temp = temp * 5000 / 1023 / 110 - 1; // Temperatura do sensor
printf(lcd_putc, "\fTemp. = %2.1f ", temp); // Mostra a temperatura no LCD
lcd_send_byte(1, 0b11011111); // Coloca o símbolo de "grau" no LCD
printf(lcd_putc, "C\n"); // Mostra o C no LCD
erro = temp_ref - temp; // Calcula o erro
if (erro >= 0.5)
{
control_on = 0; // Desliga o sistema de controle
set_pwm1_duty(0); // Desliga o cooler
}
if (control_on)
{
const int Ki = 1; // Ganhos do controlador Fuzzy PI
const int K = 10;
const int Ku = 40; // Ganho de controle incremental
float out_fuzzy; // Saída do controlador Fuzzy PI
signed int16 ciclo; // Ciclo de trabalho do PWM1
float taxa; // Taxa em que o erro varia
float abs_taxa; // Módulo da taxa
float abs_erro_ant; // Módulo do erro anterior
float out_inc_fuzzy; // Incremento na saída do controlador Fuzzy PI
taxa = erro - erro_anterior; // Calcula a derivada do erro
erro_anterior = erro;
abs_erro_ant = abs(erro_anterior); // Calcula o módulo do erro
abs_taxa = abs(taxa); // Calcula o módulo da derivada do erro
// *** Calcula a saída da base de regras do controlador nebuloso ***
// *** Regiões IC1, IC2, IC5 e IC6 ***
if ((K * abs_taxa <= Ki * abs_erro_ant) && (Ki * abs_erro_ant <= 1))
out_inc_fuzzy = (Ki * erro + K * taxa) / (2 * (2 - Ki * abs_erro_ant));
// *** Regiões IC3, IC4, IC7 e IC8 ***
else if ((Ki * abs_erro_ant <= K * abs_taxa) && (K * abs_taxa <= 1))
out_inc_fuzzy = (Ki * erro + K * taxa) / (2 * (2 - K * abs_taxa));
// *** Regiões IC9 e IC10 ***
else if ((Ki * erro > 1) && (K * abs_taxa < 1))
out_inc_fuzzy = 0.5 * (K * taxa + 1);
// *** Regiões IC11 e IC12 ***
else if ((K * taxa > 1) && (Ki * abs_erro_ant < 1))
out_inc_fuzzy = 0.5 * (Ki * erro + 1);
// *** Regiões IC13 e IC14 ***
else if ((Ki * erro < -1) && (K * abs_taxa < 1))
out_inc_fuzzy = 0.5 * (K * taxa - 1);
// *** Regiões IC15 e IC16 ***
else if ((K * taxa < -1) && (Ki * abs_erro_ant < 1))
out_inc_fuzzy = 0.5 * (Ki * erro - 1);
// *** Região IC17 ***
else if ((Ki * erro > 1) && (K * taxa > 1))
out_inc_fuzzy = 1;
// *** Regiões IC19 ***
else if ((Ki * erro < -1) && (K * taxa < -1))
out_inc_fuzzy = -1;
// *** Regiões IC18 e IC20 ***
else out_inc_fuzzy = 0;
// *** Calcula a saída do controlador fuzzy PI ***
out_fuzzy = out_fuzzy_anterior + Ku * out_inc_fuzzy;
ciclo = out_fuzzy; // Seta o ciclo de trabalho do cooler
ciclo = abs(ciclo); // Calcula o módulo do ciclo de trabalho
if (ciclo > 1020) ciclo = 1020; // Saturação no máximo
if (ciclo < 255) ciclo = 255; // Saturação no mínimo
out_fuzzy = ciclo;
set_pwm1_duty(ciclo); // Seta o ciclo de trabalho para o PWM1
out_fuzzy_anterior = -out_fuzzy;
// *** Calcula a porcentagem do ciclo de trabalho ***
out_fuzzy = out_fuzzy / 1020 * 100;
out_fuzzy = abs(out_fuzzy);
// *** Mostra o ciclo de trabalho do PWM1 ***
printf(lcd_putc, "Ciclo = %3.1f ", out_fuzzy);
lcd_send_byte(1, 0b00100101); // Envia o símbolo de porcentagem ao LCD
}
}
}
#int_ext // Interrupção para o funcionamento do botâo que altera o setpoint
void trata_rb()
{
temp_ref++; // Incrementa o setpoint em uma unidade
if (temp_ref == 31) temp_ref = 26; // Volta a 30º o setpoint
printf(lcd_putc, "\fSetpoint = %u ", temp_ref); // Mostra o setpoint no LCD
lcd_send_byte(1, 0b11011111); // Coloca o símbolo de "grau" no LCD
printf(lcd_putc, "C\n"); // Coloca a letra C no LCD
delay_ms(250); // Delay para exibição da mensagem
}
void main() // Método principal do programa
{
set_tris_a(0b11111111); // Define as direção das portas
set_tris_b(0b11111111);
set_tris_c(0b11111011);
set_tris_d(0b00001000);
set_tris_e(0b00000111);
lcd_init(); // Inicializa o display
setup_ADC_ports(AN0); // Configura o conversor A/D, AN0, VRef+ = VDD, VRef- = VSS
setup_ADC(ADC_CLOCK_DIV_32); // Divide o clock interno por 64
setup_timer_2(T2_DIV_BY_16, 254, 1); // Configura as saídas PWM,Frequência de 245Hz
set_pwm1_duty(0); // Seta ciclo de trabalho em 0 para o PWM1
setup_ccp1(CCP_PWM); // Configura o CCP1 para modo PWM
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_64); // Configura o timer0, Clock interno e prescaler de 64
set_timer0(131); // Inicia o timer 0 em 131
ext_int_edge(H_TO_L); // Configuração da interrupção no pino Rb.0, do nível alto para o baixo
clear_interrupt(INT_EXT); // Limpa a interrupção externa
enable_interrupts(INT_TIMER0); // Interrupção do timer 0
enable_interrupts(INT_EXT); // Interrupção externa
enable_interrupts(GLOBAL); // Interrupção global
while (true) // Loop infinito
{
}
}