segunda-feira, 14 de agosto de 2017

Teste XD-05 Data Logger Shield

O módulo XD-05 apresenta-se como uma grande mais-valia para os nossos projetos com o Arduino, dotando estes de um relógio de tempo real e de um leitor de cartões SD.

Estas são duas funcionalidades que aumentam em muito as possibilidades do nosso Arduino e que nos vão permitir trabalhar com o tempo real e guardar no cartão SD o estado e resultados do nosso sistema em função do tempo para futura análise.



Nesta publicação pretendemos dar a conhecer na prática o nosso módulo XD-05 Data-Logger. Optamos por dividir este ensaio em 3 etapas distintas para de uma forma mais simples podermos demonstrar as suas capacidades.

Iremos iniciar pela análise do relógio de tempo real (RTC), demonstrando o seu funcionamento recorrendo a um exemplo básico.

Em seguida analisaremos a utilização do leitor de cartões SD recorrendo mais uma vez a um exemplo básicos fornecidos com a IDE, software do Arduino.

Por fim iremos elaborar uma pequena montagem recorrendo não só ao nosso Arduino e ao módulo XD-05 mas, a mais um modulo de expansão e a alguns componentes, criando-se desta forma um cenário real onde o nosso sistema passa a ter a capacidade de medir a temperatura, humidade e luminosidade ambiente e registar estes parâmetros em tempo real no cartão SD.

Saber mais sobre o nosso módulo:

O nosso módulo disponibiliza para além do relógio de tempo real e do leitor de cartões SD uma área de prototipagem com uma dimensão de 11x11 pontos (furos) onde nos permite soldar diretamente sensores e circuitos simples para teste.

Este disponibiliza para além das saídas normais do Arduino as seguintes características:
  • 3V e o regulador de tensão de 3.3V;
  • SQ é o sinal quadrado (onda quadrada) na saída do relógio;
  • WP “Write Protect” para detetar se o cartão SD está protegido contra escrita;
  • CD "Card Detect" para verificar se um cartão de memória foi inserido; 
  • CS " Chip Select" (para substituir pino 10 em caso de conflito e aceder ao cartão SD);
  • L1 e L2 os dois LED's ambos (com uma resistência de 470ohm ligada em serie), configuráveis e ativos a nível "HIGH".

Particularidades:
  • O módulo reinicia automaticamente o temporizador interno cada vez que se reiniciar o Arduino, ou seja sempre que se fizer Reset ao nosso sistema o tempo reinicia.
  • A função millis() devolve o tempo decorrido desde que se reiniciou o Arduino pela ultima vez, não devolvendo o tempo real.
  • Quando recorrermos ao relógio de tempo real RTC do módulo conseguimos manter o tempo exato decorrido, mesmo quando o modulo não esta ligado ao nosso Arduino, mas para isso tem de ter a bateria inserida no suporte.
Nota: Atenção ao reiniciar não reinicia a data e hora mas a contagem de segundos.

Ensaios:

Material necessário para a elaboração dos ensaios:
  • Arduino Duemilanove ou outro compatível com o módulo XD-05;
  • Modulo XD-05 Data-Logger Shield;
  • Bateria/Pilha CR1220; 
  • Cartão SD com capacidade entre (32 Mb a 32Gb) formatado em (FAT16 ou FAT32);
  • Cabo USB;
  • Computador com software do Arduino instalado;
  • Sensor DHT11;
  • LDR;
  • 1x Resistência de 10K;
  • Breadboard;
  • Vários jumpers (fios condutores para as ligações);
       Nota: Recorreu-se a um módulo de expansão com breadboard por razões de comodidade.



Antes de darmos início aos ensaios teremos de colocar a bateria CR1220 de lítio no suporte do nosso módulo sendo que esta serve para manter as definições do relógio ao longo do tempo, mesmo quando o nosso módulo estiver sem alimentação por muitos dias, meses ou mesmo anos.

