Autor Tópico: Usando Timer do PIC  (Lida 31486 vezes)

Description:

0 Membros e 1 Visitante estão vendo este tópico.

Offline FB

  • "... Potência não é nada sem controle!"
  • Novato
  • *
  • Posts: 15
  • Sexo: Masculino
Re: Usando Timer do PIC
« Resposta #15 Online: 05 de Agosto de 2010, 14:40 »
Obrigado pelas dicas .. Terei que fazer o meu mesmo. Realmente reconheço que é importante saber assembler, mas nunca tive aula sobre essa linguagem ...
Herbert, Jorge e demais. Saudações.
Quanto às dúvidas do nosso amigo, vamos por partes. Herbert, você quer o projeto pronto ou realmente aprender configurar o pic para este e muitos outros projetos?
Pelo que vi nas mensagens, vc quer trabalhar com velocidade baixa, algumas voltas por segundo. É possível implementar em C, mas não descarto o que o Jorge disse. Apesar de não ter conhecimento, serei obrigado aprender o assembly também.
Se aprender é sua resposta para continuar com mais projetos, recomendo que comece aqui
Use o código seguinte para descompactar: robo3001
É um excelente material (em inglês), que vai te ensinar como funciona os periféricos internos de um pic com desenhos ilustrativos. Grandioso trabalho da mikroe. Apesar dos exemplos serem para um pic maior, para seu projeto, terá que ler atentamente o datasheet do pic no esquema.
Outra coisa, sugiro não multiplexar os displays, pois pode perder pulsos na contagem do tempo.
http://img580.imageshack.us/img580/18/01aug051431.gif
Usando Timer do PIC

A imagem acima é um projeto que terminei. A saída que pude encontrar, foi colocar os decodificadores BCD pois entre uma leitura e outra no sensor, um delay de 600ms é necessário, e a cintilação nos displays foi reprovada.
Com isso tenho um briho forte nos displays e o programa apenas se preocupa em monitorar a temperatura, escrevendo no display a cada 1seg.
Seu projeto só necessita de uma fonte de interrupção que é a do timer0.


Offline FB

  • "... Potência não é nada sem controle!"
  • Novato
  • *
  • Posts: 15
  • Sexo: Masculino
Re: Usando Timer do PIC
« Resposta #16 Online: 05 de Agosto de 2010, 15:03 »
Seu projeto só necessita de uma fonte de interrupção que é a do timer0.

Na imagem abaixo, o esquema do timer0 em detalhe:
http://img440.imageshack.us/img440/2576/02aug051449.gif
Usando Timer do PIC

Qualquer pino pode ser usado para disparar seu evento. Se usar o RA4 como no esquema, o timer1 obrigatoriamente deverá ser utilizado.
Ao detectar um pulso no RA4, o programa deverá ativar o timer0 e timer1. Enquanto o Timer0 é incrementado pelos pulsos em RA4, o timer1 conta um intervalo de tempo e quando ele terminar, corta o timer0. Uma variável recebe o valor do timer0 e um comando simples se encarrega de separar as unidades e dezenas. Outro comando coloca os dois nibbles no portB. Isso foge do seu pedido, pois disse "que uma porta ativa a contagem do tempo ao receber um primeiro pulso e quando ela receber outro pulso termina a contagem, efetua os calculos e mostra a velocidade calculada.
Não sou perito em matemática e mecânica, solicito aos mais entendidos, qual das duas formas seria mais conveniente: Contar pulsos em um periodo de tempo ou contar o tempo entre dois pulsos?
Aguardo.
Abraço.

Offline C N C N o w !

  • CNCMASTER
  • ******
  • Posts: 6300
  • Sexo: Masculino
Re: Usando Timer do PIC
« Resposta #17 Online: 05 de Agosto de 2010, 15:39 »
qual das duas formas seria mais conveniente: Contar pulsos em um periodo de tempo ou contar o tempo entre dois pulsos?

Esta é uma questão interessante, pedra de tropeço para incautos ... eu pretendia comentar isto e acabei esquecendo ...

A resposta é: depende da frequência do sinal. Para sinais de frequências razoavelmente elevadas, é preferível medir a frequência, ou seja, contar o número de eventos dentro de um intervalo de tempo definido. Para frequências muito baixas, é preferível medir o período, ou seja, o tempo decorrido entre dois eventos consecutivos.

No que se refere à aplicação discutida aqui, temos que:

raio: 0,33 m ==> perímetro: 2,07 m

velocidade: 60 km/h

velocidade tangencial: 60.000 / 3.600 = 16,66 m/s

16,66 / 2,07 = 8,04 Hz

