Hello, I am a student of the Mechatronics Technician course. My teacher passed a project to show the speed of a DC motor with reduction, in RPM, in Hyper Terminal. He said we need to use the timer interrupt, however, I did not understand how to use the timer interrupt on PIC18F4550. He passed us the base program so we can only modify it to show the speed. If anyone can help me, I would greatly appreciate it.
Follow the base 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
}