The following example code will show you how use the PiCowbell Adalogger with Arduino to log data from a sensor to a file on an SD card with timestamps from the RTC module. In addition to a Raspberry Pi Pico and PiCowbell Adalogger, you will also need:

  • CR1220 coin cell battery
  • microSD card
  • STEMMA QT cable
  • MCP9808 Temperature Sensor
Angled shot of CR1220 12mm Diameter - 3V Lithium Coin Cell Battery - CR1220.
These are the highest quality & capacity batteries, the same as shipped with the iCufflinks, iNecklace, Datalogging and GPS Shields, GPS HAT, etc. One battery per order...
In Stock
Hand removing/installing micro SD card from SD adapter
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...
In Stock
Angled of of JST SH 4-Pin Cable.
This 4-wire cable is 50mm / 1.9" long and fitted with JST SH female 4-pin connectors on both ends. Compared with the chunkier JST PH these are 1mm pitch instead of 2mm, but...
In Stock
Top view of temperature sensor breakout above an OLED display FeatherWing. The OLED display reads "MCP9808 Temp: 24.19ºC"
The MCP9808 digital temperature sensor is one of the more accurate/precise we've ever seen, with a typical accuracy of ±0.25°C over the sensor's -40°C to...
In Stock
The following example assumes that you followed along with the RTC with Arduino page to set the time with the RTC module and install the RTClib library.


Connect the Raspberry Pi Pico and PiCowbell Adalogger as described in the assembly pages. Next, insert a CR1220 battery into the coin cell battery holder on the PiCowbell Adalogger. Then, insert a microSD card into the PiCowbell Adalogger microSD card slot.

Finally, connect the MCP9808 STEMMA QT board to the PiCowbell Adalogger STEMMA QT port with a STEMMA QT cable.

Library Installation

You can install the Adafruit MCP9808 library for Arduino using the Library Manager in the Arduino IDE.

Click the Manage Libraries ... menu item, search for Adafruit MCP9808 and select the Adafruit MCP9808 library:

If asked about dependencies, click "Install all".

If the "Dependencies" window does not come up, then you already have the dependencies installed. 

If the dependencies are already installed, you must make sure you update them through the Arduino Library Manager before loading the example!

Example Code

// SPDX-FileCopyrightText: 2023 Liz Clark for Adafruit Industries
// SPDX-License-Identifier: MIT

const int _MISO = 16;
const int _MOSI = 19;
const int _CS = 17;
const int _SCK = 18;

#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include "Adafruit_MCP9808.h"
#include "RTClib.h"

RTC_PCF8523 rtc;

char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

// Create the MCP9808 temperature sensor object
Adafruit_MCP9808 tempsensor = Adafruit_MCP9808();

File logfile;

// blink out an error code
void error(uint8_t errno) {
  while(1) {
    uint8_t i;
    for (i=0; i<errno; i++) {
      digitalWrite(LED_BUILTIN, HIGH);
      digitalWrite(LED_BUILTIN, LOW);
    for (i=errno; i<10; i++) {

void setup() {
  while (!Serial);
  Serial.println("\r\nPiCowbell Adalogger Test");

  // Ensure the SPI pinout the SD card is connected to is configured properly

  if (!tempsensor.begin(0x18)) {
    Serial.println("Couldn't find MCP9808! Check your connections and verify the address is correct.");
    while (1);
  Serial.println("Found MCP9808!");


  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1) delay(10);

  if (! rtc.initialized() || rtc.lostPower()) {
    Serial.println("RTC is NOT initialized, let's set the time!");
    // When time needs to be set on a new device, or after a power loss, the
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
    // Note: allow 2 seconds after inserting battery or applying external power
    // without battery before calling adjust(). This gives the PCF8523's
    // crystal oscillator time to stabilize. If you call adjust() very quickly
    // after the RTC is powered, lostPower() may still return true.

  // When time needs to be re-set on a previously configured device, the
  // following line sets the RTC to the date & time this sketch was compiled
  // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  // This line sets the RTC with an explicit date & time, for example to set
  // January 21, 2014 at 3am you would call:
  // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));

  // When the RTC was stopped and stays connected to the battery, it has
  // to be restarted by clearing the STOP bit. Let's do this to ensure
  // the RTC is running.

  float drift = 43; // seconds plus or minus over oservation period - set to 0 to cancel previous calibration.
  float period_sec = (7 * 86400);  // total obsevation period in seconds (86400 = seconds in 1 day:  7 days = (7 * 86400) seconds )
  float deviation_ppm = (drift / period_sec * 1000000); //  deviation in parts per million (μs)
  float drift_unit = 4.34; // use with offset mode PCF8523_TwoHours
  // float drift_unit = 4.069; //For corrections every min the drift_unit is 4.069 ppm (use with offset mode PCF8523_OneMinute)
  int offset = round(deviation_ppm / drift_unit);
  // rtc.calibrate(PCF8523_TwoHours, offset); // Un-comment to perform calibration once drift (seconds) and observation period (seconds) are correct
  // rtc.calibrate(PCF8523_TwoHours, 0); // Un-comment to cancel previous calibration

  Serial.print("Offset is "); Serial.println(offset); // Print to control offset

  // see if the card is present and can be initialized:
  if (!SD.begin(_CS)) {
    Serial.println("initialization failed!");
  Serial.println("initialization done.");

void loop() {
  DateTime now =;
  float c = tempsensor.readTempC();
  float f = tempsensor.readTempF();
  Serial.println("Writing to SD card");
  digitalWrite(LED_BUILTIN, HIGH);

// make a string for assembling the data to log:
  String dataString = "";

  dataString += "The current temp is: ";
  dataString += String(c);
  dataString += "C, ";
  dataString += String(f);
  dataString += "F, at ";
  dataString += String(now.year(), DEC);
  dataString += String('/');
  dataString += String(now.month(), DEC);
  dataString += String('/');
  dataString += String(, DEC);
  dataString += String(" (");
  dataString += String(daysOfTheWeek[now.dayOfTheWeek()]);
  dataString += String(") ");
  dataString += String(now.hour(), DEC);
  dataString += String(':');
  dataString += String(now.minute(), DEC);
  dataString += String(':');
  dataString += String(now.second(), DEC);

  // 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 ="datalog.txt", FILE_WRITE);

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

Upload the sketch to your board and open up the Serial Monitor (Tools -> Serial Monitor) at 115200 baud. You'll see the setup run with confirmation messages that the MCP9808 has been found over I2C and the microSD card has been initialized properly. As data is written to the microSD card, you'll see the message "Writing to SD card" appear in the Serial Monitor, along with the temperature reading and timestamp from the RTC. The onboard LED on the Raspberry Pi Pico will also light-up when a write is in progress.

After logging data to the file on the microSD card, you can open datalog.txt from the microSD card to see your data.

This guide was first published on Mar 07, 2023. It was last updated on Jun 14, 2024.

This page (Arduino Datalogging) was last updated on Jun 14, 2024.

Text editor powered by tinymce.