collapse

* Posts Recentes

Amplificador - Rockboard HA 1 In-Ear por almamater
[Ontem às 19:13]


O que é isto ? por KammutierSpule
[26 de Março de 2024, 19:35]


Bateria - Portátil por almamater
[25 de Março de 2024, 22:14]


Emulador NES em ESP32 por dropes
[13 de Março de 2024, 21:19]


Escolher Osciloscópio por jm_araujo
[06 de Fevereiro de 2024, 23:07]


TP4056 - Dúvida por dropes
[31 de Janeiro de 2024, 14:13]


Leitura de dados por Porta Serie por jm_araujo
[22 de Janeiro de 2024, 14:00]


Distancia Cabo por jm_araujo
[08 de Janeiro de 2024, 16:30]


Meu novo robô por josecarlos
[06 de Janeiro de 2024, 16:46]


Laser Engraver - Alguém tem? por almamater
[16 de Dezembro de 2023, 14:23]

Autor Tópico: Real Time Clock DS1307 (RTC) + Arduino  (Lida 167248 vezes)

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

Offline tr3s

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 811
  • char x=1, y=5; x^=y^=x^=y;
Real Time Clock DS1307 (RTC) + Arduino
« em: 13 de Março de 2009, 01:06 »
  Hello hello rapaziada :D!

  Pois é, estou de volta com mais um tutorial onde vos vou explicar como usar ou fazer interagir um RTC, mais propriamente o DS1307 da Maxim-Dallas com o Arduino! Agora já podem adicionar um relógio e dar horas no vosso projecto!


  Antes de mais o que é um RTC ou Real Time Clock? Um RTC é um dispositivo que dá horas, é verdade, conta o tempo! Todos nós os temos em casa, quer seja nos relógios digitais, na motherboard dos nossos computadores, nos telemoveis, etc..
  O RTC que vou introduzir hoje é, como já disse, o DS1307. Este RTC comunica por i2c e tem bastantes características interessantes:

  • Interface i2c;
  • Conta segundos, minutos, horas, dias de semana, dias do mes, mes, ano e considera anos bissextos;
  • Tem uma RAM de 56 bytes com capacidade para escritas infinitas;
  • Gera sinais quadrados programaveis;
  • Comuta automaticamente para a bateria se detectar falha de energia;
  • Consome menos de 500 nA (nano Amperes).

  A questão da alimentação da bateria é interessante, de certeza que todos sabem que nas motherboards dos nossos computadores temos la uma pilha, e "ah pois é" essa pilha é a que alimenta o RTC do nosso computador! Este integrado pode ser alimentado por uma fonte de energia normal como qualquer outro  integrado mas pode ainda estar a ser alimentado por uma bateria, normalmente uma pilha de 3V como as que os nossos computadores têm na motherboard (CR2032 por exemplo)! Este integrado se detectar que a fonte de alimentação não está presente comuta automaticamente para a bateria e passa a funcionar com a energia da bateria. Com uma destas pilhas totalmente carregada, o integrado matém-se a contar o tempo durante pelo menos 9 anos, "cool" não é? Ah, mas atenção, a bateria é obrigatória!

  O funcionamento do RTC, muito sucitamente, é o seguinte:

  • Ligar;
  • Alimentar com bateria;
  • Definir data de arranque;
  • Iniciar;
  • Ler data!

  Eehe até parece simples... E é! Claro que se começarmos a ler o Datasheet do DS1307 até nos assustamos com tanta informação e realmente interpretar aquilo é chato e massador! Por um lado é bom pois qualquer dúvida ou informação que queiramos saber está lá explicada, por outro lado é chato pois podiam fazer um guia mais simples do funcionamento do integrado em vez de colocarem a informação toda no mesmo documento.

  Entrando em mais promenores mas sem aprofundar muito (Ai não, queriam a papinha toda não era?! Seus malandros) como este dispositivo tem interface I²C não nos podemos esquecer das resistências de Pull-Up do canal! Se ainda não tiverem nenhum dispositivo i²c na vossa breadboard tem de colocar duas resistências na vossa montagem, caso contrário já têm as resistências colocadas (se não nem sei como funciona o vosso dispositivo) e então é so encaixarem lá o vosso novo integrado, o RTC!
  Para o cristal... pois é, é aqui que a "porca torce o rabo", o cristal que se usa com este RTC e com todos os outros RTC's (sim na motherboard está lá um mas nem pensem em tirá-lo para o bem da vossa "mobo"!) é um cristal com a frequência de 32.768KHz. É dificil de encontrar à venda nas lojas, pelo menos aqui em Lisboa, mas online encontra-se bastante facilmente e em casa também.... "O QUÊ EM CASA?" Ah pois é "bébés" em encontrei o meu num brinde do chinês, daqueles que fazem o que é suposto, não funcionar, mas que supostamente davam horas! Sim abri aquilo e tirei de lá o belo cristal de 32.768KHz ehehe mas também o podem encontrar em relógios digitais, alarmes etc., la dentro há sempre um destes cristais!


  Assim, com a introdução feita, vamos ver como são as ligações:


  Mais uma vez, A bateria é obrigatória e portanto o RTC não funciona sem a ter ligada! Eu aproveito o pino de 3V do Arduino!

  Em anexo deixo um código que vai enviar a data "actual"  por Serial, o código está bastante comentado e se seguirem os comentário fica fácil de entender. Vai também um ficheiro "ds1307.pde" com as rotinas que fiz para comunicar com o RTC. Basiei-me em código que vi em sites da internet mas que alterei de forma a respeitar o Datasheet do DS1307 e que também optimizei. Creio que é bastante fácil de entender e se tiverem dúvidas do porquê "disto e daquilo", se não estiver em comentário deixo-vos o desafio de irem consultar o datasheet :D!

  Tenham atenção à função "ds1307setup();", esta função só é necessária na primeira vez que ligam o RTC, se o alimentarem com uma pilha de 3v ou bateria nunca mais precisam desta função! Isto porque a função o que faz é preparar o RTC, definir a data de arranque e mandar o RTC contar o tempo, uma vez que ele nunca mais vai perder energia (pois tem uma bateria ligada) nunca vai parar de contar. Se por acaso lhe tirarem a alimentação, precisam de executar a função da próxima vez que o ligarem.

  Agora para o fim digo-vos que a Sparkfun vende um KIT com este RTC já com as resistências de i2c, com o cristal e pilha de 3V, tudo bonitinho sendo so preciso ligar dois fios de alimentação e os dois fios para comunicar:
  É claro que comprar isto, além de ser caro, não mete piada nenhuma porque já vem tudo feito! Mas para quem não gosta de se divertir a ligar coisas e tem dinheiro para gastar...

  Eu mandeir vir samples deste RTC do site da Maxim e aqui está o link de Samples de DS1307. Mandem vir o DS1307+, este é PDIP 8, ou seja tem 8 pinos e dá para encaixar na breadboard. O '+' significa que é RoHS Lead Free e daí dar para vir para a Europa (Se não for RoHs não podem enviar para cá, regras da U.E. e acho bem)!

 Bom... código em anexo leiam com atenção e ainda se podem rir :D

Exemplo de output do programa:
Citar
   Sao:    23:15:15   Quinta-feira dia 12 de Marco de 2009
   Sao:    23:15:16   Quinta-feira dia 12 de Marco de 2009
   Sao:    23:15:17   Quinta-feira dia 12 de Marco de 2009
Cumprimentos! ;)

Contribuição do metRo_ RTC + PCD8544
« Última modificação: 23 de Novembro de 2009, 12:09 por tr3s »
Tr3s
Daniel Gonçalves

Offline ricardo-reis

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 1.338
Re:Real Time Clock DS1307 (RTC) + Arduino
« Responder #1 em: 13 de Março de 2009, 01:20 »
muito bom.. já vem a caminho.. :P

Offline metRo_

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 3.753
Re:Real Time Clock DS1307 (RTC) + Arduino
« Responder #2 em: 13 de Março de 2009, 08:12 »
Muito obrigado :)

Eu já tenho um RTC há muito tempo em casa mas não consegui arranjar o cristal :S No entanto é um DS1337+ mas espero que o funcionamento seja identico :)

Offline Fifas

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 2.064
  • El RoboSapiens
Re:Real Time Clock DS1307 (RTC) + Arduino
« Responder #3 em: 13 de Março de 2009, 12:27 »
nice :D

tr3s mais uma vez em grande! (tens de justificar o que ganhas ;D)

Offline amando96

  • Mini Robot
  • *
  • Mensagens: 1.631
  • MAC address? But I have windows...
    • Projects, News, Blog, Tutorials
Re:Real Time Clock DS1307 (RTC) + Arduino
« Responder #4 em: 13 de Março de 2009, 20:37 »
hmmm está engraçado! mas gastar dois pinos analógicos perde a graça  :-\

;D

Offline TigPT

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 5.372
    • Tiago Rodrigues
Re:Real Time Clock DS1307 (RTC) + Arduino
« Responder #5 em: 14 de Março de 2009, 01:30 »
Perde a graça gastar dois pins analógicos, mas ganha a graça quando metes 20 ou 30 dispositivos nesses 2 pins e não gastas mais nenhuns :P


Excelente tutorial tr3s, continua o bom trabalho para receberes a bonificação ;D

Offline metRo_

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 3.753
Re:Real Time Clock DS1307 (RTC) + Arduino
« Responder #6 em: 17 de Março de 2009, 13:50 »
Olá, estava a tentar perceber o teu código mas cheguei a esta parte e não percebi umas coisas.

 1- O que me está a confundir é o facto de teres o mesmo nome em duas funcções :S embora tenha chegado à conclusão que ela vai escolher a função em função dos parâmetros!

Aqui, quando fazes isto
Código: [Seleccione]
for(byte i=0;i<7;i++)rtc[i]=ds1307get(i, 0); o
Código: [Seleccione]
ds1307get(i, 0) suponho que vai fazer isto
Código: [Seleccione]
int ds1307get(byte c, boolean refresh) por causa do i ser to tipo byte.

2-Mas depois começas
Código: [Seleccione]
  switch(c){
  case DS1307_SEG:
    v=(10*((rtc_bcd[DS1307_SEG] & DS1307_HI_SEG)>>4))+(rtc_bcd[DS1307_SEG] & DS1307_LO_BCD);
break;
  case DS1307_MIN:
e não percebo como é que quando fazes switch(c) ele vai escolher um dos case porque de onde é que vem por exemplo
Código: [Seleccione]
DS1307_SEG?? A ideia que tenho é que fazes switch(n) e ele escolhe o case com aquele numero!

3-Podias explicar melhor isto:
Código: [Seleccione]
10*((rtc_bcd[DS1307_SEG] & DS1307_HI_SEG)>>4))+(rtc_bcd[DS1307_SEG] & DS1307_LO_BCD)?? Suponho que seja para transformar o numero BCD em decimal! Mas se puderes explicar o que isto realmente faz era bom.

Obrigado!


Código: [Seleccione]
void ds1307get(int *rtc, boolean refresh){       // Adquire os dados do array rtc_bcd e converte-os para int, se pretendido, actualiza o array.
  if(refresh) ds1307read();
  for(byte i=0;i<7;i++)rtc[i]=ds1307get(i, 0);   // Percorre cada elemento do array e actualiza-o
}

int ds1307get(byte c, boolean refresh){  // Adquire cada elemento da data, retorna esse valor como int e actualiza o array se pedido
  if(refresh) ds1307read();
  int v=-1;                              // Se der "fezes" tem de retornar um valor absurdo...
  switch(c){
  case DS1307_SEG:
    v=(10*((rtc_bcd[DS1307_SEG] & DS1307_HI_SEG)>>4))+(rtc_bcd[DS1307_SEG] & DS1307_LO_BCD);
break;
  case DS1307_MIN:
    v=(10*((rtc_bcd[DS1307_MIN] & DS1307_HI_MIN)>>4))+(rtc_bcd[DS1307_MIN] & DS1307_LO_BCD);
break;
  case DS1307_HR:
    v=(10*((rtc_bcd[DS1307_HR] & DS1307_HI_HR)>>4))+(rtc_bcd[DS1307_HR] & DS1307_LO_BCD);
break;
  case DS1307_DdS:
    v=rtc_bcd[DS1307_DdS] & DS1307_LO_DdS;
break;
  case DS1307_DMES:
    v=(10*((rtc_bcd[DS1307_DMES] & DS1307_HI_DMES)>>4))+(rtc_bcd[DS1307_DMES] & DS1307_LO_BCD);
break;
  case DS1307_MTH:
    v=(10*((rtc_bcd[DS1307_MTH] & DS1307_HI_MES)>>4))+(rtc_bcd[DS1307_MTH] & DS1307_LO_BCD);
break;
  case DS1307_ANO:
    v=(10*((rtc_bcd[DS1307_ANO] &  DS1307_HI_ANO)>>4))+(rtc_bcd[DS1307_ANO] & DS1307_LO_BCD)+DS1307_BASE_ANO;
break;
  }
  return v;
}

Offline tr3s

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 811
  • char x=1, y=5; x^=y^=x^=y;
Re:Real Time Clock DS1307 (RTC) + Arduino
« Responder #7 em: 17 de Março de 2009, 16:29 »
Ok, vamos então responder a essas questões:

1)
Sim, tens razão. Embora as funções tenham o mesmo nome, têm parâmetros diferentes e por isso são consideradas duas funções diferentes pelo compilador. Dependendo dos parâmetros que passas é uma função ou outra que é chamada. Repara que uma recebe um valor de 8 bits (byte) no primeiro parâmetro e outra recebe um pointer para uma zona de memória.

2) Esses valores,  "DS1307_SEG" por exemplo, estão definidos no inicio do ficheiro com o comando "#define" (explicação do comando #define) onde lhes é atribuido um valor numérico, um significado. Assim quando o compilador encontra aquelas palavras substitui-as pelo valor/sginificado que lhes foi atribuído. Eu faço-o para ser mais fácil entender o que faz cada caso, consegue-se entender onde são tratados os segundos, minutos, horas, etc..

3) Quando se pede informação ao RTC, ele retorna-a num formato um bocado esquisito. O que se faz nesse código é filtrar toda a informação não desejada, garantindo que só fica lá o que pretendemos e de seguida movemos tudo para a posição onde é suposto estar. Estes dois passos tratam a parte alta do valor, isto é, os primeiros bits (a contar da esquerda) que constituem o valor. Multiplica-se por 10 para obtermos o algarismo das dezenas. Repetem-se os dois primeiros passos para tratar a parte baixa do valor, claro que se utiliza uma máscara diferente. Agora como vamos tratar do algarismo das unidades não multiplicamos por 10 e basta somar este às dezenas para obtermos o valor final!
Fica um link onde se explica o que é a representação BCD.

Sei que para ti não era necessário uma explicação tão extensa, mas pode haver alguém que tenha as mesmas dúvidas e que não tenha o mesmo background. ;)
« Última modificação: 17 de Março de 2009, 16:32 por tr3s »
Tr3s
Daniel Gonçalves

Offline metRo_

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 3.753
Re:Real Time Clock DS1307 (RTC) + Arduino
« Responder #8 em: 17 de Março de 2009, 18:10 »
2) Estava a olhar para o case e à espera que estivesse lá o valor e não uma variável com esse valor. duhhh

3) Será que consegues colocar um exemplo vindo do rtc em bcd?



Offline tr3s

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 811
  • char x=1, y=5; x^=y^=x^=y;
Re:Real Time Clock DS1307 (RTC) + Arduino
« Responder #9 em: 17 de Março de 2009, 18:30 »
Agora não consigo porque estou no trabalho, mas se tiveres aí tudo à mão é simples: vais ao código do case do switch e mostras a posição do array para a consola com Serial.println(rtc_bcd[posiçao_que_escolhes], BIN);

Algo assim:
Código: [Seleccione]
...
 switch(c){
  case DS1307_SEG:
    v=(10*((rtc_bcd[DS1307_SEG] & DS1307_HI_SEG)>>4))+(rtc_bcd[DS1307_SEG] & DS1307_LO_BCD);
    // inseres a linha que se segue
    Serial.println(rtc_bcd[DS1307_SEG], BIN); // Esta linha, Atencao esta linha :D
    // inseres a linha de cima, a que passou :P
    break;
  case DS1307_MIN:
    v=(10*((rtc_bcd[DS1307_MIN] & DS1307_HI_MIN)>>4))+(rtc_bcd[DS1307_MIN] & DS1307_LO_BCD);
break;
...
« Última modificação: 17 de Março de 2009, 18:47 por tr3s »
Tr3s
Daniel Gonçalves

Offline metRo_

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 3.753
Re:Real Time Clock DS1307 (RTC) + Arduino
« Responder #10 em: 17 de Março de 2009, 19:33 »
Falta-me o maldito do cristal...  :P

Offline ricardo-reis

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 1.338
Re:Real Time Clock DS1307 (RTC) + Arduino
« Responder #11 em: 17 de Março de 2009, 19:34 »
motherboards antigas, n há aí por casa?

Offline metRo_

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 3.753
Re:Real Time Clock DS1307 (RTC) + Arduino
« Responder #12 em: 17 de Março de 2009, 19:55 »
Não mas tenho que ir aqui ao lado ao meu primo que ele tem para lá uma...

Offline amando96

  • Mini Robot
  • *
  • Mensagens: 1.631
  • MAC address? But I have windows...
    • Projects, News, Blog, Tutorials
Re:Real Time Clock DS1307 (RTC) + Arduino
« Responder #13 em: 17 de Março de 2009, 21:26 »
motherboards antigas, n há aí por casa?
feira da ladra :)

Offline ricardo-reis

  • Administrator
  • Mini Robot
  • *****
  • Mensagens: 1.338
Re:Real Time Clock DS1307 (RTC) + Arduino
« Responder #14 em: 17 de Março de 2009, 23:44 »
Não mas tenho que ir aqui ao lado ao meu primo que ele tem para lá uma...

então tens aí uma solução.. e n te deixes enganar.. elas têm dois cristais.. :P