SD card not detected when AirLift Wing is plugged in

My Adalogger works without my AirLift plugged in. If it's plugged in, either on a quad side by side or just through female headers, the SD card will not initialize. Even if I use code that does not utilize the AirLift in any way, the SD card won't initialize. I'm assuming it's because they both use SPI but I want to make sure before I go cutting traces and soldering around. Any help with getting them both to work simultaneously would be greatly appreciated.

I posted this same issue in the Adafruit forums and someone suggested the ESPGPIO0 pin being enabled, as it would conflict with the SDCS pin on the Adalogger but that is disabled.

Do you deactivate the AirLift in the code? Otherwise the board will block the SPI bus of the Feather system. The AirLift implements a correct SPI bus interface where a pulled up CS line will set MISO tri-state.

As you failed to post your code we cannot check that.

You also failed to tell us which base Feather module you use.

My code neither activates or deactivates the AirLift. This code that I'm working with right now is just to try to get the SD card to work while the AirLift is plugged in too. I eventually want both to be utilized for some code but I'm starting here now. I'm using the Feather M4 Express

/*
  Listfiles

  This example shows how print out the files in a
  directory on a SD card

  The circuit:
   SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4 (for MKRZero SD: SDCARD_SS_PIN)

  created   Nov 2010
  by David A. Mellis
  modified 9 Apr 2012
  by Tom Igoe
  modified 2 Feb 2014
  by Scott Fitzgerald

  This example code is in the public domain.

*/
#include <SPI.h>
#include <SD.h>

File root;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  Serial.print("Initializing SD card...");

  if (!SD.begin(5)) {
    Serial.println("initialization failed!");
    while (1);
  }
  Serial.println("initialization done.");

  root = SD.open("/");

  printDirectory(root, 0);

  Serial.println("done!");
}

void loop() {
  // nothing happens after setup finishes.
}

void printDirectory(File dir, int numTabs) {
  while (true) {

    File entry =  dir.openNextFile();
    if (! entry) {
      // no more files
      break;
    }
    for (uint8_t i = 0; i < numTabs; i++) {
      Serial.print('\t');
    }
    Serial.print(entry.name());
    if (entry.isDirectory()) {
      Serial.println("/");
      printDirectory(entry, numTabs + 1);
    } else {
      // files have sizes, directories do not
      Serial.print("\t\t");
      Serial.println(entry.size(), DEC);
    }
    entry.close();
  }
}


Thank you

Add

pinMode(D10, OUTPUT);
digitalWrite(D10, HIGH);

at the start of setup(): This should deactivate the AirLink.

No dice. It acts exactly as it did before. I tried the SD CS pin on 10 as well as 5 and it behaved no differently. I had to change it from

pinMode(D10, OUTPUT);
digitalWrite(D10, HIGH);

to

pinMode(10, OUTPUT);
digitalWrite(10, HIGH);

It would not compile with "D10" only "10"

/*
  Listfiles

  This example shows how print out the files in a
  directory on a SD card

  The circuit:
   SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4 (for MKRZero SD: SDCARD_SS_PIN)

  created   Nov 2010
  by David A. Mellis
  modified 9 Apr 2012
  by Tom Igoe
  modified 2 Feb 2014
  by Scott Fitzgerald

  This example code is in the public domain.

*/
#include <SPI.h>
#include <SD.h>

File root;

void setup() {

  pinMode(10, OUTPUT);
  digitalWrite(10, HIGH);
  
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  Serial.print("Initializing SD card...");

  if (!SD.begin(5)) {
    Serial.println("initialization failed!");
    while (1);
  }
  Serial.println("initialization done.");

  root = SD.open("/");

  printDirectory(root, 0);

  Serial.println("done!");
}

void loop() {
  // nothing happens after setup finishes.
}

