Ir ao conteúdo
  • Cadastre-se
CIS

Precisão do timer 1

Recommended Posts

Fiz um temporizador com o PIC12F675, que era para ficar ligado durante sete dias seguidos e depois desligar, fiz isso usando o laço de repetição "do while", e usando o temporizador timer 1, com o oscilador interno do pic, porém não obtive precisão do tempo, pois o temporizador desligou com 5 dias... Agora as duvidas. Qual seria a precisão de contagem do oscilador interno ? Será que ao usar um oscilador externo, esse problema sera resolvido? Qual a melhor maneira de obter o maximo de precisão?

Valeu!!!

Compartilhar este post


Link para o post
Compartilhar em outros sites

voce tem 2 opções,ou programa em ASM ou analisa o códgio ASM gerado pelo compilador para calcular com exatidão toda a temporização.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Em C não é possível obter uma exatidão ? Eu fiz uns teste em protoboard aqui com cristal de 8 MHz e 4 MHz, mas todos os dois ainda tenho um perca de contagem, que com o passar do tempo vai aumentando. Vou seguir as dicas e tentar iniciar com assembly, mas não entendo nada. Obrigado pela dica. Valeu!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Cis,

Calma.... problema bem simples de resolver.

Abandone o laço DO WHILE, faça por Hardware, já existente nos Pic's !!!!

Primeiro e mais importante : use um oscilador a cristal para gerar o clock, ou até mesmo pode usar o clock interno, mas utilize um cristal de relógio de 32 Khz para o Timer do PIC.

Programe o Timer1 para utilizar um cristal de relógio de 32.768 Hz, incremente um contador a cada interrupção do timer, e pronto, voce terá uma base de tempo digitalmente correta.

Claro, isto se voce puder abrir mão de dois pinos de I/O.... senão só usando o clock interno, que não tem precisão nem estabilidade para isso.

Se voce só puder abrir mão de 1 pino de I/O, terá de usar um oscilador a cristal externo, e aplicar o clock diretamente no pino do PIC.

Só vai depender da precisão e estabilidade de temperatura do cristal oscilador, que normalmente permite um erro máximo de uns 15 segundos por dia.

voce pode comprar também um cristal oscilador super-preciso, mas vai custar bem caro.

Enquanto voce utilizar o oscilador RC interno, esquece qualquer precisão, pois ele varia bastante com a temperatura, além de não haver nenhuma garantia da frequência exata pelo fabricante.

Não entendo nadinha de C, mas aqui temos membros "feras", com certeza algum pode te passar essa programação do Timer1 e a rotina de interrupção para base de tempo de 1 segundo.

Alguém se habilita ?

Paulo

Compartilhar este post


Link para o post
Compartilhar em outros sites

Não entendi muita coisa, mas vou ler novamente e pesquisar sobre as dicas... talvez seja realmente a hora e aprender um pouco mais sobre linguagem assembly.

valeu pela ajuda, vou aguardar mais algum conselho.

Compartilhar este post


Link para o post
Compartilhar em outros sites
Em C não é possível obter uma exatidão ?

No seu caso sem analisar o código gerado em ASM não,pois voce tem que saber quanto tempo leva cada instrução de máquina e calcular o total pois o Timer pode até ser exato mas quanto tempo(microssegundos)vai durar as outras tarefas que seu programa provavelmente vai usar?

C não é linguagem Real Time,voce precisaria implementar um RTOS.

Sei que o MulderFox postou uma resposta para um problema parecido com o seu,em ASM,num post aqui onde um código ASM gerava essa temporização sem erros.

Compartilhar este post


Link para o post
Compartilhar em outros sites
Não entendi muita coisa.

Cis,

voce tem dois caminhos : estudar o ASM , ou estudar melhor o hardware de um Pic !

Conhecendo como funciona um Timer, você faz um programinha de menos de 15 linhas em C e resolve o seu problema da maneira mais simples e rápida.

Se escolher o caminho do ASM, vai ter de ficar calculando ciclos de máquina por instrução, e vai continuar sem aprender o mais importante, que é saber utillizar todos os periféricos embutidos em um PIC. E, me desculpe pela sinceridade, vai continuar não entendendo quase nada sobre um microcontrolador, vai virar uma calculadora burra de somar ciclo de máquina... E o pior, vai sempre levar muito mais tempo para conseguir um resultado que pode ser conseguido muitas vezes em menos de um décimo do tempo que levaria se utilizasse uma linguagem de alto nível.

Deixe o ASM para quem realmente precisa do ASM, seja prático !

Minha opinião é que voce deve estudar o hardware melhor, ver como funciona um Timer de um PIC, e implementar em C mesmo. Vai te abrir um novo horizonte em seus projetos.

Fiz um temporizador com o PIC12F675, que era para ficar ligado durante sete dias seguidos

Só para definir isto de vez....

NAO EXISTE PRECISÃO USANDO CLOCK INTERNO para um período tão grande de tempo, seja em ASM ou em qualquer linguagem!

Paulo

Compartilhar este post


Link para o post
Compartilhar em outros sites

Paulo,existem varios exemplos aqui e na net onde se consegue precisão suficiente para 'relógios' usando ASM,uma boa prática é montar o circuito proposto e usar o código aqui mostrado e ver na prática.

Boa prática tambem é entender o que é ciclo de máquina e saber que um circuito digital segue uma temporização específica que se tiver um cristal como referencia não haverá erros e que matemática é uma ciencia EXATA.

MulderFox provavelmente vai achar o tópico que ele solucionou.

NAO EXISTE PRECISÃO USANDO CLOCK INTERNO para um período tão grande de tempo, seja em ASM ou em qualquer linguagem!

Eu não me referí a oscilador interno onde voce tem razão.

Se meu erro foi não ter citado isso,realmente é impossível ter precisão exata com oscilador interno.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Não achei o tópico ,mas era relacionado a uma contagem de 1 segundo por X dias que atrasava conforme os dias e o erro era que o programador não tinha alterado o banco de memoria num trecho do código e isso alterava alguns ciclos de máquina código.

De qualquer maneira não aconselho ninguem que queira ser bom no que faz,partir para 'meia-boca'.

Aconselho a sempre estudar o que se pretende a fundo,sem preguiça.

CIS,se possível caso solucione seu problema,volte a postar ok?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Oi, Vtrx, não quis dizer nada sobre se existe algum erro seja de quem for !

Heheheh isto é uma discussão conceitual kkkkk ! O problema do CIS é o maldito oscilador interno !

Se fosse para temporizar um periodo pequeno, até dá para usar o oscilador interno; mas para SETE dias, os erros vão se acumulando e compromete o resultado, a menos que seja em ambiente de temperatura constante. Se fizer isto, independente da linguagem utilizada, através da estatística pode-se ajustar o loop de tempo no software, sem utilizar interrupção do timer, seja em C ou em ASM.

O que eu quis deixar bem claro é o seguinte : se tem um timer no hardware, porque não usar ele ???????????????

Assim não precisa ficar contando ciclo de máquina, que convenhamos , enche o saco !

Concordo que a matemática continua sendo exata, só que o oscilador interno não tem nada de exato !

Agora, se usar um cristal oscilador, vai ter a precisão necessária, e já que o CIS usa o C, basta fazer a interrupção do timer , e pronto, problema resolvido , e eu acredito que ele vai achar isto bem mais fácil do que aprender a programar em ASM.

Estou olhando do lado prático, não quis dizer nada sobre vantagens de linguagens, mas sem conhecer os periféricos do PIC fica difícil fazer um programa um pouco mais sofisticado...

Paulo

Compartilhar este post


Link para o post
Compartilhar em outros sites

Segue um link de uns anos atrás onde eu estava iniciando com os PIC em C. Ajudei um membro sobre esse assunto.

o código esta no post número 20. Ficou grande mas é simples de entender.

Como exercício fiz um relógio todo em C onde o mesmo não apresentou problemas de atraso.

No final do tópico tem o video.

http://forum.clubedohardware.com.br/lcd-pic-relogio/936112?p=5046173#post5046173

Falou

Compartilhar este post


Link para o post
Compartilhar em outros sites

Pessoal, quero agradecer toda a ajuda. Hoje o dia foi meio corrido , e estou aqui na madrugada tentando alguma coisa. Vou continuar lendo e pesquisando, mas por enquanto não obtive sucesso.

Valeu!!

Compartilhar este post


Link para o post
Compartilhar em outros sites

CIS,monte algum circuito com alguma coisa encontrada aqui no forum,deixa por 7 dias e 7 noites(LOL) e poste os resultados,ok?!

Sei que para usar como um relógio de precisão,o cristal tem que ser de 32 768 Hz,isso porque a divisão dos cilcos de máquino do PIC ficarão com a temporização perfeita,e isso é matemátcia LOL.

Mas voltando ao o que o CIS perguntou,em qualquer linguagem e com o clock correto,se ativar a interrupção do Timer e RECARREGÁ-LO corretamente quando estoura,(o que a maioria esqueçe),e as rotinas restante não ultrapassarem o estouro correto do Timer,tudo vai funcionar.

Quando o timer estoura,internamente ele continua incrementando o registro,ciclo a ciclo de máquina e a recarga,se não for planejada,não conta esse tempo e por um período grande,(como 7 dias),vai dar diferença.

Se alguem tiver paciencia e curiosidade sobre este assunto,(usando C para temporização perfeitas),tem tópico no forum da Microchip,C18,que pode ser usado como pesquisa.

É para PIC18 mas a teoria é a mesma para qualquer linguagem de alto nível.

É comum usuários da linguagem C e outras,na linha PIC 18,analisar o código gerado na lsitagem Assembler pois esses pic trabalham com muitas variantes de códigos e pode gerar o mesmo resultado com variaçãoes de tempo diferentes:

Microchip Forum C18/Timers

Compartilhar este post


Link para o post
Compartilhar em outros sites

Matheus, eu vi o tópico sim... ainda que de maneira rápida. Vou montar o relógio para um teste e estudar bastante, e tentar tirar do código o que eu preciso. Obrigado pela dica.

E VTRX, valeu pelo esforço em ajudar. Vou fazer sim alguns testes e retorno os resultados assim que possível. Só não tenho ainda o cristal de 32KHz , mas pretendo comprar alguns logo essa semana, gostaria de saber como usa-lo, se no lugar do oscilador normalmente, ou como sinal de clock em algum outro pino especial ? Vou ir pesquisando e tentando aqui, valeu pela dica do forum da Microchip, com certeza vou tirar proveito dele. Valeu, muito obrigado.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Estou com duvida nos cálculos e na configuração no mikroC Pro para usar o cristal de 32768KHz.

Os cálculos são os mesmos para osciladores de 4 MHz e 8 MHz?

O quanto aos fusíveis no mikroC, devo usar LP mesmo ?

Já quebrei a cabeça um pouco aqui, se alguem puder dar uma ajudinha...

Compartilhar este post


Link para o post
Compartilhar em outros sites

CIS,

Meio atrasado,mas quem sabe ainda ajuda....

Existe uma técnica bem interessante, que é deixar o Timer estourar, sem recarregar o valor do timer! É muito usada quando se usa linguagem de alto nível.

Só precisamos criar uma variável para usar como contador de ciclos de clock, assim usaremos apenas um cristal, que é o que vai gerar o clock do Pic.

Vou supor aqui o caso do Timer0, como 8 bits, e com um divisor de 1024.

A cada vez que se passarem 256 x 1024 ciclos de clock, o timer gera uma interrupção, e voce vai simplesmente incrementar um contador de exatos 256 x 1024 !

Após isso, você compara com a frequência do cristal em Hertz, e se for maior ou igual, significa que já passou um segundo, e neste caso voce vai recomeçar o contador com a sobra da conta (256x1024) - Frequência do cristal.

Quando acontecer isto, voce seta um flag, para que o seu programa principal saiba que já se passou um segundo. E zera o flag. Ou pode fazer a rotina de incrementar segundos, minutos, etc, dentro da própria interrupção, mas eu costumo fazer no programa principal.

Caso o contador seja menor do que a frequência do cristal, você simplesmente sai da interrupção.

Desta maneira, a longo prazo o seu relógio vai estar matemáticamente exato , tão preciso quanto for o seu cristal oscilador.

Pode usar qualquer frequência de cristal, 4Mhz, 20Mhz, qqr um que você quiser, como clock do Pic.

O truque é justamente não interferir no contador, assim não temos o problema de achar o momento exato de recarregar o timer com um numero exato, o que é simplesmente impossivel sem usar o Assembler.

Paulo

Compartilhar este post


Link para o post
Compartilhar em outros sites

aphawk, eu não entendi bem o raciocínio. Ainda estou vendo o relógio do mateus e testando.Muito obrigado pela dica. Estou vendo que preciso estudar muito ainda.

Compartilhar este post


Link para o post
Compartilhar em outros sites

CIS,

É a mesma coisa que contar os ciclos de clock !

Um timer de 8 bits só pode contar de 0 a 255, ou seja , 256 contagens.

E cada timer possui um prescaler, que nada mais é que um divisor da frequência do clock do oscilador.

Usando um precaler de 1024 é a mesma coisa que dizer que a cada 1024 ciclos do clock do oscilador é aplicado 1 pulso ao timer de 8 bits, ou seja, se o seu cristal for de 1.024 Mhz , será aplicado ao timer uma frequência de exatos 1 KHz.

Vamos fazer um exemplo completo para você entender melhor.

Suponha que temos um cristal oscilador de 1.048576 Mhz.

Se programarmos o prescaler para 1024, teremos aplicado ao timer a frequência de exatos 1024 Hz.

Agora, se simplesmente deixarmos o timer trabalhar sem recarregar nenhum valor, ele vai gerar UMA interrupção a cada 256 ciclos do clock aplicado a ele.

então, teremos 1024 / 256 = 4 interrupções por segundo, certo ?

Dentro da rotina de interrupção do timer, fazemos um contador, que a cada vez que ocorre essa interrupção somamos a ele o valor de 262.144 (1024 x 256 ).

E sempre comparamos esse valor ao valor do cristal oscilador, que é 1.048.576 .

Quando o valor da nossa contagem for maior ou igual ao do cristal, significa que já se passou um segundo com certeza, e podemos incrementar o nosso contador de segundos.

E ao mesmo tempo, recarregamos o nosso contador, com os ciclos que tenham ultrapassado a frequência do cristal, que por acaso, devido aos valores que escolhí para o cristal, na quarta vez que ocorre a interrupção a contagem chega a 1.048.576, e a diferença resulta em zero ! Ou seja, o contador vai começar novamente todo o processo a partiz do valor zero.

Caso a nossa contagem seja menor do que o valor do cristal, simplesmente saímos da interrução sem fazer nada !

Repare que isto equivale a contar os ciclos de clock do cristal oscilador !

E como nunca interferimos no valor do timer, ou seja, sempre ele vai contar 256 ciclos antes de gerar uma interrupção, temos um relógio tão preciso quanto for o cristal utilizado no clock.

Se quiser um exemplo de programação, posso postar um código simples que utilizo em Basic do Bascom.

E quanto ao estudo, voce tem mesmo de estudar o funcionamento dos periféricos de um microcontrolador Pic para entender como eles funcionam.

O resto são pequenos truques de programação que a gente vai aprendendo com os outros, e vamos incorporando à nossa biblioteca mental...

Paulo

Compartilhar este post


Link para o post
Compartilhar em outros sites

Valeu Paulo, muito obrigado. Tive uma boa ideia do que fazer. Se puder postar o código, mesmo em basic, eu vou ler e imaginar o que ele faz. Vou seguir com os testes. Estou deixando o timer estourar sem recarrega-lo, consegui um bom resultado com a temporização de um minuto, vendo o acionamento de um led, e cronometrando eu conseguir para o cronometro em 60.09, mas quando coloquei um tempo maior, este .09 se transforma numa diferença muito grande. Fazendo um teste de 24 horas(ainda esta rodando), quero ver quanto será a diferença, eu liguei o circuito ontem as 20:00 horas, o vou observar a que horas ele desligará hoje.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Seguem os trechos de código que interessam :

 

 

'  A seguir, a declaração da frequência do cristal :

Const Xtal = 12500000                      '  This is the CPU clock frequency 12.5 Mhz

$crystal = Xtal

' Agora, a seguir, a configuração do timer0 com prescaler de 1024 :

Config Timer0 = Timer , Prescale = 1024   ' configure the timer

On Ovf0 Tim0_isr                          ' Define ISR handler for clock

Enable Timer0                             '  Enable timer 0 interrupt

Dim Bres As Long                          '  --This is the timer value

Enable Interrupts                         '  enable global Interrupts

' E agora, a seguir, a rotima de interrupção do timer0, repare que a variável Brea é o tal de contador de ciclos de clock que falei no post acima :

Tim0_isr:

Bres = Bres + 262144                      '   262144 = prescaler:1024 * timer0:256

If Bres > Xtal Then                       '  = xtal frequency

Bres = Bres - Xtal

Incr L2                                   ' Increment system seconds

End If

Return

 

Simples e muito funcional, espero que lhe ajude.

Uma coisa muito importante : no seu programa, não suspenda a interrupção do timer em nenhum momento !

Se precisar desabilitar alguma das outras interrupções, faça manualmente uma a uma, em vez de desabilitar TODAS as interrupções, pois é muito importante que nada suspenda a interrupção desse Timer !

Paulo

Compartilhar este post


Link para o post
Compartilhar em outros sites

Pessoal, estou retomando o projeto. Consegui a precisão para o protótipo, depois de muitos teste e alterações quanto a contagem. Mas agora vou precisar de produzir muitas unidades, cerca de 25, no inicio, e ficar testando um por um será demorado. Creio que exista uma maneira de um mesmo código hexadecimal servir para qualquer PIC 12F675, pois nos teste que realizei, precisei fazer uma especie de "personalização" para cada unidade, porque a contagem de um da sempre diferente de outro.

Resumindo tudo isso, preciso de ajudar para desenvolver um código em linguagem C com precisão (margem de erro de 15 segundos) num total de 168 horas, usando o PIC 12F675 com cristal oscilador de 8MHZ.

Segue o código utilizado até o momento.


/* TEMPORIZADOR 7 DIAS LIGADO . TESTES.

PIC12F675 ;
CRISTAL OSCILADOR DE 8MHZ .
MCLR -- HABILITADO
WDT -- DESABILITADO
BROWNOUT -- DESABILITADO
POWER UP TIMER -- DESABILITADO


*/

#define motor GPIO.f0

unsigned int contador = 0; //de 0 a 65.535 variavel de 2 bytes inteira sem sinal
unsigned int minuto = 0;
unsigned int segundo = 0;
unsigned int hora = 0;
unsigned char buzzer = 0;


void main(){
CMCON = 0x07;
ANSEL = 0x00 ;
TRISIO = 0x00;
GPIO = 0x00;

while(hora < 169 ) { // enquanto hora for menor que 169 ; faça :

motor = 1; // liga motor

contador++; // incrementa contador
delay_ms(1000); // aguarda 1 segundo

if(contador == 60 ){ // se contador for igual a 60
minuto++; // incrementa minuto
contador = 0; // zera contador
}
if(minuto == 60){ // se minuto for igual a 60
hora++; // incrementa hora
minuto = 0; // zera minuto
}

} // quando hora for maior ou igual a 169 , sai do laço while e faça :

motor = 0; // desliga motor

for(buzzer=0;buzzer<10;buzzer++){ // aviso sonoro de desligamento do motor.
GPIO.F1 = 1;
delay_ms(500);
GPIO.F1 = 0;
delay_ms(250);
}

}

A todos, muito obrigado, e em especial aos que tiverem paciência em me ensinar !!!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Em quais pinos do PIC12F675 eu ligo o cristal de 327668hz ?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Eai galera, estou com m problema em relação ao timer 1, eu habilitei o modo de 16 bits dele, que a resolução é de 65mil, porém quando a contagem do timer 1 chega nos 32 mil ele passa a ser -32 mil, como faço para reverter este problema?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro 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 publicações 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

×