SD Card with BMP and DHT

Hello, I've been able to combine a couple of codes to get some weather data, which seems to work pretty well. I want to log this data to an SD Card. I've tried writing code to do this using tutorials and posts in forums as well as examples, but I keep getting errors. I would really appreciate help with this. Thank you. Here is my code that works as it is for serial data:

#include "BMP280.h"
#include "Wire.h"
#define P0 1013.25
BMP280 bmp;
#include "DHT.h"

#define DHTPIN 2     // what digital pin we're connected to

// Uncomment whatever type you're using!
#define DHTTYPE DHT22   // DHT 11
DHT dht(DHTPIN, DHTTYPE);

void setup()
{
  Serial.begin(9600);
  Serial.println("Test");
  bmp.begin();
  dht.begin();
  
  bmp.setOversampling(4);
  
}
void loop()
{
  delay(5000);

  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f = dht.readTemperature(true);
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }

  // Compute heat index in Fahrenheit (the default)
  float hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(t, h, false);
  
  double T,P;
  char result = bmp.startMeasurment();
 
  if(result!=0){
    delay(result);
    result = bmp.getTemperatureAndPressure(T,P);
    
      if(result!=0)
      {
        double A = bmp.altitude(P,P0);
        
  Serial.print("P: ");
  Serial.print(P,2);
  Serial.print(" mBar, ");
  Serial.print("Temperature: ");
  Serial.print(t);
  Serial.print(" *C, ");
  Serial.print(f);
  Serial.print(" *F, ");
  Serial.print("Humidity: ");
  Serial.print(h);
  Serial.println(" %, ");
      
      }
      else {
        Serial.println("Error.");
      }
  }
  else {
    Serial.println("Error.");
  }  }

Why not post the code for writing to the SD card and the errors. Then we can help get it working.

Ok, basically I think these two lines are preventing this code from working:
String stringP = dtostrf(p,6,2,buffer);
dataString += stringP;
I'm getting the error message of exit status 1, p was not declared in this scope.

Those two lines I basically took from an SD code that does work involving only the DHT22. I know that it's probably because the DHT library is different from the BMP280, but those two lines I just do not know how to format them to get the pressure data like I can get in the serial data. I think everything else in the code would allow it to work. Thank you.

Here is my code:

#include "BMP280.h"
#include "Wire.h"
#define P0 1013.25
BMP280 bmp;
#include "DHT.h"
#include <SPI.h>
#include <SD.h>

#define DHTPIN 2     // what digital pin we're connected to
const int chipSelect = 10;

// Uncomment whatever type you're using!
#define DHTTYPE DHT22   // DHT 22
DHT dht(DHTPIN, DHTTYPE);

void setup()
{
  Serial.begin(9600);
  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:
    return;
  }
  Serial.println("card initialized.");
  Serial.println("Test");
  bmp.begin();
  dht.begin();
  
  bmp.setOversampling(4);
  
}
void loop()
{
  delay(5000);

  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f = dht.readTemperature(true);
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }

  // Compute heat index in Fahrenheit (the default)
  float hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(t, h, false);
  
  double T,P;
  char result = bmp.startMeasurment();
 
  if(result!=0){
    delay(result);
    result = bmp.getTemperatureAndPressure(T,P);
    
      if(result!=0)
      {
        double A = bmp.altitude(P,P0);
        
  Serial.print("P: ");
  Serial.print(P,2);
  Serial.print(" mBar, ");
  Serial.print("Temperature: ");
  Serial.print(t);
  Serial.print(" *C, ");
  Serial.print(f);
  Serial.print(" *F, ");
  Serial.print("Humidity: ");
  Serial.print(h);
  Serial.println(" %, ");
      
      }
      else {
        Serial.println("Error.");
      }
  }
  else {
    Serial.println("Error.");

// make a string for assembling the data to log:
String dataString = "";
char buffer[10];  
String stringH = dtostrf(h,6,2,buffer);  
dataString = stringH;
dataString += ", ";
String stringF = dtostrf(f,6,2,buffer); 
dataString += stringF;
String stringP = dtostrf(p,6,2,buffer);
dataString += stringP;

  // 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 = SD.open("datalogtest.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 datalogtest.txt");
  }
}
  }  }

You are mixing data types in the dtostrf function. Check this tutorial out dtostrf function. The dtostrf function works with null terminated character arrays (string with a small s) not String objects (String with a capital s).