void printDirectory(File dir, int numTabs) {
  while (true) {

    File entry =  dir.openNextFile();
    if (! entry) {
      // no more files
      break;
    }
    for (uint8_t i = 0; i < numTabs; i++) {
      Serial.print('\t');
    }
    Serial.print(entry.name());
    if (entry.isDirectory()) {
      Serial.println("/");
      printDirectory(entry, numTabs + 1);
    } else {
      // files have sizes, directories do not
      Serial.print("\t\t");
      Serial.println(entry.size(), DEC);
    }
    entry.close();
  }
}


pinMode(13, OUTPUT);
digitalWrite(13, HIGH);

This gets the SD card to work with the AirLift plugged in... However since it deactivates the AirLift... I can't get on WiFi

You need to assign the AirLift's pin 13 to another pin since you deactivated it and it was conflicting with your SD card. Change it in your code and solder a wire from the 13 on the AirLift to another pin. You may need to cut the current 13 depending on how you have it wired.

You don't have any WiFi code in above sketch.

According to schematics pin 13 isn't used by the SD card of the Adalogger shields.

#include <Adafruit_APDS9960.h>
#include <Adafruit_BMP280.h>
#include <Adafruit_LIS3MDL.h>
#include <Adafruit_LSM6DS33.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_SHT31.h>
#include <Arduino.h>
#include <Adafruit_PWMServoDriver.h>
#include <MemoryFree.h>
#include <SD.h>
#include <SPI.h>
#include <Wire.h>
#include "RTClib.h"
#include "config.h"

/* #define BMP_SCK  (13)
#define BMP_MISO (12)
#define BMP_MOSI (11)
#define BMP_CS   (10)*/
#define DEBOUNCE_TIME 15
#define CALC_INTERVAL 1000
#define ANEMOMETER_PIN 9 // Interrupt pin tied to anemometer reed switch

unsigned long _nextCalc;
unsigned long _timer;

volatile int _anemometerCounter;
volatile unsigned long last_micros_an;

int _windSpd;
int WindSensorPin = A0;
int WinD = 180;

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();  // the default address 0x40
RTC_PCF8523 rtc;

Adafruit_LSM6DS33 lsm6ds33; // accelerometer & gyro
Adafruit_APDS9960 apds9960; // proximity, light, color, gesture
Adafruit_BMP280 bmp280;     // temperautre, barometer
Adafruit_LIS3MDL lis3mdl;   // magnetometer
Adafruit_SHT31 sht30;       // humidity

AdafruitIO_Feed *Temperature = io.feed("Temperature");
AdafruitIO_Feed *Humidity = io.feed("Humidity");
AdafruitIO_Feed *WindD = io.feed("Wind Direction");
AdafruitIO_Feed *WindS = io.feed("Wind Speed");
AdafruitIO_Feed *Pressure = io.feed("Pressure");
AdafruitIO_Feed *Vbat = io.feed("Vbat");

#define VBATPIN A6
#define USMIN  650 // This is the 'minimum' pulse length count (out of 4096) set to 650 for 7.8 Turns
#define USMAX  868 // This is the 'maximum' pulse length count (out of 4096) set to 2350 for 7.8 Turns
#define SERVO_FREQ 50 // Analog servos run at ~50 Hz updates
uint8_t MainWinch = 0;
uint8_t RudderWinch = 1;
short delayN;
short s = 1500;
short ss;
const int chipSelect = 10; //set the pin that the SD card is on

uint8_t proximity;
uint16_t r, g, b, c;
float temperature, pressure, altitude;
int magnetic_x, magnetic_y, magnetic_z;
int t;
float accel_x, accel_y, accel_z;
float gyro_x, gyro_y, gyro_z;
float humidity;

