SD data logging of BPM280 with inconsistent temp and pressure

Hello,

I'm new to Arduino and appreciate all the code examples and discussions out there, learning rapidly.

I'm building a data logger with an Arduino MKR 1010 board and MKR SD shield.
I'm testing with various sensors and currently with the logging on a SD card.
This proves to be a challenge and I have read many comments on similar issues around combinations of BMP280 sensor and SD card, but not been able to solve it.
Without the logging to a text file on the SD card the BMP280 sensor returns valid temperatures and pressure readings. But when the values are written to an SD card only the first reading returns (and writes) correct temperature and pressure. From the second sampling temperature gives 187.4C and pressure 225.52 mbar.

I have the BMP280 wired to MISO/MOSI/SCK as per MKR board 10/9/8 with CS digital pin 7. The MKR SD shield I read somewhere that it uses digital pin 4 for CS and have defined likewise in my code. I have also included a suggestion to write these pins High and Low according to which is to be addressed, but this does not resolve the issue.

What am I overlooking that could resolve the issue and return and log correct readings from the BMP280 sensor?

/*
  SD card datalogger

  logging real time from RTC and  data from sensors to an SD card using the SD library.

  programmed by Wolfgang Lex based on some example programs for BMP280 with Adafruit_BMP280.h
  and example program for data logging shield from MAKERFACORY / Velleman

*/

#include <SPI.h>
#include <SD.h>
#include <Wire.h>         // this #include still required because the RTClib depends on it
#include <RTCZero.h>
#include <Adafruit_BMP280.h>

#define BMP_SCK 9
#define BMP_MISO 10
#define BMP_MOSI 8
#define BMP_CS 7
#define SD_CS 4

//Adafruit_BMP280 bmp; // I2C
//Adafruit_BMP280 bmp(BMP_CS); // hardware SPI
Adafruit_BMP280 bmp(BMP_CS, BMP_MOSI, BMP_MISO, BMP_SCK);

const int chipSelect = 4;

File dataFile;

/* Create an rtc object */
RTCZero rtc;

/* Change these values to set the current initial time */
const byte seconds = 0;
const byte minutes = 0;
const byte hours = 12;

/* Change these values to set the current initial date */
const byte day = 10;
const byte month = 3;
const byte year = 22;

float temp1, temp2, press1, press2, diffp, difft;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  delay(3000); // wait for console opening

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

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1);
  }
  Serial.println("card initialized.");
  SD.begin();

  rtc.begin(); // initialize RTC
  rtc.setTime(hours, minutes, seconds);
  rtc.setDate(day, month, year);

  if (!bmp.begin()) {
    Serial.println(F("Could not find a valid BMP280 sensor, check wiring!"));
    while (1);
  }
}

void loop() {
  digitalWrite(BMP_CS, LOW);
  digitalWrite(SD_CS, HIGH);
  String dataString = "";        // make a string for assembling the data to log:

  dataString = dataString + rtc.getDay() + ('.') + rtc.getMonth() + ('.') + rtc.getYear() + (',') + rtc.getHours() + (':') + rtc.getMinutes() + (':') + rtc.getSeconds() + (',');

  temp1 = bmp.readTemperature(); // read out now actual temperature from BMP280

  press1 = bmp.readPressure() / 100; // read out now actual air pressure from BMP280 and divide by 100 in order to get hPa = mbar out of original value in Pascal

  dataString = dataString + temp1;
  dataString += ",";
  dataString = dataString + press1;
  digitalWrite(BMP_CS, HIGH);
  digitalWrite(SD_CS, LOW);
  // open the file for logging of data
  SD.begin(SD_CS);
  dataFile = SD.open("datalog.txt", FILE_WRITE);

  // if the file is available, write to it:
  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");
  }
  delay(30000);
}

You must not use the SPI software emulation if you use the same pins as you use for the hardware SPI for the SD card interface.

Thank you. As I said I'm new at this and do not yet see these differences.
I have changed the declaration to the one for hardware SPI:

Adafruit_BMP280 bmp(BMP_CS); // hardware SPI
//Adafruit_BMP280 bmp(BMP_CS, BMP_MOSI, BMP_MISO, BMP_SCK);

The output is now correct for the barometric pressure, but not yet for temperature (except for the first sampling):

Initializing SD card...card initialized.
10.3.22,12:0:0,23.48,1026.76
10.3.22,12:0:30,-149.39,1026.75
10.3.22,12:1:0,-149.39,1026.72
10.3.22,12:1:30,-149.39,1026.72
10.3.22,12:2:0,-149.39,1026.71
...

What could be the cause of this? Or did I misunderstand your remark and have to make additional changes?

This is actually quite interesting because the library needs a correct temperature reading to calculate the pressure return value.

Are you actually using above code with only the object construction changed?

Try to make temp1 and press1 local variables.

Indeed it is interesting when you consider that.

I only changed the object construct and now have changed variables temp1 and press1 to local type. But still the same readings:

Initializing SD card...card initialized.
10.3.22,12:0:0,22.76,963.70
10.3.22,12:0:30,-149.39,963.71
10.3.22,12:1:0,-149.39,963.70
...

/*
  SD card datalogger

  logging real time from RTC and  data from sensors to an SD card using the SD library.

  programmed by Wolfgang Lex based on some example programs for BMP280 with Adafruit_BMP280.h
  and example program for data logging shield from MAKERFACORY / Velleman

*/

#include <SPI.h>
#include <SD.h>
#include <Wire.h>         // this #include still required because the RTClib depends on it
#include <RTCZero.h>
#include <Adafruit_BMP280.h>

#define BMP_SCK 9
#define BMP_MISO 10
#define BMP_MOSI 8
#define BMP_CS 7
#define SD_CS 4

//Adafruit_BMP280 bmp; // I2C
Adafruit_BMP280 bmp(BMP_CS); // hardware SPI
//Adafruit_BMP280 bmp(BMP_CS, BMP_MOSI, BMP_MISO, BMP_SCK);

const int chipSelect = 4;

File dataFile;

/* Create an rtc object */
RTCZero rtc;

/* Change these values to set the current initial time */
const byte seconds = 0;
const byte minutes = 0;
const byte hours = 12;

/* Change these values to set the current initial date */
const byte day = 10;
const byte month = 3;
const byte year = 22;



void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  delay(3000); // wait for console opening

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

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1);
  }
  Serial.println("card initialized.");
  SD.begin();

  rtc.begin(); // initialize RTC
  rtc.setTime(hours, minutes, seconds);
  rtc.setDate(day, month, year);

  if (!bmp.begin()) {
    Serial.println(F("Could not find a valid BMP280 sensor, check wiring!"));
    while (1);
  }
}

void loop() {
  digitalWrite(BMP_CS, LOW);
  digitalWrite(SD_CS, HIGH);
  String dataString = "";        // make a string for assembling the data to log:
  float temp1, press1;

  dataString = dataString + rtc.getDay() + ('.') + rtc.getMonth() + ('.') + rtc.getYear() + (',') + rtc.getHours() + (':') + rtc.getMinutes() + (':') + rtc.getSeconds() + (',');

  temp1 = bmp.readTemperature(); // read out now actual temperature from BMP280

  press1 = bmp.readPressure() / 100; // read out now actual air pressure from BMP280 and divide by 100 in order to get hPa = mbar out of original value in Pascal

  dataString = dataString + temp1;
  dataString += ",";
  dataString = dataString + press1;
  digitalWrite(BMP_CS, HIGH);
  digitalWrite(SD_CS, LOW);
  // open the file for logging of data
  SD.begin(SD_CS);
  dataFile = SD.open("datalog.txt", FILE_WRITE);

  // if the file is available, write to it:
  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");
  }
  delay(30000);
}

Can you try to swap the temperature and pressure requests? So to first read the pressure and after that read the temperature. Does that change the result?

Just to ensure I'm looking at the same code you're using: you have version 2.6.2 of the Adafruit_BMP280 library installed, haven't you?

Remove that line and also the SD.begin() call inside loop! Also remove all digitalWrite() calls in loop()!

Resolved!
The version of Adafruit_BMP280 was 2.6.1. I changed it and ran the program again.
This did not change the output.
Then I took away the SD.begin() statements and digitalWrite() calls.
After this it runs smooth

Initializing SD card...card initialized.
10.3.22,12:0:0,22.15,964.00
10.3.22,12:0:30,22.15,963.96
10.3.22,12:1:0,22.16,964.01
10.3.22,12:1:30,22.18,964.00
10.3.22,12:2:0,22.16,964.00
10.3.22,12:2:30,22.18,964.00
10.3.22,12:3:0,22.18,963.99

I checked the datalog and that's all fine too.

Now I can continue to add sensors to my program and data logging.

Thank you!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.