Boa noite amigos.
Estou montando um motor estilo keppe motor com algumas modificações para estudos mas detalhados. desenhei este motor todo em 3D e depois subdividi as peças em 2D para usar um cortador a laser, obtive peças bastante precisas e com as medidas exatas para não haver erros na hora dos testes, o eixo está estável e levitando muito bem.
preciso montar um tacômetro para que com esses dados eu possa controlar alguns leds de informação.
montei o circuito no proteus e comprei um pickit 3, 5 pic12F675, e 2 sensores foto elétricos.
Ficaria muito grato se me dessem uma força apenas com a programação referente ao tacometro para o PIC12F675, vou usar um cristal de 4Mhz.
Olá Murilo,
Qual a faixa de frequencia que você espera obter nesta medida elétrica, o sinal é uma onda quadrada 0 e 5V?
sim, é uma onda quadrada, comprei esse sensor foto elétrico
analisando melhor eu nem vou precisar do cristal oscilador, pois o cristal interno do pic12F675 já da conta.
preciso saber a velocidade do eixo para poder dar comandos baseado na velocidade.
basicamente eu preciso fazer esse eixo ficar entre 600rpm e 800rpm, se a velocidade estiver abaixo de 600rpm deve se mandar energia para as bobinas até atingir 800rpm, quando ficar outra vez com 600rpm liga-se outra vez as bobinas.
obs: Não quero usar onda quadrada no motor para controlar sua velocidade com precisão, pois com isso estaria gastando energia desnecessária.
acredito que pelo fato do eixo está levitando o atrito é minimo e a perda de velocidade também é minima.
neste site o amigo usou o pic12f675 como tacômetro ecolocou um lcd, entretanto devido ele usar um cristal oscilador, não sobrou pinos para comandos esterno, pensei em tirar o cristal, mas não consegui arrumar os códigos para o que eu preciso, pois sou meio leigo na programação.
seria até interessante ter um LCD.
Como a frequencia é baixa, 13,3 Hz, dá pra usar isto sem problemas e com uma boa precisão.
Eu recomendo você implementar um contador do sinal do tacômetro, e utilizar o Módulo Timer1 (vide datasheet) para controlar o tempo, a partir daí você pode estabelecer uma relação entre o número de pulsos do tacômetro e dividindo pelo tempo de estouro do Timer1, tem-se a frequencia em Hz ou rpm.
Obrigado amigo
Vou tentar
Boa tarde amigos,
tentei usar o timer0 do PIC12F675 para usar como tacômetro, mas ta dando errado, quando testo no proteus não funciona.
char numflancos=0;
int rpm;
void main()
{
ANSEL = 0x00; //desliga as entradas AD
CMCON = 7; //desliga os comparadores
OPTION_REG = 0X10111000;
TMR0 = 0;
trisio=0b11000000;
GPIO = 0;
while(1)
{
TMR0=0; //Inicializa o registro TMR0 com o valor 0.
Delay_ms(1000); //Conta durante 1 segundo.
numflancos=TMR0; //numflancos=velocidade em rps.
rpm=60*numflancos; //Transforma para rpm.
if(rpm < 600)
{
GPIO.F4 = 1;
GPIO.F5 = 0;
}
else
{
GPIO.F4 = 1;
GPIO.F5 = 0;
}
}
}