void setup() {
  Serial.begin(115200);

  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);

  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
  }

  if (! rtc.initialized() || rtc.lostPower()) {
    Serial.println("RTC is NOT initialized, let's set the time!");
  }
    
  apds9960.begin();
  apds9960.enableProximity(true);
  apds9960.enableColor(true);
  bmp280.begin();
  lis3mdl.begin_I2C();
  lsm6ds33.begin_I2C();
  sht30.begin();
  SD.begin(10);
  rtc.start();
  
  pwm.begin();
  pwm.setOscillatorFrequency(27000000);
  pwm.setPWMFreq(SERVO_FREQ);  // Analog servos run at ~50 Hz updates
  pwm.writeMicroseconds(MainWinch, 1500);
  pwm.writeMicroseconds(RudderWinch, 1400);

  pinMode(ANEMOMETER_PIN, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(ANEMOMETER_PIN), countAnemometer, FALLING); 

  DateTime now = rtc.now();
  t = now.minute();

  // connect to io.adafruit.com
  io.connect();

  // wait for a connection
  while(io.status() < AIO_CONNECTED) {
    Serial.println(".");
    delay(500);
  }
}

void setServoPulse(uint8_t n, double pulse) {
  double pulselength;

  pulselength = 1000000;   // 1,000,000 us per second
  pulselength /= SERVO_FREQ;   // Analog servos run at ~60 Hz updates
  Serial.print(pulselength); Serial.println(" us per period");
  pulselength /= 4096;  // 12 bits of resolution
  Serial.print(pulselength); Serial.println(" us per bit");
  pulse *= 1000000;  // convert input seconds to us
  pulse /= pulselength;
  Serial.println(pulse);
  pwm.setPWM(n, 0, pulse);
}

void loop() {
  io.run();  // io.run(); is required at the top for all sketches.
  _timer = millis();

  if (_timer > _nextCalc) {
    _nextCalc = _timer + CALC_INTERVAL;
    //UPDATE ALL VALUES
    _windSpd = readWindSpd() / 1.151;
  }

  DateTime now = rtc.now();
  proximity = apds9960.readProximity();
  apds9960.getColorData(&r, &g, &b, &c);
  temperature = (bmp280.readTemperature() * 1.8) + 32;
  pressure = bmp280.readPressure();
  altitude = bmp280.readAltitude(1013.25);
  humidity = sht30.readHumidity();
  
  lis3mdl.read();
  magnetic_x = lis3mdl.x;
  magnetic_y = lis3mdl.y;
  magnetic_z = lis3mdl.z;

  sensors_event_t accel;
  sensors_event_t gyro;
  sensors_event_t temp;
  lsm6ds33.getEvent(&accel, &gyro, &temp);
  accel_x = accel.acceleration.x;
  accel_y = accel.acceleration.y;
  accel_z = accel.acceleration.z;
  gyro_x = gyro.gyro.x;
  gyro_y = gyro.gyro.y;
  gyro_z = gyro.gyro.z;

  float measuredvbat = analogRead(VBATPIN);
  measuredvbat *= 2;    // we divided by 2, so multiply back
  measuredvbat *= 3.6;  // Multiply by 3.6V, our reference voltage
  measuredvbat /= 1024; // convert to voltage
  
  int sensorValue = analogRead(WindSensorPin);
  float voltage = sensorValue * (3.3 / 1023);

  if (voltage > 2.36 && voltage < 2.39) WinD = 0;
  else if (voltage > 1.25 && voltage < 1.29) WinD = 45;
  else if (voltage > 0.24 && voltage < 0.27) WinD = 90;
  else if (voltage > 0.44 && voltage < 0.46) WinD = 135;
  else if (voltage > 0.75 && voltage < 0.79) WinD = 180;
  else if (voltage > 1.80 && voltage < 1.84) WinD = 225;
  else if (voltage > 2.99 && voltage < 3.03) WinD = 270;
  else if (voltage > 2.69 && voltage < 2.73) WinD = 315;


  if (WinD < 46 && _windSpd > 0) {
    pwm.writeMicroseconds(RudderWinch, 2500);
    delay(3000);
    pwm.writeMicroseconds(RudderWinch, 1400);
  }
  else if ( WinD == 90 || WinD == 270) {
   pwm.writeMicroseconds(MainWinch, 1270);
  }
  else if (WinD == 135 || WinD == 225) {
   pwm.writeMicroseconds(MainWinch, 1250);
  }
  else if (WinD == 180) {
   pwm.writeMicroseconds(MainWinch, 1175);
  }

 /* ss = s;
  s = map(WinD, 0, 360, 600, 2400);
  pwm.writeMicroseconds(MainWinch, s);
  delay(abs(ss - s) * 20);
  if (ss - s > 100) pwm.writeMicroseconds(MainWinch, s + 15); // issues
  else pwm.writeMicroseconds(MainWinch, s - 10); */

  String dataString = "";  //making a string of sensor data to be logged

  dataString += String(now.month()) += "/";
  dataString += String(now.day()) += "/";
  dataString += String(now.year()) += " ";
  dataString += String(now.hour()) += ":";
  dataString += String(now.minute()) += ":";
  dataString += String(now.second()) += " ";
  dataString += String(_windSpd) += " kn ";
  dataString += String(WinD) += " Degrees ";
  dataString += String(temperature) += " C Humidity:";
  dataString += String(humidity) += "% ";
  dataString += String(pressure) += " Pa ";
  dataString += String(altitude) += " m MagX:";
  dataString += String(magnetic_x) += " MagY:";
  dataString += String(magnetic_y) += " MagZ:";
  dataString += String(magnetic_z) += " uTesla Acc x:";
  dataString += String(accel_x) += " Acc y:";
  dataString += String(accel_y) += " Acc z:";
  dataString += String(accel_z) += " m/s^2 Gyro x:";
  dataString += String(gyro_x) += " Gyro y:";
  dataString += String(gyro_y) += " Gyro z:";
  dataString += String(gyro_z) += " dps Proximity:";
  dataString += String(apds9960.readProximity()) += " R:";
  dataString += String(r) += " G:";
  dataString += String(g) += " B:";
  dataString += String(b) += " C:";
  dataString += String(c) += " Vbat:";
  dataString += String(measuredvbat);

    File dataFile = SD.open("datalog.txt", FILE_WRITE); //Opens new text file on SD card called datalog.txt

    if (dataFile) {
      digitalWrite(LED_BUILTIN, HIGH);
      dataFile.println(dataString);
      dataFile.close();
      digitalWrite(LED_BUILTIN, LOW);
    }
    Serial.println(dataString);
    Serial.println(freeMemory(), DEC);  
  delay(1000);

if(now.minute() - t > 2){
  Temperature->save(temperature);
  Humidity->save(humidity);
  WindD->save(WinD);
  WindS->save(_windSpd);
  Vbat->save(measuredvbat);
  Pressure->save(pressure);
  pwm.writeMicroseconds(RudderWinch, 2500);
  delay(9000);
  pwm.writeMicroseconds(RudderWinch, 1400);  
  t = now.minute();
 }
}

