Gravação e leitura de SD card com Arduino


Na eletrônica e na biomédica, tanto quanto em outras áreas da tecnologia, utilizamos muitos sensores. Assim, muitos dados são gerados e várias análises têm de ser feitas para melhor rendimento de um sistema ou simplesmente o monitoramento do mesmo. Hoje, vamos utilizar um gravador de SD card para gravação de dados vindos de sensores e assim podermos analisá-los depois.

micro sd card

Antes de começarmos, precisamos definir o que é um SD Card. Este é uma das mais modernas formas de armazenamento de dados de forma ágil e ocupando quase nenhum espaço físico. Surgiu em 1997 a partir de uma parceria entre Siemens e SanDisk para melhora dos meios de armazenamento existentes naquele momento. O micro SD Card consiste em uma memória flash não-volátil, isso quer dizer que é uma memória que pode ser apagada e escrita novamente utilizando apenas sinais elétricos e não precisando de aparatos complicados e complexos de se usar. Além disso, o “não-volátil” quer dizer que mesmo sem fluxo contínuo de energia elétrica (dispositivo sempre ligado), os dados na memória continuam os mesmos, sem perdas de dados.

Sd card, o pai do micro sd. Fonte: P^2 – Paul / CC BY-NC 2.0.
Módulo SD card

Hoje neste tutorial iremos utilizar um módulo próprio para SD Card que podemos utilizar em nossos projetos de prototipagem.

Micro SD card adapter.

Características:

  •  Nível lógico: 3,3V (divisor de tensão já embutido no módulo)
  • Tensão de operação: 4,5 – 5,5VDC
  • Interface de comunicação: SPI
  • Cartões compatíveis: micro SD Card / SDHC
Protocolo SPI

Para comunicação entre o módulo e o microcontrolador, utilizamos o protocolo SPI (Serial Peripheral Interface). Este protocolo de comunicação foi desenvolvido para solucionar os problemas do antigo RX/TX, sendo um protocolo síncrono e com a possibilidade de comunicação de mais de um dispositivo ao mesmo tempo. De forma similar ao já visto antes I2C, no SPI temos o “controlador”, dispositivo normalmente sendo o microcontrolador principal do sistema, e os “periféricos”, sendo normalmente os sensores, leitores ou displays.

Curiosidade

Nos últimos anos tornou-se cada vez mais comum a adoção de terminologias mais inclusivas e que não pudessem ser consideradas politicamente incorretas. Assim, diversas empresas e associações têm alterado a nomenclatura “mestre/escravo” para “controlador/periférico” ou outras equivalentes. Saiba mais neste link.

Neste protocolo de comunicação temos 4 conexões:

  • SCK – Sinal clock para sincronização entre os componentes
  • CIPO – Canal para o “periférico” enviar informação para o “controlador”
  • COPI – Canal para o “controlador” enviar informação para o “periférico”
  • CS – Canal para selecionar com qual periférico a comunicação está sendo feita. Na comunicação SPI, deve existir um sinal CS separado para cada periférico
SCKCIPOCOPICSVCCGND
UNO13121110*5VGND
MEGA52505153*5VGND

*No código de exemplo deste post, o sinal CS é configurado no pino 4.

Demonstração

Neste projeto, vamos criar um arquivo texto (“.txt”) dentro do micro SD Card e salvar todas as informações vindas de um sensor ultrassônico e de um RTC.

Esquema de ligação.
Código

Neste código, vamos analisar a distância do sensor ultrassônico sem o uso de bibliotecas, apenas medindo o tempo de resposta entre um pulso enviado e o reflexo recebido e multiplicando pela velocidade do som. O código salva a distância lida pelo sensor e o horário lido pelo módulo RTC no cartão micro SD e mostra todas as informações salvas no Monitor Serial.

O código apenas termina de salvar as informações quando o número de ciclos for maior que o valor da variável “ciclos”. Para isso ele usa um contador (variável “cont”) que vai aumentando a cada término de leitura.

Utilizamos duas bibliotecas para o módulo leitor SD card que já estão incluídas na IDE Arduino por padrão, e para a utilização do modulo RTC, utilizamos uma biblioteca externa que pode ser vista neste post com mais detalhes.

