Fork me on GitHub

28/10/12

Projeto 10: Tacômetro Digital (2)

Tacômetro Digital com PIC16F877A



O circuito consiste de um PIC16F877A, um LCD 2x16, um sensor para medir a rotação( pode ser do tipo magnético, indutivo, óptico ou capacitivo);


O TIMER0 do PIC no modo contador, funciona fornecendo pulsos no pino RA4/T0CKI durante 1 segundo. Este valor corresponde ao número de revoluções por segundo (RPS), que é transformado para rpm para exibição no LCD.

A rotação máxima é de 15300rpm e a mínima é de 120rpm.

Para o projeto utlizei um cristal de 4Mhz.

DOWNLOAD
Arquivo de simulação do Proteus:tacometro_digital.dsn;


CÓDIGO-FONTE
MikroC PRO PIC
//Configuração dos pinos do LCD
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;

sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;

//variaveis
char texto1[7], numflancos=0;
int rpm, rads;

void main() {
OPTION_REG=0b10111111;//configura o timer0 com clock externo e prescaller off.
Lcd_Init();                //Inicializa o LCD.
Lcd_Cmd(_LCD_CLEAR);       //Limpa o display.
Lcd_Cmd(_LCD_CURSOR_OFF);  //Apaga o cursor.
Lcd_Out(1,1,"MICROCONTROLANDOS"); //Escreve no LCD
Lcd_Out(2,1,"TACOMETRO DIGITAL"); //Escreve no LCD
Delay_ms(10);
Lcd_Cmd(_LCD_CLEAR);       //Limpa o display.
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.
IntToStr(rpm,texto1);     //Transforma rpm em texto.
Lcd_Out(1,10,texto1);     //Escreve no LCD
Lcd_Out(1,1,"RPM :");     //Escreve no LCD
Delay_ms(10);           //Espera para nova medição.
}
}