I checked out that tutorial, but I guess I'm just not grasping it all. I am sorry for any inconvenience I have caused. Since the BMP280 is an analog sensor, must the code be a different function in order to write it to the SD Card? I made some changes to my code and added a float function for the pressure sensor, and now I'm not getting any error messages. It says the SD Card initializes and the Serial port data shows up fine, but it is not writing the data to the SD Card. I just want the pressure from the BMP280 sensor to be included in this DHT22 code that works great to write to an SD Card. I also want to add real time clock data from a DS3231 sensor, once I get that sensor in the mail hopefully soon, so any help with that would greatly be appreciated as well. Here is the DHT22 SD Card code that works fine:

#include <stdlib.h>

#include "DHT.h"

#define DHTPIN 2     // what pin we're connected to
#define DHTTYPE DHT22   // DHT 22  (AM2302)
DHT dht(DHTPIN, DHTTYPE);


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

const int chipSelect = 10;

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


  Serial.print("Initializing SD card...");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  pinMode(10, OUTPUT);

  // 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:
    return;
  }
  Serial.println("card initialized.");
  
  Serial.println("DHTxx test!");
 
  dht.begin();
}

void loop()
{
  
    // Wait a few seconds between measurements.
  delay(60000);

  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit
  float f = dht.readTemperature(true);
  
  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }

  // Compute heat index
  // Must send in temp in Fahrenheit!
  float hi = dht.computeHeatIndex(f, h);

  Serial.print("Humidity: "); 
  Serial.print(h);
  Serial.print(" %\t");
  Serial.print("Temperature: "); 
  Serial.print(f);
  Serial.println(" *F\t");

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



char buffer[10];  
String stringH = dtostrf(h,6,2,buffer);  
dataString = stringH;
dataString += ", ";
String stringF = dtostrf(f,6,2,buffer); 
dataString += stringF;

  // 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 = 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");
  }
}

And here is the updated code to try to add pressure data, but as I stated before this code does not write to my SD Card:

#include "BMP280.h"
#include "Wire.h"
#define P0 1013.25
BMP280 bmp;
#include "DHT.h"
#include <SPI.h>
#include <SD.h>
#include <stdlib.h>

#define DHTPIN 2     // what digital pin we're connected to
const int chipSelect = 10;

// Uncomment whatever type you're using!
#define DHTTYPE DHT22   // DHT 22
DHT dht(DHTPIN, DHTTYPE);

void setup()
{
  Serial.begin(9600);
  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:
    return;
  }
  Serial.println("card initialized.");
  Serial.println("Test");
  bmp.begin();
  dht.begin();
  
  bmp.setOversampling(4);
  
}
void loop()
{
  delay(5000);

  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f = dht.readTemperature(true);
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }

  // Compute heat index in Fahrenheit (the default)
  float hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(t, h, false);
  
  double T,P;
  char result = bmp.startMeasurment();
 
  if(result!=0){
    delay(result);
    result = bmp.getTemperatureAndPressure(T,P);
    
      if(result!=0)
      {
        double A = bmp.altitude(P,P0);

  float p = bmp.getTemperatureAndPressure(T,P);
        
  Serial.print("P: ");
  Serial.print(P,2);
  Serial.print(" mBar, ");
  Serial.print("Temperature: ");
  Serial.print(t);
  Serial.print(" *C, ");
  Serial.print(f);
  Serial.print(" *F, ");
  Serial.print("Humidity: ");
  Serial.print(h);
  Serial.println(" %, ");
      
      }
      else {
        Serial.println("Error.");
      }
  }
  else {
    Serial.println("Error.");

// make a string for assembling the data to log:
String dataString = "";
char buffer[40];  
String stringH = dtostrf(h,6,2,buffer);  
dataString = stringH;
dataString += ", ";
String stringF = dtostrf(f,6,2,buffer); 
dataString += stringF;
dataString += ", ";
String stringP = dtostrf(P,15,5,buffer);
dataString += stringP;

  // 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 = SD.open("datalogtest.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 datalogtest.txt");
  }
}}

You don't really need to convert your floats to Strings or strings. You can use the print method just like you are sending data to the serial port.

Here is how I would do it.

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

  // if the file is available, write to it:
  if (dataFile)
 {
      dataFile.print(h, 2); // send humidity to file with 2 decimal places
      dataFile.print(",");
      dataFile.print(t, 2);
      dataFile.print(",");
      dataFile.print(f, 2);
      dataFile.print(",");
      dataFile.print(hif, 2);
      dataFile.print(",");
      dataFile.print(hic, 2);
      dataFile.print(",");
      dataFile.println(p,2);  // send press and cr/lf so next data goes to new line
}
dataFile.close();