Frequência bastante baixa, o que recomenda a mensuração pelo período.
« Última modificação: 05 de Agosto de 2010, 15:42 por C N C N o w ! »

Offline minilathe

  • How to ask questions - The Smart Way...
  • Moderadores
  • CNCMASTER
  • ******
  • Posts: 4295
  • Sexo: Masculino
  • http://science-lakes.com/article43-html.html
  • Cidade - UF: Rio de Janeiro - RJ
  • Nome:: Gil Pinheiro
  • Profissão: Engenheiro e professor universitário
Re: Usando Timer do PIC
« Resposta #18 Online: 05 de Agosto de 2010, 16:10 »
Outra coisa, sugiro não multiplexar os displays, pois pode perder pulsos na contagem do tempo.
http://img580.imageshack.us/img580/18/01aug051431.gif
Usando Timer do PIC

A imagem acima é um projeto que terminei. A saída que pude encontrar, foi colocar os decodificadores BCD pois entre uma leitura e outra no sensor, um delay de 600ms é necessário, e a cintilação nos displays foi reprovada.
Com isso tenho um briho forte nos displays e o programa apenas se preocupa em monitorar a temperatura, escrevendo no display a cada 1seg.
Seu projeto só necessita de uma fonte de interrupção que é a do timer0.

Pode ser feito sem decodificadores!! É uma questão de encadear as tarefas na interrupção de tempo, pois são tarefas de curta duração (atualizar o display e ler o Timer) executadas num intervalo regular, a cada 1/24 s ou menos. Cada tarefa consome bem menos que 1/24 s, o que torna o procedimento viável, sem perda de luminosidade ou ocorrência de cintilação do display.

Eu já fiz isso num projeto de fotoplestimógrafo (medidor de pulsação cardíaca através de sensor óptico) com display de LCD LEDs de 7 segmentos, medindo o batimento através do cálculo do período médio de 6 pulsos e também atualizando o display. Usando aritmética de 16 bits e um clock de 4MHz apenas.
« Última modificação: 05 de Agosto de 2010, 18:59 por minilathe »

Offline FB

  • "... Potência não é nada sem controle!"
  • Novato
  • *
  • Posts: 15
  • Sexo: Masculino
Re: Usando Timer do PIC
« Resposta #19 Online: 05 de Agosto de 2010, 16:33 »
... Eu já fiz isso num projeto de foto...

Olá Gil. No projeto acima, tentei a multiplexação. No período de leitura do sensor DS1820, um dos displays chegava a apagar, pois eu era obrigado a desligar o bit de interrupções globais.
Como o pic possui o latch para o portB (configurados como digitais), o valor da última leitura é sempre exibido, mesmo durante a leitura do sensor, atualizado após esta rotina. O CD4511 ficou perfeito nesta combinação. Com LCD também concordo, uma vez que ele só vai mostrar novos parametros, quando receber comandos. Neste caso, pode-se até utilizar qualquer pino ligado ao lcd para receber os pulsos de entrada, basta apenas mudar a direção do tris durante a execução do código (entrada quando lê os pulsos, saída quando escreve no lcd).
Quanto à multiplexar, aí apóio o Jorge com assembly, mas neste caso fico limitado, pois aprendi somente C
Vou me dedicar ao assembly, em algumas aplicações, é melhor colocar códigos direto em asm dentro de um programa em C. Já faço isto, mas não tenho domínio.
Abraço.

Offline minilathe

  • How to ask questions - The Smart Way...
  • Moderadores
  • CNCMASTER
  • ******
  • Posts: 4295
  • Sexo: Masculino
  • http://science-lakes.com/article43-html.html
  • Cidade - UF: Rio de Janeiro - RJ
  • Nome:: Gil Pinheiro
  • Profissão: Engenheiro e professor universitário
Re: Usando Timer do PIC
« Resposta #20 Online: 05 de Agosto de 2010, 19:10 »
Retificando, já mudei acima...

Com LCD também concordo, uma vez que ele só vai mostrar novos parametros, quando receber comandos.

Usei LEDs, mas como faz muito tempo e hoje quase só uso LCD, escrevi LCD por força do hábito  :)

(Já alterei aí em cima no meu Post anterior)

Foi na década de 90, usei um 8751 da Intel e linguagem assembly. Mas também daria para fazer em C (e um bom compilador), é só atentar para o que eu disse antes...

A opção de uso do C ou assembly nesse caso é uma questão de atentar para o tamanho do código gerado. No caso do C, se for grande (o que depende do compilador), o problema é não tornar o programa excessivamente lento. O que acho pouco provável pela simplicidade do código.

