Convertendo: Programa deixa o config.h como comentário por que o mesmo causava erro __Delay_ms(); --> delay_ms(); TRISA(); --> set_tris_a(); #define en1 PORTAbits.RA2 --> en1 PIN_A2 ADC_read(); --> read_adc(); /* Titulo: PID digital * Versão: 1.0 * Autor: * Data: 02/06/2018 * Compilador: XC8 --> CCS * IDE: MplabX 4.10 * Dispositivo: PIC18f4550 * ======================================= Descrição ========================================== * * Este codigo realiza o controle PID de maneira discreta. Através dos dados de entrada * * referência e feedback, ambos medidos pelo conversor A/D em AN0 e AN1, encontra-se o erro, * * que então e usado como parametro para calcular um valor de pwm necessário para corrigi-lo * * isso através da função: PID_set_PF(). O sentido de giro do motor e controlado através das * * saidas digitais RA2, RA3. * * ============================================================================================ * */ // PIC18F4550 Configuration Bit Settings #include // compilador #include <18f4550.h> // dispositivo #include // para utilizar a funcao sprintf #include // para utilizar a funcao sprintf //#include "config.h" // configuracoes do pic //================== defines e mapeamento de hardware =============// #use delay(clock = 48000000) // constante usada pelo delay, clock #define SHIFT 256 // usado para calculos com ponto fixo <<8 #define en1 PIN_A2 // en1 da ponte H, pino 4 do pic #define en2 PIN_A3 // en2 da ponte H, pino 5 do pic #define RS PIN_D1 #define EN PIN_D0 #define D4 PIN_D4 #define D5 PIN_D5 #define D6 PIN_D6 #define D7 PIN_D7 //==================== variaveis globais =========================// long int ref = 0; // guarda o valor do potenciomentro de referencia long int fb = 0; // guarda o valor do potenciomentro de feedback long int pwm = 0; // guarda valor de dutycicle do pwm float kp; // coeficiente da acao proporcional float ki; // coeficiente da acao integral float kd; // coeficiente da acao derivativa float T = 0.005; // periodo de amostragem long int k1; // coeficiente auxiliar, para uso de ponto fixo long int k2; // coeficiente auxiliar, para uso de ponto fixo long int k3; // coeficiente auxiliar, para uso de ponto fixo long int erro0 = 0; // erro da amostra atual e(n) long int erro1 = 0; // erro da amostra anterior e(n-1) long int out0 = 0; // saida da funcao do PID long int integral = 0; // parcela integral long int derivativo = 0; // derivativo //========================= funcoes =============================// void ADC_init() { ADCON1 = 0b00001101; //Somente AN0 e AN1 como entrada analogica, referencia e realimentacao ADCON2 = 0b10001110; //justificado a direita, 64 fosc , 2 Tda }// fim ADC_init unsigned ADC_read(unsigned char canal) { ADCON0 = canal; delay_us(10); // tempo para carregar capacitor interno ADCON0bits.GODONE = 1; // inicia a conversao while (ADCON0bits.GODONE); // espera o fim da conversao AD { } return ((ADRESH << 8) + ADRESL); // retorna um valor convertido de 0 - 1023 }// fim ADC_read unsigned long int PID_set_PF() { erro0 = ref - fb; erro1 = erro0; // atualiza valores // calculo do PID integral = integral + (erro0 * T); derivativo = ((erro0-erro1)/T); out0 = ((k1 * erro0)+ (k2 * integral) + (k3 * derivativo)); out0 = out0 >> 8; // deslocamento devido ao uso de ponto fixo if (out0 < -1) { // caso negativo out0 = out0*(-1); // multiplica por -1 } if(out0>1023) // caso estoure { out0 = 1023; // saturar saida } return out0; }// fim PID_set_PF #ORG 0x1000, 0x3000 void interrupt high_priority interrupcoes(void) { if (INTCONbits.TMR0IF == 1) { INTCONbits.TMR0IF = 0; PORTBbits.RB7 = !PORTBbits.RB7; ref = read_adc(0b00000001); // ler valor potenciomentro de referencia AN0 pino 2 delay_us(10); // tempo para descarregar capacitor interno fb = read_adc(0b00000101); // ler valor potenciomentro de realimentacao AN1 pino 3 pwm = PID_set_PF(); // calcula valor do PID TMR0L = 22 + TMR0L; // interrupcao a cada 0.005 segundos } } void setup() { CMCON = 0x07; // desabilita os comparadores internos // configura saidas e entradas set_tris_a = 0b00000011; // somente RA0,RA1 como entrada analogica, demais pinos saida set_tris_b = 0x00; // todo o PORTB como saida set_tris_c = 0x00; // todo o PORTC como saida, onde pino 17 RC2/CCP1 sera a saida PWM set_tris_d = 0x00; // todo o PORTD como saida, onde se encotra conectado o LCD set_tris_e = 0x00; // todo o PORTE como saida PORTB = 0xFF; // inicia o PORTB todo em alto ADC_init(); // inicia configuracoes do ADC ADCON0bits.ADON = 1; // liga o modulo adc PORTDbits.RD2 = 0; // pino onde se encontra o RW do LCD, para escrita deve estar em nivel logico baixo // configuracao PWM T2CON = 0x07; // Liga timer2 e ativa prescaler 16 PR2 = 0x7F; // Carrega PR2 CCP1CON = 0x3C; CCPR1L = 0x00; CCP1CONbits.DC1B0 = 0; CCP1CONbits.DC1B1 = 0; }// fim setup //====================== funcao principal =======================// void main() { // inicio main setup(); // faz set up das configuracoes PORTDbits.RD2 = 0; // pino onde se encontra o RW do LCD, para escrita deve estar em nivel logico baixo en1 = 0; // saida digital RA2 para ponte H en2 = 0; // saida digital RA3 para ponte H // calculo de coeficientes do PID kp = 1; ki = 0; kd = 0; // calculo dos coeficientes para ponto fixo k1 = (kp) * SHIFT; k2 = (ki) * SHIFT; k3 = (kd) * SHIFT; // configuracoes TIMER0 T0CONbits.TMR0ON = 1; T0CONbits.T08BIT = 1; T0CONbits.T0CS = 0; T0CONbits.T0SE = 0; T0CONbits.PSA = 0; T0CONbits.T0PS = 0b111; TMR0L = 22; // configuracoes de interrupcao INTCONbits.TMR0IE = 1; INTCON2bits.TMR0IP = 1; RCONbits.IPEN = 0; INTCONbits.GIE_GIEH = 1; INTCONbits.PEIE_GIEL = 0; while (1) { // inicio loop if (ref > fb) { // verifica sentido de giro necessario para o motor en1 = 0; // pino 4 en2 = 1; // pino 5 } else { en1 = 1; en2 = 0; } // seta o PWM -> 0-1023 CCPR1L:CCPxCON<5:4> CCPR1L = pwm >> 2; // 8 bits mais significativos CCP1CONbits.DC1B1 = pwm >> 1; // segundo bit menos significativo CCP1CONbits.DC1B0 = pwm; // bit menos significativo delay_ms(50); }// fim loop }// fim main