34 comentários:

  1. Boa tarde, alguém conseguiria incluir uma rotina no programa para ligar um led quando a rotação atingir 100RPM e desligar quando estiver abaixo deste valor, obrigado.

    ResponderExcluir
    Respostas
    1. Olá!
      Após "void main(){" coloque "TRISC.F0=0;" para definir o pino rc0 como saida e após "rpm=60*numflancos;" insira "if(rmp>=100) PORTC.F0=1; else PORTC.F0=0;"

      Excluir
  2. Boa tarde pegando carona na idéia deste projeto do RPM estou tentando criar um frequencímetro com o pic 18f4520 de forama mais simples usando o TIMER1 e esta funcionando bem e estável, porém só estou conseguindo ler até 256HZ preciso que ele leia até no mínimo 5KHZ goataria de uma ajuda.
    Estou usando o compilador Mikroc-Pro, segue o código.




    //****************************// VARIÁVEIS //******************************
    char texto1 [20];
    int contador;
    int HZ;
    // **************************// FUNÇÃO PRINCIPAL // ***********************
    void main() {
    T1CON=0b00000011; // Timer 1 configurado no modo contador
    TMR1H=0Xec; //Parte auta da contagem
    TMR1L=0x78; // Parte baixa da contagem
    TRISC.RC0=1; // Configura porta como entrada
    PORTC.RC0=0; // Condição inicial zero
    ADCON1=0X0F; //Configura todos os pinos A/D como I/O xde uso geral
    Lcd_Init(); //Inicializa o LCD.
    Lcd_Cmd(_LCD_CLEAR); //Limpa o display.
    Lcd_Cmd(_LCD_CURSOR_OFF); //Apaga o cursor.
    Lcd_Out(1,5,"PROJETO."); //Escreve no LCD
    Lcd_Out(2,2,"FREQUENCIMETRO"); //Escreve no LCD
    Delay_ms(2000); // Aguarda
    Lcd_Cmd(_LCD_CLEAR); //Limpa o display.

    //***************************// LAÇO DE REPETIÇÃO //***********************
    while (1){
    tmr1l=0;//Zera parte baixa do timer1
    Delay_ms(1000); //Conta durante 1 segundo.
    contador = tmr1l; //Atribui o a contador o valor contido em tmr1l.
    HZ=1*contador;//1*contador; //Transforma para Hz.
    IntToStr(contador,texto1); //Transforma HZ em texto.
    Lcd_Out(2,7,texto1); //Escreve no LCD
    Lcd_Out(1,4,"FREQUENCIA"); //Escreve no LCD
    Lcd_Out(2,6,"HZ :");
    Delay_ms(5); //Espera para nova medição.

    }
    }

    ResponderExcluir
    Respostas
    1. voce tem que utilizar a parte alta e baixa do timer1.
      Dentro do while vc pegou somente o valor de TMR1L(o valor max. é 255)
      voce tem q fazer o seguinte:
      ...
      while(1){
      TMR1L=0;
      TMR1H=0;
      Delay_ms(1000);
      contador = (TMR1H << 8) + TMR1L;
      //o valor max q é 65536
      ...

      Excluir
  3. Boa noite
    Estou com uma dúvida estou montando esse projeto só que não está dando certo estou usando essa programação com está relação de itens gostaria de uma ajuda?

    Emissor IR
    Receptor IR
    Arduino Uno
    Resistor 220ohm
    LCD 16x2
    potenciômerto de 10ohms

    Programa

    #include
    /*
    * Optical Tachometer
    *
    * Uses an IR LED and IR phototransistor to implement an optical tachometer.
    * The IR LED is connected to pin 13 and ran continually. A status LED is connected
    * to pin 12. Pin 2 (interrupt 0) is connected across the IR detector.
    *
    *
    */
    int ledPin = 13; // IR LED connected to digital pin 13
    int statusPin = 6; // LED connected to digital pin 12
    volatile byte rpmcount;
    volatile int status;
    unsigned int rpm;
    unsigned long timeold;
    LiquidCrystal lcd(12, 11, 10, 9, 8, 7);
    void rpm_fun()
    {
    //Each rotation, this interrupt function is run twice, so take that into consideration for
    //calculating RPM
    //Update count
    rpmcount++;

    //Toggle status LED
    if (status == LOW) {
    status = HIGH;
    } else {
    status = LOW;
    }
    digitalWrite(statusPin, status);
    }
    void setup()
    {
    Serial.begin(9600);
    //Interrupt 0 is digital pin 2, so that is where the IR detector is connected
    //Triggers on FALLING (change from HIGH to LOW)
    attachInterrupt(0, rpm_fun, FALLING);
    lcd.begin(16,2);
    //Turn on IR LED
    //pinMode(ledPin, OUTPUT);
    //digitalWrite(ledPin, HIGH);

    //Use statusPin to flash along with interrupts
    //pinMode(statusPin, OUTPUT);
    rpmcount = 0;
    rpm = 0;
    timeold = 0;
    status = LOW;
    }
    void loop()
    {
    //Update RPM every second
    delay(1000);
    lcd.clear();
    //Don't process interrupts during calculations
    detachInterrupt(0);
    //Note that this would be 60*1000/(millis() - timeold)*rpmcount if the interrupt
    //happened once per revolution instead of twice. Other multiples could be used
    //for multi-bladed propellers or fans
    rpm = 10*1000/(millis() - timeold)*rpmcount;
    timeold = millis();
    rpmcount = 0;

    //Write it out to serial port
    Serial.println(rpm,DEC);
    lcd.print("RPM: ");
    lcd.print(rpm);
    //Restart the interrupt processing
    attachInterrupt(0, rpm_fun, FALLING);
    }

    ResponderExcluir
    Respostas
    1. Olá!!
      esse código rpm = 10*1000/(millis() - timeold)*rpmcount; resultara em erros, pois recebe o valor do rpm durante 1000ms, mas neste calculo, (millis()-timeold) será um valor um pouco maior que 1000ms e tbm não há necessidade de colocá-lo.

      Tomei a liberdade de resumir seu código:

      int ledPin = 13; // IR LED connected to digital pin 13
      int statusPin = 6; // LED connected to digital pin 12
      volatile char rpmcount;
      unsigned int rpm;
      LiquidCrystal lcd(12, 11, 10, 9, 8, 7);

      void rpm_fun()
      {
      rpmcount++;
      digitalWrite(statusPin, !digitalRead(statusPin));
      //OU
      //digitalWrite(statusPin, digitalRead(statusPin)^1);
      }

      void setup()
      {
      Serial.begin(9600);
      pinMode(statusPin,OUTPUT);
      lcd.begin(16,2);
      rpmcount = 0;
      attachInterrupt(0, rpm_fun, FALLING);
      }

      void loop()
      {
      delay(1000);
      detachInterrupt(0);
      rpm = 10 * rpmcount;
      lcd.clear();
      lcd.print("RPM: ");
      lcd.print(rpm);
      Serial.println(rpm, DEC);
      attachInterrupt(0, rpm_fun, FALLING);
      rpmcount = 0;
      }

      Excluir
  4. Gostaria de saber como ficaria o codigo fonte (pic) pra usar um sensor de efeito hall e que a cada 4 ou 8 pulsos seria um rpm. e para incluir um Velocimetro seria posivel no mesmo PIC e LCD.
    POis tenho uma Mobilete e gostaria de colocar um LCD 16x2 com velocidade e RPM

    ResponderExcluir
    Respostas
    1. Caso voce utilize um sensor hall com saida digital,
      voce teria que modificar a seguinte linha:
      rpm = 60 * numflancos;
      e substituir por:
      rpm = (60/4) * numflancos;

      Excluir
  5. gostaria de implementar um velocimetro juntamente com este tacômetro, alguem poderia me ajudar?

    ResponderExcluir
  6. boa noite.
    quais são as alterações necessárias para que o sensor indutivo conte cada metal que ele identificar ? por exemplo em uma esteira de latinhas,para que possa contar quantas latinhas passam na esteira.
    obrigado !

    ResponderExcluir
    Respostas
    1. Se for com saída digital, não há necessidade de alterar nada, mas deve alimentar o sensor indutivo com 5V.

      Excluir
  7. Olá,
    Eu estou tentando compilar o código com o mikroC mas está dando alguns erros, um deles é que a variável não está declarada, poderia me ajudar??

    ResponderExcluir
  8. Olá,
    Consegui compilar deu certo, mas agora tenho um novo problema, esse PIC 16F877A está saindo de linha, estou tentando usar o PIC16F887 no lugar dele, mas não ta rodando, saberia me dizer se é possível? e o que mudaria no código?

    Muito obrigado

    ResponderExcluir
  9. Montei o projeto conforme acima e estou usando um sensor optico PNP, liguei a saida do sensor no pino 6 do PIC...porém os valores de RPM ficam oscilando e não me retornam nenhuma resposta consistente... variam entre 9000 - 12000...saberia me dizer o que pode ser?

    ResponderExcluir
  10. Teria como fazer um tacometro com maior resolução? pois este pula de 60 em 60 RPM certo? gostaria de um que tivesse precisão de 1 RPM...

    ResponderExcluir
  11. Cara, por favor tem como me ajudar?
    Este é um trabalho que preciso fazer para faculdade, e não estou conseguindo.. e o que preciso é exatamente isto, não consegui testar o seu código porque não tenho certeza do que mudar, o meu pic é o F184550, além de que preciso visualizar isto no Pc em vez de no Lcd, mas não consegui nem fazer o básico (estou usando CCP no modo compare), mas o led fica oscilando. Me passa seu e-mail (se vc puder), te envio o código..)
    Valeu!!

    ResponderExcluir
  12. Olá bom dia.
    Gosto muinto do seu site e tenho aprendido muinto com seus projetos, fiz um curso na microgenios do pic 18f452 copilador mikroc e notei que para o pic16f877 muda os comandos. Vc teria um programa fonte para o pic18f452, vc teria pra vender ou alguma coisa curso, documentários, etc, sobre pic16f628a para mikroc.
    no aguardo, Toninho

    ResponderExcluir
  13. Ola gostaria de um codigo pronto de pic 18f4550 para um limitador de velocidade ou seja se a velocidade em km/h atingir acima de 10km/h corta um rele.

    alguem pode me ajudar

    negociamos valor.

    ResponderExcluir
  14. Não Funciona Direito !!
    a resolução vai de 60 em 60 . Você não consegue alcançar 134 rpm ,só múltiplos de 60 .
    O RPM de verdade é calculado pela largura de pulso.

    ResponderExcluir
  15. Olá. achei interessante o seu projeto... gostaria de construir um hodómetro baseando-se neste tecómetro, neste caso como seria a programação, o que mudaria?

    ResponderExcluir
  16. Porque o minimo de 120RPM.
    Como posso chegar a 0,1RPM?

    ResponderExcluir
  17. Olá, estou com certa dificuldade se puder auxiliar muito grato..

    Estou fazendo um projeto onde vou usar volts para aquecer uma resistência ( resistência de choveiro) onde vai de 0* celsius a 90* celsius ,porém ao chegar nos 90* deve ficar fixa e abrir uma contagem de 15 minutos . terminando a contagem sera desligado o aquecedor.
    VC usou timer0 no modo contador e com pulsos no pino r4 , com o valor sendo de rpm sendo calculado para LCD.. Nao estou conseguindo fazer o mesmo porém mandar pulsos no r4 e exibir a temperatura em celsius no LCD simultaneamente com o contador de tempo de 15 minutos, estou usando LM35 para temperatura, sendo 0,01 volts = 1* celsius.

    ResponderExcluir
    Respostas
    1. Dê uma estudada em PID (Proporcional Integral derivativa). Acredito que lhe será útil para entender seu projeto. Boa sorte.

      Excluir
    2. PID é lógica de controle. Não tem muito a ver com a dúvida dele. O problema é que o pic não consegue ler o LM35 e mostrar com resolução de 0,1°C por conta dos limites do conversor AD. O valor da diferença entre as tensões de referencia máxima e mínima é de 2,5 volts em alguns modelos e 3,0 volts em outros.

      Excluir
  18. Olá, gostaria de poder ajustar o rpm de forma analógica, numa interface entre o gerador de sinal e o microcontrolador, como devo prosseguir. Obrigado

    ResponderExcluir
  19. Boa tarde,eu pretendo fazer um tac[ometro com 2 saidas a reles.Um rele e acionado quando atingir por exemplo 500rpm e o outro quando atingir por exemplo 10000rpm, mas queria que estes valores fossem selecionados externamente e nao por software ,por um dip switch ou por um trimpot=trimmer potentiometer.Alguem me pode ajudar.Agradecido Abraço

    ResponderExcluir
  20. Boa tarde gostaria de usar para o tacômetro o pic 16F628A e como entrada de sinal o pino RA1 para o RPM , e estou fazendo junto um para temperatura que quero usar de entrada o pino RA0 , o que eu precisaria moodificar no código para isso. estou arecem aprendendo e estou apanhando um pouco .

    ResponderExcluir
    Respostas
    1. Lucas. O problema inicial que vejo é que você pretende usar o PIC16F628A, porém o mesmo não tem conversor analógico-digital (CAD) e portanto você não vai conseguir ler temperatura com precisão.

      Excluir
  21. Olá amigo, o que seris necessario para mim transformar isso num velocimetro que imprime a velocidade instantânea em km/h ?

    ResponderExcluir

Postagens Relacionadas!!