int readWindSpd() {
  unsigned char i;
  long spd = 14920; // one turn = 1.492 miles per hour
  spd *= _anemometerCounter;
  spd /= 10000;
  _anemometerCounter = 0;
  return (int) spd;
}

void countAnemometer() {
  if ((long)(micros() - last_micros_an) >= DEBOUNCE_TIME * 1000) {
    _anemometerCounter++;
    last_micros_an = micros();
  }
}

// visit io.adafruit.com if you need to create an account,
// or if you need your Adafruit IO key.
#define IO_USERNAME "JohnnyRealName"
#define IO_KEY "Secret"

#define WIFI_SSID "Wifi"
#define WIFI_PASS "SuperSecret"

#define USE_AIRLIFT

#include "AdafruitIO_WiFi.h"

#if defined(USE_AIRLIFT) || defined(ADAFRUIT_METRO_M4_AIRLIFT_LITE) ||         \
    defined(ADAFRUIT_PYPORTAL)
// Configure the pins used for the ESP32 connection
#if !defined(SPIWIFI_SS) // if the wifi definition isnt in the board variant
// Don't change the names of these #define's! they match the variant ones
#define SPIWIFI SPI
#define SPIWIFI_SS 13 // Chip select pin
#define NINA_ACK 11    // a.k.a BUSY or READY pin
#define NINA_RESETN 12 // Reset pin
#define NINA_GPIO0 -1 // Not connected
#endif
AdafruitIO_WiFi io(IO_USERNAME, IO_KEY, WIFI_SSID, WIFI_PASS, SPIWIFI_SS,
                   NINA_ACK, NINA_RESETN, NINA_GPIO0, &SPIWIFI);
