domingo, 29 de março de 2015

Usando FatFs com Arduino

Introdução

O Arduino divide opiniões quando o assunto é desenvolvimento de pequenos sistemas embarcados. Alguns amam a plataforma e todo o 'ecossistema' criado a seu redor, enquanto outros odeiam, por considerar que as facilidades de uso acabam escravizando os usuários à plataforma, tornando-os incapazes de fazer qualquer coisa para a qual não haja uma biblioteca pronta, mas mesmo esses últimos reconhecem que como ferramenta de prototipação o Arduino é fantástico.

Entre as 'bibliotecas prontas' do Arduino existe uma para lidar com cartões SD que é bastante completa, porém é muito complicado utilizar as bibliotecas do Arduino fora do ambiente do Arduino, por causa da interdependência entre suas bibliotecas.

Por outro lado existe uma biblioteca de Fat de código aberto que é muito poderosa chamada FatFs e que pode ser facilmente portada para várias plataformas, inclusive para o Arduino.

O objetivo deste artigo é adaptar a FatFs para funcionar como uma biblioteca do Arduino de forma a permitir utiliza-lo (o Arduino) como plataforma de desenvolvimento ou de prototipagem para projetos envolvendo cartões SD e sistemas de arquivos FAT.

A FatFs 

FatFs é uma biblioteca genérica de FAT criada pelo ChaN com o objetivo de ser utilizada em em microcontroladores e outros sistemas embarcados de pequeno porte. Entre suas principais características cabe destacar:
  •   Portabilidade;
  •  Atualizações e otimizações constantes ;
  •  Licença de uso.
  A portabilidade é a primeira característica a chamar atenção. É extremamente fácil portar a FatFs para várias plataformas por causa de dois fatores considerados pelo autor durante o desenvolvimento da biblioteca:
  1. Código totalmente escrito em ANSI C: Praticamente qualquer compilador C é capaz de compilar a FatFS;
  2. Segregação: As funções que lidam com o sistema de arquivos e as que acessam o 'hardware' são completamente  segregadas. Isso faz com que o 'port' para outras plataformas se resuma a implementar algumas poucas chamadas de acesso ao hardware para acesso aos dados gravados na mídia;

As atualizações são outro ponto importante. Desde a primeira versão disponibilizada em fevereiro de 2006  até a versão mais atual (considerando momento em que escrevo este artigo), de fevereiro de 2015 a biblioteca já recebeu 26 atualizações, sendo a maioria delas com a agregação de novos recursos, inclusive um 'spinoff' de código chamado PetitFatFs que ocupa bem menos espaço de código e pode ser utilizado em dispositivos com pouquíssima memória RAM (que nem precisa ser capaz de conter 1 setor inteiro de disco). Além disso existe um fórum de discussões bem ativo onde se pode tirar dúvidas ou enviar sugestões.

A licença da FatFs é outra característica importante para quem precisa de uma biblioteca de FAT para uso profissional. A fim de permitir maior usabilidade em produtos comerciais, a licença desobriga a distribuição do código fonte junto com o binário, ao estilo da licença BSD de cláusula única. 

A FatFs é distribuída num pacote contendo o código fonte com implementação para diversas plataformas inclusive uma versão 'AVR_foolproof' já com as funções de baixo nível implementadas e compatíveis com vários microcontroladores da família AVR. É esta versão que vai ser adaptada para uso com o Arduino.

 Atividades


 A primeira tarefa criar uma pasta chamada 'FatFs' dentro do diretóro '/libraries' da instalação do Arduino e copiar para dentro desta pasta os arquivos do diretório '/avr_foolproof' do pacote da FatFs.

Copiar da pasta /avr_foolproof para o diretório /libraries da IDE do Arduino
Em seguida retire os arquivos 'main.c' e 'Makefile' pois eles atrapalham na hora de fazer a compilação. O  'Makefile' pode ser apagado. Já o  'main.c' ainda vai ser utilizado como base para o nosso 'sketch' de teste

Remova os arquivos 'main.c' e 'Makefile' da pasta '/libraries/FatFs'


A segunda tarefa necessária é descobrir a pinagem do 'shield' com o soquete para o cartão SD. No caso do 'shield' ethernet/SD da DF Robot a documentação é muito ruim, pois o esquema da placa não mostra as funções dos pinos do cartão SD nem identifica os pinos/'headers' do Arduino.


Diagrama parcial do 'shield' da DF-Robot

O jeito foi utilizar o multímetro para identificar a conexão entre os pinos do cartão SD e os pinos dos 'headers' do Arduino e então fazer a correspondência ao Pino e Porta do ATMega328. Os pinos marcados em AZUL são os pinos utilizados para a comunicação em modo SPI.

