Relógio "|Perfeito|" - Ajuda

Venho a alguns meses postando coisas sobre o relógio que estou fazendo para um LCD timer que também funciona como base para qualquer outro projeto, o problema era o ajuste do tempo e a implementação de hora pelo próprio arduino, sem uso do pc pra nada depois de programar.

Fiquei insistindo na programação enquanto muitos falaram q era mais fácil pegar um RTC para ajustar o tempo, se eu tivesse dinheiro teria pego mas...
fiquei tentando corrigir o delay(x) e ele se aproximou muito, o melhor q consegui foi em 5 dias deu 8 minutos de atraso. mas isso vira uma bola de neve se for pensar em 1 mes 32min de atraso não é possível.
então pesquisando muito achei a biblioteca MsTimer2.h que desde o início meu professor chegou comentar q deveria ter algum regulador de tempo para os ATMega (ele nao sabia o nome pois so trabalha com PIC) ...
Agora achei a biblioteca que se diz "Estável" e o tempo é calculado corretamente...
No pc fiz em PASCAL o relógio com o delay(x) e ele não atrasou 1s por 3semanas.

Projeto Inicial tem até sensor de temperatura...

Se alguém conseguir explicar-me o código abaixo, não entendo voi flash, e nem !output...

// Toggle LED on pin 13 each second
#include <MsTimer2.h>

void flash() {
static boolean output = HIGH;

digitalWrite(13, output);
output = !output;
}

void setup() {
pinMode(13, OUTPUT);

MsTimer2::set(500, flash); // 500ms period
MsTimer2::start();
}

void loop() {
}

Antes de mais... o problema do relógio nunca (raramente) está no código do relógio, mas em dois componentes importantes. O cristal que usas para o microcontrolador e os condensadores que ligam o cristal ao GND. O problema é que cristais bons de 16 ou 8MHz, são caros e certamente não estão no Arduino. O outro problema é que o valor dos condensadores depende do desenho da placa, do microcontrolador e também da qualidade do cristal que usaste.

Depois entram em jogo as tolerâncias (aquilo que torna os componentes caros) e desvios de tolerância no cristal ou no condensador, ou deriva devido à temperatura, vão afectar a leitura do teu relógio perfeito.

Uma ideia aproveitada em tempos para temporizar circuitos era, uma vez que isto é regulado pelo Governo (em Portugal pelo menos), utilizar a frequência da rede eléctrica para criar uma onda digital que pulsava a 50Hz. Isto não era completamente correcto porque a lei também permite certos desvios na frequência, mas como é medido em média, podia dizer-se que o relógio tanto podia funcionar muito bem num intervalo, como muito mal. Mas normalmente funcionava.

O teu computador tem um cristal muito melhor do que o Arduino... logo o código que fizeste, apesar de bom, não indica que vá funcionar no Arduino, principalmente pelo que referi atrás.

Quanto a soluções... usar um RTC com um oscilador de 32kHz (que podes arranjar numa mother board de computador, ou num relógio Casio) é realmente a melhor solução, não necessitas de usar uma pilha a não ser que queiras manter o tempo sem alimentação à placa.

Se tiveres uma placa com um ATmega1280 ou 2560, podes tentar ver se os pinos TOSC1 e TOSC2 estão disponíveis e ligar lá o cristal de 32kHz. Se não me engano, estes pinos não estão disponíveis no Arduino Mega, mas estão no Seeeduino Mega. Depois tens de alterar o prescaler para 8, definir uma interrupção do programa principal quando o buffer do timer 2 fizer overflow e voilá. Tens o programa a interromper de segundo a segundo. Depois só tens de contar segundos, minutos e horas. Assim é capaz de ser mais barato, se já tiveres uma placa que te permita fazer isto.

Eu percebi que com o Delay(x) ele depende muito do tamanho do código, eu usava sensor de temp, atrasava mais do que sem sensor...
e também achei extremamente extranho isso que falou de não ter solução por software, pois no PC eu fiz com delay(x) em PASCAL e funcionou perfeitamente...

O melhor é utilizar timed interrupts. Com o delay() não vai funcionar e se funcionar é má prática de programacão. O teu computador é mais rápido que o Arduino e tem um relógio muito mais certinho. Não sei como testaste o programa, mas quase de certeza que deixaste o computador ligado e sozinho a correr o relógio.