Considere também que, dependendo da qualificação do programador, experiência e de como este escreve seus programas, até códigos em assembly podem ficar lentos....  :)

Offline minilathe

  • How to ask questions - The Smart Way...
  • Moderadores
  • CNCMASTER
  • ******
  • Posts: 4295
  • Sexo: Masculino
  • http://science-lakes.com/article43-html.html
  • Cidade - UF: Rio de Janeiro - RJ
  • Nome:: Gil Pinheiro
  • Profissão: Engenheiro e professor universitário
Re: Usando Timer do PIC
« Resposta #21 Online: 05 de Agosto de 2010, 22:29 »

Com relação a cintilação, é importante ressaltar que os displays (todas as posições) devem ser atualizados a cada 1/24 s ou menos. Pois o olho humano pode ser enganado nessas taxas (como no cinema, na TV analógica, ...). Se forem 4 algarismos, entre um digito e outro devem ser gastos menos do que 1/96 s!!! O que dá 1/24 para os 4 algarismos...

 
« Última modificação: 05 de Agosto de 2010, 22:33 por minilathe »

Offline pedrorose

  • Novato
  • *
  • Posts: 4
  • Sexo: Masculino
  • GUIA-CNC
Re: Usando Timer do PIC
« Resposta #22 Online: 25 de Setembro de 2010, 23:58 »
Olá, estou com um pequeno problema, quero usar um temporizador no MikroC, para fazer as seguinte função, quando um pino é acionado, o temporizador inicia a contagem, o PIC faz a verificação de mais 2 pinos, e se as mudanças ocorrerem em 15s, aciona uma saída, se não permanece como está. Alguém sabe como fazer?

Offline Beto_s

  • Hobby
  • ****
  • Posts: 284
  • Sexo: Masculino
  • Cidade - UF: S.José dos Pinhais-PR
  • Nome:: Alberto
  • Profissão: Téc. em Eletrônica
Re: Usando Timer do PIC
« Resposta #23 Online: 26 de Setembro de 2010, 00:23 »
è muito facil de fazer no miKroC , dê mais detalhes sobre os dois pinos a serem controlados , se será uma logica E por exemplo .

Depois que aciona a saída , como irá resetar ?

Sempre coloque o máximo de detalhes e entao a ajuda vêm mais rápido ...

Beto.

Offline pedrorose

  • Novato
  • *
  • Posts: 4
  • Sexo: Masculino
  • GUIA-CNC
Re: Usando Timer do PIC
« Resposta #24 Online: 26 de Setembro de 2010, 00:50 »
è muito facil de fazer no miKroC , dê mais detalhes sobre os dois pinos a serem controlados , se será uma logica E por exemplo .

Depois que aciona a saída , como irá resetar ?

Sempre coloque o máximo de detalhes e entao a ajuda vêm mais rápido ...

Beto.

os pinos podem ser quaisquer um, RB0 e RB1 por exemplo, mas será uma comparação lógica, será a leitura de dois sensores digitais, assim que o RB0 for acionado, ele iniciará o temporizador, e incrementará 1 em uma variável relacionada ao RB0, e também verificará o RB1, que se estiver em 1, também incrementara 1, mas em uma variável diferente, assim que ambas as variáveis estiverem em 4, o temporizador deve parar, e o PIC deve verificar se os sensores atuaram 4 vezes dentro de 15 segundos, se for, acionara o RC0, por exemplo, e se não for, zerará as variáveis e voltará ao inicio da programação, pretendo usar um goto para voltar ao inicio, e para resetar, usarei a seguinte função

if(PORTB.F3==0) //no caso estou utilizando um push button, que está mandando 5v direto pro pino
{
"variável do RB0"=0;
"variável do RB1"=0;
goto inicio;
}

Offline Beto_s

  • Hobby
  • ****
  • Posts: 284
  • Sexo: Masculino
  • Cidade - UF: S.José dos Pinhais-PR
  • Nome:: Alberto
  • Profissão: Téc. em Eletrônica
Re: Usando Timer do PIC
« Resposta #25 Online: 26 de Setembro de 2010, 22:24 »
Então pedrorose acho que isso deve dar pra começar alguma coisa...
Fiz um esboço usando um PIC 16f877A em 4MHz , já que vc não definiu qual Pic está usando .
Rb0 e Rb1 são as duas entradas , considerando ligadas quando são colocadas a nivel zero , ou seja , use resistores de Pull up .
 
Rc0 terá um led que liga quando as duas entradas forem pulsadas quatro vezes dentro de 15 segundos .

Rc1 terá um led que liga quando o tempo chega a 15 segundos , mesmo nao acionando nenhuma entrada , só para monitorar o funcionamento do temporizador .

