5
Hello, I am a student of the Technical course in Mechatronics. My teacher passed a project to show the speed of a reduced CC motor, in RPM, in the Hyper Terminal. He said we need to use the timer interruption, however, I did not understand how to use the timer interruption in PIC18F4550. He gave us the base program to only modify to show speed. If anyone can help me, I would really appreciate it.
Follows the basic program:
/*
Exemplo para controle de Motor de Corrente Contínua
*/
#include <18F4550.h>
#use delay(clock = 20MHz)
#fuses HS, NOWDT, PUT, NOBROWNOUT, NOLVP
#use rs232(baud = 9600, parity = N, xmit = pin_c6, rcv = pin_c7, bits = 8)
#include <stdlib.h> // biblioteca de conversão de valores
#define led pin_e2
// Definição de nomes para os canais do encoder. Para determinação do
sentido de giro,
// ao menos um dos canais deve ser conectado à algum pino de interrupção
externa
#define CanalB pin_b1
// Definição de nomes para a seleção de sentido de acionamento da Ponte H
#define PonteH_1 pin_d0
#define PonteH_2 pin_d1
// Definição de variável(is) global(is)
int1 i1_Sentido;
int16 i16_iPWM = 0, i16_pPWM = 0;
float f_Resolucao = 0, f_Angulo = 0, f_Posicao = 0;
char s_Resolucao[4], s_Posicao[10], s_pPWM[4];
signed int16 Contador = 0;
// Declaração de funções utilizadas no programa
void PiscaLed(void)
{
// Pisca-pisca para led
output_high(led);
delay_ms(250);
output_low(led);
delay_ms(250);
return;
}
void Inicializacao(void)
{
// Inicialização para controle do motor cc
printf("Resolucao do Encoder [ppv = pulsos por volta] = ");
gets(s_Resolucao); // após <enter>, lê o valor do tipo string
digitado
printf("\n\r");
f_Resolucao = atof(s_Resolucao); // converte string em número do tipo
float
f_Resolucao = 360/f_Resolucao;
delay_ms(250);
return;
}
// Declaração das interrupções e suas respectivas funções
#int_EXT
void EXT_isr(void)
{
// Este pedaço de código será executado se a interrupção for acionada, ou
seja, o Canal A do encoder
// passar de nível Alto para Baixo [H_TO_L], conforme configuração no
programa principal [void main()]
if ( !input(CanalB) ) // Se o Canal B estiver em nível Baixo ->
Sentido Horário
{
Contador--;
}
if ( input(CanalB) ) // Se o Canal B estiver em nível Alto ->
Sentido Anti-Horário
{
Contador++;
}
return;
}
// Função principal
void main()
{
PiscaLed();
// Configuração da(s) Interrupção(ões) Externa(s)
disable_interrupts(GLOBAL); // Desabilita todas as interrupções se
estiverem habilitadas
enable_interrupts(INT_EXT); // Habilita a interrupção externa 0
ext_int_edge(0, H_TO_L); // Configuração da interrupção externa para
borda de descida :: High TO Low [H_TO_L]
// Se fosse borda de subida :: Low TO High
[L_TO_H]
enable_interrupts(GLOBAL); // Habilita todas as interrupções
// Configuração do sinal PWM
setup_ccp1(CCP_PWM); // Configura CCP1 como um PWM
// O tempo de ciclo (período, T) será dado pela seguinte expressão:
// T = (1/clock)*4*t2div*(período+1)
// onde:
// T = período (será dado em segundos)
// clock = clock configurado em <#use delay(clock = #)>
// t2div = número de vezes de oscilação do cristal por instrução (pode
ser: T2_DIV_BY_1 ou T2_DIV_BY_4 ou T2_DIV_BY_16)
// período = valor que determina quando o valor de clock será resetado
(pode ser um inteiro de 0 a 255)
// Neste programa o clock é de 20MHz = 20000000Hz, t2div será por 16
(T2_DIV_BY_16) e o período selecionado será de 249. Assim,
// T = (1/20000000)*4*16*(249+1) = 0.0008s = 800us :: f = 1/T =
1/0.0008 = 1250Hz (aprox. 1,25kHz)
setup_timer_2(T2_DIV_BY_16, 249, 1);// Configura o período T do sinal PWM
// Inicialização de escrita na porta serial
printf("\n\n\n\r");
printf("::...[ Curso Tecnico em Mecatronica ]...::\n\r");
delay_ms(250);
printf(":: Controle de Motor CC ::\n\r");
printf("\n\r");
delay_ms(250);
Inicializacao(); // Chama função de inicialização do motor
while ( True )
{
printf("\n\rDigite a posicao angular desejada: ");
gets(s_Posicao);
printf("\n\r");
f_Posicao = atof(s_Posicao);
delay_ms(250);
printf("Digite o percentual de sinal PWM desejado [0 - 100]: ");
gets(s_pPWM);
printf("\n\n\r");
i16_pPWM = atoi(s_pPWM);
delay_ms(250);
// Conversão do valor percentual de 0 a 100 para inteiro de 10bits
i16_iPWM = i16_pPWM*10; // 100% = 1000 :: 1000/100 = 10
// Exemplo para uso do canal PWM: definição do tempo de ciclo ativo
set_pwm1_duty(i16_iPWM);
printf("PWM selecionado: %5ld\n\r", i16_iPWM);
printf("Posicao atual: %5.1f\n\r", f_Angulo);
printf("Posicao desejada: %5.1f\n\r", f_Posicao);
if ( f_Posicao <= f_Angulo )
{
i1_Sentido = 0;
printf("Sentido de giro: Horario\n\r");
}
else
{
i1_Sentido = 1;
printf("Sentido de giro: Anti-Horario\n\r");
}
if ( i1_Sentido == 0 ) // sentido horário
{
while ( f_Angulo > f_Posicao )
{
// Escrita/Acionamento do Motor CC
output_high(PonteH_1);
output_low(PonteH_2);
f_Angulo = Contador*f_Resolucao;
printf("Contador: %5ld :: Angulo: %5.1f\n\r", Contador, f_Angulo);
}
output_high(PonteH_1);
output_high(PonteH_2);
}
if ( i1_Sentido == 1 ) // sentido anti-horário
{
while ( f_Angulo < f_Posicao )
{
// Escrita/Acionamento do Motor CC
output_high(PonteH_2);
output_low(PonteH_1);
f_Angulo = Contador*f_Resolucao;
printf("Contador: %5ld :: Angulo: %5.1f\n\r", Contador, f_Angulo);
}
output_high(PonteH_1);
output_high(PonteH_2);
}
}
disable_interrupts(GLOBAL); // Desabilita todas a interrupcoes
externas se estiverem habilitadas
}