Em seguida vamos acoplar o nosso módulo ao nosso Arduino e por fim realizar a formatação do cartão SD que iremos utilizar através do nosso computador. Esta terá de ser formatada em FAT32 e só poderemos utilizar um cartão de memória com uma capacidade máxima até 32GB.
Para os ensaios recorremos a um cartão de 128Mb de capacidade.




Primeira parte: Testando o RTC - Relógio de Tempo Real

Como já referido este módulo permite dotar os nossos projetos de um relógio de tempo real, que é algo muito útil e que vem dar muitas mais utilidades ao nosso Arduino.



Vamos começar por fazer Download e instalar biblioteca RTClib na pasta bibliotecas, esta será a biblioteca que vai permitir a utilização do relógio de tempo real o RTC.
Está pode ser encontrada aqui no github ou no final da publicação na área de Downloads.

Para demonstramos o funcionamento do RTC Iremos recorrer a um exemplos fornecidos com esta biblioteca o DS1307 que permite definir a Data e Hora atual do nosso módulo através do PC e permite ver a Data e Hora atual bem como o tempo decorrido.


Código Fonte
O código necessário para a elaboração do primeiro teste que pode ser carregado a partir de File / Example / RTClib / ds1307 ou então copiado daqui: 

//***********************
// TecnoDomos 2017   
//
//***********************
// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
#include <Wire.h>
#include "RTClib.h"

RTC_DS1307 rtc;

char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

void setup ()
 {
      while (!Serial); // for Leonardo/Micro/Zero

      Serial.begin(57600);
      if (! rtc.begin())
      {
           Serial.println("Couldn't find RTC");
           while (1);
      }

      if (! rtc.isrunning())
      {
           Serial.println("RTC is NOT running!");
          // following line sets the RTC to the date & time this sketch was compiled
          // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
          // This line sets the RTC with an explicit date & time, for example to set
          // January 21, 2014 at 3am you would call:
          // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
       }
 }

void loop ()
 {
       DateTime now = rtc.now();
 
       Serial.print(now.year(), DEC);
       Serial.print('/');
       Serial.print(now.month(), DEC);
       Serial.print('/');
       Serial.print(now.day(), DEC);
       Serial.print(" (");
       Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
       Serial.print(") ");
       Serial.print(now.hour(), DEC);
       Serial.print(':');
       Serial.print(now.minute(), DEC);
       Serial.print(':');
       Serial.print(now.second(), DEC);
       Serial.println();
 
       Serial.print(" since midnight 1/1/1970 = ");
       Serial.print(now.unixtime());
       Serial.print("s = ");
       Serial.print(now.unixtime() / 86400L);
       Serial.println("d");
 
       // calculate a date which is 7 days and 30 seconds into the future
       DateTime future (now + TimeSpan(7,12,30,6));
 
       Serial.print(" now + 7d + 30s: ");
       Serial.print(future.year(), DEC);
       Serial.print('/');
       Serial.print(future.month(), DEC);
       Serial.print('/');
       Serial.print(future.day(), DEC);
       Serial.print(' ');
       Serial.print(future.hour(), DEC);
       Serial.print(':');
       Serial.print(future.minute(), DEC);
       Serial.print(':');
       Serial.print(future.second(), DEC);
       Serial.println();
 
       Serial.println();
       delay(3000);
 }



Ensaio prático e resultados:
Não foram feitas alterações ao código original disponibilizado na biblioteca "RTClib", este permite definir a Data e Hora do nosso módulo e permite posteriormente ver através do monitor serie a Data e Hora atuais vem como o dia atual por extenso em Inglês e ainda o tempo decorrido desde o dia 1 de Janeiro de 1970 em segundos e em dias e por fim o dia atual mais 7 dias e 30 segundos.

Para se definir a Data e Hora atuais tem de ser descomentar a linha RTC.adjust para definir a data e hora no exato momento da compilação do programa no PC.



O programa ds1307 irá exibir a hora interna do nosso módulo e vai ainda fazer alguns cálculos com o tempo:


As principais funções utilizadas foram:
  • Now() que nos permite saber a data e hora atual;
  • unixtime permite saber o número de segundos decorridos desde o dia 01 de Janeiro de 1970 (norma UNIX).

Segunda parte: Utilização do cartão SD

Tal como já referido o nosso módulo permite incorporar nos nossos projetos a capacidade de registar o seu estado e o estado dos sensores num cartão SD o que é algo muito útil nos tempos que corem onde a informação é tudo.



Aqui não teremos de recorrer a novas bibliotecas, pois o IDE, Software do Arduino já tem disponível as bibliotecas e funções necessárias para se poder trabalhar com o cartão SD.

Aqui também realizamos o ensaio recorrendo a um exemplo disponibilizado pela biblioteca o CardInfo que permite ler a informação geral do cartão SD, dando-nos a conhecer o tipo de ficheiros em que foi formatado, a sua capacidade total e utilizada bem como listar os ficheiros que estiverem guardados no cartão.

Código Fonte
Código para o primeiro teste que pode ser carregado a partir de File / Example / SD/ CardInfo ou então copiado daqui: 

//***********************
// TecnoDomos 2017   
//
//***********************

/*  SD card test

 This example shows how use the utility libraries on which the'
 SD library is based in order to get info about your SD card.
 Very useful for testing a card when you're not sure whether its working or not.

 The circuit:
 ** SD card attached to SPI bus as follows:
 ** MOSI - pin 11 on Arduino Uno/Duemilanove/Diecimila
 ** MISO - pin 12 on Arduino Uno/Duemilanove/Diecimila
 ** CLK - pin 13 on Arduino Uno/Duemilanove/Diecimila
 ** CS - depends on your SD card shield or module.
 ** Pin 4 used here for consistency with other Arduino examples


 created  28 Mar 2011
 by Limor Fried
 modified 9 Apr 2012
 by Tom Igoe
 */

// include the SD library:
#include <SPI.h>
#include <SD.h>

// set up variables using the SD utility library functions:
Sd2Card card;
SdVolume volume;
SdFile root;

// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
// MKRZero SD: SDCARD_SS_PIN
const int chipSelect = 10;

void setup()
 {
      // Open serial communications and wait for port to open:
      Serial.begin(9600);
      while (!Serial)
     {
           ; // wait for serial port to connect. Needed for native USB port only
      }


       Serial.print("\nInitializing SD card...");

     // we'll use the initialization code from the utility libraries
    // since we're just testing if the card is working!
    if (!card.init(SPI_HALF_SPEED, chipSelect)) 
    {
        Serial.println("initialization failed. Things to check:");
        Serial.println("* is a card inserted?");
        Serial.println("* is your wiring correct?");
    Serial.println("* did you change the chipSelect pin to match your shield or module?");
        return;
     }
    else 
    {
        Serial.println("Wiring is correct and a card is present.");
     }

  // print the type of card
  Serial.print("\nCard type: ");
  switch (card.type()) {
    case SD_CARD_TYPE_SD1:
      Serial.println("SD1");
      break;
    case SD_CARD_TYPE_SD2:
      Serial.println("SD2");
      break;
    case SD_CARD_TYPE_SDHC:
      Serial.println("SDHC");
      break;
    default:
      Serial.println("Unknown");
  }

  // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
  if (!volume.init(card)) {
    Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
    return;
  }


  // print the type and size of the first FAT-type volume
  uint32_t volumesize;
  Serial.print("\nVolume type is FAT");
  Serial.println(volume.fatType(), DEC);
  Serial.println();

  volumesize = volume.blocksPerCluster();    // clusters are collections of blocks
  volumesize *= volume.clusterCount();       // we'll have a lot of clusters
  volumesize *= 512;                            // SD card blocks are always 512 bytes
  Serial.print("Volume size (bytes): ");
  Serial.println(volumesize);
  Serial.print("Volume size (Kbytes): ");
  volumesize /= 1024;
  Serial.println(volumesize);
  Serial.print("Volume size (Mbytes): ");
  volumesize /= 1024;
  Serial.println(volumesize);


  Serial.println("\nFiles found on the card (name, date and size in bytes): ");
  root.openRoot(volume);

  // list all files in the card with date and size
  root.ls(LS_R | LS_DATE | LS_SIZE);
}