Ficou faltando um reset da saída , pois nao ficou muito claro como vai fazer isso , apenas coloquei um reset dos contadores de pulsos de entrada caso chegar a 15 segundos e as entradas nao totalizarem os quatro pulsos cada . Para reset desligar e ligar o simulador ou o circuito.

Ainda :  a interrupção do timer 1 fica continuamente ligada , apenas criei um flag que é ligado ao primeiro pulso tanto na entrada 1 ou 2 que habilita o contador de 15 segundos.

Espero que sirva de ponto de partida .
MP com  arquivo que simulei no proteus , se vc usar aí .
Também o .hex e o .cof necessários para simularno proteus



// programa MikroC

unsigned short in1 = 0;   //flags das entradas
unsigned short in2 = 0;   // flags das entradas
unsigned counter, tmp;
unsigned T1_count=0;                      // counter variable, temporary variable
unsigned short f_inc;        // Timer1 counter, Usart Send flag
unsigned short f_temporizador ;// flag liga temporizador
unsigned  contador_in1=0;      // inicializa os contadores
unsigned contador_in2=0;
unsigned  temporizador=0; // inicializa temporizador

void interrupt() {

  if (PIR1.TMR1IF) {
    T1_count++;                              // increment T1_count
     TMR1H = 11;                            // write values to Timer1 registers
      TMR1L = 220;
    if (T1_count == 2) {                  // valor original =4 !!!!!!!!! para  clock 8 Mhz
      T1_count = 0;
    if (f_temporizador)
      f_inc = 1;              // se o temporizador estiver ligado seta f_inc
      }
    PIR1.TMR1IF = 0;
    }

  PIE1.TMR1IE = 1;            // Enable Timer1 interrupt
  INTCON = 0xC0;              // Enable GIE, PIE
}//~

void main() {
  ADCON1   = 0;               // Set AN pins to digital I/O
  TRISA    = 0;               // PORTA is output
  TRISD    = 0;               // PORTD is output
  TRISB    = 0XFF;               // PORTB.0 IN
  TRISC    = 0;                //PORTC OUT
  PORTC    = 0;

  T1_count = 0;
           // initialize T1_count

  TMR1H = 23;                 // Values are calculated for 8MHz
  TMR1L = 184;
  T1CON = 0b00110001;               // Set internal clock, start timer, prescaler 1:8


  PIE1.TMR1IE = 1;            // Enable Timer1 interrupt
  INTCON = 0xC0;              // Enable GIE, PIE

      do {


//  TESTE BOTOES PORT B DE 1 A 2
     if (Button(&PORTB, 0, 1, 0))  {

     in1 = 1;
     }
      if (Button(&PORTB, 0, 1, 1))
      if (in1) {
      f_temporizador=1 ; // liga flag temporizador
      contador_in1= contador_in1+1;    // incrementa o contador se rbo acionado
      in1 = 0;
      }
      if (Button(&PORTB, 1, 1, 0)) {

        in2 = 1;
        }
         if (Button(&PORTB, 1, 1, 1))
         if (in2) {
         f_temporizador=1; // liga  temporizador
         contador_in2=contador_in2+1;    // incrementa o contador se rb1 acionado
         in2=0;
         }
 // se os contadores das entradas ja chegaram a quatro
 
    if (contador_in1>=4 && contador_in2>=4) {
    PortC.F0 = 1   ;  // liga a saida indicando que os dois contadores
                      // chegarama quatro antes dos 15 segundos
    temporizador=0 ; // zera o contador de temporizador
    f_temporizador=0 ; // desliga o temporizador
    contador_in1=0 ; // zera o contador de entrada 1
    contador_in2=0 ; // zera o contador de entrada 2
    }
   
 // incrementando o contador
         
    if (f_inc) {
    temporizador=temporizador+1; // incrementa os segundos
    f_inc=0 ; // limpa o flag que foi foi setado na interuupçao
    if (temporizador==15) {
    PortC.F1 =1 ; // liga um led só pra saber que totalizou  os 15 segundos
    f_temporizador=0;  // desliga a temporizaçao até uma das entradas ser acionada novamente
    temporizador=0;    // reinicializa o contador do temporizador
    contador_in1=0;
    contador_in2=0;
                   }
    }
   
   
   
                                         // negates value on PORTD
    } while (1);                         // endless loop
 }
« Última modificação: 26 de Setembro de 2010, 22:40 por Beto_s »

Offline pedrorose

  • Novato
  • *
  • Posts: 4
  • Sexo: Masculino
  • GUIA-CNC
Re: Usando Timer do PIC
« Resposta #26 Online: 26 de Setembro de 2010, 23:53 »
vlw cara, testei aqui e é quase isso que eu quero
só faltam alguns ajustes

só me fala, como eu chego nos valores dos TMR1?

Offline Beto_s

  • Hobby
  • ****
  • Posts: 284
  • Sexo: Masculino
  • Cidade - UF: S.José dos Pinhais-PR
  • Nome:: Alberto
  • Profissão: Téc. em Eletrônica
Re: Usando Timer do PIC
« Resposta #27 Online: 27 de Setembro de 2010, 01:10 »
O timer 1 tem mais recursos que o timer 0 , pois opera com dois registradores
TMR1H - registrados do byte alto
TMR1L - registrador do Byte baixo
Totalizando 16 bits no contador ( contra 8 bits do timer0 ).

Para setar estes dois registradores de maneira correta devemos levar alguns pontos em consideração .
O cristal utilizado ou a frequencia do oscilador interno.
O preescaler selecionado em T1CON
Outros divisores que tenham sido implementados dentro ou fora da prórpia interrupção.

Utilizando o exemplo que escrevi:

Xtal utilizado no PIC = 4 Mhz
Lembrando que o ciclo de máquina devido a arquitetura interna do Pic é igual Fosc/4 .
Ciclo de máquina = 1us ( 0,000001s)

Preescaler selecionado em T1CON = 1:8 ou seja (T1CON = 0b00110001;    // Set internal clock, start timer, prescaler 1:8)

O nosso timer1 sera incrementado a cada 8 ciclos de máquina = 0,000008 = 8us.

Como a interrupção se dá no estouro dos registradores de TMR1 , na passagem de 65535 para 0 , ou de FFFF em hexadecimal
para 0000 , temos mais uma conta para fazer.
O valor que temos que escrever nos registradores será a diferença entre o valor total possível e o tempo que queremos medir.

Como ainda criei um outro divisor dentro da interrupçao ( T1_count==2) , a interrupçao ocorrerá duas vezes para que o flag f_int seja setado.
Isto é útil quando queremos colocar um led piscando a cada 0,5 segundos , por exemplo, mas queremos ter um temporizador com a unidade em segundos.

O valor a ser escrito nos registradores será :

ciclo desejado =  1 segundo
ciclo desejado / t1_count= 0,5 segundos
como nosso preescaler é de 1:8 o nosso Timer 1 será incrementado a cada 8us.
0,5 s / 8us =   62500

Aqui temos que prestar atenção , pois devemos escrever a DIFERENÇA nos registradores :

65536 - 62500 = 3036

Temos que escrever 3036 ( numero decimal) , em dois registradores separados( que juntos formam um hexadecimal de 16 bits)  .
Então :

3036 ( decimal)  = BDC (hexadecimal )

TMR1H = 0X0B 
TMR1L = 0XDC 

transformando novamente em decimal ,
TMR1H = 11 ( decimal)   
TMR1L =   220 (decimal)

Poderiamos escrever os valores diretamente em hexadecimal no compilador, mas acredito que assim fica mais fácil de fixar estas informações. Bastaria observar a sintaxe 0X00 ...
Ficou meio extenso , mas servirá para aqueles que estão iniciando também.

 
« Última modificação: 27 de Setembro de 2010, 02:09 por Beto_s »

Offline pedrorose

  • Novato
  • *
  • Posts: 4
  • Sexo: Masculino
  • GUIA-CNC
Re: Usando Timer do PIC
« Resposta #28 Online: 27 de Setembro de 2010, 18:34 »
certo, mas e os TMR1H = 23;  TMR1L = 184;? que são valores diferentes dos anteriores

Offline Beto_s

  • Hobby
  • ****
  • Posts: 284
  • Sexo: Masculino
  • Cidade - UF: S.José dos Pinhais-PR
  • Nome:: Alberto
  • Profissão: Téc. em Eletrônica
Re: Usando Timer do PIC
« Resposta #29 Online: 28 de Setembro de 2010, 00:46 »
Falha minha, bem observado.
Aproveitei uma rotina que já tinha pra outra função, outro cristal etc...
Esse valores sao carregados na inicialização do PIC , seria o config  numa rotina ASM .
Vão servir apenas até ocorrer a primeira interrupção .
A partir da primeira interrupção os valores carregados são 11(dec) e 220 (dec) , dentro da propria interrupçao . 
No seu caso poderia alterar para os valores acima já na inicialização e a partir do momento que a interrupçao é habilitada , ela passa a ocorrer de 0,5s em 0,5s .

 

 

/** * */