# Adafruit Adalogger FeatherWing

## Overview

![](https://cdn-learn.adafruit.com/assets/assets/000/035/520/medium800/feather_2922-05.jpg?1473134030)

A Feather board without ambition is a Feather board without FeatherWings! This is the **Adalogger FeatherWing** : it adds both a battery-backed Real Time Clock and micro SD card storage to any Feather main board. Using our [Feather Stacking Headers](https://www.adafruit.com/products/2830) or [Feather Female Headers](http://www.adafruit.com/products/2886) you can connect a FeatherWing on top of your Feather board and let the board take flight!

![](https://cdn-learn.adafruit.com/assets/assets/000/035/521/medium800/feather_2922-01.jpg?1473134035)

This FeatherWing will make it real easy to add datalogging to any of our existing Feathers. You get both an I2C real time clock (PCF8523) with 32KHz crystal and battery backup, and a microSD socket that connects to the SPI port pins (+ extra pin for CS). Tested and works great with _any_ of our Feathers, based on ATmega32u4,&nbsp; ATmega328P, ATSAMD21, ATSAMD51, nRF52, Teensy, or ESP32/ESP8266.

![](https://cdn-learn.adafruit.com/assets/assets/000/035/523/medium800/feather_2922-03.jpg?1473134045)

We recommend the Arduino's default SD library to talk to the microSD card socket. On ESP8266, the SD CS pin is on GPIO 15, on Atmel M0, M4, 328P or 32u4 it's on GPIO 10. You can cut the trace to the default pin and change this to any pin. To use the RTC, [use our RTClib library](https://github.com/adafruit/RTClib).&nbsp; If you need a[precision RTC, check out our DS3231 FeatherWing](https://www.adafruit.com/products/3028)

![](https://cdn-learn.adafruit.com/assets/assets/000/035/522/medium800/feather_2922-02.jpg?1473134041)

Great for any kind of datalogging or even data _reading_! Some light soldering is required to attach the headers onto the 'Wing but it's a 10 minute task.

# Adafruit Adalogger FeatherWing

## Pinouts

![](https://cdn-learn.adafruit.com/assets/assets/000/035/524/medium800/feather_feathpin.jpg?1473134134)

Evern though every pin from the Feather is 'doubled up' with an inner header, not all of the pins are actually used!

# Power Pins
![](https://cdn-learn.adafruit.com/assets/assets/000/035/616/medium800/feather_power.jpg?1473271428)

On the bottom row, the **3.3V** (second from left) and **GND** (fourth from left) pin are used to power the SD card and RTC (to take a load off the coin cell battery when main power is available)

# RTC & I2C Pins
![](https://cdn-learn.adafruit.com/assets/assets/000/035/526/medium800/feather_i2c.jpg?1473134281)

In the top right, **SDA** (rightmost) and **SCL** (to the left of SDA) are used to talk to the RTC chip.

- **SCL** - I2C clock pin, connect to your microcontrollers I2C clock line. This pin has a 10K pullup resistor to 3.3V
- **SDA** - I2C data pin, connect to your microcontrollers I2C data line. This pin has a 10K pullup resistor to 3.3V

These pins are in the same location on every Feather

![](https://cdn-learn.adafruit.com/assets/assets/000/035/529/medium800/feather_int.jpg?1473134699)

There's also a breakout for **INT** which is the output pin from the RTC. It can be used as an interrupt output or it could also be used to generate a square wave.

Note that this pin is **open drain** - you must enable the internal pullup on whatever digital pin it is connected to!

# SD & SPI Pins
![](https://cdn-learn.adafruit.com/assets/assets/000/035/527/medium800/feather_spi.jpg?1473134394)

Starting from the left you've got

- **SPI Clock** (SCK) - output from feather to wing
- **SPI**  **M** icrocontroller **O** ut **S** ensor **I** n&nbsp;(MOSI) - output from feather to wing
- **SPI**  **M** icrocontroller **I** n **S** ensor **O** ut&nbsp;(MISO) - input from wing to feather

These pins are in the same location on every Feather. They are used for communicating with the SD card. When the SD card is not inserted, these pins are completely free. MISO is tri-stated whenever the **SD**  **CS** pin is pulled high

The **SDCS** pin is the chip select line.

- On ESP8266, the SD CS pin is on GPIO **15**
- On ESP32 it's GPIO **33**
- On WICED it's&nbsp;GPIO **PB5**
- On the nRF52832 it's&nbsp;GPIO **11**
- On Atmel M0, M4, 328p or 32u4 it's on GPIO **10**
- On Teensy 3.x it's on GPIO **10**

**Some users report ESP32 variants may use GPIO10 instead. For the FeatherS3, users report GPIO3.**

You can cut the trace to the default pin and change this to any pin by soldering a wire to any available pad.

![](https://cdn-learn.adafruit.com/assets/assets/000/035/528/medium800/feather_sdcs.jpg?1473134564)

# Adafruit Adalogger FeatherWing

## Assembly

When putting together your Featherwings, think about how you want it to connect, you can use stacking headers:

![](https://cdn-learn.adafruit.com/assets/assets/000/035/531/medium800/feather_adafruit_products_2830-00.jpg?1473134895)

Or plain female socket headers:

![](https://cdn-learn.adafruit.com/assets/assets/000/035/532/medium800/feather_adafruit_products_2886-00.jpg?1473134901)

The most common method of attachment for the featherwing is putting stacking or female headers on the _Feather mainboard_ and then putting the Wing on top:

![](https://cdn-learn.adafruit.com/assets/assets/000/035/530/medium800/feather_2922-00.jpg?1473134868)

But don't forget, you can **also put the stacking headers on the wing and stack the Feather on top of it!**

# Adafruit Adalogger FeatherWing

## Using the Real Time Clock

## What is a Real Time Clock?

When logging data, it's often really really useful to have timestamps! That way you can take data one minute apart (by checking the clock) or noting at what time of day the data was logged.

The Arduino IDE does have a built-in timekeeper called **millis()** and theres also timers built into the chip that can keep track of longer time periods like minutes or days. So why would you want to have a separate RTC chip? Well, the biggest reason is that **millis()** only keeps track of time _since the Feather was last powered **-** _ that means that when the power is turned on, the millisecond timer is set back to 0. The Feather doesnt know its 'Tuesday' or 'March 8th' all it can tell is 'Its been 14,000 milliseconds since I was last turned on'.

OK so what if you wanted to set the time? You'd have to program in the date and time and you could have it count from that point on. But if it lost power, you'd have to reset the time. Much like very cheap alarm clocks: every time they lose power they blink **12:00**

While this sort of basic timekeeping is OK for some projects, a data-logger will need to have **consistent timekeeping that doesnt reset when the power goes out or is reprogrammed**. Thus, we include a separate RTC! The RTC chip is a specialized chip that just keeps track of time. It can count leap-years and knows how many days are in a month, but it doesn't take care of Daylight Savings Time (because it changes from place to place)

![](https://cdn-learn.adafruit.com/assets/assets/000/035/533/medium800/feather_adafruit_products_Realtimeclock_Motherboard_Baby_AT_crop.jpg?1473135026)

_This image shows a computer motherboard with a Real Time Clock called the [DS1387](http://www.maxim-ic.com/app-notes/index.mvp/id/503). Theres a lithium battery in there which is why it's so big._

The RTC we'll be using is the _[PCF8523](http://www.nxp.com/products/interface-and-connectivity/interface-and-system-management/i2c-bus-portfolio/i2c-real-time-clocks-rtc/real-time-clock-rtc-and-calendar:PCF8523)_

# Battery Backup

As long as it has a coin cell to run it, the RTC will merrily tick along for a long time, even when the Feather loses power, or is reprogrammed.

Use any CR1220 3V lithium metal coin cell battery:

### CR1220 12mm Diameter - 3V Lithium Coin Cell Battery

[CR1220 12mm Diameter - 3V Lithium Coin Cell Battery](https://www.adafruit.com/product/380)
These are the highest quality & capacity batteries, the same as shipped with the iCufflinks,&nbsp;iNecklace, Datalogging and GPS Shields, GPS HAT, etc. One battery per order (you'll want one battery per cufflink or pendant.)  
  
Brand may vary but all battery brands are verified...

In Stock
[Buy Now](https://www.adafruit.com/product/380)
[Related Guides to the Product](https://learn.adafruit.com/products/380/guides)
![Angled shot of CR1220 12mm Diameter - 3V Lithium Coin Cell Battery - CR1220.](https://cdn-shop.adafruit.com/640x480/380-01.jpg)

Warning: 

![](https://cdn-learn.adafruit.com/assets/assets/000/035/534/medium800/feather_coin.jpg?1473135082)

# Adafruit Adalogger FeatherWing

## RTC with Arduino

# Wiring

Wiring it up is easy, connect it up as shown below.

- **GND** to **GND (black wire on STEMMA QT version)** on your board 
- **VCC (red wire on STEMMA QT version)** to the logic level power of your board (on classic Arduinos & Metros use 5V, on 3.3V devices use 3.3V)
- **SDA** to the **SDA (blue wire on STEMMA QT version)** i2c data pin
- **SCL** to the **SCL (yellow wire on STEMMA QT version)** i2c clock pin

There are internal 10K pull-ups on the PCF8523 on SDA and SCL to the VCC voltage

![adafruit_products_PCF8523_QT_Arduino_STEMMA_bb.jpg](https://cdn-learn.adafruit.com/assets/assets/000/103/717/medium640/adafruit_products_PCF8523_QT_Arduino_STEMMA_bb.jpg?1628027533)

![adafruit_products_PCF8523_QT_Arduino_breadboard_bb.jpg](https://cdn-learn.adafruit.com/assets/assets/000/103/718/medium640/adafruit_products_PCF8523_QT_Arduino_breadboard_bb.jpg?1628030607)

![adafruit_products_PCF8523_Arduino_wiring.png](https://cdn-learn.adafruit.com/assets/assets/000/103/719/medium640/adafruit_products_PCF8523_Arduino_wiring.png?1628030618)

[pcfmetro Fritzing](https://cdn-learn.adafruit.com/assets/assets/000/047/734/original/pcfmetro.fzz?1509306338)
# Talking to the RTC

The RTC is an i2c device, which means it uses 2 wires to to communicate. These two wires are used to set the time and retrieve it.

For the RTC library, we'll be using a fork of JeeLab's excellent RTC library **,** [which is available on GitHub](https://github.com/adafruit/RTClib).&nbsp;You can do that by visiting the github repo and manually downloading or, easier go to the **Arduino Library Manager**

![](https://cdn-learn.adafruit.com/assets/assets/000/047/724/medium800/circuitpython_libmanage.png?1509302390)

Type in **RTClib** - and find the one that is by **Adafruit** and click **Install**

![](https://cdn-learn.adafruit.com/assets/assets/000/047/725/medium800/circuitpython_lib.png?1509302433)

Warning: 

We also have a great tutorial on Arduino library installation at:  
http://learn.adafruit.com/adafruit-all-about-arduino-libraries-install-use

Once done, restart the IDE

# First RTC test

The first thing we'll demonstrate is a test sketch that will read the time from the RTC once a second. We'll also show what happens if you remove the battery and replace it since that causes the RTC to halt. So to start, remove the battery from the holder while the Feather is not powered or plugged into USB. Wait 3 seconds and then replace the battery. This resets the RTC chip. Now load up the matching sketch for your RTC

Open up **Examples-\>RTClib-\>pcf8523**

Upload it to your board _with the PCF8523 breakout board or FeatherWing connected_

![](https://cdn-learn.adafruit.com/assets/assets/000/047/726/medium800/circuitpython_feather_example.png?1509302575)

Now open up the Serial Console and make sure the baud rate is set correctly at **57600 baud** you should see the following:

![](https://cdn-learn.adafruit.com/assets/assets/000/047/727/medium800/circuitpython_feather_rtcnotrunning.png?1509302620)

Whenever the RTC chip loses all power (including the backup battery) it will reset to an earlier date and report the time as 0:0:0 or similar. Whenever you set the time, this will kickstart the clock ticking.

So, basically, the upshot here is that you should never ever remove the battery once you've set the time. You shouldn't have to and the battery holder is very snug so unless the board is crushed, the battery won't 'fall out'

# Setting the time

With the same sketch loaded, uncomment the line that starts with **RTC.adjust** like so:

```
  if (! rtc.initialized()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date &amp; time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
```

This line is very cute, what it does is take the Date and Time according the computer you're using (right when you compile the code) and uses that to program the RTC. If your computer time is not set right you should fix that first. Then you must press the **Upload** button to compile and then immediately upload. If you compile and then upload later, the clock will be off by that amount of time.

Then open up the Serial monitor window to show that the time has been set

![](https://cdn-learn.adafruit.com/assets/assets/000/047/728/medium800/circuitpython_feather_rtcset.png?1509302662)

From now on, you won't have to ever set the time again: the battery will last 5 or more years

# Reading the time

Now that the RTC is merrily ticking away, we'll want to query it for the time. Let's look at the sketch again to see how this is done

```
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();
```

There's pretty much only one way to get the time using the RTClib, which is to call **now()**, a function that returns a DateTime object that describes the year, month, day, hour, minute and second when you called **now()**.

There are some RTC libraries that instead have you call something like **RTC.year()** and **RTC.hour()** to get the current year and hour. However, there's one problem where if you happen to ask for the minute right at **3:14:59** just before the next minute rolls over, and then the second right after the minute rolls over (so at **3:15:00** ) you'll see the time as **3:14:00** which is a minute off. If you did it the other way around you could get **3:15:59** - so one minute off in the other direction.

Because this is not an especially unlikely occurance - particularly if you're querying the time pretty often - we take a 'snapshot' of the time from the RTC all at once and then we can pull it apart into **day()** or **second()** as seen above. It's a tiny bit more effort but we think its worth it to avoid mistakes!

We can also get a 'timestamp' out of the DateTime object by calling **unixtime** which counts the number of seconds (not counting leapseconds) since midnight, January 1st 1970

```
    Serial.print(" since 2000 = ");
    Serial.print(now.unixtime());
    Serial.print("s = ");
    Serial.print(now.unixtime() / 86400L);
    Serial.println("d");
```

Since there are 60\*60\*24 = 86400 seconds in a day, we can easily count days since then as well. This might be useful when you want to keep track of how much time has passed since the last query, making some math a lot easier (like checking if it's been 5 minutes later, just see if **unixtime()** has increased by 300, you dont have to worry about hour changes)

# Adafruit Adalogger FeatherWing

## RTC with CircuitPython

# Wiring

Wiring it up is easy, connect it up as shown below.

- **GND** to **GND** on your board
- **VCC** to the logic level power of your board - every CircuitPython board uses 3.3V
- **SDA** to the **SDA** i2c data pin
- **SCL** to the **SCL** i2c clock pin

There are internal 10K pull-ups on the PCF8523 on SDA and SCL to the VCC voltage

![adafruit_products_PCF8523_QT_Arduino_STEMMA_bb.jpg](https://cdn-learn.adafruit.com/assets/assets/000/125/995/medium640/adafruit_products_PCF8523_QT_Arduino_STEMMA_bb.jpg?1699494463)

![adafruit_products_PCF8523_QT_Arduino_breadboard_bb.jpg](https://cdn-learn.adafruit.com/assets/assets/000/125/996/medium640/adafruit_products_PCF8523_QT_Arduino_breadboard_bb.jpg?1699494538)

![adafruit_products_PCF8523_Arduino_wiring.png](https://cdn-learn.adafruit.com/assets/assets/000/125/997/medium640/adafruit_products_PCF8523_Arduino_wiring.png?1699494393)

# Adafruit CircuitPython Library Install

To use the RTC sensor&nbsp;with your&nbsp;[Adafruit CircuitPython](../../../../welcome-to-circuitpython/)&nbsp;board you'll need to install the&nbsp;[Adafruit\_CircuitPython\_PCF8523](https://github.com/adafruit/Adafruit_CircuitPython_PCF8523) module on your board.

First make sure you are running the&nbsp;[latest version of Adafruit CircuitPython](../../../../welcome-to-circuitpython/installing-circuitpython)&nbsp;for your board.

Next you'll need to install the necessary libraries&nbsp;to use the hardware--carefully follow the steps to find and install these libraries from&nbsp;[Adafruit's CircuitPython library bundle](https://github.com/adafruit/Adafruit_CircuitPython_Bundle).&nbsp; Our introduction guide has&nbsp;[a great page on how to install the library bundle](../../../../welcome-to-circuitpython/circuitpython-libraries)&nbsp;for both express and non-express boards.

Remember for non-express boards like the, you'll need to manually install the necessary libraries from the bundle:

- **adafruit\_bus\_device** folder
- **adafruit\_register** folder
- **adafruit\_pcf8523.mpy**

Before continuing make sure your board's **lib** folder or root filesystem has the&nbsp; **adafruit\_pcf8523.mpy** module, the&nbsp; **adafruit\_register** folder, and the&nbsp; **adafruit\_bus\_device** folder copied over.

![](https://cdn-learn.adafruit.com/assets/assets/000/047/732/medium800/circuitpython_libs.png?1509305137)

# Usage

To&nbsp;demonstrate the usage of the PCF8523 module you can connect to your board's serial REPL to see the output while saving our example sketch to **code.py**

Next&nbsp;[connect to the board's serial REPL&nbsp;](../../../../welcome-to-circuitpython/the-repl)so you are at the CircuitPython&nbsp; **\>\>\>** &nbsp;prompt.

Then save this script to **code.py** (back up or remove whatever was there before)

https://github.com/adafruit/Adafruit_CircuitPython_PCF8523/blob/main/examples/pcf8523_simpletest.py

# Setting the time

The first time you run the program, you'll need to **set the time**

find these lines:

https://github.com/adafruit/Adafruit_CircuitPython_PCF8523/blob/1b60cc4fb62a867a3649b94971dc78a4c3cdad48/examples/pcf8523_simpletest.py#L22-L29

Change the **False** to **True** in the first line, and update the `time.struct_time` to have the current time starting from `year` to `weekday`. The last two entries can stay at -1

Re-run the sketch by saving and you'll see this out of the REPL:

![](https://cdn-learn.adafruit.com/assets/assets/000/047/729/medium800/circuitpython_replout.png?1509304605)

Note the part where the program says it is **Setting time to:**

Now you can go back and change the if **True** to if **False** and save, so you don't re-set the RTC again.

The script will now output the time and date

![](https://cdn-learn.adafruit.com/assets/assets/000/047/730/medium800/circuitpython_replou2.png?1509304622)

# Adafruit Adalogger FeatherWing

## Using the SD Card

The other half of the adalogger FeatherWing is the SD card. The SD card is how we store long term data. While the Feather may have a permanent EEPROM storage, its only a couple hundred bytes - tiny compared to a 2 gig SD card. SD cards are so cheap and easy to get, its an obvious choice for long term storage so we use them for the 'Wing!

The FeatherWing kit doesn't come with an SD card but [we carry one in the shop that is guaranteed to work](http://www.adafruit.com/index.php?main_page=product_info&cPath=18&products_id=102). Pretty much any SD card should work but be aware that some cheap cards are 'fakes' and can cause headaches.

You'll also need a way to read and write from the SD card. Sometimes you can use your camera and MP3 player - when its plugged in you will be able to see it as a disk. Or you may need an [SD card reader](http://www.adafruit.com/products/939). The Wing **doesnt** have the ability to display the SD card as a 'hard disk' like some MP3 players or games, the Feather does not have the hardware for that, so you will need an external reader!

## Formatting under Windows/Mac

If you bought an SD card, chances are it's already pre-formatted with a FAT filesystem. However you may have problems with how the factory formats the card, or if it's an old card it needs to be reformatted. The Arduino SD library we use supports both **FAT16** and **FAT32** filesystems.

If you have a very small SD card, say 8-32 Megabytes you might find it is formatted **FAT12** which isn't supported. You'll have to reformat these card. Either way, it's **always** good idea to format the card before using, even if it's new! Note that formatting will erase the card so save anything you want first.

Cards above 32GB cannot use FAT16 so try to keep your card use to 32GB and below.

Warning: 

The official SD formatter is available from[https://www.sdcard.org/downloads/formatter\_4/](https://www.sdcard.org/downloads/formatter_4/)

Download it and run it on your computer, there's also a manual linked from that page for use

[Download the official SD Formatter software for Windows](https://www.sdcard.org/downloads/formatter_4/)
# Basic SD Card Test

The Arduino SD Card library has a built in example that will help you test the Wing and your connections

Open the file **listfiles** example sketch in the **SD** library:

![](https://cdn-learn.adafruit.com/assets/assets/000/099/276/medium800/adafruit_products_sdcard_screen1.jpg?1612482812)

This sketch will not write any data to the card, just list the contents. This can be **very** useful when trying to figure out whether an SD card is supported. Before trying out a new card, please try out this sketch!

Scroll to the line where you see `SD.begin()` and change the value in the parentheses to match the chip select (CS) pin for your board.

- On ESP8266, the SD CS pin is on GPIO 15
- On Atmel M0, M4, 328p or 32u4 it's on GPIO 10
- On Teensy 3.x it's on GPIO 10
- On STM32F2/WICED, its on PB5
- On ESP32, it's on GPIO 33
- On nRF52832, it's on GPIO 11
- On nRF52840, it's on GPIO 10
- On ESP32-C6, its on GPIO 8

![](https://cdn-learn.adafruit.com/assets/assets/000/099/278/medium800/adafruit_products_sdcard_screen2.jpg?1612483271)

OK, now insert the micro SD card into the FeatherWing and upload the sketch.

![](https://cdn-learn.adafruit.com/assets/assets/000/035/540/medium800/feather_2922-05.jpg?1473135401)

Open up the **Serial Monitor** and you should see a listing of the files and folder layout. The specifics will depend on the card contents, but should look something like:

![](https://cdn-learn.adafruit.com/assets/assets/000/099/279/medium800/adafruit_products_Screenshot_from_2021-02-04_16-02-47.png?1612483382)

If you have a bad card, or some other formatting issue, you'll probably see:

![](https://cdn-learn.adafruit.com/assets/assets/000/099/280/medium800/adafruit_products_Screenshot_from_2021-02-04_16-06-03.png?1612483572)

It couldn't even initialize the SD card. This can also happen if there's a soldering error or if the card is _really_ damaged

**If you're having SD card problems, we suggest using the SD formatter mentioned above first to make sure the card is clean and ready to use!**

# Next steps!

Once you know the SD card works, check out the [SD card library](https://www.arduino.cc/en/reference/SD) examples, [SD library documentation](https://www.arduino.cc/en/reference/SD) and [Notes](https://www.arduino.cc/en/Reference/SDCardNotes)!

Warning: 

# Example logging sketch

If you want to try saving data to the SD card in the simplest sketch, try this example. You can adjust the **delay()** to set how often analog data is read from pin **A0** and saved to the SD card. The red LED will blink if there's an error, and the green LED will blink when data is written to the SD card.

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/adalogger/adalogger-logging.ino

Danger: You will need to change the sketch's SD_CS pin to match the SD card's Chip Select pin on your Feather if it is not detected by the code at the beginning of the sketch.

If you really want to make sure you save every data point, ensure there is a

`logfile.flush();`

right after the **logfile.print**'s. The example does this.

However this will cause the adalogger to draw a lot more power, maybe about 3x as much on average (30mA avg rather than about 10mA).&nbsp;

# Adafruit Adalogger FeatherWing

## CircuitPython

Warning: As of CircuitPython 9, a mount point (folder) named **/sd** is required on the **CIRCUITPY** drive. Make sure to create that directory after upgrading CircuitPython.

[Follow these steps to create the /sd directory](https://learn.adafruit.com/adafruit-memento-camera-board/circuitpython-memento-starter-projects)
## Adafruit CircuitPython Module Install

To use a microSD card with your&nbsp;Adafruit CircuitPython&nbsp;board you'll need to install the&nbsp;[Adafruit\_CircuitPython\_SD](https://github.com/adafruit/Adafruit_CircuitPython_SD)&nbsp;module on your board.&nbsp;

First make sure you are running the&nbsp;[latest version of Adafruit CircuitPython](../../../../welcome-to-circuitpython/installing-circuitpython)&nbsp;for your board.

Next you'll need to install the necessary libraries&nbsp;to use the hardware--carefully follow the steps to find and install these libraries from&nbsp;[Adafruit's CircuitPython library bundle](https://github.com/adafruit/Adafruit_CircuitPython_Bundle).&nbsp; Our introduction guide has&nbsp;[a great page on how to install the library bundle](../../../../welcome-to-circuitpython/circuitpython-libraries)&nbsp;for both express and non-express boards. **Be sure to use the latest CircuitPython Bundle** as it includes an updated version of the SD card module with a few necessary fixes!

[If your board supports **sdcardio**](https://docs.circuitpython.org/en/latest/shared-bindings/support_matrix.html), then this is the preferred method to do things. **sdcardio&nbsp;** is a built-in module on boards that support it, so you don't have to copy it over.

Remember for non-express boards like the Feather M0 Basic, you'll need to manually install the necessary libraries from the bundle:

- **adafruit\_sdcard.mpy**
- **adafruit\_bus\_device**

If your board doesn't support USB mass storage, like the ESP8266, then&nbsp;[use a tool like ampy to copy the file to the board](../../../../micropython-basics-load-files-and-run-code). You can use the latest version of ampy and its&nbsp;[new directory copy command](../../../../micropython-basics-load-files-and-run-code/file-operations#copy-directories-to-board)&nbsp;to easily move module directories to the board.

Before continuing make sure your board's lib folder or root filesystem has the&nbsp; **adafruit\_sdcard.mpy** and **adafruit\_bus\_device&nbsp;** modules&nbsp;copied over.

![](https://cdn-learn.adafruit.com/assets/assets/000/046/756/medium800/micropython_Screen_Shot_2017-09-13_at_2.33.52_PM.png?1506538847)

## Usage

The following section will show how to initialize the SD card and read & write data to it&nbsp;from the board's Python prompt / REPL.&nbsp;

Next&nbsp;[connect to the board's serial REPL&nbsp;](../../../../welcome-to-circuitpython/the-repl)so you are at the CircuitPython&nbsp; **\>\>\>** &nbsp;prompt.

Info: 

## Initialize & Mount SD Card Filesystem Using **sdcardio**

Before using this method, verify that your board supports sdcardio using the [support matrix](https://docs.circuitpython.org/en/latest/shared-bindings/support_matrix.html). If it does not, try using **adafruit\_sdcard&nbsp;** instead.

Before you can use the microSD card you need to initialize its SPI connection and mount its filesystem. First import all the modules we'll need:

```python
import board
import busio
import sdcardio
import storage
```

Next create the SPI bus and a digital output for the microSD card's chip select line (be sure to select the right pin names for your wiring):

```auto
# Use the board's primary SPI bus
spi = board.SPI()
# Or, use an SPI bus on specific pins:
#spi = busio.SPI(board.SD_SCK, MOSI=board.SD_MOSI, MISO=board.SD_MISO)

# For breakout boards, you can choose any GPIO pin that's convenient:
cs = board.D10
# Boards with built in SPI SD card slots will generally have a
# pin called SD_CS:
#cs = board.SD_CS
```

Warning: If you are using some non-standard CircuitPython board, you may need to use specific GPIO pins for MISO and MOSI to get the SPI recognized appropriately

Info: If your SPI chip select pin is different or not defined like SD_CS, put the appropriate pin number in the code, like board.D5.

Note that when you use&nbsp;`sdcardio`,&nbsp;`cs`&nbsp;is a&nbsp;`Pin`&nbsp;object, not a&nbsp;`DigitalInOut`&nbsp;object. If you change your code to use&nbsp;`adafruit_sdcard`, you need to use a&nbsp;`DigitalInOut`&nbsp;object instead.

At this point you're ready to create the microSD card object and the filesystem object:

```auto
sdcard = sdcardio.SDCard(spi, cs)
vfs = storage.VfsFat(sdcard)
```

Notice the&nbsp;`sdcardio`&nbsp;module has a&nbsp;`SDCard`&nbsp;class which contains all the logic for talking to the microSD card at a low level. This class needs to be told the SPI bus and chip select pin in its constructor.

After a&nbsp;`SDCard`&nbsp;instance is created it can be passed to the&nbsp;`storage`&nbsp;module's&nbsp;`VfsFat`&nbsp;class. This class has all the logic for translating CircuitPython filesystem calls into low level microSD card access. Both the&nbsp;`SDCard`&nbsp;and&nbsp;`VfsFat`&nbsp;class instances are required to mount the card as a new filesystem.

Finally you can mount the microSD card's filesystem into the CircuitPython filesystem. For example to make the path&nbsp; **/sd** &nbsp;on the CircuitPython filesystem read and write from the card run this command:

```auto
storage.mount(vfs, "/sd")
```

At this point, you can read and write to the SD card using common Python functions like&nbsp;`open`,&nbsp;`read`, and&nbsp;`write`. The filenames will all begin with&nbsp;`"/sd/"`&nbsp;to differentiate them from the files on the&nbsp; **CIRCUITPY** &nbsp;drive. If you're not familiar, and all this worked, skip ahead to the section labeled&nbsp; **Reading & Writing Data**.

Primary: 

## Initialize & Mount SD Card Filesystem Using **adafruit\_sdcard**

Before you can use the microSD card you need to initialize its SPI connection and mount its filesystem. &nbsp;First import the necessary modules to initialize the SPI and CS line physical connections:

```
import board
import busio
import digitalio
```

Next create the SPI bus and a digital output for the microSD card's chip select line (be sure to select the right pin name or number for your wiring):

```python
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
# Use board.SD_CS for Feather M0 Adalogger
cs = digitalio.DigitalInOut(board.SD_CS)
# Or use a digitalio pin like 5 for breakout wiring:
#cs = digitalio.DigitalInOut(board.D5)
```

Now import modules to access the SD card and filesystem:

```
import adafruit_sdcard
import storage
```

At this point you're ready to create the microSD card object and the filesystem object:

```
sdcard = adafruit_sdcard.SDCard(spi, cs)
vfs = storage.VfsFat(sdcard)
```

Notice the **adafruit\_sdcard** module has a **SDCard** class which contains all the logic for talking to the microSD card at a low level. &nbsp;This class needs to be told the SPI bus and chip select digital IO pin in its initializer.

After a **SDCard** class is created it can be passed to the **storage** module's **VfsFat** class. &nbsp;This class has all the logic for translating CircuitPython filesystem calls into low level microSD card access. Both the **SDCard** and **VfsFat** class instances are required to mount the card as a new filesystem.

Finally you can mount the microSD card's filesystem into the CircuitPython filesystem. &nbsp;For example to make the path **/sd** on the CircuitPython filesystem read and write from the card run this command:

```
storage.mount(vfs, "/sd")
```

The first parameter to the storage.mount command is the **VfsFat** class instance that was created above, and the second parameter is the location within the CircuitPython filesystem that you'd like to 'place' the microSD card. &nbsp;Remember the mount location as you'll need it to read and write files on the card!

Primary: 

## Reading & Writing Data

Once the microSD card is mounted inside CircuitPython's filesystem you're ready to read and write data from it. &nbsp;Reading and writing data is simple using Python's file operations like [open](https://docs.python.org/3/library/functions.html#open), [close](https://docs.python.org/3/library/io.html#io.IOBase.close), [read](https://docs.python.org/3/library/io.html#io.RawIOBase.read), and [write](https://docs.python.org/3/library/io.html#io.RawIOBase.write). &nbsp;The beauty of CircuitPython and MicroPython is that they try to be as similar to desktop Python as possible, including access to files.

For example to create a file and write a line of text to it you can run:

```
with open("/sd/test.txt", "w") as f:
    f.write("Hello world!\r\n")

```

Notice the with statement is used to create a context manager that opens and automatically closes the file. &nbsp;This is handy because with file access you Python you must close the file when you're done or else all the data you thought was written might be lost! &nbsp;

The open function is used to open the file by telling it the path to it, and the mode (w for writing). &nbsp;Notice the path is under **/sd** , **/sd/test.txt**. &nbsp;This means the file will be created on the microSD card that was mounted as that path.

Warning: Starting with CircuitPython 9, the SD card MUST be mapped to /sd on the CircuitPython file system. Create an empty sd directory in the root directory of the CIRCUITPY drive, especially if you get messages complaining of a missing mount point.

Inside the context manager you can access the f variable to operate on the file while it's open. &nbsp;The **write** function is called to write a line of text to the file. &nbsp;Notice that unlike a print statement you need to end the string passed to write with explicit carriage returns and new lines.

You can also open a file and read a line from it with similar code:

```
with open("/sd/test.txt", "r") as f:
    print("Read line from file:")
    print(f.readline())

```

If you wanted to read and print all of the lines from a file you could call **readline** in a loop. &nbsp;Once **readline** reaches the end of the file it will return an empty string&nbsp;so you know when to stop:

```
with open("/sd/test.txt", "r") as f:
    print("Printing lines in file:")
    line = f.readline()
    while line != '':
        print(line)
        line = f.readline()
```

There's even a **readlines** function that will read all of the lines in the file and return them in an array of lines. &nbsp;Be careful though as this means the entire file must be loaded into memory, so if the file is very large you might run out of memory. &nbsp;If you know your file is very small you can use it though:

```
with open("/sd/test.txt", "r") as f:
    lines = f.readlines()
    print("Printing lines in file:")
    for line in lines:
        print(line)

```

Finally one other very common file scenario is opening a file to add new data at the end, or append data. &nbsp;This works exactly the same as in Python and the **open** function can be told you'd like to append instead of erase and write new data (what normally happens with the **w** option for **open** ). &nbsp;For example to add a line to the file:

```
with open("/sd/test.txt", "a") as f:
    f.write("This is another line!\r\n")

```

Notice the **a** option in the open function--this tells Python to add data at the end of the file instead of erasing it and starting over at the top. &nbsp;Try reading the file with the code above to see the new line that was added!

That's all there is to manipulating files on microSD cards with CircuitPython!

Here are a few more complete examples of using a SD card from the [Trinket M0 CircuitPython guides](../../../../adafruit-trinket-m0-circuitpython-arduino/circuitpython-spi-sd-card).&nbsp; These are great as a reference for more SD card usage.

# List Files

Load this into **code.py** (CircuitPython) or **main.py** (MicroPython):

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Introducing_Trinket_M0/Trinket_SDCardList/code.py

Once it's loaded up, open up the REPL (and restart it with ^D if necessary) to get a printout of all the files included. We recursively print out all files and also the filesize. This is a good demo to start with because you can at least tell if your files exist!

![](https://cdn-learn.adafruit.com/assets/assets/000/048/636/medium800/micropython_adafruit_products_sdlist.png?1511808030)

## Logging Temperature

But you probably want to do a little more, lets log the temperature from the chip to a file.

Here's the new script

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Introducing_Trinket_M0/Trinket_SDlogger/code.py

When saved, the Trinket will start saving the temperature once per second to the SD card under the file&nbsp; **temperature.txt**

![](https://cdn-learn.adafruit.com/assets/assets/000/048/638/medium800/micropython_adafruit_products_templog.png?1511808155)

The key part of this demo is in these lines:

```
print("Logging temperature to filesystem")
# append to the file!
while True:
    # open file for append
    with open("/sd/temperature.txt", "a") as f:
        led.value = True   # turn on LED to indicate we're writing to the file
        t = microcontroller.cpu.temperature
        print("Temperature = %0.1f" % t)
        f.write("%0.1f\n" % t)
        led.value = False   # turn off LED to indicate we're done
    # file is saved
    time.sleep(1)
```

This is a slightly complex demo but it's for a good reason. We use&nbsp; **with** &nbsp;(a 'context') to open the file for&nbsp; **a** ppending, that way the file is only opened for the very short time its written to. This is safer because then if the SD card is removed or the board turned off, all the data will be safe(r).

The LED is used to let the person using this know that the temperature is being written, it turns on just before the write and then off right after.

After the LED is turned off the&nbsp; **with** &nbsp;ends and the context closes, the file is safely stored.

# Adafruit Adalogger FeatherWing

## Downloads

# Datasheets and Files

- [EagleCAD PCB files on GitHub](https://github.com/adafruit/Adafruit-Adalogger-FeatherWing-PCB)
- [3D models on GitHub](https://github.com/adafruit/Adafruit_CAD_Parts/tree/main/2922%20FeatherWing%20Adalogger)
- [Fritzing object in Adafruit Fritzing library](https://github.com/adafruit/Fritzing-Library/)
- [PCF8523 product page](http://www.nxp.com/products/interface-and-connectivity/interface-and-system-management/i2c-bus-portfolio/i2c-real-time-clocks-rtc/real-time-clock-rtc-and-calendar:PCF8523)

# Schematic
![](https://cdn-learn.adafruit.com/assets/assets/000/044/116/medium800/feather_schem.png?1500667618)

# Fabrication Print
![](https://cdn-learn.adafruit.com/assets/assets/000/035/545/medium800/feather_fabprint.png?1473135902)


## Featured Products

### Adalogger FeatherWing - RTC + SD Add-on For All Feather Boards

[Adalogger FeatherWing - RTC + SD Add-on For All Feather Boards](https://www.adafruit.com/product/2922)
A Feather board without ambition is a Feather board without FeatherWings! This is the **Adalogger FeatherWing** : it adds both a battery-backed Real Time Clock and micro SD card storage to any Feather main board. Using our [Feather...](https://www.adafruit.com/products/2830)

In Stock
[Buy Now](https://www.adafruit.com/product/2922)
[Related Guides to the Product](https://learn.adafruit.com/products/2922/guides)
### CR1220 12mm Diameter - 3V Lithium Coin Cell Battery

[CR1220 12mm Diameter - 3V Lithium Coin Cell Battery](https://www.adafruit.com/product/380)
These are the highest quality & capacity batteries, the same as shipped with the iCufflinks,&nbsp;iNecklace, Datalogging and GPS Shields, GPS HAT, etc. One battery per order (you'll want one battery per cufflink or pendant.)  
  
Brand may vary but all battery brands are verified...

In Stock
[Buy Now](https://www.adafruit.com/product/380)
[Related Guides to the Product](https://learn.adafruit.com/products/380/guides)
### Header Kit for Feather - 12-pin and 16-pin Female Header Set

[Header Kit for Feather - 12-pin and 16-pin Female Header Set](https://www.adafruit.com/product/2886)
These two&nbsp; **Female&nbsp;Headers** &nbsp;alone are, well, lonely. But pair them with any of our&nbsp;[Feather](https://www.adafruit.com/categories/777)&nbsp;boards and you're in business!

What do they do? They get soldered on either side of the Feather...

Out of Stock
[Buy Now](https://www.adafruit.com/product/2886)
[Related Guides to the Product](https://learn.adafruit.com/products/2886/guides)
### Short Headers Kit for Feather - 12-pin + 16-pin Female Headers

[Short Headers Kit for Feather - 12-pin + 16-pin Female Headers](https://www.adafruit.com/product/2940)
These two&nbsp; **Short** &nbsp; **Female&nbsp;Headers** &nbsp;alone are, well, lonely. But pair them with any of our&nbsp;[Feather](https://www.adafruit.com/categories/777)&nbsp;boards and you're in business!

These headers are particularly cute and...

Out of Stock
[Buy Now](https://www.adafruit.com/product/2940)
[Related Guides to the Product](https://learn.adafruit.com/products/2940/guides)
### Stacking Headers for Feather - 12-pin and 16-pin female headers

[Stacking Headers for Feather - 12-pin and 16-pin female headers](https://www.adafruit.com/product/2830)
These two **Female Stacking Headers** alone are, well, lonely. But pair them with any of our [Feather](https://www.adafruit.com/categories/777) boards and you're in business!

What do they do? They stack. Put the headers through your Feather and then you can...

Out of Stock
[Buy Now](https://www.adafruit.com/product/2830)
[Related Guides to the Product](https://learn.adafruit.com/products/2830/guides)
### SD/MicroSD Memory Card (8 GB SDHC)

[SD/MicroSD Memory Card (8 GB SDHC)](https://www.adafruit.com/product/1294)
Add mega-storage in a jiffy using this 8 GB class 4 micro-SD card. It comes with a SD adapter so you can use it with any of our shields or adapters. Preformatted to FAT so it works out of the box with our projects. Tested and works great with our <a...></a...>

In Stock
[Buy Now](https://www.adafruit.com/product/1294)
[Related Guides to the Product](https://learn.adafruit.com/products/1294/guides)

## Related Guides

- [Color Sensing Music Player](https://learn.adafruit.com/color-sensing-music-player.md)
- [RP2040 RunCPM Emulator with USB Keyboard & HDMI screen](https://learn.adafruit.com/rp2040-runcpm-emulator-with-usb-keyboard-hdmi-screen.md)
- [Daily Cheer Automaton](https://learn.adafruit.com/daily-cheer-automaton.md)
- [Feather RP2040 DVI CircuitPython Day 2024 Countdown Clock](https://learn.adafruit.com/feather-rp2040-dvi-circuitpython-day-2024-countdown-clock.md)
- [NES Emulator for RP2040 & RP2350 DVI Boards](https://learn.adafruit.com/nes-emulator-for-rp2040-dvi-boards.md)
- [Disconnected CO2 Data Logger](https://learn.adafruit.com/disconnected-co2-data-logger.md)
- [Data Logging with Feather and CircuitPython](https://learn.adafruit.com/data-logging-with-feather-and-circuitpython.md)
- [CircuitPython Hardware: SD Cards](https://learn.adafruit.com/micropython-hardware-sd-cards.md)
- [Plotting Offline Data - JSONL to CSV files, filters and graphs](https://learn.adafruit.com/plotting-offline-data-jsonl-to-csv-files-filters-and-graphs.md)
- [No-Code Offline Data Logger with WipperSnapper](https://learn.adafruit.com/no-code-offline-data-logging-with-wippersnapper.md)
- [Pulse Oximeter Wireless Data Logger](https://learn.adafruit.com/pulse-oximeter-wireless-data-logger.md)
- [Current Limiting Stepper Driver with DRV8871](https://learn.adafruit.com/current-limiting-stepper-driver-with-drv8871.md)
- [Adafruit PCT2075 Temperature Sensor](https://learn.adafruit.com/adafruit-pct2075-temperature-sensor.md)
- [Adafruit CC3000 WiFi](https://learn.adafruit.com/adafruit-cc3000-wifi.md)
- [Adafruit LC709203F LiPoly / LiIon Fuel Gauge and Battery Monitor](https://learn.adafruit.com/adafruit-lc709203f-lipo-lipoly-battery-monitor.md)