Agora experimenta correr o programa do relógio, abre um documento no Microsoft Word, outro no Excel e corre um jogo que tome partido do máximo das capacidades do teu computador... vais ver que o relógio vai atrasar.

eu testei com o pc por 1 semana ... sério não atrasou e usei pc normalmente, só não desliguei ele,... o resto fiz, internet, documentos...

#include <LiquidCrystal.h>
#include <MsTimer2.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //essa é a pinagem LCD no MEGA.
int segundo;
int minuto;
int hora;
int cont;
int i;

void contahora() {

segundo=segundo + 1;
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Data:");
lcd.setCursor(6,0);
lcd.print("30/06/2011");
lcd.setCursor(0,1);
lcd.print("Hora:");
lcd.setCursor(8,1);
if (segundo >=60) {
segundo = 0;
minuto = minuto+1;
}
if (minuto >=60){
segundo =0;
minuto=0;
hora = hora+1;
}
if (hora >=24) {
hora = 0;
minuto = 0;
segundo = 0;
}
if ((segundo < 10) & (minuto < 10) & (hora < 10)) {
lcd.print("0");
lcd.print(hora);
lcd.print(":");
lcd.print("0");
lcd.print(minuto);
lcd.print(":");
lcd.print("0");
lcd.print(segundo);
}
if ((segundo >= 10) & (minuto >= 10) & (hora >= 10)){
lcd.print(hora);
lcd.print(":");
lcd.print(minuto);
lcd.print(":");
lcd.print(segundo);
}
if ((segundo >= 10) & (minuto < 10) & (hora < 10))
{
lcd.print("0");
lcd.print(hora);
lcd.print(":");
lcd.print("0");
lcd.print(minuto);
lcd.print(":");
lcd.print(segundo);
}
if ((segundo >= 10) & (minuto < 10) & (hora >= 10)){
lcd.print(hora);
lcd.print(":");
lcd.print("0");
lcd.print(minuto);
lcd.print(":");
lcd.print(segundo);
}
if ((segundo >= 10) & (minuto >= 10) & (hora < 10)) {
lcd.print("0");
lcd.print(hora);
lcd.print(":");
lcd.print(minuto);
lcd.print(":");
lcd.print(segundo);
}
if ((segundo < 10) & (minuto >= 10) & (hora >= 10)){
lcd.print(hora);
lcd.print(":");
lcd.print(minuto);
lcd.print(":");
lcd.print("0");
lcd.print(segundo);
}
if ((segundo < 10) & (minuto >= 10) & (hora < 10)) {
lcd.print("0");
lcd.print(hora);
lcd.print(":");
lcd.print(minuto);
lcd.print(":");
lcd.print("0");
lcd.print(segundo);
}
if ((segundo < 10) & (minuto < 10) & (hora >= 10)) {
lcd.print(hora);
lcd.print(":");
lcd.print("0");
lcd.print(minuto);
lcd.print(":");
lcd.print("0");
lcd.print(segundo);
}
loop();
}

void setup() {

lcd.begin(16, 2);
hora = 22;
minuto = 45;
segundo = 00;
MsTimer2::set(1000, contahora); // 500ms period
MsTimer2::start();
}

void loop(){

}

Funciona? não estou conseguindo testar por erro na librarie e não consigo atualizar a versão do arduino no ubuntu to com a 0018 e ja tem a 0022.

Como eu já disse... o melhor é usar interrupções. Dá mais trabalho, é certo, mas consegues muito melhores resultados. Vai por mim.

me mostra um exemplo...
sérioO!

O MsTimer conta overflows do timer2, se não me engano, é o mesmo que usar interrupções e configurar o timer á mão, a diferença é que a interrupção do milis tem um monte de código lá dentro e algumas variaveis de ajuste.
Pode ver no meu blog como usar um timer para basicamente implementar um millis muito simples mas muito preciso, tão preciso quanto o cristal que usar, e como a interrupção só incrementa uma variavel do tipo long é muito rápida, quando tiver tempo irei trazudir para portugues e colocar no site lusorobótica e tambem no blog:

ok ...muito obrigado estou tentando aqui...
é seu blog?
muito bom

Sim, e tem em portugues aqui, mas em portugues ainda não escrevi o tutorial sobre os timers:

Ainda bem que gosta do meu trabalho :smiley:

Entretanto fui dormir e não vi mais o post.

O blog do Senso tem muito boa informacão lá que podes adaptar também para outros temporizadores como o T1 (com alguns cuidados) e T0.
O principal a reter deste exemplo é como configurar o hardware e perceber a flexibilidade de desenvolvimento e facilidade de troubleshooting quando se sabe exactamente o que o Arduino está a fazer.