// Teste com leitor/gravador de SD Card.
//
// Neste código, vamos analisar a distância do sensor ultrassônico
// sem o uso de bibliotecas, apenas medindo o tempo de resposta
// entre um pulso enviado e o reflexo recebido e multiplicando pela
// velocidade do som. O código salva a distância lida pelo sensor e
// o horário lido pelo módulo RTC no cartão micro SD e mostra todas
// as informações salvas no Monitor Serial.
//
// Criado por: Lucas Jácome Cabral, 2022

///////////////////////////////////////////////
// Bibliotecas utilizadas
#include "RTClib.h"
#include <SPI.h>
#include <SD.h>

///////////////////////////////////////////////
// Criação de objetos para uso das bibliotecas
RTC_DS3231 rtc;
File meuArquivo;

///////////////////////////////////////////////
// Variáveis utilizadas ao longo do código.
int ciclos = 30;
long cont  = 0;
long distancia;
int pinoTrig = 3; // pino usado para disparar os pulsos do sensor.
int pinoEcho = 2; // pino usado para ler a saída do sensor.

///////////////////////////////////////////////
// Esta função só roda quando é chamada dentro de outra função
void leitura(){
    digitalWrite(pinoTrig, HIGH); // Manda um sinal de nível alto por 10 microssegundos
    delayMicroseconds(10);
    digitalWrite(pinoTrig, LOW);
    
    distancia = pulseIn(pinoEcho, HIGH); // Le o comprimento de onda em alta
}

///////////////////////////////////////////////
// Esta função só roda uma vez, no início
void setup () {
    Serial.begin(9600);
    
    pinMode(pinoTrig, OUTPUT); // configura pino TRIG como saída
    pinMode(pinoEcho, INPUT); // configura pino ECHO como entrada
    
    ///////////////////////////////////////////////
    // Inicializa o SD Card
    if (SD.begin(4)) {
        Serial.println("SD Card pronto para uso."); // imprime na tela
    }
    else {
        Serial.println("Falha na inicialização do SD Card.");
        return;
    }
    meuArquivo = SD.open("teste.txt", FILE_WRITE);
    
    ///////////////////////////////////////////////
    // Laço para identificar qualquer problema com o módulo RTC
    if (! rtc.begin()) {
        // caso  o modulo nao seja encontrado, irá aparecer um aviso no monitor serial
        Serial.println("Módulo RTC não encontrado");
        Serial.flush();
        while (1) delay(10);
    }
    ///////////////////////////////////////////////
    // Comando para alterar o horario do modulo RTC
    // Ajusta com data e hora em que o programa foi compilado
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}

///////////////////////////////////////////////
// Esta função se repete indefinidamente
void loop () {
    ///////////////////////////////////////////////   
    // Leitura da distancia e cálculos. 
    leitura();
    // Divide por 2 pois esse eh o tempo da onda ir e voltar
    distancia = distancia/2;
    distancia = distancia*0.034029;
    
    ///////////////////////////////////////////////
    //Seção para envio de informações para o monitor serial
    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(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.print(" ***** ");
    Serial.print("Leitura da distancia: ");
    Serial.println(distancia);
    
    // Seção para envio de informações para o módulo Micro SD
    meuArquivo.print(now.year(), DEC);
    meuArquivo.print('/');
    meuArquivo.print(now.month(), DEC);
    meuArquivo.print('/');
    meuArquivo.print(now.day(), DEC);
    meuArquivo.print('-');
    meuArquivo.print(now.hour(), DEC);
    meuArquivo.print(':');
    meuArquivo.print(now.minute(), DEC);
    meuArquivo.print(':');
    meuArquivo.print(now.second(), DEC);
    meuArquivo.print(" ***** ");
    meuArquivo.print("Leitura da distancia: ");
    meuArquivo.println(distancia);

    delay(1000); // tempo entre as medidas
    cont +=1; // contagem de ciclos
    
    ///////////////////////////////////////////////
    //Laço para fechamento das medidas (quantas vezes queremos medir)
    if (cont >= ciclos)
    {
        // Interrompe o processo e fecha o arquivo
        meuArquivo.close();
        Serial.println("Processo de gravacao interrompido. Retire o SD!");
        while (1) {}
    }
}
Você pode encontrar este e outros códigos do blog no link:
https://github.com/edlbcamargo/embarcasaude
Arquivo final

Abrindo o arquivo salvo no cartão micro SD em um computador com leitor de arquivos “.txt”, temos as informações desejadas: horário da medida e distância calculada.


Texto por: Lucas Jácome Cabral

Revisão: Erick León


, , , , ,

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *