terça-feira, 14 de fevereiro de 2017

Usando o RTC DS3234 com o ESP8266 pela interface do Arduino.

           Olá, hoje vou demonstrar como comunicar com o RTC DS3234 e o modulo ESP8266(gravado pela IDE arduino) com uma SPI emulada,pois a lib do Arduíno não deu certo com este modulo, tentei de varias formas usar a lib do Arduino e não deu certo, até que em um dos blogs e sites que pesquisei(chegou a afirmar) que os pinos de SPI que vem no moduloESP8266 só servem para gravação do chip(achei isso estranho), mas como não estava dando certo a comunicação e já havia passado horas de tentativa resolvi implementar uma comunicação SPI na "unha", como esse tipo de comunicação é relativamente simples aceitei o desafio de fazê-lo funcionar assim.Uma vantagem disso é que vc fica livre pra escolher os pinos que quiser, podendo inclusive usar esta ideia para microcontroladores que não possui uma SPI. Veja como ficou as conexões entre os dois chips:
           Uma das vantagens de usar este RTC é que não precisa de nenhum hardware adicional, assim como o ESP8266,basicamente  só é necessário esses 2 chips,mas dai ainda coloquei um led para piscar, só mesmo pra saber que o programa está rodando.
           O ESP8266 irá inicialmente setar uma data qualquer no chip e depois ira ler qual a data e a hora que está no chip a cada 2s, imprimindo na porta serial RS232 e usando um conversor usb serial isso chega ao PC.O programa que usei no pc foi este, mas pode ser usado qualquer outro terminal serial inclusive o do Arduíno.

O código fonte:

#include <ESP8266WiFi.h>

const int  LED_STATUS = 5; // led de status 
///emulando uma porta SPI generica - aqui se configura quais pinos se quer usar ////////////////
const int  SPI_CLK = 14; //ligue no sinal de clock
const int  SPI_IN  = 13; //ligue no Mosi 
const int  SPI_OUT = 12; //ligue no Miso
const int  SPI_CS  = 16; //ligue no chip select 


//***********************************************************************************************************
// Registradores do chip DS3234 - endereço de leitura,para escrever basta somar 0X80 ao valor hexadecimal
//***********************************************************************************************************
#define DS3234_SEG               0X00 // registrador de segundos
#define DS3234_MIN               0X01 // registrador de minutos
#define DS3234_HORA              0X02 // registrador de horas
#define DS3234_DIA_SEMANA        0X03 // registrador de dia da semana
#define DS3234_DIA               0X04 // registrador de dia
#define DS3234_MES               0X05 // registrador de Mes
#define DS3234_ANO               0X06 // registrador de ano

#define DS3234_ALM1_SEG          0X07 // registrador Alarme 1 de segundos
#define DS3234_ALM1_MIN          0X08 // registrador Alarme 1 de minutos
#define DS3234_ALM1_HORA         0X09 // registrador Alarme 1 de horas
#define DS3234_ALM1_DIA_SEMANA   0X0A // registrador Alarme 1 de dia e dia da semana

#define DS3234_ALM2_MIN          0X0B // registrador Alarme 2 de minutos
#define DS3234_ALM2_HORA         0X0C // registrador Alarme 2 de horas
#define DS3234_ALM2_DIA_SEMANA   0X0D // registrador Alarme 2 de dia e dia da semana

#define DS3234_CONTROLE          0X0E // registrador de controle(config)
#define DS3234_STAT_CONTROLE     0X0F // registrador de controle e status
#define DS3234_CONF_CRISTAL      0X10 // registrador do cristal interno

#define DS3234_TEMP_H            0X11 // registrador do sensor de temperatura parte alta(msb))
#define DS3234_TEMP_L            0X12 // registrador do sensor de temperatura parte baixa(lsb)

#define DS3234_S_RAM             0X18 // registrador da memoria S_RAM
#define DS3234_S_RAM_DADOS       0X18 // registrador da memoria S_RAM dados


void setup() {
  Serial.begin(115200); 
  pinMode(LED_STATUS, OUTPUT);
  digitalWrite(LED_STATUS, LOW);
  inicializa_spi();
  inicializa_DS3234(); 
}
void loop() {
  digitalWrite(LED_STATUS,HIGH);
  Serial.print("DATA:");
  Serial.print(DS3234_ler_spi(DS3234_DIA), HEX);
  Serial.print("/"); 
  Serial.print(DS3234_ler_spi(DS3234_MES), HEX);
  Serial.print("/");
  Serial.print(DS3234_ler_spi(DS3234_ANO), HEX);
  Serial.print(" -> ");
  Serial.print(DS3234_ler_spi(DS3234_HORA), HEX);
  Serial.print(":");
  Serial.print(DS3234_ler_spi(DS3234_MIN), HEX);
  Serial.print(":");
  Serial.println(DS3234_ler_spi(DS3234_SEG), HEX);
  delay(1000);//1s
  digitalWrite(LED_STATUS,LOW);
  delay(1000);//1s
}
/*
 * Funções usadas no laço principal
 * eu poderia ter montado uma lib - mas a ideia é compartilhar como se faz 
 * uma comunicação spi com o DS3234 que sirva em qualquer dispositivo.
 */
 ////////////////////////////////////////////////////////////////////
//cria estado padrão dos pinos spi
////////////////////////////////////////////////////////////////////
void inicializa_spi()
{ 
  pinMode(SPI_CLK, OUTPUT);
  digitalWrite(SPI_CLK, HIGH);
  pinMode(SPI_IN, INPUT);
  pinMode(SPI_OUT, OUTPUT);
  digitalWrite(SPI_OUT, LOW);
  pinMode(SPI_CS, OUTPUT);
  digitalWrite(SPI_CS,HIGH);
  return;
}
////////////////////////////////////////////////////////////////////
//inicializa o chip
////////////////////////////////////////////////////////////////////
void inicializa_DS3234()
{
    DS3234_escr_spi(DS3234_CONTROLE,0X80);//80= desliga saida do oscilador , SQ wave @1hz, Alarme desabilitados
    DS3234_escr_spi(DS3234_ANO,0X17);//configura data para 25/08/2017 - 15:05
    DS3234_escr_spi(DS3234_MES,0X08);//colocar os valores sempre em hexadecimal
    DS3234_escr_spi(DS3234_DIA,0X25);
    DS3234_escr_spi(DS3234_HORA,0X15);
    DS3234_escr_spi(DS3234_MIN,0X05);
    return;
}
////////////////////////////////////////////////////////////////////
//essa rotina serve tanto para escrever quanto para ler 
////////////////////////////////////////////////////////////////////
int DS3234_ler_spi_byte(int valor,int liga_cs)
{//já escreve e já lê
  int dados = 0;
  int pos=128;
  digitalWrite(SPI_CS, LOW);
  delayMicroseconds(1); 
  while(pos>0)///bit mais significativo primeiro
  {
      if((valor&pos)>0)//faz uma operaçao and e checa se é 1
        {digitalWrite(SPI_OUT,HIGH);}
      else
        {digitalWrite(SPI_OUT,LOW);}
        digitalWrite(SPI_CLK,LOW);
        delayMicroseconds(1); ///tempo em nivel baixo do clock
        if(digitalRead(SPI_IN)==HIGH)
        {dados = dados|pos;}      
        digitalWrite(SPI_CLK,HIGH);
        delayMicroseconds(1); ///tempo em nivel baixo do clock//tempo em nivel alto do clock
    pos=pos/2;//rotaciona 1 bit
  }
  if(liga_cs == 1)
  {digitalWrite(SPI_CS, HIGH);}
   return(dados);
}
////////////////////////////////////////////////////////////////////
//essa rotina lê um byte do registrador colocado em endereço
////////////////////////////////////////////////////////////////////
int DS3234_ler_spi(int endereco)
{
  int dados;
  DS3234_ler_spi_byte(endereco,0);
  dados = DS3234_ler_spi_byte(0X00,1);//não envia nada somente para pegar os dados
  return(dados);
}
////////////////////////////////////////////////////////////////////
//essa rotina escreve um byte no registrador  em endereço
////////////////////////////////////////////////////////////////////
void DS3234_escr_spi(int endereco,int dados)
{
  endereco = endereco|0X80;//pronto pra escrever
  DS3234_ler_spi_byte(endereco,0);
  DS3234_ler_spi_byte(dados,1);  
}


Veja o vídeo de demonstração :




Um comentário :

  1. Finally a working example for SD3234 + ESP8266. Thanks for sharing! Just 2 comments:
    - in inicializa_DS: DS3234_escr_spi should be 0x1C, NOT 0x80, because the oscillator is disabled when powered off or on battery with 0x80
    - DS3234_S_RAM_DADOS should be 0x19 instead of 0x18

    ResponderExcluir

olá,digite aqui seu comentário!