Data-Logger SD/MMC com Arduino

Os cartões de memória Secure Digital ou MultiMedia Card , são dispositivos capazes de armazenar dados

O SD (Secure Digital) é um padrão de armazenamento portável, usado em celulares, câmeras mp3 players, computadores pessoais, impressoras, sistemas de navegação GPS entre outros. O termo Segure Digital (Segurança Digital) provém da capacidade destes dispositivos de armazenar direitos autorais em seus arquivos [1].

A adoção dos cartões de memória da família SD no mercado de eletroeletrônicos vem crescendo muito nos últimos anos, desta maneira percebemos que é uma excelente tecnologia para ser usada em projetos eletrônicos em geral.

Adoção padrão SD por eletroeletrônicos

Fonte: http://www.sdcard.org/developers/tech/sdcard – 2

Comunicação via SPI

Os cartões SD comunicam-se através de uma Interface Periférica Serial (SPI – Serial Peripheral Interface), que permite que vários dispositivos troquem dados em full-duplex. O SPI é um protocolo síncrono que permite um dispositivo mestre (master) iniciar a comunicação com um escravo (slave). Para prover o sincronismo, o sinal de clock (pino SCK) pode ser gerado somente pelo mestre, e este sinal controla quando os dados podem mudar e quando são válidos para leitura. Por ser síncrono, esse protolo torna-se interessante para ser usado em um oscilador não tão estável, como um oscilador RC, pois a taxa de transferência varia apenas de acordo com as subidas e descidas do oscilador, não afetando a integridade dos dados. Por permitir vários escravos, o SPI precisa controlar qual deles está sendo acessado, e o faz com um sinal CS (Chip Select) ou SS (Slave Select), que não precisa ser conectado caso haja apenas um escravo[3].

Portas SPI no Arduino

O Arduino nomeia os pinos de entrada e saída sendo MOSI (Master Out Slave In) e MISO (Master In Slave Out) respectivamente. O Duemilanove e outros Arduinos baseados no chip Atmega168/328 usam o SPI nos pinos: 10 (SS), 11 (MOSI), 12 (MISO) e 13 (SCK). Atenção especial ao Arduino Mega: nele os pinos são em outras portas, isso pode salvar um bom tempo seu: 50 (MISO), 51 (MOSI), 52 (SCK) e 53 (SS). Lembrando sempre que o pino SS precisa ser configurado no setup() como OUTPUT, do contrário a interface SPI irá por o microprocessador em escravo (slave), ficando então inoperável. [4].

Dica: Se estiver trabalhando com alguma biblioteca específica e receber um erro como este: “no sd/mmc pin mapping available!” significa que a biblioteca em questão não implementa as pinagens de seu Arduino. Isso ocorreu-me em quanto trabalhava com o Arduino Mega 1280 em testes com softwares de leitura do sistema de arquivos FAT dos cartões SDs.

Os pinos do cartão MMC/SD

Os cartões MMC possuem apenas 7 pinos, já os SD 9, fora as conexões de controle de bloqueio de escrita do cartão que nesta versão do projeto não serão implementadas. Visto isso a figura abaixo ilustra com facilidade a identificação dos pinos.

pinagem cartão MMC/SD

Os cartões MMC/SD funcionam com alimentação de 2,7 à 3,6 Volts e seu nível lógico alto é 3.3 Volts. Confira abaixo a tabela dos pinos:

Pino # Nome do Pino Função do Sinal
1 CS ou SS Chip Select – Slave Select
2 SI ou MOSI Serial Input – Master Out Slave In (SPI)
3 GND Ground
4 Vcc Tensão CC de 2.7 à 3.6 Volts
5 SCK Serial Clock (SPI)
6 GND Ground
7 SO ou MISO Serial Output – Master In Slave Out (SPI)
8 NC
9 NC

Esquema elétrico

esquema elétrico arduino e cartão sd-mmc

O esquema elétrico é bastante simples não envolvendo nada mais que seis resistores que atuam como divisores de tensão.