Correspondência entre pinos do soquete SD/MMC e o ATMega328
 Com os pinos identificados, o segundo passo é abrir o arquivo 'sdmm.c' e incluir as definições dos pinos de acordo com o 'shield'.

Incluir as definições dos pinos
 Em seguida substitua as macros existentes, responsáveis pela troca de estado e leitura dos pinos, pelas macros mais genéricas. Cabe notar que a ativação do 'pull-up' no pino de entrada de sinal é fundamental para que a comunicação com o cartão SD funcione caso, é claro, o 'shield' não possua este resistor.


Editar as macros que cuidam da mudança de estado e leitura dos pinos de I/O
A biblioteca original permite o uso com cristais até 14MHz. Como o Arduino roda a 16MHz é necessário incluir as linhas abaixo na função dly_us()

Modificação para suportar operação a 16Mz

Salve o arquivo e abra o 'ffconf.h' para fazer duas alterações. A primeira delas é mudar a configuração da definição responsável por remover algumas funções da biblioteca a fim de economizar espaço. Como a função  a função 'f_lseek()' é bem útil vamos mantê-la alterando a definição _FS_MINIMIZE para o valor '2'.

Modifique a opção _FS_MINIMIZE para manter a função f_lseek()

A próxima alteração é na definição _CODE_PAGE. Vamos alterar do original (japonês) para o latino (Code Page 850).

Modifique o 'Code Page' para Latino em vez de Japonês

Salve o arquivo e abra a IDE do Arduino para criar um novo projeto. Em seguida faça as modificações conforme a figura abaixo. A maioria das linhas pode ser copiada de dentro do arquivo 'main.c' que retiramaos da pasta '/libraries/fatfs'.


Modificações necessárias a partir de um 'sketch' básico

Em seguida compile (verifique) o 'sketch'.

Eis o 'sketch' de teste completo. Após compilado ele ocupa 11K

Agora insira um cartão SD no soquete e faça o 'upload' do sketch para o Arduino. Assim que terminar abra o terminal serial e após alguns instantes (o tempo que demora para o Arduino dar 'timeout' no 'bootloader') a palavra "Sucesso" deve aparecer no terminal indicando que tudo deu certo.


Conclusão:

 A biblioteca de FAT após compilada com as configurações que fizemos vai ocupar aproximadamente 11Kbytes de Flash. É meio grandinho, mas é uma biblioteca de FAT completa com várias funções integradas. Caso algumas destas funções não sejam desejadas, o tamanho do código gerado pode ser reduzido, ficando entre 4,6K e 13,3K de código, mas devemos adicionar nesta soma os recursos que as demais bibliotecas do Arduino consomem. Em nosso exemplo somente o uso da porta serial mais o print ocupam 1,8K de código.


Links:

Site do ChaN
Artigo sobre a FatFS e a PetitFatFs
Nota de Aplicação da FatFS
Download dos exemplos de aplicação, incluindo o utilizado aqui.
Download do Sketch que usei para testes (que é um pouco mais completo)
Donload dos arquivos sdmm.c e ffconf.h já modificados.

















2 comentários:

Code Master disse...

Olá amigo! Primeiramente, obrigado pela ajuda!

Estou trabalhando em um projeto, e necessito armazenar informações referente a alguns sensores. Estou utilizando um Atmega16, e ele faz comunicação SPI com um cartão SD.

Já faz um tempo que estou tentando armazenar informações no cartão, utilizando a biblioteca FatFs, a mesma que você usou no tutorial. Mas, o código, está lançando o erro: "ErrorCode=3".

No arquivo "ff.h", na struct "FRESULT", contém a variável que referencia este erro. Seu nome é: "FR_NOT_READY". Ela nos diz que a unidade física não pode trabalhar...

Para testar meu circuito, mais precisamente a comunicação SPI entre o microcontrolador e o cartão SD, utilizei outro código que faz a leitura de um arquivo no cartão... e ocorreu tudo certo! Então a comunicação está Ok!

Agora, depois de ler seu tutorial, testei o circuito usando um Arduino MEGA, com seu código, porém sem sucesso! Ocorre o mesmo erro.

O que você acha que está acontecendo? Já testei dois cartões SD, e nada... Eles estão no formato FAT16. Tentei criar uma imagem dentro do cartão, e nada... como formatou?

Obrigado amigo! Abraço.

DVM - Delphi Virtual Machine disse...

Será que seus cartões estão Ok? Ou os pinos do uPC que vc. está usando estão Ok tambem?
Se já testou ou conseguiu fazer funcionar deixe uma resposta.
Obrigado.
Euclides.