1

I am trying to get DHT22 and DS18B20 to work together. The code below is the one I am using:

#include <SD.h>
#include "SPI.h"
#include "DHT.h"
#include <RTClibExtended.h>
#include <Wire.h>
#include <LowPower.h>
#include <stdlib.h>
#include <avr/interrupt.h> // library for interrupts handling
#include <avr/sleep.h> // library for sleep
#include <avr/power.h> // library for power control
#include <OneWire.h>
#include <DallasTemperature.h>

#define DHTPIN 7 // what pin we're connected to
#define DHTTYPE DHT22 // DHT 22  (AM2302)
#define wakePin 2 //use interrupt 0 (pin 2) and run function wakeUp when pin 2 gets LOW
#define ONE_WIRE_BUS 4  //DS18B20 is plugged into pin 4

RTC_DS3231 rtc;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
const int chipSelect = 10;
int interval_sec=0; //An alarm interval in seconds
int interval_min=5; //An alarm interval in minutes
int interval_hr=0; //An alarm interval in hours
char file_name[25]="Readings.csv"; //
DHT dht(DHTPIN, DHTTYPE);
OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
DallasTemperature sensors(&oneWire); // Pass our oneWire reference to Dallas Temperature. 

void setup () {
  Serial.begin(9600);
  delay(3000); // wait for console opening
  /**RTC**/
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

  /**INTERRUPT**/
  //Set pin D2 as INPUT for accepting the interrupt signal from DS3231
  pinMode(wakePin, INPUT_PULLUP);
  Wire.begin();
  //clear any pending alarms
  rtc.armAlarm(1, false);
  rtc.clearAlarm(1);
  rtc.alarmInterrupt(1, false);
  rtc.armAlarm(2, false);
  rtc.clearAlarm(2);
  rtc.alarmInterrupt(2, false);
  //Set SQW pin to OFF (in my case it was set by default to 1Hz)
  //The output of the DS3231 INT pin is connected to this pin
  //It must be connected to arduino D2 pin for wake-up
  rtc.writeSqwPinMode(DS3231_OFF);
  //Initialize DS18B20 libraries
  sensors.begin();
  /**SD CARD**/
  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.");
  //Remove File from SD card and create a new one
  SD.remove(file_name);
  File dataFile = SD.open(file_name, FILE_WRITE);
  dataFile.println("Date,Hour,Minute,Air_Temp,Humidity,Surface_Temp");  //Write the header
  dataFile.close();
   Serial.println("Initialisation complete.");
  delay(100); //Allow for serial print to complete.
}

void loop () {
  DateTime now = rtc.now();
  Serial.print(now.year(), DEC);
  Serial.print('/');
  Serial.print(now.month(), DEC);
  Serial.print('/');
  Serial.print(now.day(), DEC);
  Serial.print(" (");
  Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
  Serial.print(") ");
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.print(now.second(), DEC);
  Serial.println();
  /**Temperature and Humidity**/
  // 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)) {
    if (isnan(h) || isnan(t)) {
      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(t);
    Serial.println(" *C\t");
    delay(3000); // wait for console
    /**DS18B20**/
    // call sensors.requestTemperatures() to issue a global temperature request to all devices on the bus
    sensors.requestTemperatures(); // Send the command to get temperatures
    float surface_temp=sensors.getTempCByIndex(0);
    Serial.print("Temperature for the device 1 (index 0) is: ");
    Serial.println(surface_temp);  
    delay(3000); // wait for console

    /**Store on SD**/
    // 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(file_name, FILE_WRITE);
    String dataString = now.day() + String("/") + now.month() + String("/") + now.year() + String(",") + now.hour() + String(",") + now.minute() + String(",") + t + String(",") + h + String(",") + surface_temp;
    //String dataString = now.day() + String("/") + now.month() + String("/") + now.year() + String(",") + now.hour() + String(",") + now.minute() + String(",") + t + String(",") + h + String(",") + String("surface_temp");
    //Serial.println(dataString);
    // 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 file to log data");
    }
    /**INTERRUPT Based sleep**/
    DateTime nextAlarm = now + TimeSpan(0, interval_hr, interval_min, interval_sec);
    //Format is TimeSpan(day,hour,min,sec). Either use interval_min or interval_sec
    Serial.print("Alarm at:");
    Serial.println(nextAlarm.hour());
    Serial.println(nextAlarm.minute());
    Serial.println(nextAlarm.second());
    rtc.setAlarm(ALM1_MATCH_HOURS, nextAlarm.second(), nextAlarm.minute(), nextAlarm.hour (), 1); //set wake-up time here
    rtc.alarmInterrupt(1, true);
    delay(3000); // wait for console
    attachInterrupt(0, wakeUp, LOW); //use interrupt 0 (pin 2) and run function wakeUp when pin 2 gets LOW
    LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
    //Arduino enters sleep mode here
    detachInterrupt(0);
    //execution resumes from here after wake-up
    //When exiting the sleep mode we clear the alarm
    rtc.armAlarm(1, false);
    rtc.clearAlarm(1);
    rtc.alarmInterrupt(1, false);
    Serial.println();
    delay(3000);
}