That makes it much easier than putting strings together. Thank you so much. Unfortunately, it is still not writing to my SD card like the DHT22 sketch does. Do you have any more advice as to why this is? Here is my updated full code:

#include "BMP280.h"
#include "Wire.h"
#define P0 1013.25
BMP280 bmp;
#include "DHT.h"
#include <SPI.h>
#include <SD.h>
#include <stdlib.h>

#define DHTPIN 2     // what digital pin we're connected to
const int chipSelect = 10;

// Uncomment whatever type you're using!
#define DHTTYPE DHT22   // DHT 22
DHT dht(DHTPIN, DHTTYPE);

void setup()
{
  Serial.begin(9600);
  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:
    return;
  }
  Serial.println("card initialized.");
  Serial.println("Test");
  bmp.begin();
  dht.begin();
  
  bmp.setOversampling(4);
  
}
void loop()
{
  delay(5000);

  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f = dht.readTemperature(true);
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }

  // Compute heat index in Fahrenheit (the default)
  float hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(t, h, false);
  
  double T,P;
  char result = bmp.startMeasurment();
 
  if(result!=0){
    delay(result);
    result = bmp.getTemperatureAndPressure(T,P);
    
      if(result!=0)
      {
        double A = bmp.altitude(P,P0);

  float bmp.getTemperatureAndPressure(T,P);
        
  Serial.print("P: ");
  Serial.print(P,2);
  Serial.print(" mBar, ");
  Serial.print("Temperature: ");
  Serial.print(t);
  Serial.print(" *C, ");
  Serial.print(f);
  Serial.print(" *F, ");
  Serial.print("Humidity: ");
  Serial.print(h);
  Serial.println(" %, ");
      
      }
      else {
        Serial.println("Error.");
      }
  }
  else {
    Serial.println("Error.");

  // 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 = SD.open("datalogtest.txt", FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile)
 {
      dataFile.print(h, 2); // send humidity to file with 2 decimal places
      dataFile.print(",");
      dataFile.print(t, 2);
      dataFile.print(",");
      dataFile.print(f, 2);
      dataFile.print(",");
      dataFile.print(hif, 2);
      dataFile.print(",");
      dataFile.print(hic, 2);
      dataFile.print(",");
      dataFile.println(P,2);  // send press and cr/lf so next data goes to new line
}
dataFile.close();
  }  }

Here is an updated code. I'm still not sure why this one won't work either. This BMP280 library is rather quirky it seems like. I wish the Adafruit one would work, but this is a different one. P,2 which is the function to get pressure is the only thing I would really like in addition to the data from the DHT22. I think maybe I've done an incorrect declaration of that. I tried float P,2 but that doesn't work. I'm just really surprised that the serial data shows up just fine, but it won't write to an SD card. What other advice do you or anyone else have for this? I'd really appreciate anymore help. Thanks.

#include "BMP280.h"
#include "Wire.h"
#define P0 1013.25
BMP280 bmp;
#include "DHT.h"
#include <SPI.h>
#include <SD.h>
#include <stdlib.h>

#define DHTPIN 2     // what digital pin we're connected to
const int chipSelect = 10;

// Uncomment whatever type you're using!
#define DHTTYPE DHT22   // DHT 22
DHT dht(DHTPIN, DHTTYPE);

void setup()
{ 
  Serial.begin(9600);
  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:
    return;
  }
  Serial.println("card initialized.");
  Serial.println("Test");
  bmp.begin();
  dht.begin();

  bmp.setOversampling(4);

}
void loop()
{
  delay(5000);

  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f = dht.readTemperature(true);
  if (isnan(h) || isnan(t) || isnan(f))
  {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }

  // Compute heat index in Fahrenheit (the default)
  float hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(t, h, false);

  double T,P;
  char result = bmp.startMeasurment();

  if(result!=0)
  {
    delay(result);
    result = bmp.getTemperatureAndPressure(T,P);

    if(result!=0)
    {
      double A = bmp.altitude(P,P0);
      bmp.getTemperatureAndPressure(T,P);

      Serial.print("P: ");
      Serial.print(P,2);
      Serial.print(" mBar, ");
      Serial.print("Temperature: ");
      Serial.print(t);
      Serial.print(" *C, ");
      Serial.print(f);
      Serial.print(" *F, ");
      Serial.print("Humidity: ");
      Serial.print(h);
      Serial.println(" %, ");

      // 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 = SD.open("datalogtest.txt", FILE_WRITE);

      // if the file is available, write to it:
      if (dataFile)
      {
        dataFile.print(h, 2); // send humidity to file with 2 decimal places
        dataFile.print(",");
        dataFile.print(t, 2);
        dataFile.print(",");
        dataFile.print(f, 2);
        dataFile.print(",");
        dataFile.print(hif, 2);
        dataFile.print(",");
        dataFile.print(hic, 2);
        dataFile.print(",");
        dataFile.println(P,2);  // send press and cr/lf so next data goes to new line
      }
      dataFile.close();
    }
    else
    {
      Serial.println("Error.");
    }
  }
  else
  {
    Serial.println("Error.");
  }  
}