Isso é necessário, pois como já dito, os cartões SD/MMC trabalham com nível lógico alto em 3.3 Volts. Repare também que a alimentação do cartão é feita na porta 3V3 do Arduino.

Após a passagem pelos resistores temos as conexões do pino 1 do SD ao pino 53 do Arduino, o pino 2 conecta-se ao 51, o pino 5 ao 52 e por último o pino 7 conecta-se diretamente ao pino 50. O Arduino  interpreta a tensão de 3 Volts como sendo nível lógico 1 e 0 Volts como nível lógico 0.

Os resistores usados foram 10k (10000 ohms) e 4k7 (4700 ohms). Se juntarmos os dois em série e conectarmos um deles em 5 Volts e outro em 0 Volts, a diferença de tensão (ddp) entre o positivo da fonte e a conexão dos resistores será de 3.4 Volts. Vamos à fórmula: Vres = V x R1 / R1 + R2 = 23500 / 14700 = 1.60 Volts. Agora Pegamos a tensão total (5 Volts) menos a tensão obtida e teremos 5 – 1.60 = 3.4 Volts que se encaixa muito bem nos requisitos do cartão de memória.


Circuito elétrico - Arduino com cartão de memória SD-MMC
Parece um pouco difícil de acreditar, mas é só este hardware mesmo que é ncessário para interfacear os cartões SD-MMC com o Arduino. Agora falta a camada de software que nos permitirá gravar e ler arquivos no cartão de memória. Inicialmente você precisa formatar seu cartão de memória com sistema de arquivos FAT16, se tiver dúvidas segue a dica: http://www.ladyada.net/make/logshield/sd.html.

Atualização em 24-10-11 – Circuito opcional com outros valores de resistores

Uso de outros resistores para dividir tensão

Outro exemplo de conexão entre o Arduino e o cartão SD pode ser visto aqui: http://img441.imageshack.us/img441/2391/schematicuo7.jpg. Neste caso temos o uso de resistores de resistores com 1.8k e 3.3k, mas se fizermos os cálculos chegaremos a 3.23 Volts, o que também está dentro da faixa de tensão aceitável pelo cartão de memória. Usei os resistores de 10k e 4k7 pois eram os que eu tinha aqui, você pode usar quaisquer resistores, desde que consiga uma ddp perto de 3.3 Volts.

Atualização em 09-07-12 – Detectando remoção do cartão SD

Nosso amigo Edipo me pediu sobre como poderíamos detectar se o cartão foi removido para poder então reiniciar o acesso via software. Bom, todos os soquetes de cartões que conheço possuem um sensor de presença do cartão. Alguns usam este mesmo sensor para detectar se ele é protegido contra gravação ou não.

Este sensor é basicamente um botão, logo podemos conectá-lo à uma interrupção externa do Arduino a qual pode informar nosso software que o cartão foi inserido ou removido. O status do cartão (inserido ou removido) pode ser controlado por uma simples flag.

Abaixo a foto de dois soquetes diferentes, encomendados na Farnell – excelente loja para se comprar componentes eletrônicos no Brasil, quais possuem diferentes contatos, porém ambos permitem a verificação da presença do cartão. Os dois contatos selecionados pela área em amarelo são as conexões que devem ser tratados como dois pinos de um botão. Para mais detalhes de como podemos trabalhar com botões, acesse esse material usado no curso de Arduino que estou ministrando em nossa cidade.

A camada de software – leitura e escrita de arquivos no cartão de memória

Feita a formatação você precisará de uma biblioteca capaz de ler sistema de arquivos FAT16. Fiz testes com várias, mas a primeira que consegui fazer funcionar com o Arduino Mega foi esta: http://code.google.com/p/sdfatlib/. Talvez pelo fato de que as outras assumem que você está com o Arduino padrão Duemilanove.

