Datalogging With Multiple Sensors

General project help for Adafruit customers

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
samoht
 
Posts: 3
Joined: Wed Jan 30, 2013 1:59 am

Datalogging With Multiple Sensors

Post by samoht »

I'm trying to build a datalogger that takes information from an ADXL335 accelerometer, a TSL2561 luminosity sensor, a BMP085 pressure sensor, a DHT22 temperature sensor, and an Ultimate GPS and writes it to an SD card reader through an Arduino Uno. My code seems to work as long as I don't include the GPS, but when I add the GPS library and initialization commands in the library declarations and setup function the it looks like the setup function just keeps looping over and over, only getting through setting up the DHT. I've done my best to follow the wiring instructions for each sensor, so it would be my guess that the problem is with the code somewhere. Has anyone else run into this problem? I've included the library declarations and setup function below, mostly recycled from the example functions for the sensors. Thanks.

Code: Select all

#include "DHT.h"
#include <Wire.h>
#include "Adafruit_BMP085.h"
#include "TSL2561.h"
#include "Adafruit_GPS.h"
#include "SD.h"

#if ARDUINO >= 100
 #include <SoftwareSerial.h>
#else
#endif

#define DHTPIN 4
#define DHTTYPE DHT22
DHT dht(DHTPIN,DHTTYPE);

Adafruit_BMP085 bmp;

TSL2561 tsl(TSL2561_ADDR_LOW); 

#if ARDUINO >= 100
  SoftwareSerial mySerial(3, 2);
#else
  NewSoftSerial mySerial(3, 2);
#endif
Adafruit_GPS GPS(&mySerial);

#define GPSECHO false
const int chipSelect = 10;
boolean usingInterrupt = false;
const int dec_place  = 100;

const int groundpin = 18;             // analog input pin 4 -- ground
const int powerpin = 19;              // analog input pin 5 -- voltage
const int xpin = A3;                  // x-axis of the accelerometer
const int ypin = A2;                  // y-axis
const int zpin = A1;                  // z-axis (only on 3-axis models)

void setup()
{
  Serial.begin(115200);
  Serial.println("Into Setup");
  dht.begin();
  Serial.println("DHT complete");
  bmp.begin();
  Serial.println("BMP complete");
  
  pinMode(groundpin, OUTPUT);
  pinMode(powerpin, OUTPUT);
  digitalWrite(groundpin, LOW);
  digitalWrite(powerpin, HIGH);
  Serial.println("ADXL complete");
  
  tsl.setGain(TSL2561_GAIN_16X);
  tsl.setTiming(TSL2561_INTEGRATIONTIME_13MS);
  tsl.begin();
  Serial.println("TSL complete");
  
  GPS.begin(9600);
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);
  Serial.println("GPS complete");
  delay(1000);
  
  mySerial.println(PMTK_Q_RELEASE);
  Serial.println("Beginning SD test");
  pinMode(10, OUTPUT);
  if (!SD.begin(chipSelect)){
      Serial.println("Recognition of SD card reader failed!");
      return;
  }
  Serial.println("SD test complete");
  
  String hdrstr = "Humidity (%)\tTemp (dht,*C)\tTemp (bmp,*C)\tPressure (hPa)\tAltitude (m)\tX Accel \tY Accel \tZ Accel \tIR\tFull\tVisible\tLux\tTime\tDate\tFix\tQuality\tLat\tLon\tSpeed (kt)\tAngle\tAltitude (ft)\tSatellites";
  //Serial.println(hdrstr);
  File hdrFile = SD.open("datalog.txt", FILE_WRITE);
  if (hdrFile) {
    hdrFile.println(hdrstr);
    hdrFile.close();
    Serial.println(hdrstr);
  }else{
    Serial.println("FAILURE!");
  }
  Serial.println("SD test complete");  
}
uint32_t timer = millis();
void loop()
{
   if (! usingInterrupt) {
    // read data from the GPS in the 'main loop'
    char c = GPS.read();
    // if you want to debug, this is a good time to do it!
    if (GPSECHO)
      if (c) UDR0 = c;
      // writing direct to UDR0 is much much faster than Serial.print 
      // but only one character can be written at a time. 
  }
  
  // if a sentence is received, we can check the checksum, parse it...
  if (GPS.newNMEAreceived()) {
    // a tricky thing here is if we print the NMEA sentence, or data
    // we end up not listening and catching other sentences! 
    // so be very wary if using OUTPUT_ALLDATA and trytng to print out data
    //Serial.println(GPS.lastNMEA());   // this also sets the newNMEAreceived() flag to false
  
    if (!GPS.parse(GPS.lastNMEA()))   // this also sets the newNMEAreceived() flag to false
      return;  // we can fail to parse a sentence in which case we should just wait for another
  }
  if (timer > millis())  timer = millis();

  // approximately every 5 seconds or so, print out the current stats
  if (millis() - timer > 5000) { 
    Serial.println("INTO TIMER LOOP");
    
    timer = millis(); // reset the timer
    File dataFile = SD.open("datalog.txt", FILE_WRITE);
    if (dataFile) {
      //Write DHT data to file
      dataFile.print(dht.readHumidity());
      dataFile.print("\t");
      dataFile.print(dht.readTemperature());
      dataFile.print("\t");
      //Write BMP data to file
      dataFile.print(bmp.readTemperature());
      dataFile.print("\t");
      dataFile.print(bmp.readPressure());
      dataFile.print("\t");
      dataFile.print(bmp.readAltitude());
      dataFile.print("\t");
      //Write ADXL data to file
      dataFile.print(analogRead(xpin));
      dataFile.print("\t");
      dataFile.print(analogRead(ypin));
      dataFile.print("\t");
      dataFile.print(analogRead(zpin));
      dataFile.print("\t");
      //Write TSL data to file
      uint32_t lum = tsl.getFullLuminosity();
      uint16_t ir, full;
      ir = lum >> 16;
      full = lum & 0xFFFF;
      dataFile.print(ir);
      dataFile.print("\t");
      dataFile.print(full);
      dataFile.print("\t");
      dataFile.print(full-ir);
      dataFile.print("\t");
      dataFile.println(tsl.calculateLux(full, ir));
      dataFile.print("\t");
      //Write GPS data to file
      dataFile.print(GPS.hour);
      dataFile.print(":");
      dataFile.print(GPS.minute);
      dataFile.print(":");
      dataFile.print(GPS.seconds);
      dataFile.print(".");
      dataFile.print(GPS.milliseconds);
      dataFile.print("\t");
      dataFile.print(GPS.day);
      dataFile.print("/");
      dataFile.print(GPS.month);
      dataFile.print("/20");
      dataFile.print(GPS.year);
      dataFile.print("\t");
      dataFile.print((int)GPS.fix);
      dataFile.print("\t");
      if (GPS.fix) {
        Serial.println("Fix Achieved!");
        dataFile.print((int)GPS.fixquality);
        dataFile.print("\t");
        dataFile.print(GPS.latitude);
        dataFile.print("\t");
        dataFile.print(GPS.lat);
        dataFile.print("\t");
        dataFile.print(GPS.longitude);
        dataFile.print("\t");
        dataFile.print(GPS.lon);
        dataFile.print("\t");
        dataFile.print(GPS.speed);
        dataFile.print("\t");
        dataFile.print(GPS.angle);
        dataFile.print("\t");
        dataFile.print(GPS.altitude);
        dataFile.print("\t");
        dataFile.println(GPS.satellites);
      }else {
        dataFile.println(GPS.fixquality);
      }
      dataFile.close();
      Serial.println("Wrote to file");
    }
  }
}

User avatar
adafruit_support_bill
 
Posts: 88097
Joined: Sat Feb 07, 2009 10:11 am

Re: Datalogging With Multiple Sensors

Post by adafruit_support_bill »

It is possible that you are running out of RAM. The symptoms of that can be unpredictable, but continuous resetting of the processor is a likely scenario.

Try reducing some of the string literals in your program. Or better yet, you can move them to flash memory using the "F()" macro. For example, change this:
Serial.println("Into Setup");
into this:
Serial.println(F("Into Setup"));

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Datalogging With Multiple Sensors

Post by adafruit_support_rick »

Are you using the Adafruit Datalogger Shield? You should be aware that you have some 3.3V I2C devices in your list. The RTC on the shield is a 5V I2C device. Make sure that you are using level-shifters between that and your 3.3V I2C devices, or remove the I2C pullup resistors on the shield. See the warning on this page

samoht
 
Posts: 3
Joined: Wed Jan 30, 2013 1:59 am

Re: Datalogging With Multiple Sensors

Post by samoht »

Thank you for the responses.

I'll try changing all the serial statements to F statements and see if that helps.

I'm not currently using the Datalogger Shield. In that case, would I still have to remove the pull-up resistors for both the BMP (although my V2 board should be able to handle 5V according to the Adafruit page for this sensor) and the TSL?

Incidentally, since I have two sensors slaved to the same Arduino I2C pin, I've been wiring the pullup resistors between the I2C input pins on the Arduino and the both the sensors' pins, so the order on a breadboard would be (arduinopin -> resistor -> sensor1 connection-> sensor2 connection). Is this correct, or should I wire the pullup resistors in front of each individual sensor? I hope my description makes sense. Thanks.

User avatar
adafruit_support_bill
 
Posts: 88097
Joined: Sat Feb 07, 2009 10:11 am

Re: Datalogging With Multiple Sensors

Post by adafruit_support_bill »

Yes. The i2c lines will be pulled up to 5v even if the shield is not being used.

The other alternative mentioned by Driverblock is to use an i2c level shifter.
http://www.adafruit.com/products/757

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: Datalogging With Multiple Sensors

Post by adafruit_support_rick »

You don't need to remove pullups at every device. What you want to do is make sure that 3.3V devices like the TSL2561 are not exposed to 5V levels on the SCL and SDA lines. Our latest version BMP085 has built-in level-shifters so it can tolerate 5V levels, but the TSL cannot.

Looks like you only have those two I2C devices? If so, you can operate them as-is on your Uno - no level-shifting or pullup removal required.

However, if you were to add the Adafruit Logger Shield (whether you use the shield's DS1307 or not), you would have to do one of two things:
1) remove the pullup resistors on SCL and SDA on the shield. Leave the BMP085 and TSL2561 as-is.
or
2) Put a level shifter between the shield and the TSL2561. Not necessary to remove any resistors anywhere (the BMP085 can go on either side of the level-shifter)

The level-shifter is added cost, but if you plan on adding any other I2C sensors, it allows you to segment your I2C bus into 5V and 3.3V sections without any concerns about whether or not to remove pullup resistors.

samoht
 
Posts: 3
Joined: Wed Jan 30, 2013 1:59 am

Re: Datalogging With Multiple Sensors

Post by samoht »

Thank you again for your responses. It appears that I was running out of SRAM. I commented out most of the serial statements and the large header string, and everything seems to be working fine now.

Locked
Please be positive and constructive with your questions and comments.

Return to “General Project help”