Does anything get written to the SD card? Or everything but the pressure?

Nothing at all unfortunately.

The SD library has the old DOS limitation on filenames. 8 character filename and 3 character extension. Your filename is not legal (datalogtest.txt) with 10 character filename.

How is the card formatted? I use SD Fomatter to format my cards and have not had any trouble.

Could you post the serial monitor output of the sketch?

I had used that formatter before, but used it again earlier. Then I changed the file name. Many thanks to letting me know to change that. It still wasn't working, so I then altered the dataFile.print lines to remove the number of decimals. It seems like the values round to 2 places as is. Then it FINALLY worked. Yay! Many thanks to you groundfungus.

I'm fairly close to being all the way done with the code part of this project. I got my DS3231 in the mail today, so I'll try to come up with a code for that later. I've downloaded a few libraries thus far. I've found it's tough to get just the right time on the RTC as there is of course a delay in uploading the code to Arduino and when the code actually starts running, so I was seconds off earlier, but now I have it almost just right. Probably 2 or 3 tenths of a second off, so not a big deal. Is there a way to make it just right by the way? And, what is the best library in your opinions?

Thank you again. This code measures absolute pressure by the way if anyone wanted to know. Excel has helped me convert this into proper weather pressure for where I live, and it is just about spot on comparing it with local weather readings, so this BMP280 is apparently pretty good. Just let me know if you want the formulas. It is the least I could do for all the help from this community. Here is the code that works by the way in case anyone wants to do this for themself:

#include "BMP280.h"
#include "Wire.h"
#define P0 1013.25
BMP280 bmp;
#include "DHT.h"
#include <SPI.h>
#include <SD.h>
#include <stdlib.h>

#define DHTPIN 2     // what digital pin we're connected to
const int chipSelect = 10;

// Uncomment whatever type you're using!
#define DHTTYPE DHT22   // DHT 22
DHT dht(DHTPIN, DHTTYPE);

void setup()
{ 
  Serial.begin(9600);
  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:
    return;
  }
  Serial.println("card initialized.");
  Serial.println("BMP DHT22 Measurement");
  bmp.begin();
  dht.begin();

  bmp.setOversampling(4);

}
void loop()
{
  delay(5000);

  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f = dht.readTemperature(true);
  if (isnan(h) || isnan(t) || isnan(f))
  {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }

  // Compute heat index in Fahrenheit (the default)
  float hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(t, h, false);

  double T,P;
  char result = bmp.startMeasurment();

  if(result!=0)
  {
    delay(result);
    result = bmp.getTemperatureAndPressure(T,P);

    if(result!=0)
    {
      double A = bmp.altitude(P,P0);
      bmp.getTemperatureAndPressure(T,P);

      Serial.print("P: ");
      Serial.print(P,2);
      Serial.print(" mBar, ");
      Serial.print("Temperature: ");
      Serial.print(t);
      Serial.print(" *C, ");
      Serial.print(f);
      Serial.print(" *F, ");
      Serial.print("Humidity: ");
      Serial.print(h);
      Serial.println(" %, ");

      // 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 = SD.open("dhtbmp.txt", FILE_WRITE);

      // if the file is available, write to it:
      if (dataFile)
      {
        dataFile.print(f);
        dataFile.print(",");
        dataFile.print(t);
        dataFile.print(",");
        dataFile.print(h); // send humidity to file with 2 decimal places
        dataFile.print(",");
        dataFile.println(P,2);  // send press and cr/lf so next data goes to new line
      }
      dataFile.close();
    }
    else
    {
      Serial.println("Error.");
    }
  }
  else
  {
    Serial.println("Error.");
  }  
}