Olha só, fiz testes agora (10/05/11 às 20:49 kk) e percebi que com a biblioteca padrão do Arduino funciona também. Basta que alteremos o chipSelect para 53 (const int chipSelect = 53;) logo após a inclusão de <SD.h> e que dentro do setup() definamos pinMode(53, OUTPUT). Feito isso, testei aqui e funcionou perfeitamente. Mesmo sendo simples, segue aqui o fonte usado (disponível na instalação padrão da IDE do Arduino):

/*
  SD card datalogger

 This example shows how to log data from three analog sensors
 to an SD card using the SD library.

 The circuit:
 * analog sensors on analog ins 0, 1, and 2
 * SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4

 created  24 Nov 2010
 updated 2 Dec 2010
 by Tom Igoe

 This example code is in the public domain.

 */

#include <SD.h>

// On the Ethernet Shield, CS is pin 4. Note that even if it's not
// used as the CS pin, the hardware CS pin (10 on most Arduino boards,
// 53 on the Mega) must be left as an output or the SD library
// functions will not work.
const int chipSelect = 53;

void setup()
{
  Serial.begin(9600);
  Serial.print("Initializing SD card...");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(53, OUTPUT);

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");
}

void loop()
{
  // make a string for assembling the data to log:
  String dataString = "";

  // read three sensors and append to the string:
  for (int analogPin = 0; analogPin < 3; analogPin++) {
    int sensor = analogRead(analogPin);
    dataString += String(sensor);
    if (analogPin < 2) {
      dataString += ",";
    }
  }

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
    // print to the serial port too:
    Serial.println(dataString);
  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  }
}

Com o arquivo acima carregado no Arduino, ele irá gerar um arquivo chamado datalog.txt dentro do cartão com as informações de leitura dos sensores analógicos 0 à 2. Isso pode ser muito útil para as mais difersas coisas, como por exemplo um logger de sensor de temperatura, direção do vento e umidade do ar.

Faça agora testes com o exemplo ReadWrite da biblioteca do Arduino lembrando sempre de alterar o pino 4, padrão em shields com SD/MMC, para 53 que é o usado no Arduino Mega.

Estudos e melhorias futuras

Com certeza o que apresentei aqui foi só uma introdução ao funcionamento de cartões de memória com Arduino. Entre futuros estudos podemos citar a redução do tamanho da biblioteca para que possa funcionar com o Atmega8, estudo aprofundado do protocolo SPI e quem sabe também, implementar sistema de arquivos ext4.

Referências

[1] http://www.sdcard.org/developers/tech

[2] http://www.sdcard.org/developers/tech/sdcard

[3] http://ww1.microchip.com/downloads/en/devicedoc/spi.pdf

[4] http://arduino.cc/en/Reference/SPI

http://www.interfacebus.com/Multi_Media_Card_Pinout_MMC.html

http://www.ladyada.net/make/logshield/sd.html

http://www.ladyada.net/learn/arduino/ethfiles.html

Minha Reflexão

O custo de um shield SD é alto. Com cerca de 25 centavos (6 resistores) e uma câmera fogográfica/placa mãe de notebook queimada, que tem como destino o lixo, podemos montar um DataLogger funcional e pronto para uso. Se tiveres vontade de montar um adaptador como esse, divirta-se, aprende-se muito fazendo isso! Se gostou deste estudo, comente abaixo, vamos trocar algumas ideias!

170 Comments

  1. Desculpe-me a falta de conhecimento, gostaria de saber se é possivel colocar o arduino na rede com SD card, e através de conexão IP acessar o SD card, já consegui várias coisas com o arduino contudo isso esta parecendo que não é nada fácil. (MEGA2560+ethernet_sdcardSHIELD)
    Agradeço-lhe desde já vossa ajuda.

  2. Tentei o exemplo de ftp mais não obtive sucesso, o que eu preciso é enviar e receber arquivos do sdcard do arduino através de conexão de ethernet.

    Obrigado desde já.

  3. Apesar de vossa ajuda ainda não obtive uma solução, o que preciso é que o arduino tenha uma rotina e transfira os arquivos que ele gravou (datalogger), para um ip fixo na rede a cada 1o minutos, isto é possível? (o ip fixo na rede é meu computador servidor), ou que o meu servidor possa entrar via (ethernet-IP) no arduino e copiar os arquivos do sdcard.

    Desde já agradeço vossa ajuda.

    1. Você pode usar o ethernetShield para isso. O que irá precisar fazer é alternar entre modo salvar dados (usar o cartão sd com arduino) e o modo enviar dados (usar o ethernet Shield). Tudo isso você faz via software usando o pino chip select (de cada módulo) do protocolo SPI.

  4. Ola Paulo, parabéns por seu site, tem me ajudado muito.
    Mais uma ajuda por favor, tenho um arduino uno, um modulo chines de rede enc28j60 e um sd card montado com resistores.
    Por acaso vc já conseguiu conectar tudo isso junto? Digo isso porque os dispositivos são SPI e até agora vi muita teoria mas nada que me ajude a funcionar isso.
    Estou usando o SS do cartão na port 4 e do módulo na porta 10…tem o lance de nível alto e baixo para as portas..para ligar e desligar o módulo..mas nada…ou funciona um ou outro…com programas destintos..mas quando juntos os códigos em 1 só…ao para tudo.
    Pode me ajudar?

    Obrigado

    1. Oi Sergio, fico feliz que o conteúdo aqui tenha lhe sido útil!

      Este problema que você descreve é muito comum, já passei por isso. O que acontece é que ambos trabalham em SPI, e somente um deles pode funcionar ao mesmo tempo. O que você pode fazer é ativar um (através do SS), usá-lo, desativá-lo e então usar o outro módulo. Eles não podem enviar dados para o Arduino ao mesmo tempo, mas você pode ficar intercalando entre módulo ethernet e cartão sd.

      O segredo é usar um de cada vez, fazendo a ativação através dos pinos chip select de cada um deles.

      1. O Paulo, obrigado por sua resposta. Pois é, é isso que venho tentando, mas não consigo fazer esse controle.
        Será que tem algum exemplo?

        Muito obrigado

        Sérgio

        1. Infelizmente não encontrei nenhum tutorial para lhe ajudar Sergio. Sugiro que comece a busca por servidores ftp com Arduino. Esses servidores precisam estar conectados ao cartão e a placa ethernet “ao mesmo tempo”.

          Talvez você encontre o método nestes exemplos. Se encontrar, agradeceria se pudesse trazer o link aqui.

          Bons estudos!

  5. bom dia
    tenho uma dúvida, quais as alterações neste projeto eu precisaria fazer caso eu esteja usando a shield ethernet que vem com slot de cartão Sd ?

  6. Bom dia, é possivel transferir os dados lidos do ethernet shield diretamente para um ficheiro no pc? Recorrendo ao ip do shield?

  7. Amigo me da uma forca… estou usando um ethernet shield conectado a um arduino mega 2560… o problema é… o arduino mega usa.os pinos 50 51 e 52 para acessar o SD que tem no ethernet shield como vou acessar o sd se o sd da placa do ethernet shield nao esta conectado nessas portas do mega? Tem como mudar a biblioteca spi para que o mega acesse o sd pelas portas 11 12 e 13 (como acontece com o arduino uno)?

  8. Da pra usar o micro sd com o adaptador? ou seja um cartão igual ao da imagem só que permite inserir o cartão de memória utilizado em celulares por exemplo.

  9. Bom dia, parabéns pelo artigo. Estou com problema sobre como conectar ethernet e usb host shield (JUNTOS, separadamente já consegui!) no arduino, sei que ambos utilizam comunicação ICSP e pinos 10,11,12,13 gostaria de saber como eu configurar estas placas para correto funcionamento. Projeto é para receber dados de alguns equipamentos pela usb e enviar pela rede. Muito obrigado.

  10. Bom dia, parabéns pelo trabalho excelente.

    Minha dúvida é a seguinte: o pino 7 do cartão SD não necessita da divisão de tensão (resistores)?

    Grato.

  11. Ola Paulo,

    queria ti agradecer pelas informações foram bem uteis, atualmente estou tentando ler um sensor de temperatura e um rtc ds1302 e queria fazer uma logica if, por exemplo que ele leia toda vez que for 6 e 9 horas em ponto, mas sinceramente estou penando

    1. Oi Fernando.

      De uma forma simples, dentro do loop você fica lendo o horário, se for 6 ou 9 horas, você executa determinada função. O RTC retorna hora, minuto, segundo separadamente. É muito útil!

  12. olá paulo!
    gostaria de saber se você já trabalhou com data loggers ? se não trabalhou pode ria me indicar quem faz esse serviço?

    1. Olá Felipe, já trabalhei, mas não faço mais serviços na área.

      Não conheço nenhuma empresa que seja especializada, mas você mesmo pode fazer isso se comprar um Arduino mais um SD shield, é simples e funciona.

  13. ola Paulo, tudo bem? minha duvida acredito ser simples, mas não menos importante para mim , pois já tentei de varias maneiras e ainda não conseguido, ai vai…
    estou trabalhando em um datalogger com cartao SD. queira saber como faço para que o usurario entre no serial monitor com o nome do arquivo quer será gerado.

  14. Bom dia Paulo. Seu site está nota 10. Parabéns.
    Cara preciso de uma ajuda. Estou usando um Arduino Uno para fazer comunicação serial entre duas máquinas. A informação que está sendo passada gostaria de armazenar numa shield SD, porém fiz testes e o arquivo que era guardado no SD card não era o arquivo que eu gostaria de enviar (ele criou um arquivo prórpio em vez de armazenar o que eu queria) Como posso solucionar esse problema? E como posso fazer com que esse arquivo seja enviado para a outra máquina? Aguardo resposta e muito obrigado. Abraço!

  15. Bom dia Paulo, gostei muito da sua pagina, mas gostaria de saber se pode me ajudar, ontem durante alguns testes com a base WriteRead do SD, até gravou a mensagem “testing 1, 2, 3.” só que depois de alguns testes o mesmo não grava mais a mensagem inteira no SDCard, grava apensas “te”, poderia me ajudar? Será alguma falha no Arduino? Aguardo.

    1. Olá, pode ser algum problema de mau contato, verifique seu circuito.
      Do contrário, começe do zero, faça o exemplo mais simples possível e depois vá evoluindo ele novamente, talvez encontre alguma falha em seu código.

  16. Olá Marcos,
    Kra, muito bom o seu site! Várias vezes já me salvou na minha iniciação ao Arduino. Esse artigo aqui mesmo me abriu a mente para fazer um datalogger para um equipamentozinho que estou projetando. Mas, tenho uma dúvida ainda, minha situação é a seguinte:
    para cada equipamento que eu testo, eu gero no SD uma tabela com os resultados, até aqui td ok!…eu queria era uma rotina para gerar um novo arquivo no SD quando eu passasse dos testes de um equipamento para outro, ou seja, fiz os testes no equip. 1, daí eu aperto um botão, p exemplo, e salvo esses dados no arquivo teste1.doc…daí faço os testes para o segundo equip., aperto novamente o botão e salvo os dados no arquivo teste2.doc….e assim sucessivamente….pelo que estou pensando é possível, mas como sou novo em arduino e programação ainda não consegui desenrolar…..valeu pela ajuda!!

    1. Olá Renato, obrigado pelas considerações ao site!

      Ok, para resolver seu problema é simples: crie uma variável global, chamada contador, e faça com que ao pressionar um botão externo ele incremente ela em + 1. Na rotina que você grava os dados no cartão, gere o nome do arquivo baseado nessa variável contador que você criou.

      Assim, toda vez que for salvar algo ele vai pegar o nome da varíavel, e quando você pressionar o botão, salvará o nome do arquivo diferente da última vez que rodou.
      Bons estudos!

  17. Oi, Paulo
    Eu usei um software similar ao datalogger do site do Arduíno onde eu salvo os dados lidos pelas portas analógicas em um cartão SD, usei uma shield ethernet que traz um slot SD card . Funcionou muito bem. Mas eu retirava o cartao do Arduíno e colocava no PC sempre q eu queria ler os dados gravados. Eu quero saber se eu poderia acessar o cartão diretamente pelarduino.l do Arduíno e ler o meu arquivo no cartão sem retirá-lo da shield, ou seja, ler os arquivos gravados no cartão a partir da USB do arduino

    1. Tem como sim Tacy, mas você vai precisar fazer um software (no pc e no arduino) que se comunique via serial e desenvolver algumas chamadas do tipo: Le-cartão, aí o arduino pode escrever na serial (via usb) tudo que está em determinado arquivo.

  18. Olá amigo, estou fazendo um trabalho de conclusao de curso, para monitorar a temperatura ambiente e 4 sensores ldr para a radiação encima de uma placa fotovoltaica , o problema é que nao sei como fazer um banco de dados com esses valores, precisaria de algo com data e hora, e talvez uma leitura a cada 1 minuto. Estava pensando em usar um cartãoSD para armazenar esses dados, teria algo sobre isso ?

    1. Olá Vitor,
      o que você vai precisar é gravar uma linha de informações no cartão SD com as informações de cada sensor e data/hora separadas por “;”, aí você pode abrir isso no Excel depois. Isso funciona como um simples banco de dados, pois ao abrir num PC as informações estarão bem organizadas.

  19. Boa noite Paulo,
    Tenho uma duvida, se eu tiver uma lista com códigos dentro de um arquivo TXT, e queira que o arduino verifique se o valor lido via serial esta contido na lista, como posso fazer esta verificação?

    1. Boa tarde Rafael,
      recomendo você colocar um código em cada linha no arquivo TXT. Aí você vai precisar ler cada caractere do arquivo txt até encontrar o \n que é a quebra de linha. Com isso, você consegue comparar a linha lida com o código recebido.

  20. Boa noite Paulo,
    Parabéns pelo blog. é de uma ajuda fantástica.
    Preciso de alguma ajuda sua se possível.
    Estou a fazer um projecto de fim de curso e estou com dificuldades em concluir.
    O projecto consiste em utilizar um contador (accionado por um sensor e botões para subtrair e reset ), RTC 1302, LCD com I2C , SD-Card e módulo HI-FI ESP8266 com alternativa Ethernet Shield W5100
    O problema: Há uma incompatibilidade que ainda não descobri como ultrapassar. Quando coloco o programa para SD-Card, tenho que iniciar a porta Serial, mas o contador fica louco e não pára de contar.
    A ideia é: a uma determinada hora, o SD grava o número de peças, envia a contagem para um PC, e o contador recomeça novamente do zero.
    Espero que me possa ajudar. Obrigada.

    1. Olá José, obrigado pelas considerações.
      O que faço quando passo por situações como essa é reduzir ao máximo as possibilidades de erro, ou seja, retirando tudo que não tem relação com o problema. Tente começar com um código simples que faça leitura dos dados e envie via serial, depois vá adicionando os outros componentes e isolando os problemas, vai chegar um momento em que a falha se tornará óbvia.

  21. Boa noite! Instalei o módulo SD Card no Arduíno Mega 2560, mas estou com um problema: não estou conseguindo gravar os dados no arquivo de texto que é iniciado. Na porta serial diz que tudo foi iniciado com sucesso (SD Card e arquivo aberto com sucesso) porém quando retiro o cartão de memória do módulo, o arquivo de texto está em branco sem nenhum dado gravado. Além disso, há 20 dias eu fiz vários testes e todos ocorreram com sucesso, ou seja, os dados estavam sendo gravados corretamente. Daí fiquei sem mexer no arduíno durante esse tempo e quando coloquei novamente para funcionar hoje os dados não estavam sendo mais gravados, sendo que o código de programação era o mesmo. Você teria alguma sugestão pra que eu possa resolver esse problema, amigo?

Leave a Reply