Como obtenho um horário exato?

16

Eu fiz um relógio usando um Arduino, mas o tempo parece estar à deriva. Estou ciente do problema de sobreposição ; o relógio parece flutuar cerca de 15 minutos ao longo de uma semana.

Estou usando um PCB personalizado com este ressonador da Digi-key. O código lê a função millis () no início de cada loop e funciona a partir desse valor.

Minha pergunta é: Como posso medir o tempo com um Arduino, com precisão suficiente para criar um relógio de mesa aceitável?

John Walthour
fonte
3
A função de milissegundo é fornecida com dados de uma interrupção, que leva alguns ciclos de clock para ser executada. Isso adiciona uma quantidade minúscula de tempo a cada marca.
TheDoctor 12/02
3
@ TheDoctor: Isso está incorreto. A interrupção não diminui o tempo do hardware que é acionado millis().
Edgar Bonet

Respostas:

15

Nota: embora minha resposta tenha sido aceita e tenha uma pontuação mais alta de votos, leia a excelente resposta de Edgar Bonet sobre como fazer seu Arduino manter o tempo sem um RTC.

Fui bastante bem-sucedido ao usar o DS1307 Real Time Clock. Aqui está um link para sua folha de dados .

Abaixo estão alguns dos seus recursos:

  • Ele usa a interface IC para comunicação com o Arduino, facilitando a programação usando as bibliotecas corretas (disponíveis na rede).

  • É conectado ao Arduino através dos pinos SCL e SDA (analógico A4 e A5, respectivamente), usando apenas 2 pinos.

  • Requer muito pouco componente externo para ser executado.

  • A TI pode ser conectada a uma bateria de célula tipo moeda para manter o tempo mesmo enquanto o Arduino estiver desligado. No modo de baixa energia, a bateria de célula tipo moeda dura anos.

  • Ele deriva muito pouco (no meu caso, ele deriva apenas alguns segundos por semana).

  • Não é muito caro.

Se você não pretende usar um RTC, pode substituir o cristal que é comumente usado para fornecer clock ao arduino para um módulo de oscilador de cristal como este da Farnel ou outro . Eles vêm em pacotes de 4 pinos, como nas imagens abaixo. Eles irão gerar um relógio muito mais preciso para o seu arduino.

Imagem do oscilador de cristal Imagem do oscilador de cristal Imagem do oscilador de cristal

Ambos os módulos mencionados têm tolerâncias de 50 ppm e operam a 5V.

Novamente, só para esclarecer, esses módulos do oscilador de cristal não devem ser confundidos com o cristal de 2 pinos comum como este abaixo. Isso faz parte do circuito de relógios externos para MCUs, por exemplo.

Oscilador de cristal

Ricardo
fonte
O DS1302 é bom o suficiente ou devo mudar para o DS1307?
Kelly S. Francês
14

Você não precisa de um RTC para construir um relógio: o chip ATmega possui todo o hardware necessário para desempenhar as funções do próprio RTC. Aqui está como:

  1. Obtenha um cristal de relógio de 32768 Hz: compre-o ou desmonte um relógio antigo. Esses cristais, projetados especificamente para manter o tempo, apresentam uma variação de temperatura extremamente pequena. Você também precisaria de um desses se quisesse usar um chip RTC.

  2. Configure os fusíveis do seu ATmega para executar o oscilador RC de 8 MHz. Isso tornará sua millis()função terrivelmente imprecisa e também libertará os pinos XTAL1 e XTAL2.

  3. Conecte o cristal do relógio aos pinos TOSC1 e TOSC2. Esses são os mesmos pinos que XTAL1 e XTAL2 (9 e 10 no 328P). Os nomes diferentes são usados ​​para significar funções diferentes.

  4. Configure o Timer / Contador 2 para operação assíncrona, modo de contagem normal, pré-calibrador definido como 128 e ative a interrupção de estouro do timer.

Agora você receberá uma interrupção TIMER2_OVF a uma taxa muito constante de uma vez por segundo. Você só precisa avançar a exibição do relógio em um segundo no ISR. Entre as interrupções, você pode colocar o MCU em sono muito profundo (modo de economia de energia: nada funciona além do Timer / Contador 2) e pode ser executado por anos em algumas células AA. A menos que a tela tenha muita energia, obviamente.

Fiz exatamente isso para construir meu relógio de parede de 24 horas com uma mão . Este link aponta agora para a tradução em inglês da documentação original em francês.

Calibração de quartzo

Se você não calibrar seu quartzo, poderá esperar um desvio significativo, geralmente alguns segundos por semana . A taxa de desvio depende da capacitância dispersa dos traços que conectam o cristal à MCU. Em princípio, poderia ser removido adicionando alguma capacitância extra e afinada. Vale a pena notar que você teria o mesmo problema de desvio com um RTC.

Se você estiver satisfeito com esse tipo de precisão, viva com ele e seja feliz. No entanto, se você deseja medir a deriva, notará que é muito estável. Você pode compensar isso facilmente em software e obter uma precisão de alguns segundos por ano .