Olá Murilo,
Está chegando próximo, mas notei algumas falhas no seu código:
-
A função Delay_ms(1000) faz com que o microcontrolador “pare” por 1 segundo, não realizando nenhuma operação de leitura, nem de contagem neste tempo, apenas um estouro de interrupção o tiraria deste estado antes dos 1000 ms.
-
Não identifiquei nenhuma função de contador no código, algo que monitore alguma porta e detecte se houve mudança de nível, caso haja então encrementar contador.
-
Não estou familiriazado com o Proteus, mas não encontrei as instruções de configuração dos registradores de interrupções.
Obrigado pela valiosa ajuda amigo
Vou aplicar suas dicas.
Desculpe o encomodo
andei estudando e cheguei mais perto rsrsr
amanha eu acredito que termino essa programação
int rpm, P, I,numflancos;
Void interrupt
{
numflancos++; //Conta o numero de pulços
TMR0 = 0x00; //Inicia a contagem no 0
}
void main()
{
ANSEL = 0x00; //desliga as entradas AD
CMCON = 7; //desliga os comparadores
OPTION_REG = 0X10111000; //Modo contador
//Desabilita os registradores de pull-up internos
INTCON = 0b01110000; //Habilita a interrupção global
//Habilita a interrupção por perifericos
//Habilita a interrupção por estouro do TMR0
TMR0 = 0x00;
TRISIO2_bit = 1;
TRISIO4_bit = 0;
TRISIO5_bit = 0;
GPIO = 0;
while(1)
{
if(rpm > 800)
{
I=1;
P=1;
}
if(rpm < 800, rpm > 600)
{
{
if(P != 4)
I=2;
P=2;
}
}
if(rpm < 600)
{
I=3;
}
if(I == 3, P != 1, GPIO.F2 == 1)
{
GPIO.F4 = 1;
}
if(I == 2,P != 1, GPIO.F2 == 1)
{
GPIO.F4 = 1;
}
if(P == 1, GPIO.F2 == 1, rpm > 600)
{
P=4;
}
if(P == 4, GPIO.F2 == 1, rpm < 600)
{
GPIO.F4 = 1;
P=2;
I=2;
}
if(rpm < 800, rpm > 600)
{
GPIO.F5 = 1;
}
}
}
preciso que o motor acelere e depois que chegar a 800rpm pare e só acelere quando estiver em 600rpm
Olá Murilo,
Ainda falta uma instrução para utilizar os dados armazenados em “numflancos” e dividir pelo tempo, após isso, deve-se atribuir o valor a numflandos = 0; e recomeçar a contagem.
Mas melhorou muito o código e em pouco tempo, parabéns.
Obrigado amigo
com sua ajuda está cada vez vais fácil estudar e entender como funciona a programação.
vou fazer as alterações.
Finalmente consegui
muito obrigado pela ajuda amigos
vou usar um cristal de 16MHz
usei o TIMER1 para poder contar 65536
e o TIMER0 para temporizador
com overflow de 1s
// Lcd pinout settings
sbit LCD_RS at RB2_bit;
sbit LCD_EN at RB3_bit;
sbit LCD_D7 at RB7_bit;
sbit LCD_D6 at RB6_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D4 at RB4_bit;
// Pin direction
sbit LCD_RS_Direction at TRISB2_bit;
sbit LCD_EN_Direction at TRISB3_bit;
sbit LCD_D7_Direction at TRISB7_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB4_bit;
int pe, ie;
unsigned counter = 0x00; //Conta até 1000
unsigned pulse = 0x00; //Armazena o número de pulsos
char txt[7]; //String de texto auxiliar
void interrupt()
{
counter++; //Incremento a cada interrupção
TMR0 = 56; //Inicia otimer0 56
INTCON.T0IF = 0x00; //Limpa a flag de interrupção
}
void main()
{
CMCON = 0x07; // Desabilita os comparadores
T1CON = 0x03; // Habilita o Timer1 e Clock Externo
TMR1L = 0x00; // Inicia o Timer1 em 0000
TMR1H = 0x00;
INTCON.GIE = 0X01; //Ativa a interrupção global
INTCON.PEIE = 0X01; //Ativa a interrupção por perifericos
INTCON.T0IE = 0X01; //Ativa a interrupção do TMR0
TMR0 = 0x00;
OPTION_REG = 0b10000001; //Modo de temporização, prescaler 1:4
//Cristal = 16MHz PIC = 4MHz/4 PIC = 4MHz
//f = 1/4000000
//Tempo = 0,00000025
//Overflow = 0,00000025 * 4 * 200 = 0,0002
TRISB = 0; // Todo PORTB será saída (Exceto RB0 e RB1)
TRISC = 0b11001111; // 1110 0111 Apenas o RC4 como saída
PORTB = 0x00; // Inicia todo PORTB em low
PORTC = 0b00000000; // RC4 em low
Lcd_Init(); // Inicializa Display
Lcd_Cmd(_LCD_CURSOR_OFF); //Apaga o cursor
Lcd_Cmd(_LCD_CLEAR); // Limpa o display
// TMR1H TMR1L
// 00000000 00000000 2^16 = pode contar até 65536
while(1)
{
if(counter == 5000) //Quando a contagem chegar em 0,0002 * 5000 = 1s
{
pulse = (TMR1H << 8) + TMR1L; //Armazena o valor de 16 bits do Timer1 em pulse
IntToStr(pulse, txt); //Converte o valor inteiro para string
Lcd_Out(1,1,"FREQUENCIA:"); //Escreve na linha 1
Lcd_Out(2,1,txt); //Imprimir o número da frequancia
if ((pulse <= 6)||(pulse >= 3))
{
RC5_bit = 0x01;
}
if ((pulse > 6)||(pulse < 3))
{
RC5_bit = 0x00;
}
RB0_bit = ~RB0_bit; //Inverte o RB0
counter = 0x00; //Zera o counter
TMR1H = 0x00; //Zera o TMR1H
TMR1L = 0x00; //Zera o TMR1L
}
if(RC0_bit == 0x01)
{
if(pulse > 6)
{
ie=1;
pe=1;
}
if ((pulse <= 6)&&(pulse >= 3))
{
if(pe != 4)
{
ie=2;
pe=2;
}
}
if(pulse < 3)
{
ie=3;
pe=3;
}
if ((ie == 3)&&(pe != 1))
{
RC4_bit = 0x01;
}
if ((ie == 2)&&(pe != 1))
{
RC4_bit = 0x01;
}
if ((ie == 1)&&(pulse >= 3))
{
pe=4;
}
if ((pe == 4)&&(pulse < 3))
{
RC4_bit = 0x01;
pe=2;
ie=2;
}
}
if(RC0_bit == 0x00)
{
RC4_bit = 0x00;
}
}
} //end main
Parabéns, muito bem.