1

I have an ADXL355 accelerometer attached to an Adafruit Feather Adalogger. I can configure and read the sensor. I can also write binary values to the SD card. The problem occurs when I try to read from the sensor and then write that data to the SD card. The only thing I can think of is I'm somehow messing up the SPI communication but I can't see where. I looked through pins_arduino.h for my board and the SD Card (pin 4) is on a different register than pin 10 so I don't see how I'm breaking things.

My operations proceed like this. Global sensor creation, Serial.begin, SD.begin, SPI.begin, Test sensor connection, Create file for output on SD card, Initialize sensor, Read sensor FIFO, Write to file, repeat last 2 forever.

The file is created but remains at 0 file size, ie nothing is actually written to the card.

The sensor can operate at 4 kHz which was hard to achieve using the digitalWrite functions so I switched to using the port registers on the Feather. I do it like this:

#include <SM_ADXL355_SPI_fast.h>
#include <SPI.h>
#include <SD.h>

#define cardSelect 4

ADXL355_SPIF adxl355(&DDRB, &PORTB, _BV(6)); // values taken from pins_arduino.h, tested and working on pin 10
void setup() {
  Serial.begin(57600);
  while(!Serial){
    // wait for Serial
  }
  SD.begin(cardSelect);
  SPI.begin();
  while(!adxl355.TestConnection()){
    delay(1000);  
  }
  adxl355.OpenFile("TestSPI.bin");
  adxl355.Initialize(1, 10, 0); // set range to 2g's, frequency to 4 Hz and filter to off
}

void loop() {
  while(true){ // avoid Arduino overhead of their loop function
    adxl355.ReadFIFO();
    adxl355.WriteFIFOToFile();
  }
}

Here is the ADXL constructor

ADXL355_SPIF::ADXL355_SPIF(volatile uint8_t * outReg, volatile uint8_t * outPort, uint8_t bitValue) : sensorOutReg(outReg), sensorPort(outPort), sensorBitValue(bitValue){
    *sensorOutReg |= sensorBitValue;
    *sensorPort |= sensorBitValue;
    sensorWriteCount = 0;
}

TestConnection tests that the DeviceID reads 0xAD. Initialize sets the G range, sample rate in Hz and filter. I have tested these with serial output and they work properly.

OpenFile looks like this:

bool ADXL355_SPIF::OpenFile(const String& fileName){
    sensorFile = SD.open(fileName, FILE_WRITE);
    if (!sensorFile){
        Serial.print("Could not create file: ");
        Serial.println(fileName);
        return false;
    }
    return true;
}

After running this a file does get created on the SD card called "TESTSPI.BIN" with 0 file size.

ReadFIFO reads the numbers of entries in FIFO, stored as fifoCount and then populates a buffer (sensorFIFO[32][3]) with the values from the FIFO. I've printed this buffer to Serial to show that it's working. Here is that function

void ADXL355_SPIF::ReadFIFO(){
    ReadRegister(ADXL355_RA_FIFO_ENTRIES, 1);
    fifoCount = buffer[0];
    ReadFIFOInternal();
    return;
}

void ADXL355_SPIF::ReadFIFOInternal(){
    SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
    *sensorPort &= ~sensorBitValue;
    uint8_t spiCommand = ADXL355_RA_FIFO_DATA << 1 | ADXL355_READ;
    SPI.transfer(spiCommand);
    int i = 0;
    unsigned long tempV;
    unsigned long value;
    while(i < fifoCount){
        for (int ptr = 0; ptr < 3; ++ptr){
            buffer[0] = SPI.transfer(0x0);
            value = buffer[0];
            value <<= 12;
            tempV = SPI.transfer(0x0);
            tempV <<= 4;
            value |= tempV;
            tempV = SPI.transfer(0x0);
            tempV >>=4;
            value |= tempV;
            if (buffer[0] & 0x80) {
                value |= 0xFFF00000;
            }
            long lValue = static_cast<long>(value);
            sensorFIFO[i][ptr] = scaleFactor * lValue;
        }
        i += 3;
    }
    SPI.endTransaction();
    *sensorPort |= sensorBitValue;
    return;
}

Here is WriteFIFOToFile:

void ADXL355_SPIF::WriteFIFOToFile(){
    if (fifoCount > 0){
        sensorFile.write(reinterpret_cast<const char *>(&sensorFIFO), 4 * fifoCount);
    }
    sensorWriteCount += fifoCount;
    if (sensorWriteCount >= 100){
        sensorFile.flush();
        sensorWriteCount = 0;
    }
}

After allowing this to run for a while the file size is always 0. I tried a simple binary write function just to test the card. It looks like this and it worked.

#include <SD.h>

#define cardSelectPin 4

const float pi=3.14159;

File oFile;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  while(!Serial){
    // wait for serial
  }
  SD.begin(cardSelectPin);
  oFile = SD.open("Test.bin", FILE_WRITE);
  Serial.println(sizeof(int));
  Serial.println(sizeof(float));
  float testFloat[32][3];
  for (int i = 0; i < 32; ++i){
    for (int j = 0; j < 3; ++j){
      testFloat[i][j] = pi * (i + 1) + j;
    }
  }
  oFile.write(reinterpret_cast<const char *>(&testFloat), sizeof(float) * 96);
  oFile.close();
  Serial.println("Finished writing file.");
}

void loop() {
  // put your main code here, to run repeatedly:

}
  • SD cards are reportedly not fully compatible with shared SPI busses - though I'd been under the impression that it was usually the other devices impacted, since well-behaved SPI peripherals shouldn't be getting in the way of access to the card. – Chris Stratton Oct 11 '17 at 3:58
  • This is a Feather board? Make sure your supporting software is up to date. I had plenty of problems with a Feather board as they were new at the time. – st2000 Oct 11 '17 at 4:47
  • @st2000 I use the Arduino IDE and I update everything it says it out of date when it opens. Are you referencing another "supporting software"? Yes it's the Feather 32u4 Adalogger. – Matt Oct 11 '17 at 15:51
  • Go to the Adafruit web site for information as to what is necessary to add to your Arduino IDE in order to program Adafruit Feather boards. Remember, different Arduinos do not necessarily use the same processors. The ARM core processors used on a Feather are likely orders of magnitudes more complex than that of the lowly Arduino Uno. – st2000 Oct 12 '17 at 0:25
1

The problem here was caused by flush never being called within WriteFIFOToFile. The variable sensorWriteCount was defined incorrectly. Changing to call flush directly after each write statement fixed the problem. This lead to the debugging of the if statement and variable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.