// DS1307_LCD (C)2010 Henning Karlsen
// web: Electronics - Henning Karlsen
//
// A quick demo of how to use my DS1307-library to make a quick
// clock using a DS1307 and a 16x2 LCD.
//
// I assume you know how to connect the DS1307 and LCD.
// DS1302: SDA pin -> Arduino Digital 2
// SCL pin -> Arduino Digital 3
// LCD: DB7 -> Arduino Digital 6
// DB6 -> Arduino Digital 7
// DB5 -> Arduino Digital 8
// DB4 -> Arduino Digital 9
// E -> Arduino Digital 10
// RS -> Arduino Digital 11

#include <LiquidCrystal.h>
#include <DS1307.h>

// Init the DS1307
DS1307 rtc(2, 3);

// Init the LCD
LiquidCrystal lcd(11, 10, 9, 8, 7, 6);

void setup()
{
// Set the clock to run-mode
rtc.halt(false);

// Setup LCD to 16x2 characters
lcd.begin(16, 2);

// The following lines can be commented out to use the values already stored in the DS1307
rtc.setDOW(SUNDAY); // Set Day-of-Week to SUNDAY
rtc.setTime(12, 0, 0); // Set the time to 12:00:00 (24hr format)
rtc.setDate(3, 10, 2010); // Set the date to October 3th, 2010

// Set SQW/Out rate to 1Hz, and enable SQW
rtc.setSQWRate(SQW_RATE_1);
rtc.enableSQW(true);
}

void loop()
{
// Display time centered on the upper line
lcd.setCursor(4, 0);
lcd.print(rtc.getTimeStr());

// Display abbreviated Day-of-Week in the lower left corner
lcd.setCursor(0, 1);
lcd.print(rtc.getDOWStr(FORMAT_SHORT));

// Display date in the lower right corner
lcd.setCursor(6, 1);
lcd.print(rtc.getDateStr());

// Wait one second before repeating :slight_smile:
delay (1000);
}

rtc-1.jpg

não tenho dinheiro para comprar o RTC.. ou qualquer coisa to literalmente quebradoO...
por enquantoO!

mas valeu ai pessoal...

Tira um de uma motherboard velha de um computador jogado ai no canto!

Oi pessoal estava lendo a respeito do relógio " perfeito " algumas respostas. Então antes de mais nada me apresentar sou engenheiro eletrônico e processamento de sinais. A maior parte das das respostas são bem coerentes. Mas alguns cuidados devem ser tomados para a temporização precisa.

1: utilização de RTC: solução mais segura, para uma temporização precisa. Normalmente caro e chato: O cristal de 32.768khz deve ser colocado exatamente ao lado como o datasheet sugere, pois normalmente caso contrário não funciona.

2: Sincronismo vai rede elétrica: Uma ótima solução para locais onde a qualidade da energia é ótima, em outras palavras, longe de grandes industrias. O sincronismo via rede elétrica é realizado por meio de uma técnica denomina TVZ ou comutação em passagem por zero. Essa técnica é muito eficiente em caso da qualidade de energia ser muito boa, caso exista um equipamento denominado banco de capacitor industrial essa técnica normalmente falha . Isso acontece pois quando o capacitor é ativado ( normalmente na passagem por zero ) esse gera um surto de corrente que faz com que a tensão da rede retorne a zero novamente. assim fazendo com que dois pulsos sejam contados em vez de um.

Uma sugestão muito simples e barata que dou para utilizar algo semelhante é fazer a contagem dos ciclos da rede, por algo similar a passagem por zero. Mas utilizando um opto acoplador diodo e resistor. O custo não é superior a 5 reais.
Verifique no osciloscópio de seu curso se não fez nada errado. vai sair uma onda quadrada pino ENT1 como no desenho abaixo. Basta contar 60 ciclos que você terá aproximadamente 1 segundo. Vale a pena ressaltar que a rede varia normalmente entre 59.6Hz a 60.4Hz.
Muita atenção para não danificar seu arduino. A montagem é de inteira responsabilidade do usuário. Caso queira verificar o funcionamento do circuito utilize um simulador ( TINA, SPICE, Multsim, proteus )

Abracos a todos ...e não esqueça ...eletrônica é arte ...rsrs...

opto.pdf (62.1 KB)