#else
AdafruitIO_WiFi io(IO_USERNAME, IO_KEY, WIFI_SSID, WIFI_PASS);
#endif

It would seem as though I need a way to reactivate the AirLift. The code goes through once and then stops. Although, it does save that one string to the SD card, so there's some progress.

Why don't you just redefine the pin mode every time? Every loop, before you utilize the SD card, then set it back when you're done using the SD card.

That should be done in the Adafruit library You told it that the CS pin for the Airlift is pin 13, so it should know how to handle it.

Adafruit IO doesn't simply use WiFi but a commercial service of Adafruit. Did you pay for it? Otherwise it may be that the service is blocking you in some way because you overuse the free account?

I would start with a simple sketch that you can control completely and use that interface in a documented way. You only have to include the code for the SPI devices because these may block the bus if they are not configured correctly. But to start you should remove all I2C based sensors from your sketch and make more serial output so may have a chance to see where the sketch stops (and maybe how long it stops).

This code works and I'm unsure why. I cut the trace for the CS pin on the adalogger and wired it to pin 9 and reflected that in the code. I also have it connect to Adafruit IO before it initializes the SD card. However I do not have it deactivating or reactivating the AirLift. I added "MemoryFree" to check for memory leaks and see if I could see why it was stopping. This code uploads to Adafruit IO and saves to the SD card. Thanks for the suggestion of starting over.

#include "config.h"
#include <SPI.h>
#include <SD.h>
#include <MemoryFree.h>


const int chipSelect = 9;
int count = 0;

// set up the 'counter' feed
AdafruitIO_Feed *counter = io.feed("counter");

void setup() {
  Serial.begin(115200);

   while(! Serial);

  Serial.print("Connecting to Adafruit IO");

  io.connect();

  while(io.status() < AIO_CONNECTED) {
    Serial.print(".");
    delay(500);
  }

  Serial.println();
  Serial.println(io.statusText());

  Serial.print("Initializing SD card...");

  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    //while (1);
  }
  Serial.println("card initialized.");
}

void loop() {
  
  io.run();  // io.run(); is required at the top for all sketches.

  Serial.print("sending -> ");
  Serial.println(count);
  counter->save(count);

  // increment the count by 1
  count++;

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

  dataString += String(count);

  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  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");
  }  
  Serial.println(freeMemory(), DEC);
  delay(5000);

}

// visit io.adafruit.com if you need to create an account,
// or if you need your Adafruit IO key.
#define IO_USERNAME "X"
#define IO_KEY "x**"

#define WIFI_SSID "realwifi"
#define WIFI_PASS "securepassword"

#define USE_AIRLIFT

#include "AdafruitIO_WiFi.h"

#if defined(USE_AIRLIFT) || defined(ADAFRUIT_METRO_M4_AIRLIFT_LITE) ||         \
    defined(ADAFRUIT_PYPORTAL)
// Configure the pins used for the ESP32 connection
#if !defined(SPIWIFI_SS) // if the wifi definition isnt in the board variant
// Don't change the names of these #define's! they match the variant ones
#define SPIWIFI SPI
#define SPIWIFI_SS 13 // Chip select pin
#define NINA_ACK 11    // a.k.a BUSY or READY pin
#define NINA_RESETN 12 // Reset pin
#define NINA_GPIO0 -1 // Not connected
#endif
AdafruitIO_WiFi io(IO_USERNAME, IO_KEY, WIFI_SSID, WIFI_PASS, SPIWIFI_SS,
                   NINA_ACK, NINA_RESETN, NINA_GPIO0, &SPIWIFI);
#else
AdafruitIO_WiFi io(IO_USERNAME, IO_KEY, WIFI_SSID, WIFI_PASS);
#endif