29.02.2016

Arduino 3.3V a SD karta na baterie

Pokud si zakoupíte SD modul, jako je na obrázku níže, můžete zjistit, že jeho spotřeba i při power down režimu je cca 2mA, což není možné provozovat na baterie a není ho proto možné použít pro projekty, kde potřebujete něco logovat ve volné přírodě, nebo prostě tam kde nemáte k dispozici elektrickou síť.

sd card module
typický logger s velkou spotřebou

Dlouho jsem nevěděl, v čem tkví problém. SD karty jsou dělané tak, aby se při nečinnosti samy uspaly. Ty moje (a zkoušel jsem jich několik od SanDisku a Kingstonu) se ale neuspávaly.

Zapojení jsem měl klasické, tedy SPI. Knihovnu pro operace s daty na kartě jsem použil SdFat.
Pokud máte nedostatek paměti, je prý lepší použít knihovnu SD, která má ušetřit pamět, ačkoliv je vlastně wrapperem nad SdFat. Bohužel, v této knihovně je chyba, která nedovoluje opakovaně volat metodu SD.begin(), takže není možné kartu vyjmout a znovu vložit, protože karta by se nechytla a nezbývá než provést reset (i když i to je možnost).
V případě SdFat je možné opakovaně volat metodu SdFat.begin(), takže manipulace vyjmutí a vložení karty nevadí. Metodu doporučuji volat před každou operací nad SD kartou.

Tento článek je ale hlavně o spotřebě. Po měsících tápání, jak spotřebu snížit, jsem zkusil nepoužít modul a zkusil připojit se k SD kartě napřímo. Jelikož je karta 3.3V a moje Arduino Pro Mini rovněž, tak by to neměl být problém. Nevěděl jsem jen, jestli nepoužít nějaké pull-up/pull-down rezistory, ale nakonec to nebylo nutné a fungovalo to!
obvod

Původní modul jsem upravil a okleštil tak, abych měl jen pouzdro, do které se karta vloží. Dráty jsem připájel dle fotky:
upravný modul
Z naznačené SD karty by mělo být zřejmé, že se jedná o spodní stranu.

SPI zapojení

SD pin (dle obrázku) Arduino pin
CS 10 (volitelné)
SCK 13
MOSI 11
MISO 12
VCC 3.3V
GND x 2 GND

Testovací kód

#include "Arduino.h"
#include "SdFat.h"
#include "LowPower.h"
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/wdt.h>

const int chipSelect = 10;

SdFat sd;
SdFile myFile;

void setup() {
    pinMode(chipSelect, OUTPUT);
    Serial.begin(9600);
}

void loop() {
    Serial.println("Loop");
    saveData();
    Serial.flush();
    digitalWrite(chipSelect, HIGH);
    digitalWrite(5, LOW);
    LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
}

void saveData() {
    if (!sd.begin(chipSelect, SPI_FULL_SPEED)) {
        Serial.print("Halting!");
        Serial.flush();
        return;
    }

    if (!myFile.open("test.txt", O_RDWR | O_CREAT | O_AT_END)) {
        sd.errorHalt("opening test.txt for write failed");
    }
    // if the file opened okay, write to it:
    Serial.print("Writing to test.txt...");
    myFile.println("testing 1, 2, 3.");
    // close the file:
    myFile.close();
    Serial.println("done.");
    // re-open the file for reading:
    if (!myFile.open("test.txt", O_READ)) {
        return;
    }
    Serial.println("test.txt:");
    // read from the file until there's nothing else in it:
    int data;
    while ((data = myFile.read()) > 0)
        Serial.write(data);
    // close the file:
    myFile.close();
}

Spotřeba samotné karty mi v power down režimu vycházela okolo 130µA, což je rozdíl! S Arduinem Pro Mini to bylo cca 170µA, což se dá provozovat na baterky.

Závěr

Původní modul není vůbec dobře navržený. Jeho obvod má vliv na to, že se SD karta neuspí. Karta je totiž dělaná pro napětí 5V a proto je tam regulátor napětí. Bohužel, obvod se nějak zapojuje i při použití pinu 3.3V (dalo by se předpokládat že ne, protože obvod vypadá jen jako regulace z 5V na 3.3V a já regulaci nepožaduji - přivádím rovnou 3.3V).
Plánuji proto kupovat jen pouzdra na SD karty (případně pokud již mám v šuplíku adaptér z SD na micro SD , tak i ten) a jednoduše dráty pájet dle tohoto prototypu.