Ir ao conteúdo
  • Cadastre-se

PIC Utilizando PIC 16F887 Com timer0 Para fazer a contagem em centimetro


Ir à solução Resolvido por Arthur Bispo de Lima,

Posts recomendados

Bom Dia, Boa Tarde, Boa Noite.

 

Farei um projeto Traçador de Altura Digital que consta em fazer a contagem de pulsos Analógicos de um sensor(Enconder) assim realizar a contagem transformando esses pulsos em uma contagem em centímetros/milímetros/polegadas.

 

Estou encontrando dificuldade em lidar com os pulsos do enconder, a situação é o seguinte:

o enconder mandara pulsos para o PIC 16F887 que por sua vez, mandara para o LCD que mostrará a contagem .

Só que durante os testes, eu percebi que o Funcionamento até a parte do enconder está saindo como planejado, só que  quando passo os pulsos para o PIC(utilizando o Timer0-Tipo contagem) esses pulsos não são todos lidos, apenas alguns. onde é mostrado no LCD.

 

Tenho duas hipóteses:

 

pode ser a frequencia do Timer 0 ou do PIC

ou alguma interferencia externa.

 

Testei com um Clock(imitando um encoder) com uma frequência 10 Hz no Proteus e ele contava, mas quando coloco mais de 10 Hz ele não consegue contar.   

 

 

//----------------------------------LCD---------------------------------------//
sbit LCD_RS at RD4_bit;
sbit LCD_EN at RD5_bit;
sbit LCD_D4 at RD0_bit;
sbit LCD_D5 at RD1_bit;
sbit LCD_D6 at RD2_bit;
sbit LCD_D7 at RD3_bit;

sbit LCD_RS_Direction at TRISD4_bit;
sbit LCD_EN_Direction at TRISD5_bit;
sbit LCD_D4_Direction at TRISD0_bit;
sbit LCD_D5_Direction at TRISD1_bit;
sbit LCD_D6_Direction at TRISD2_bit;
sbit LCD_D7_Direction at TRISD3_bit;
//--------------------------------VARIAVEIS-----------------------------------//
float clk;
float Milimetros;
float MM;
float timer;
float timer1;
int a=0;
int af=0;
float valor;
char txt[15];

void main()
 {
  ANSEL= 0x02;              // Configuração AN2 pin as analog
  ANSELH = 0;                 // Configuração de outros AN pinos as digital I/O
  C1ON_bit = 0;               // Disabilita comparadores
  C2ON_bit = 0;
//------------------------Habilitando a porta Analógica-----------------------//
  Adc_Init();                 // Inicia porta analógica
//---------------------------Saidas e Entradas--------------------------------//
  TRISA  = 255;              // PORTA is input
  TRISC  = 0;                 // PORTC is output
  TRISB  = 255;                 // PORTB is input
  TRISD  = 0;                // PORTD is output
  INTCON = 0;
//-----------------------------Configuração do TMR0---------------------------//
  OPTION_REG=0b0101000;     //modo contador
  TMR0=0;                   //Inicializa o registro TMR0 com o valor 0.
//-----------------------------Saida do LCD-----------------------------------//
  Lcd_Init();                // Initialize LCD
  Lcd_Cmd(_LCD_CLEAR);       // Clear display
  Lcd_Cmd(_LCD_CURSOR_OFF);          // Cursor off
  Lcd_Out(1,2,"TRACADOR");
  Lcd_Out(1,12,"DE");
  Lcd_Out(2,2,"ALTURA");
  Lcd_Out(2,10,"DIGITAL");
//------------------------------Contador--------------------------------------//
   while(1)
    {
    Delay_ms(100);
    valor = Adc_Read(0);//Faz a com que a variavel valor seja igual a porta analogica lida que é a RA0
     if(TMR0==1&&a==0)
      {
       af=1;
      }
      if(af==1)
       {
        af=2;
        Lcd_Cmd(_LCD_CLEAR);
       }
        if(af==2)
         {
          if(INTCON.TMR0IF)
           {
            INTCON.TMR0IF=0; //limpa a flag
            TMR0 = 0;
            a++;
           }
          timer=TMR0+(a*255);
          timer1=timer/1000;
          floatToStr(timer1,txt);
          txt[5] = 0;
          Lcd_Out(1,2,txt);
         }
//----------------------------PORTA ANALÓGICA "CLOCK"-------------------------//
           if(valor<614) //Quando valor for menor que 3V
           {
            RC0_bit = 0; //Manda zero
           }
            else //Se não
           {
            RC0_bit = 1; //Manda um
           }
    }
 }

//------------------------------Conversão dos valores-------------------------//

Proteus.png

Link para o comentário
Compartilhar em outros sites

@Arthur Bispo de Lima ,

 

Não entendo nada de C, mas sei que fazer cálculos com variáveis Float demoram demais, e isso vai fazer você perder pulsos.

 

A maneira correta é usar interrupção, usar variáveis do tipo Word ( nem sei se é isso no C mas digo variáveis com 16 bits ou 2 Bytes ) para totalizar, e fazer as contas mais complexas no loop principal, FORA da interrupção.

 

Aguarde pelo pessoal mais acostumado com isso !

 

Paulo

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

Paulão tem razão. E tem +...

Usar entrada analógica pra medir pulso até que não é totalmente desinteressante pois tens a opção de controlar a amplitude. Mas penso que isso seria algo digamos "avançado" pra sua "idade". Deixe pra depois.

 

Por enquanto considere deixar o hw do mc trabalhar pra você. Algo como programe o timer pra contar com pino externo. O algoritmo é simples: leia o timer, zere-o, e releia depois de um tempo conhecido. Pode sar uma interrupt. Me lembro que ele tem entrada st o que ajuda 1 pouco. Publique o esquema de verdade

Link para o comentário
Compartilhar em outros sites

18 minutos atrás, aphawk disse:

@Arthur Bispo de Lima ,

 

Não entendo nada de C, mas sei que fazer cálculos com variáveis Float demoram demais, e isso vai fazer você perder pulsos.

 

A maneira correta é usar interrupção, usar variáveis do tipo Word ( nem sei se é isso no C mas digo variáveis com 16 bits ou 2 Bytes ) para totalizar, e fazer as contas mais complexas no loop principal, FORA da interrupção.

 

Aguarde pelo pessoal mais acostumado com isso !

 

Paulo

Obrigado, Aphawk (Paulo) por responder.

Mas a questão das variáveis Float, acho que não ira interferir nos pulsos. Já que até aonde eu sei, o float só demora mais para efetuar as leituras dos sinais, mas isso naõ quer dizer que ele perdera os sinais. ( Claro que posso estar errado)

 

Mas vou dar uma olhada nas variáveis do tipo Word

valeu  

adicionado 39 minutos depois
40 minutos atrás, Isadora Ferraz disse:

Paulão tem razão. E tem +...

Usar entrada analógica pra medir pulso até que não é totalmente desinteressante pois tens a opção de controlar a amplitude. Mas penso que isso seria algo digamos "avançado" pra sua "idade". Deixe pra depois.

 

Por enquanto considere deixar o hw do mc trabalhar pra você. Algo como programe o timer pra contar com pino externo. O algoritmo é simples: leia o timer, zere-o, e releia depois de um tempo conhecido. Pode sar uma interrupt. Me lembro que ele tem entrada st o que ajuda 1 pouco. Publique o esquema de verdade

Então a primeira foto foi um teste para ver se o encoder estava mandando pulso com isso colocamos um LED na saída e um Display e ele contou normalmente. Mas a partir disto colocamos  o PIC e o LCD  ai eu coloquei OPTION_REG=0b0101111; como no final 111 ou seja antes estava OPTION_REG=0b0101000; ai ele contava devagar com o 111 ele contou mais rápido mas mesmo assim ele não conta suficientemente melhor ai eu queria saber como aumentar a Frequencia ou seja que lê consigna ler praticamente um moto(encoder) que esta na foto em baixo ai eu queria saber se meu option reg ta errado ou alguma linha do codigo ou até mesmo usar algo diferente Obrigado! Isadora 

9fa051cc-9ecc-42e0-80cb-194122234e3f.jpg

31677643-9351-4007-b1bd-91431f479d7a.jpg

640bcb33-a755-4cd5-b704-d950562e479b.jpg

Link para o comentário
Compartilhar em outros sites

@Arthur Bispo de Lima ,

 

Que tal fazer a dica da @Isadora Ferraz , que é aplicar os pulsos na entrada do Timer0, configurado como Counter, e

programar um outro Timer para

gerar uma temporização precisa, por exemplo o Timer1 gerando uma interrupção a cada 200 mseg, assim voce zera o contador de pulsos numa interrupção do timer, e na próxima interrupção voce pega a contagem do counter e armazena em uma variável para ser tratada pelo programa principal, o qual será responsavel por apresentar a contagem no display ?

 

Pode brincar à vontade, usando Timers/Counters diferentes, tempos diferentes, claro que dependendo da quantidade de pulsos por segundo que você está esperando obter.

 

É quase igual a um frequencímetro!

 

Paulo

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

6 minutos atrás, aphawk disse:

@Arthur Bispo de Lima ,

 

Que tal fazer a dica da @Isadora Ferraz , que é aplicar os pulsos na entrada do Timer0, configurado como Counter, e

programar um outro Timer para

gerar uma temporização precisa, por exemplo o Timer1 gerando uma interrupção a cada 200 mseg, assim voce zera o contador de pulsos numa interrupção do timer, e na próxima interrupção voce pega a contagem do counter e armazena em uma variável para ser tratada pelo programa principal, o qual será responsavel por apresentar a contagem no display ?

 

Pode brincar à vontade, usando Timers/Counters diferentes, tempos diferentes, claro que dependendo da quantidade de pulsos por segundo que você está esperando obter.

 

É quase igual a um frequencímetro!

 

Paulo

Vou tentar fazer isso se der certo vou dar o feedback ok até mais 

Link para o comentário
Compartilhar em outros sites

  • Membro VIP
15 horas atrás, Arthur Bispo de Lima disse:

coloquei OPTION_REG=0b0101111; como no final 111 ou seja antes estava OPTION_REG=0b0101000

É... tudo bem... você tentou mas... tentativa e erro não é muito lógico no caso de circuitos lógicos. O lógico é você usar a lógica e olhar no d.s. a função dos bits e programá-los corretamente de acordo com sua  lógica. Ou isso foi ... 'lógico demais'?

 

Vida longa e próspera.

t+

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

  • Solução
Em 17/04/2018 às 08:43, Isadora Ferraz disse:

É... tudo bem... você tentou mas... tentativa e erro não é muito lógico no caso de circuitos lógicos. O lógico é você usar a lógica e olhar no d.s. a função dos bits e programá-los corretamente de acordo com sua  lógica. Ou isso foi ... 'lógico demais'?

 

Vida longa e próspera.

t+

Isadora Ferraz e Paulo muito obrigado pela ajuda eu consegui fazer a medição em altas frequências.

 

O que eu fiz primeiramente utilizei um transistor que manda 0 ou 1 na sua saida em altas frequências depois alterei um pouco o código tirando a porta analógica,pois antes eu utilizava, por que usava um amplificador operacional(como comparador) e tirei a última relação do PortC por isso também.

Agora eu joguei a saída do transistor na entrada do portRA4 e todo sinal que ele manda o Pic recebe e conta então agora é só fazer a conversão correta de centímetros milímetro e polegada para conseguir reproduzir um traçador de altura Digital 

 

Agradeço a vocês pela ajuda

 

peço só mais 1 ajuda que é nessa questão de conversão.

Quando eu mando á contagem para variável float tenho que dividi-lá por 1000 que seria milímetro mais wuando mando compilar e mostrar no LCD o número 1 fica 1.9999 ou seja queria que ficasse 0.001 como faço para que mostre no LCD isso obrigado desde já.

 

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

Publique a parte do fonte onde você acha que isso deve ocorrer e não está ocorrendo. Seria por aqui?

timer=TMR0+(a*255);
          timer1=timer/1000; //tente /1000.0
          floatToStr(timer1,txt);
          txt[5] = 0;
          Lcd_Out(1,2,txt);

Nem tentei entender mas porque txt[5]=0?

E de novo... mc de 8 bits e variáveis float não se dão muito bem... Faça com só int e coloque o . na raça ... e coragem

Link para o comentário
Compartilhar em outros sites

6 horas atrás, Isadora Ferraz disse:

Publique a parte do fonte onde você acha que isso deve ocorrer e não está ocorrendo. Seria por aqui?

timer=TMR0+(a*255);
          timer1=timer/1000; //tente /1000.0
          floatToStr(timer1,txt);
          txt[5] = 0;
          Lcd_Out(1,2,txt);

Nem tentei entender mas porque txt[5]=0?

E de novo... mc de 8 bits e variáveis float não se dão muito bem... Faça com só int e coloque o . na raça ... e coragem

Então int eu não posso usar porque quero vírgula  ou seja int só são variáveis inteiras já float usa decimais eu vi esse word eu ainda estou vendo a biblioteca dele por isso não uso 

 

Chat txt[5] e pra definir as casas decimais mostradas 

 

Queria saber se tem como declarar uma variável e mostrar através do String 0.001 o valor pois dividiu por 1000 ou seja o código está agora 

 

Timer=TMR0+(a*255);

FloatToStr (timer/1000, txt);

Lcd_Out (1,2,txt);

Delay_ms (10);

 

Eu usaria outro tipo como longToStr ou não?

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

Ah tá.

Acho que você fez txt[5]=0 pra limitar o tamanho da palavra. Ou não foi você quem fez?! Aumente 1 pouco pra txt[6 ou 7]=0 pra ver que merdadá

 

O que me diz do ...

8 horas atrás, Isadora Ferraz disse:

tente /1000.0

timer=timer/1000.0

FloatToStr (timer, txt);

 

O long não tem vírgula. Ao invés de enviar pro display, envie prum terminal algo como

printf(%f, txt);

Link para o comentário
Compartilhar em outros sites

3 horas atrás, Arthur Bispo de Lima disse:

Então int eu não posso usar porque quero vírgula  ou seja int só são variáveis inteiras já float usa decimais eu vi esse word eu ainda estou vendo a biblioteca dele por isso não uso 

 

 

Quer dizer que você só sabe fazer contas com float se precisar mostrar com algumas casas decimais ???????

 

Te garanto que dá para fazer com tipo Word ( 0 a 65535 ), com um pouco de matemática, e fica mais rápido !

 

Paulo

Link para o comentário
Compartilhar em outros sites

  • Membro VIP
12 horas atrás, aphawk disse:

Te garanto que dá para fazer com tipo Word ( 0 a 65535 )

Em c  na minha época era unsigned int . Então vamos escrever 123.45 no display com a matemática do Paulão? Pra isso tens que pesquisar um função que escreve um (01) caracter asc por vez, algo como

putchar_LCD();//inventei isso agora

 

unsigned int a=12345;
unsigned char temp=0;
while(a)
{
if (temp++==3) putchar_LCD(','); //posição da vírgula
else
putchar_LCD(a%10+0x30);//converte pra asc-ii
a/=10;
}

Tem potencial? Tem mas acho que vai notar algo estranho...

 

Tarefa: adicione os comandos de posicionamento no display e coloque no argumento da função. Coloque também um argumento pra posicionar a vírgula (ou ponto decimal)

dica:

void float_LCD(unsigned int a, unsigned char virgula, unsigned char x, unsigned char y) {

...

}

abç

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

6 horas atrás, Isadora Ferraz disse:

Em c  na minha época era unsigned int . Então vamos escrever 123.45 no display com a matemática do Paulão? Pra isso tens que pesquisar um função que escreve um (01) caracter asc por vez, algo como

putchar_LCD();//inventei isso agora

 


unsigned int a=12345;
unsigned char temp=0;
while(a)
{
if (temp++==3) putchar_LCD(','); //posição da vírgula
else
putchar_LCD(a%10+0x30);//converte pra asc-ii
a/=10;
}

Tem potencial? Tem mas acho que vai notar algo estranho...

 

Tarefa: adicione os comandos de posicionamento no display e coloque no argumento da função. Coloque também um argumento pra posicionar a vírgula (ou ponto decimal)

dica:

void float_LCD(unsigned int a, unsigned char virgula, unsigned char x, unsigned char y) {

...

}

abç

Ok vou estar fazendo isso quando eu terminar eu aviso se tive dúvidas ou se consegui até + obrigado por tudo mesmo

 

Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...