void loop(void)
{


}


Ensaio prático e resultados:
Este é o código original disponibilizado na biblioteca disponível no IDE, este é um código que tal como já foi referido permite ler as características do cartão SD bem como listar as pastas e ficheiros guardados no cartão.




Terceira parte: Mini estação meteorológica

Para terminar esta serie de ensaios nada como um caso-pratico, algum que possa despertar a atenção e que tem uma grande aplicabilidade.
Vamos dar utilidades as duas principais funcionalidades do módulo XD-05, na criação de uma mini estação meteorologia.



Aqui vamos utilizar em conjunto com o nosso Arduino e Modulo XD-05 os sensores DHT11 e o um sensor LDR, estes vão nos permitir captar o valor da temperatura e Humidade do ar bem como a intensidade luminosa que incide sobre o nosso sistema.

Para este ensaio optamos por acoplar ao nosso Arduino mais o módulo XD-05 um outro módulo, módulo este que disponibiliza uma pequena placa de ensaios (Breadboard) bem como todo as funcionalidades e ligações do Arduino para mais facilmente podermos juntar os sensores DHT11 e o LDR ao nosso projecto, mantendo este mais compacto e simples possível.

Montagem
Para iniciar devemos ligar os sensores ao nosso projectos segundo o seguinte esquema, tendo sempre em atenção a correcta montagem de cada componente para evitar danificar os mesmos bem como os nossos módulos ou mesmo o nosso Arduino.




Código Fonte
Código desenvolvido para responder as necessidades do nosso projeto e que tem de ser carregado para o nosso Arduino. 

//*****************************************************
// Estação meteorológica
// Weather station
//-----------------------------------------------------
// Data logger para registar os dados captados nos
// sensor DHT11 e LDR no cartão SD.
// (Data, Hora,  Temperatura, Humidade e Luminosidade)
//-----------------------------------------------------
// Sensor 1 = LDR Luminosidade                        -> pino A0
// Sensor 2 = DHT11 Temperatura e Humidade -> pino D5
//
// TecnoDomos 24-07-2017
//*****************************************************

#include <dht.h>         //Biblioteca DHT
#include <SD.h>         //Biblioteca SD
#include <Wire.h>      //Para aceder ao RTC
#include <RTClib.h>  //Biblioteca RTC para o RTC-Real Time Clock

// Intervalo de aquisição de dados, 1000ms = a cada segunda
//#define LOG_INTERVAL  1000  // mills between entries (reduce to take more/faster data)
#define LOG_INTERVAL  2000    // 2 segundos é o tempo minimo, nao diminuir este valor.
                              // 2 seconds is the minimum time, not decrease this value.
                              // Ideal é a leitura a cada 2 segundos!
                              // Ideally  reading every 2 seconds!
                
// Intervalo de escrita no cartão SD 
// Definir o LOG_INTERVAL para gravar os dados a cada medição (mais seguro)
// Configurar 10 x LOG_INTERVAL para gravar 1 vez em 10, mais rápido e eficiente ao nivel de energia
//#define SYNC_INTERVAL 1000    //mills between calls to flush() - to write data to the card
#define SYNC_INTERVAL 2000      //mills between calls to flush() - to write data to the card

uint32_t syncTime = 0;          //time of last sync()

#define ECHO_TO_SERIAL   1      //1 para indicar a porta serial
#define WAIT_TO_START    0      //Enquanto se aguarda a entrada em série na setup()

// LEDs do módulo datalogger
#define redLEDpin 2             //vermelho
#define greenLEDpin 3           //verde

// --- Sensores ---
// Sensor 1 =  LDR, luminosidade                       -> pino A0
// Sensor 2 =  DHT11, temperatura e humidade -> pino D5

#define dht_pin 5      // Definição o pino de dados.
                                   // Setting the data pin.
dht DHT;                   // Inicializa o sensor.
                                   // Initialize the sensor.
                           
int temperatura=0;        // Temperatura
int humidade=0;            // Humidade

int lum = 0;              // Luminosidade
int lumPin = 0;           // LDR no pino A0 com uma resistência de 1OK