O algoritmo para corrigir a deriva é muito simples. A partir da deriva medida, você descobre o atraso preciso entre as interrupções, que deve estar muito próximo de 10 9  nanossegundos, depois:

#define ONE_SECOND    1000000000  // in nanoseconds
#define ONE_INTERRUPT  999993482  // for example

ISR(TIMER2_OVF_vect)
{
    static uint32_t unaccounted_time;

    unaccounted_time += ONE_INTERRUPT;
    while (unaccounted_time >= ONE_SECOND) {
        advance_display_by_one_second();
        unaccounted_time -= ONE_SECOND;
    }
}

No exemplo acima, o quartzo é um pouco rápido demais e o software compensa "faltando" um tiquetaque a cada poucos dias. Se o quartzo fosse muito lento, o mesmo código ocorreria duas vezes a cada poucos dias.

Esse tipo de calibração também poderia ser feito para um RTC, mas seria significativamente mais complexo, porque o RTC relata o tempo em uma forma discriminada que não se presta naturalmente a operações aritméticas.

Edgar Bonet
fonte
Uau, esse é um design realmente liso! Eu realmente gosto de como você colocou fotos suficientes para deixar o design claro, mesmo para nós, bobo-americanos monoglotes :) Eu realmente amo ver documentação explícita do projeto como essa!
precisa
2
@ JohnWalthour: Obrigado! Agora você está me incentivando a escrever uma tradução. :-)
Edgar Bonet
2
@JohnWalthour: Feito! O link agora aponta para a tradução em inglês.
Edgar Bonet
Só para esclarecer, quando você diz: "O chip ATmega possui todo o hardware necessário", isso não é totalmente verdade quando você precisa obter um novo cristal. Eu acho que sua solução é lisa e não estou acima de substituir o cristal, mas fiquei um pouco confusa quando você diz que não preciso de hardware e depois se vira e diz que precisa substituir um pedaço de hardware.
555777
@ KellyS.French: Minha frase foi “o chip ATmega possui todo o hardware necessário para desempenhar as funções do próprio RTC ” (ênfase adicionada). Mas é importante notar que a maioria dos RTCs, incluindo o onipresente DS1307, precisa de um cristal externo para operar. O ATmega não é diferente: ele tem tudo o que é necessário para substituir o próprio RTC , mas não para substituir o cristal que você precisaria conectar ao RTC de qualquer maneira. Observe que um módulo RTC é mais do que apenas um RTC, pois inclui o cristal.
Edgar Bonet
6

O ressonador que você especificou possui uma estabilidade de 0,3%, onde o cristal ou o oscilador de cristal (conforme mencionado por Ricardo) é de 50 ppm. Muitas vezes mais estável. Sem mencionar que a variação de temperatura do ressonador é horrível. O aquecimento pela luz solar mudará. Portanto, um ressonador não deve ser usado para manter o tempo por longos períodos.

Portanto, o uso de um oscilador de cristal ou de cristal obterá o que você deseja. Ou usando-o no ATmega e defina os fusíveis respectivamente ou nos conectados a um RTC.

mpflaga
fonte
Onde 50ppm é 0,005% de estabilidade?
Matthew G.
Eu generalizo essa especificação, para manter a resposta breve. Observe a estabilidade de lado Res. tem uma tolerância muito maior e pode ser bastante prejudicial. Como John W está experimentando. "a parte direita para o trabalho direito"
mpflaga
Ah, eu estava curioso sobre a terminologia @mpflaga ... nova para mim.
Matthew G.
4

Se você não quiser usar hardware extra como um relógio em tempo real (por exemplo, DSDS1307), poderá melhorar significativamente a precisão do tempo desativando todas as interrupções não utilizadas. Por padrão, os esboços do Arduino vêm com várias rotinas de interrupção ativadas e geralmente não são usadas para o seu esboço. A maneira mais rápida de descobrir se você pode fazer sem tentar desativá-los, emitindonoInterrupts();

jippie
fonte
3
-1 (embora isso mereça -4) porque: 1. A menos que você realmente precise delas, todas as interrupções são desativadas por padrão, com a única exceção de TIMER0_OVF, necessária para manter o tempo. 2. A precisão do tempo do Arduinos é limitada principalmente pela qualidade do ressonador. 3. As interrupções não afetam a precisão, a millis()menos que você consiga gastar mais de um milissegundo por vez, atendendo-as; nesse caso, você tem outros problemas ... 4. Desabilitar interrupções com noInterrupts()impedirá a millis()manutenção do tempo!
Edgar Bonet
2

Entendo que muito do espírito do Arduino está sendo frugal e, ocasionalmente, se arrastando por um problema. Eu uso o Arduino (e agora o chipKIT, já que possui 10 vezes a RAM e 10 vezes a velocidade do relógio) no meu local de trabalho e preciso que as "funções periféricas" sejam atualizadas e funcionem o mais rápido possível.

Eu uso o relógio em tempo real em um dos meus projetos e estou muito feliz com ele. Eles também têm uma variante "Dead on" .

Chris K
fonte