void wakeUp() {
  // here the interrupt is handled after wakeup
}

The above code ideally should read and store the temperature from DS18B20, and temperature and humidity from DHT22 and then go to sleep for a pre-determined time (5mins now) and then wake up when an interrupt is generated from the RTC.

However, I am unable to get both DHT22 and DS18B20 to work together. The code above works as expected if I comment out the code for DS18B20. Similarly, if I just run the examples (named Single and Simple) for DS18B20 as provided by DallasTemperature on the same Arduino keeping all the connections intact (DHT, RTC, SD Card, along with DS18B20) the DS18B20 also work as expected. Hence, I think I can be certain that the connections are proper. However, if I run the code above which include both DHT22 and DS18B20, then the output I get is as follows:

Initializing SD card...card initialized.
Initialisation complete.
201Initializing SD card...card initialized.
Initialisation complete.
2⸮

I would appreciate if someone can point me to where I am going wrong.

P.S.: I have also successfully tried a simple program like the one below to ensure that there are no conflicts in libraries of DHT22 and DS18B20.

#include <DallasTemperature.h>
#include <OneWire.h>
#include <DHT.h>

#define ONE_WIRE_BUS 4
#define DHTPIN 7     // what pin we're connected to
#define DHTTYPE DHT22   // DHT 22  (AM2302)

DHT dht(DHTPIN, DHTTYPE);
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

void setup(void) {
  Serial.begin(9600);
  Serial.println("Dallas Temperature IC Control Library Demo");
  sensors.begin();
}

void loop(void) {
  sensors.requestTemperatures(); 
  Serial.print("Temperature1: ");
  Serial.print(dht.readTemperature());
  Serial.print(" Temperature 2 : ");
  Serial.println(sensors.getTempCByIndex(0)); 
}
  • What does the compiler say about the used memory ? – Jot Jun 11 '17 at 5:04
  • 1
    @Jot: Yes! There is a warning saying that there is too less free memory and the program might not work properly. I have reduced the number of print statements and now it works as expected. Can you add your comment as an answer? – DotPi Jun 11 '17 at 6:09
1

My first thought was that sram is being overwritten. That seems to be the case, as you have confirmed.

The SD library uses a lot of sram memory, because it has to handle a table of the FAT data structure from the SD memory card.

You don't use the 'PSTR()' or the 'F()' macro and not the PROGMEM.
For example this code:
Serial.println("Dallas Temperature IC Control Library Demo");
creates that text in Flash memory and during startup that text is also copied to sram memory. You can avoid that by forcing that text to stay in flash memory only with the 'F()' macro:
Serial.println(F("Dallas Temperature IC Control Library Demo"));

Perhaps you have already seen sketches that use the 'F()' macro a lot.

The names of the days of the week can be placed in Flash code with PROGMEM. It requires special functions to read data from PROGMEM, since the AVR microcontrollers can not read data from flash directly.

[ADDED] The 'F()' macro, the 'PSTR()' and the PROGMEM are explained here: Nick Gammon about PROGMEM

  • 1
    Nice tidbit about F(), @Jot. It is predefined? – SDsolar Jun 12 '17 at 2:04
  • Yes, it is part of the Arduino and mostly used with AVR microcontrollers like the Arduino Uno, Nano, Leonardo, and so on. I have added a link to my answer to Nick Gammon's page about it. – Jot Jun 12 '17 at 10:01

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.