// indicador do medidor de bandgap
#define BANDGAPREF 14           

// Ligação no AREef 3.3V, tensão precisas que vai servir de referência para as medições analógicos 
// On relie 3.3V sur ARef, tension précise qui sert de référence aux mesures analogiques
#define aref_voltage 3.3         
#define bandgap_voltage 1.1      

RTC_DS1307 RTC; // Objet - Real Time Clock

// Shield data-logger, SD = pin 10 
const int chipSelect = 10;

// Ficheiro de registo dos resultados 
File logfile;

// === Gestão de Erros ===
void error(char *str)
{
  Serial.print("erreur: ");
  Serial.println(str);

  // LED vermelho indica os erros
  digitalWrite(redLEDpin, HIGH);

  while(1);
}

// ==== Initialisation ====
void setup(void)
{
  Serial.begin(9600);   //Serial monitor pour le debugage
  Serial.println("-------------------------------------");
  Serial.println("Estação Meteorológica com Datalogger");
  Serial.println("V1.0                 TecnoDomos 2017");
  Serial.println("-------------------------------------");
  Serial.println();

  // LEDs indicadores de Debug
  pinMode(redLEDpin, OUTPUT);
  pinMode(greenLEDpin, OUTPUT);

  #if WAIT_TO_START
  Serial.println("Prima um botão para iniciar o registo");
  while (!Serial.available());
    #endif //WAIT_TO_START

  // Initialiser la SD 
  Serial.println("Inicializar o cartão SD ...");
  pinMode(10, OUTPUT);  //mesmo se não estiver em uso

  // Verifica se o cartão está presente e inicializa
  if (!SD.begin(chipSelect)) 
  {
    error("Falha no cartão SD ou ausente!");
  }
  Serial.println("Cartão SD inicializado");

  // Criar um novo arquivo, com número sequencial
  char filename[] = "LOGGER00.CSV";
  for (uint8_t i = 0; i < 100; i++)
  {
    filename[6] = i/10 + '0';
    filename[7] = i%10 + '0';
    if (! SD.exists(filename)) 
    {
      
      // Não criar novo arquivo se já existir
      logfile = SD.open(filename, FILE_WRITE); 
      break;  // Sair do ciclo
    }
  }

  if (! logfile) 
  {
    error("Não pode criar o arquivo!");
  }

  Serial.print("Guardado em: ");
  Serial.println(filename);

  // connection  RTC
  Wire.begin();  
  if (!RTC.begin()) 
  {
    logfile.println("Falha RTC");
    #if ECHO_TO_SERIAL
    Serial.println("Falha RTC");
    #endif  //ECHO_TO_SERIAL
  }

  //.... Cabeçalho ....  
  //Primeira linha do arquivo CSV em Excel
  logfile.println("millis, stamp, DataHora, Luminosidade, Humidade, Temperatura ");    
  #if ECHO_TO_SERIAL
    Serial.println("millis, stamp, DataHora, Luminosidade, Humidade, Temperatura ");    
  #endif //ECHO_TO_SERIAL

}

// ======= Execução =======
void loop(void)
{
  DateTime now;  //Instante atual da leitura 

  // Tempo entre leituras 
  delay((LOG_INTERVAL -1) - (millis() % LOG_INTERVAL));

  digitalWrite(greenLEDpin, HIGH);  //LED Verde ON

  // Registo dos milisegundos passados desde o início
  uint32_t m = millis();
  logfile.print(m);           // milissegundos desde o início
  logfile.print(", ");    
    #if ECHO_TO_SERIAL
      Serial.print(m);         
      Serial.print(", ");  
    #endif

    // Mesurer le time RTC
    now = RTC.now();
    logfile.print(now.unixtime()); // segundos desde 01/01/1970
    logfile.print(", ");
    logfile.print('"');
    logfile.print(now.year(), DEC);    //ano
    logfile.print("/");
    logfile.print(now.month(), DEC);   //mes
    logfile.print("/");
    logfile.print(now.day(), DEC);     //dia
    logfile.print(" ");
    logfile.print(now.hour(), DEC);    //hora
    logfile.print(":");
    logfile.print(now.minute(), DEC);  //minutos
    logfile.print(":");
    logfile.print(now.second(), DEC);  //segundos
    logfile.print('"');
    #if ECHO_TO_SERIAL
    Serial.print(now.unixtime()); // segundos desde 01/01/1970
    Serial.print(", ");
    Serial.print('"');
    Serial.print(now.year(), DEC);
    Serial.print("/");
    Serial.print(now.month(), DEC);
    Serial.print("/");
    Serial.print(now.day(), DEC);
    Serial.print(" ");
    Serial.print(now.hour(), DEC);
    Serial.print(":");
    Serial.print(now.minute(), DEC);
    Serial.print(":");
    Serial.print(now.second(), DEC);
    Serial.print('"');
    #endif //ECHO_TO_SERIAL

  //=== Leitura dos nossos sensores ===
   
  //Luminosidade
  lum = analogRead(lumPin);   
  //Serial.println();  //Linha seguinte
  Serial.print(", ");
  Serial.print(lum);  //Leitura do LDR
  Serial.print(", "); 

  //Temperatura e Humidade    
  DHT.read11(dht_pin);//Lê as informações do sensor.
                      //Read the sensor information
  temperatura=DHT.temperature;
  humidade=DHT.humidity;
  
  Serial.print(humidade);
  Serial.print(" %, ");
  Serial.print(temperatura);
  Serial.println(" C ");

  //Fim da leitura dos sensores
  
  // === Guardar as medições no ficheiro de Log === 
  logfile.print(", ");   
  logfile.print(lum); 
  logfile.print(", ");    
  logfile.print(temperatura);
  logfile.print(", ");    
  logfile.print(humidade);
  logfile.println();
  
  // === Fim do registo das medições no ficheiro Log === 
  
  digitalWrite(greenLEDpin, LOW);   //LED Verde OFF após registo 

  /*Escrito no cartão SD, não sincronizar muitas vezes requer 2048 bytes de I/O
  Aqui existe elevado consumo de tempo e energia*/

  if ((millis() - syncTime) < SYNC_INTERVAL) return;
    syncTime = millis();

  // LED vermelho pisca para mostrar que os dados estão a ser guardados no cartão SD
  digitalWrite(redLEDpin, HIGH);
  logfile.flush();
  digitalWrite(redLEDpin, LOW);
}

Ensaio prático e resultados:
Após a realização da montagem segundo o esquema fornecido, temos que programar o nosso Arduino com o código atrás referido, após isto é só abrir o serial monitor e verificar os resultados.


Aqui vamos poder observar diversos parâmetros, como o tempo, a temperatura, a humidade, a luminosidade, a data e hora da medição entre outros.  



Uma vez que os resultados já são guardados no cartão SD e no formato Excel torna mais fácil a sua análise através desta mesma ferramenta, mas para tal temos de converter os dados obtidos em apenas uma coluna para o numero de colunas necessários como ilustrado a imagem anterior.
Após este passo já podemos criar gráficos, tabelas ou outros de acordo com o que pretendemos analisar.

Considerações Finais
O módulo XD-05 data-logger é mais que um simples Shield é um componente essencial em todos os projetos, que nos permite registar a atividade das nossas montagem de forma rápida, fácil e sempre em função do tempo real para, de uma forma mais fácil se compreenderem os dados recolhidos em futuras análises.

Este é um módulo muito completo e funcional, a capacidade de ser acoplado aos modelos como o Arduino Duemilanove, Uno e mesmo Mega, entre outros é um dos aspetos fundamentais ter em conta que vem permite simplificar muito as montagens.

Este é um módulo que podemos encontrar a venda em diversas lojas online por um preço muito competitivo e de boa qualidade.



Esperamos que este artigo tenha sido útil e se gostaram comentem e partilhem. Alguma dúvida ou questão deixem em comentário ou utilizem o formulário de contatos.


Um bom dia em nome da TecnoDomos.


Conteúdo redigido ao abrigo do novo Acordo Ortográfico

1 comentário: