Reset caused by data logger + thermistor + serial I2C backpack?
Moderators: adafruit_support_bill, adafruit

Reset caused by data logger + thermistor + serial I2C backpack?

by park on Tue Dec 25, 2012 12:09 am

I am using an Uno with the Adafruit data logger shield, and an extensive set of sensors. In order to get a few more pins free (to add yet another sensor) I recently changed out the serial display for an i2c backpack. So, here are the symptoms.

I can read all the sensors, including the thermistor on A2, no problem. They all read OK and they all display OK on the LCD and on the Serial display.

If I compile the code so that it does not periodically measure A2, then everything works fine--I can open a log file on the SD card and write to it, no problem. I can set analogReference( EXTERNAL), set the pin to input, and read it once, also without problem.

On the other hand, if I compile the code with a regular polling of the analog pin, then I get a very bad behavior. When I try to access the SD card, the whole Arduino resets, and goes back, for sure into the setup() routine. This will happen continuously as long as I try to access the card.

I have no plausible explanation. The only one I can think of is that I burned the Atmega. If this happened, the mechanism was because I hooked the 3V source from the data logger shield to AREF and then set the analogReference( ) wrong.

Any ideas what I can do? Any help appreciated!

-Park

Schematic and code listing attached.

Image

Code: Select all | TOGGLE FULL SIZE
/* File: RIMU_1.ino
 * Date: December 31, 2011
 *
 * Description: This Arduino sketch is intended to drive a
 * multi-sensor data logger based on an Arduino and a bunch
 * of accessory cards. Please see the design document for
 * the RIMU.1, which was stored in a file "ArduDataLogger".
 */
 
#include "Wire.h"

// These definitions control what content is included. Since sensors may be
// added and removed easily (especially during development).  The initial set
// is just the DISPLAY and the SERIAL
#define SERIAL
#define RTC_ATTACHED
//#define BMP085_ATTACHED
//#define SENSIRON_ATTACHED
//#define THRMCPL_ATTACHED
//#define TSL2561_ATTACHED // Luminosity/Lux sensor
#define THERMISTOR_ATTACHED
#define DISPLAY_ATTACHED
//#define DHT_ATTACHED

#ifdef RTC_ATTACHED
#include <SD.h>
const int chipSelect = 10;
String    dataString = "";
File      dataFile;
const char *headerline="date.time,tcpl.c,thrmstr.c,thrmstr.r,bmp085.c,bmp085.p,ir,vis,dht.c,dht.h";

#include <RTClib.h>
RTC_DS1307 RTC;
DateTime timestamp;
#endif // RTC_ATTACHED

#ifdef BMP085_ATTACHED

#include "Adafruit_BMP085.h"
Adafruit_BMP085  bmp;
float   bmp_temp_c_f = 0.0;
int32_t bmp_press_Pa_i32 = 0;
#endif // BMP085_ATTACHED

#ifdef DHT_ATTACHED
#include "DHT.h"
const unsigned char dhtpin = 6;
float               dht_temp_c;
float               dht_hum_pct;
#define DHTTYPE DHT22
#define DHT22_PIN 2
#endif // DHT_ATTACHED

#ifdef SENSIRON_ATTACHED

#endif // SENSIRON_ATTACHED

#ifdef TSL2561_ATTACHED // Luminosity/Lux sensor
#include <TSL2561.h>
// The address will be different depending on whether you let
// the ADDR pin float (addr 0x39), or tie it to ground or vcc. In those cases
// use TSL2561_ADDR_LOW (0x29) or TSL2561_ADDR_HIGH (0x49) respectively
TSL2561  tsl( TSL2561_ADDR_FLOAT);
uint16_t tsl2561_vis = 0;
uint16_t tsl2561_ir  = 0;
uint32_t tsl2561_lum = 0;
#endif // TSL2561_ATTACHED

#ifdef THRMCPL_ATTACHED
#include <max6675.h>
const byte thrmcpl_D0  = 7; // D7
const byte thrmcpl_CS  = 8; // D8
const byte thrmcpl_CLK = 9; // D9
MAX6675    thermocouple( thrmcpl_CLK, thrmcpl_CS, thrmcpl_D0);
float      thrmcpl_temp_c_f = 0.0;
#endif

#ifdef THERMISTOR_ATTACHED
const uint16_t thrmstr_series_resistor = 10000; // measured to be 10.00 kOhm 2012-1-6
const byte     thrmstr_pin = A2;
float          thrmstr_reading;
float          thrmstr_resistance_ohm;
float          thrmstr_steinhart_temp_c;
const float    thrmstr_res_nominal = 10000;
const float    thrmstr_temp_nominal_c = 25;
const float    thrmstr_b_coef = 3950;
const int      thrmstr_num_samples = 1;
#endif // THERMISTOR_ATTACHED

#ifdef DISPLAY_ATTACHED
#include <LiquidCrystal.h>
int nWrite = 16;
// The address of mine is 0
LiquidCrystal lcd( 0);
                   
/* From: http://www.quinapalus.com/hd44780udg.html
   The degree symbol:
In decimal:    12,18,18,12,0,0,0
In hex:    0xc,0x12,0x12,0xc,0x0,0x0,0x0
In binary:    %1100,%10010,%10010,%1100,%0,%0,%0
*/
unsigned char degree[8]     = {0x0c,0x12,0x12,0x0c,0x00,0x00,0x00};
unsigned char ell_logoff[8] = {0x12,0x15,0x15,0x12,0x10,0x10,0x1f};
unsigned char ell_logon[8]  = {0x12,0x12,0x12,0x12,0x10,0x10,0x1f};
#endif // DISPLAY_ATTACHED

// Pin assignments 
const int buttonDisplayPin = 3; // D3, Display on/off and state toggle
const int logSwitchPin     = 2; // D2, Logging enable/disable toggle switch
const int debounceDelay_ms = 50;
char timeStr[] = "00/00 00:00:00";

/* A note on update interval variables
 * an unsigned integer's range is 0 to 65,535 = (2^16) - 1. This
 * is only a little more than 1 minute for millisecond counters.
 * For display and button debounce, this is more than adequate, but
 * I have used unsigned long values, which are good to 49.7 days. */

// Sensor control variables
unsigned long       sensorsLastUpdateTime_ms = 0;
const unsigned int  sensorsUpdateIntvl_ms = 1000;

// Logger control variables
boolean             logEnabled = false;
byte                logSwitchState = LOW;
byte                logSwitchStateLast = LOW;
const unsigned long logUpdateIntvl_ms  = 10000; //60000;
unsigned long       logSwitchCheckTime_ms = 0;
unsigned long       logLastUpdateTime_ms  = 0;

// Display control variables
byte               dispState;
boolean            dispEnabled = false;
byte               dispButtonState = LOW;
byte               dispButtonStateLast = LOW;
unsigned long      dispButtonCheckTime_ms = 0;
unsigned long      dispButtonTime_ms = 0;
unsigned long      dispLastUpdateTime_ms  = 0;
const unsigned int dispUpdateIntvl_ms = 1000;
const unsigned int dispOnDuration_ms = 20000;

enum {S_TCPL_OR_HUM, S_LUM_IR, S_LUM_VIS, S_BAROM, S_TMIST, S_DHT, S_NUMSENS};

unsigned long timeSince_ms( unsigned long tcomp){
  // This function deal with wrap-around on the millis() clock. It can
  // It can only handle a single wrap, of course
  unsigned long tnow = millis();
 
  if( tnow < tcomp)
    return( tnow + 4294967295 - tcomp);
   
  return( tnow - tcomp);
}

int tenthsPlace(float x){
  // ToDo: update this to support rounding
  return int( x*10) - int( x)*10;
}

#ifdef DHT_ATTACHED
DHT dht( dhtpin, DHTTYPE);
#endif

#ifdef DISPLAY_ATTACHED
void dumplcd( int nWrite){ // Writes nWrite blank spaces to the LCD
  while( nWrite > 0) nWrite -= lcd.print( " ");
}
#endif
/////////////////////////////////////////////////////////////////////////
/////    setup
/////////////////////////////////////////////////////////////////////////
void setup(){
  delay( 200);
 
  pinMode( buttonDisplayPin, INPUT);
  pinMode( logSwitchPin, INPUT);
 
  Wire.begin();
  #ifdef SERIAL
  Serial.begin( 9600);
  #endif // SERIAL
 
  #ifdef RTC_ATTACHED
 
  RTC.begin();
 
  // following line sets the RTC to the date & time this sketch was compiled
  if( ! RTC.isrunning()){
    RTC.adjust( DateTime( __DATE__, __TIME__));
  }
 
  pinMode( SS, OUTPUT);
  pinMode( chipSelect, OUTPUT);
  delay( 20);
  if( !SD.begin( chipSelect)){
    #ifdef SERIAL
    Serial.println("Card failed, or not present");
    #endif // SERIAL
    return; // abort!
  }
  #endif // RTC_ATTACHED

  #ifdef BMP085_ATTACHED
  bmp.begin();
  #endif // BMP085_ATTACHED

  #ifdef SENSIRON_ATTACHED
  #endif // SENSIRON_ATTACHED

  #ifdef TSL2561_ATTACHED // Luminosity/Lux sensor
  // You can change the gain on the fly, to adapt to brighter/dimmer light situations
  //tsl.setGain(TSL2561_GAIN_0X);  // set no gain (for bright situtations)
  tsl.setGain(TSL2561_GAIN_16X);  // set 16x gain (for dim situations)

  // Changing the integration time gives you a longer time over which to sense light
  // longer timelines are slower, but are good in very low light situtations!
  tsl.setTiming( TSL2561_INTEGRATIONTIME_13MS);  // shortest integration time (bright light)
  //tsl.setTiming(TSL2561_INTEGRATIONTIME_101MS);  // medium integration time (medium light)
  //tsl.setTiming(TSL2561_INTEGRATIONTIME_402MS);  // longest integration time (dim light)
  #endif // TSL2561_ATTACHED

  #ifdef THRMCPL_ATTACHED
  // No actions required, possibly except delay(500)
  #endif // THRMCPL_ATTACHED

  #ifdef THERMISTOR_ATTACHED
  // Assumming you follow the adafruit tutorial for the 3.3 V hookup, and reduced noise
  analogReference( EXTERNAL);
  pinMode( thrmstr_pin, INPUT);
  #endif // THERMISTOR_ATTACHED
  //analogReference( EXTERNAL);
  //pinMode( A2, INPUT);
 
 
  #ifdef DHT_ATTACHED
  dht.begin();
  #endif

  #ifdef DISPLAY_ATTACHED
  lcd.createChar( 0, degree); // access the character with lcd.write(0)
  lcd.createChar( 1, ell_logon);
  lcd.createChar( 2, ell_logoff);
  // set up the LCD's number of rows and columns:
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.setCursor(0,0);
  nWrite = 16;
  nWrite -= lcd.print("RIMU.1");
  dumplcd( nWrite);
 
  lcd.setCursor(0,1);
  nWrite = 16;
  nWrite -= lcd.print("Park Hays");
  dumplcd( nWrite);
  #endif // DISPLAY_ATTACHED

  #ifdef SENSIRON_ATTACHED
  #endif // SENSIRON_ATTACHED
}

/////////////////////////////////////////////////////////////////////////
/////    loop
/////////////////////////////////////////////////////////////////////////
void loop(){
 
  /**********************************************************************************************/
  // Read the Clock and Sensors, if enough time has elapsed for it
  // ToDo: Decide if anything has changed (display or log, and the sensor read timer has fired
  //       and only update if there is some reason to do so. This might be laggy on the display,
  //       and would only be sensible if the system is in a power saving mode.
  if( timeSince_ms( sensorsLastUpdateTime_ms) > sensorsUpdateIntvl_ms){
    // read all the sensors, starting with the clock
    #ifdef RTC_ATTACHED
    timestamp = RTC.now();
    timeStr[0] = timestamp.month()/10 + '0';
    timeStr[1] = timestamp.month()%10 + '0';
    timeStr[3] = timestamp.day()/10 + '0';
    timeStr[4] = timestamp.day()%10 + '0';
    timeStr[6] = timestamp.hour()/10 + '0';
    timeStr[7] = timestamp.hour()%10 + '0';
    timeStr[9] = timestamp.minute()/10 + '0';
    timeStr[10]= timestamp.minute()%10 + '0';
    timeStr[12]= timestamp.second()/10 + '0';
    timeStr[13]= timestamp.second()%10 + '0';
   
    #ifdef SERIAL
    Serial.println( timeStr);
    #endif // SERIAL
   
    #endif // RTC_ATTACHED

    #ifdef BMP085_ATTACHED
    bmp_temp_c_f = bmp.readTemperature(); // returns temp in C 
    bmp_press_Pa_i32 = bmp.readPressure(); // returns pressure in Pa
   
    #ifdef SERIAL
    /*Serial.print("BMP085 Data: ");
    Serial.print(bmp_temp_c_f, DEC);
    Serial.print(" C, ");
    Serial.print(bmp_press_Pa_i32, DEC);
    Serial.println(" Pa");*/
    #endif // SERIAL
    #endif // BMP085_ATTACHED
 
    #ifdef SENSIRON_ATTACHED
    #endif // SENSIRON_ATTACHED
   
    #ifdef TSL2561_ATTACHED // Luminosity/Lux sensor
    // Simple data read example. Just read the infrared, fullspecrtrum diode
    // or 'visible' (difference between the two) channels.
    // This can take 13-402 milliseconds! Uncomment whichever of the following you want to read
 
    // More advanced data read example. Read 32 bits with top 16 bits IR, bottom 16
    // bits full spectrum. That way you can do whatever math and comparions you want!
 
    // ToDo: Put this in a loop to increase integration time until the result is appropriate
    tsl2561_lum = tsl.getFullLuminosity();
    tsl2561_vis = tsl2561_lum & 0xFFFF;
    tsl2561_ir = tsl2561_lum >> 16;
   
    #ifdef SERIAL
    /*Serial.print("TSL2561 (Luminosity) Data: ");
    Serial.print(tsl2561_vis, DEC);
    Serial.print(" lx Vis, ");
    Serial.print(tsl2561_ir, DEC);
    Serial.println(" lx IR");*/
    #endif // SERIAL
   
    #endif // TSL2561_ATTACHED

    #ifdef THRMCPL_ATTACHED
    thrmcpl_temp_c_f = thermocouple.readCelsius();
    #ifdef SERIAL
    /*Serial.print("Thermocouple (MAX6671) Data: ");
    Serial.print(thrmcpl_temp_c_f, DEC);
    Serial.println(" C");*/
    #endif // SERIAL
    #endif // THRMCPL_ATTACHED
   
   
    #ifdef THERMISTOR_ATTACHED
    thrmstr_reading = 0.;
    //thrmstr_reading += analogRead( thrmstr_pin);
    for( int i = 0; i < thrmstr_num_samples; i++){
      thrmstr_reading += (float)analogRead( thrmstr_pin);
      delay( 10);
    }
    thrmstr_reading /= (float)thrmstr_num_samples;
   
    thrmstr_resistance_ohm   = (1023./thrmstr_reading) - 1;
    thrmstr_resistance_ohm   = thrmstr_series_resistor / thrmstr_resistance_ohm;
    thrmstr_steinhart_temp_c = thrmstr_resistance_ohm / thrmstr_res_nominal;// (R/Ro)
    thrmstr_steinhart_temp_c = log(thrmstr_steinhart_temp_c);               // ln(R/Ro)
    thrmstr_steinhart_temp_c /= thrmstr_b_coef;                             // 1/B * ln(R/Ro)
    thrmstr_steinhart_temp_c += 1.0 / (thrmstr_temp_nominal_c + 273.15);    // + (1/To)
    thrmstr_steinhart_temp_c = 1.0 / thrmstr_steinhart_temp_c ;             // Invert
    thrmstr_steinhart_temp_c -= 273.15;                                     // convert to C
    #ifdef SERIAL
    Serial.print("Thermistor analog reading ");
    Serial.println( thrmstr_reading, DEC);
    Serial.print("Thermistor Data: ");
    Serial.print(thrmstr_steinhart_temp_c, DEC);
    Serial.println(" C");
    #endif // SERIAL
    #endif // THERMISTOR_ATTACHED

    #ifdef DHT_ATTACHED
    dht_hum_pct = dht.readHumidity();
    dht_temp_c  = dht.readTemperature(); 
    dht.begin();
   
    #ifdef SERIAL
    Serial.print("DHT Humidity ");
    Serial.println( dht_hum_pct, DEC);
    Serial.print("DHT Temperature ");
    Serial.print(dht_temp_c, DEC);
    Serial.println(" C");
    #endif // SERIAL 
    #endif // DHT_ATTACHED
 
   
    #ifdef SENSIRON_ATTACHED
    #endif // SENSIRON_ATTACHED
   
    // capture the time
    sensorsLastUpdateTime_ms = millis();
  }
 
  /**********************************************************************************************/
  // Handle the display control button

  if( timeSince_ms( dispButtonCheckTime_ms) > debounceDelay_ms){ 
 
    dispButtonState = digitalRead( buttonDisplayPin);
    dispButtonCheckTime_ms = millis();

    // someone pushed the button
    if( (dispButtonState == LOW) && (dispButtonStateLast == HIGH)){
      // reset the start time
      dispButtonTime_ms = millis();
     
      #ifdef SERIAL
      Serial.println("Someone pushed the DISPLAY button");
      if( dispEnabled){
        Serial.println("The display is ENABLED");
        Serial.print("Current display state: ");
        Serial.println(dispState);
      }else{
        Serial.println("The display is DISABLED");
      }
      #endif // SERIAL
     
      #ifdef DISPLAY_ATTACHED
      // increment the display state
      if( dispEnabled){
        lcd.display();
        dispState ++;
        dispState %= S_NUMSENS;
      }
     else{
        dispEnabled = true;
        // hack should cause the display processing to update on the first try,
        // no matter what the old data contained
        lcd.display();
        dispLastUpdateTime_ms = millis();
      }
      #endif // DISPLAY_ATTACHED
    }
   
    dispButtonStateLast = dispButtonState;
  }     

  /**********************************************************************************************/   
  // Display Handling
  // test for timeout, should I shut off the display?
  if( dispEnabled & (timeSince_ms( dispButtonTime_ms) > dispOnDuration_ms)){
     // Turn off the LED
     // lcd.noDisplay();
     
     // Change the state
     dispEnabled = false;
  }
  // Update the display if enough time has passed or if the input has changed
  else if( timeSince_ms( dispLastUpdateTime_ms) > dispUpdateIntvl_ms){

    #ifdef SERIAL
    //Serial.println("Updating Display");
    #endif // SERIAL
   
    #ifdef DISPLAY_ATTACHED
    lcd.display();
    lcd.setCursor(0,0);
    nWrite = 16;
   
    #ifdef RTC_ATTACHED
    // Update the clock (first line of display)
    nWrite -= lcd.print(timeStr);
    dumplcd( nWrite -1);
    if( logEnabled){
      lcd.write( (uint8_t)1);
    }else{
      lcd.write( (uint8_t)2);
    }
   
    #else
    nWrite -= lcd.print("RTC Not Attached");
    dumplcd( nWrite);
    #endif // RTC_ATTACHED
   
    // Update the sensor output (line 2)
    lcd.setCursor(0,1);
    nWrite = 16;
   
    // Gather & format error codes, if any
    switch(dispState){
      case S_TCPL_OR_HUM:
        #ifdef SENSIRON_ATTACHED
        nWrite -= lcd.print( "Sensiron Not Impl");
        dumplcd( nWrite);
        #endif // SENSIRON_ATTACHED
       
        #ifdef THRMCPL_ATTACHED
        nWrite -= lcd.print( thrmcpl_temp_c_f);
        nWrite -= lcd.write( (uint8_t)0);
        nWrite -= lcd.print( 'C T-CPL');
        dumplcd( nWrite);
       
        #else // no sensor attached
        nWrite -= lcd.print( "No Humid/T-CPL");
        dumplcd( nWrite);
        #endif // THRMCPL_ATTACHED
       
        break;
       
      case S_LUM_IR:
        #ifdef TSL2561_ATTACHED
        nWrite -= lcd.print( tsl2561_ir, DEC);
        nWrite -= lcd.print(" lx IR");
        dumplcd( nWrite);
       
        #else
        nWrite -= lcd.print("No IR Sensor");
        dumplcd( nWrite);
        #endif // TSL2561_ATTACHED
       
        break;
       
      case S_LUM_VIS:
        #ifdef TSL2561_ATTACHED
        nWrite -= lcd.print(tsl2561_vis, DEC);
        nWrite -= lcd.print(" lx vis");
        dumplcd( nWrite);
       
        #else
        nWrite -= lcd.print("No Vis Sensor");
        dumplcd( nWrite);
        #endif // TSL2561_ATTACHED
        break;
       
      case S_BAROM:
        #ifdef BMP085_ATTACHED
        nWrite -= lcd.print( int(bmp_temp_c_f), DEC);
        nWrite -= lcd.print(".");
        nWrite -= lcd.print( tenthsPlace( bmp_temp_c_f), DEC); //)int( bmp_temp_c_f*10) - int( bmp_temp_c_f)*10, DEC); // won't get a 0
        nWrite -= lcd.write((uint8_t)0); // write the degree symbol (custom char 0)
        nWrite -= lcd.print("C ");
        nWrite -= lcd.print( bmp_press_Pa_i32/100, DEC);
        nWrite -= lcd.print( ".");
        nWrite -= lcd.print( tenthsPlace(float(bmp_press_Pa_i32)/100));
        nWrite -= lcd.print( " mb");
        dumplcd( nWrite);

        #else
        nWrite -= lcd.print("No Press Sensor");
        dumplcd( nWrite);
        #endif // BMP085_ATTACHED
        break;
       
      case S_TMIST:
        #ifdef THERMISTOR_ATTACHED
        nWrite -= lcd.print( thrmstr_steinhart_temp_c);
        nWrite -= lcd.write((uint8_t)0);
        nWrite -= lcd.print("C t-mist");
        dumplcd( nWrite);
       
        #else
        nWrite -= lcd.print("No Thermistor");
        dumplcd( nWrite);
        #endif // THERMISTOR_ATTACHED
        break;
       
      case S_DHT:
       
        #ifdef DHT_ATTACHED
        #ifdef SERIAL
        Serial.println( "S_DHT");
        #endif
       
        // check if returns are valid, if they are NaN (not a number) then something went wrong!
        nWrite -= lcd.print( "Hum ");
        nWrite -= lcd.print( dht_hum_pct, 1);
        nWrite -= lcd.print( "% ");
       
        nWrite -= lcd.print( dht_temp_c*9./5 + 32., 1);
        nWrite -= lcd.print( "F");
        dumplcd( nWrite);
       
        #endif // DHT_ATTACHED
        break;
    }
   
    #endif // DISPLAY_ATTACHED
   
    dispLastUpdateTime_ms = millis();
  }

  /**********************************************************************************************/
  // Log switch handling
  if( timeSince_ms( logSwitchCheckTime_ms) > debounceDelay_ms){
    logSwitchStateLast = logSwitchState;
    logSwitchState = digitalRead( logSwitchPin);
    //Serial.print( "Current log switch state: ");
    //Serial.println( logSwitchState);
  }
 
  /**********************************************************************************************/
  // Log handling
  if( logEnabled == false && logSwitchState == HIGH){ // log start
    #ifdef SERIAL
    Serial.println( "Log: opening log file and starting log");
    delay( 100);
    #endif // SERIAL
   
    // Find a fresh filename and open it
    char filename[] = "RIMU_00.CSV";
    for( uint8_t i = 0; i < 100; i++){
      filename[5] = i/10 + '0';
      filename[6] = i%10 + '0';
     
      Serial.print("testing existence of file ");
      Serial.println( filename);
      delay( 50);
     
      if( ! SD.exists( filename )){
       
        #ifdef SERIAL
        Serial.print("Opening file: ");
        Serial.println( filename);
        #endif // SERIAL
       
        dataFile = SD.open( filename, FILE_WRITE);
        break;
      }
    }
   
    if( dataFile){
      // write a header
      dataFile.println( headerline );
      #ifdef SERIAL
      Serial.print("ToFile: ");
      Serial.println( headerline);
      #endif // SERIAL
     }
   
    // force the last state change, so we don't end up in here next loop
    logEnabled = true;
    logLastUpdateTime_ms = millis();
  }
  else if( logEnabled  && (logSwitchState == HIGH)){ // log continue
    if( timeSince_ms( logLastUpdateTime_ms) > logUpdateIntvl_ms){
      #ifdef SERIAL   
      Serial.println( "Log: Appending record to log");
      #endif // SERIAL

      // write a record
      if( dataFile){
        // "date.time,tcpl.c,thrmstr.c,thrmstr.r,bmp085.c,bmp085.p,ir,vis"
        dataFile.print( timestamp.year());
        dataFile.print( '/');
        dataFile.print( timeStr);
        dataFile.print( ',');
       
        //dataFile.print( thrmcpl_temp_c_f);
        dataFile.print( ',');
       
        // thermistor temperature and resistance estimate
        #ifdef THERMISTOR_ATTACHED
        dataFile.print( thrmstr_steinhart_temp_c);
        dataFile.print( ',');
        dataFile.print( thrmstr_resistance_ohm);
        dataFile.print( ',');
        #endif // THERMISTOR_ATTACHED
       
        // bmp085 temperature
        #ifdef BMP085_ATTACHED
        dataFile.print( bmp_temp_c_f);
        dataFile.print( ',');
        dataFile.print( bmp_press_Pa_i32);
        dataFile.print( ',');
        #endif // BMP085_ATTACHED
       
        // luminosity data
        #ifdef TSL2561_ATTACHED
        dataFile.print(tsl2561_ir);
        dataFile.print( ',');
        dataFile.print(tsl2561_vis);
        #endif // TSL25561_ATTACHED
       
        // DHT data
        #ifdef DHT_ATTACHED
        dataFile.print( dht_temp_c);
        dataFile.print( ',');
        dataFile.println( dht_hum_pct);
        #endif // DHT_ATTACHED
      }
      // capture the time
      logLastUpdateTime_ms = millis();
    }
  }
  else if( (logEnabled == true) && (logSwitchState == LOW)){ // log end
    #ifdef SERIAL   
    Serial.println( "Log: Closing log file");
    #endif // SERIAL
 
    if( dataFile){
      // write end-of-logging by switch record
      dataFile.println( "# Log closed");
     
      // close file
      dataFile.close();
    }
   
    logEnabled = false;
  }
}
park
 
Posts: 13
Joined: Wed Dec 28, 2011 4:12 pm

Re: Reset caused by data logger + thermistor + serial I2C backpack?

by park on Wed Dec 26, 2012 5:37 pm

I did some more Googling and found this:
http://arduino.cc/forum/index.php?topic=116362.0

This suggests that my problem may be a voltage dip on Vcc, caused by...well, I can't tell what. I have a multimeter and the Arduino, but I'd be really surprised if I'm the only person with a brown out reset. Anyone else using the adafruit data logger shield seeing this?

-Park
park
 
Posts: 13
Joined: Wed Dec 28, 2011 4:12 pm

Re: Reset caused by data logger + thermistor + serial I2C backpack?

by franklin97355 on Wed Dec 26, 2012 6:34 pm

You don't mention what you are powering all this with. Remember the regulator on the Arduino is limited and will run out of current if you try to drive too many devices. You might try an external 5v regulated power supply to provide more current.
User avatar
franklin97355
 
Posts: 5517
Joined: Mon Apr 21, 2008 2:33 pm

Re: Reset caused by data logger + thermistor + serial I2C backpack?

by adafruit_support_rick on Wed Dec 26, 2012 10:44 pm

I think you have got your thermistor pin number defined incorrectly:
Code: Select all | TOGGLE FULL SIZE
const byte     thrmstr_pin = A2;

I'm not really certain why this compiles at all, but I'll assume that it's interpreting 'A2' as a hexadecimal integer, which is equal to 162 decimal.
See if it works better like this:
Code: Select all | TOGGLE FULL SIZE
const byte     thrmstr_pin = 2;

adafruit_support_rick
 
Posts: 12938
Joined: Tue Mar 15, 2011 11:42 am
Location: Buffalo, NY

Re: Reset caused by data logger + thermistor + serial I2C backpack?

by park on Fri Dec 28, 2012 11:41 am

Interesting proposal, I tested it.

First, to specify a hexadecimal number in C you have to precede it with 0x, so for me to write 0xA2 would indicate a hex byte, and this would compile.

What is actually happening is from line 51 in "pins_arduino.h":
static const uint8_t A2 = 16;

So this notation is correctly getting pin 16 (one of the analog pins) with the code A2.

This works almost like a #define, but specifies the type cleanly. In fact, until your post I had assumed it was a #define. On my system the pins_arduino.h file is in the arduino software folder: arduina-1.0.2\hardware\arduino\variants\standard.

Thanks for your thoughtful reply!

-Park
park
 
Posts: 13
Joined: Wed Dec 28, 2011 4:12 pm

Re: Reset caused by data logger + thermistor + serial I2C backpack?

by park on Fri Dec 28, 2012 11:57 am

franklin97355,
I am powering everything from the Arduino board, via either a wall brick or USB. You're probably right that there is a power problem, but there is one odd bit of information. The project works fine using the identical physical circuit if I don't run the analog read. The addition of the analog read seems cause the reset.

Any advice on power regulators? I'll measure the current draw and see how close I am to the limits. One hint from the link above about brown-out reset may be too much equivalent series resistance (ESR) in the capacitors, which causes a momentary dip in the voltage (hard for me to diagnose without an oscilloscope).

Thanks for your reply, I really appreciate your time!

-Park
park
 
Posts: 13
Joined: Wed Dec 28, 2011 4:12 pm

Re: Reset caused by data logger + thermistor + serial I2C backpack?

by adafruit_support_rick on Fri Dec 28, 2012 12:03 pm

park wrote:So this notation is correctly getting pin 16 (one of the analog pins) with the code A2.

Except you don't want 16 for a call to analogRead. You want 2.
The definition of A2 as 16 is for calls to digitalRead.

adafruit_support_rick
 
Posts: 12938
Joined: Tue Mar 15, 2011 11:42 am
Location: Buffalo, NY

Re: Reset caused by data logger + thermistor + serial I2C backpack?

by park on Fri Dec 28, 2012 2:54 pm

driverblock,
I followed the tutorial on http://arduino.cc/en/Tutorial/AnalogInputPins, which suggests using A0, A1, A2, etc. I see in http://arduino.cc/en/Reference/analogRead that they use the just the decimal pin number (1 for analog 1). I presume that internally analogRead() is doing a modulo (or equivalently considering only the least signficant bits).

For what it's worth, reading "A2" on my project with analog read works. I get the correct temperature measurement, which changes correctly when I hold the thermistor in my hand.

-Park
park
 
Posts: 13
Joined: Wed Dec 28, 2011 4:12 pm

Re: Reset caused by data logger + thermistor + serial I2C backpack?

by adafruit_support_rick on Fri Dec 28, 2012 3:38 pm

park wrote:On the other hand, if I compile the code with a regular polling of the analog pin, then I get a very bad behavior.

I presume that you are doing this by defining the symbol THERMISTOR_ATTACHED? That is, you are not simply commenting out the call to readAnalog()?

In that case, then all this stuff would not be declared, correct?
Code: Select all | TOGGLE FULL SIZE
#ifdef THERMISTOR_ATTACHED
const uint16_t thrmstr_series_resistor = 10000; // measured to be 10.00 kOhm 2012-1-6
const byte     thrmstr_pin = A2;
float          thrmstr_reading;
float          thrmstr_resistance_ohm;
float          thrmstr_steinhart_temp_c;
const float    thrmstr_res_nominal = 10000;
const float    thrmstr_temp_nominal_c = 25;
const float    thrmstr_b_coef = 3950;
const int      thrmstr_num_samples = 1;
#endif // THERMISTOR_ATTACHED


I think you are running out of RAM, and this problem has nothing to do with analogRead. You can verify that by commenting out the call. I predict that you will still observe the bad behavior.

You should know that the keyword 'const' does not cause the constant to be stored in flash. It is still in RAM. To move constant data to flash, you must use the PROGMEM directive. Alternatively, change all your const declarations to #define.

String literals are also stored in RAM by default. Starting with Adruino 1.0, the F() macro definition has been included to make it easier to move string literals into program space. For example, in this statement, the string literal will be stored in flash, rather than in SRAM. No additional coding is necessary to retrieve the string from program space.
Code: Select all | TOGGLE FULL SIZE
   Serial.println( F("S_DHT") );

adafruit_support_rick
 
Posts: 12938
Joined: Tue Mar 15, 2011 11:42 am
Location: Buffalo, NY

Re: Reset caused by data logger + thermistor + serial I2C backpack?

by park on Sat Dec 29, 2012 1:26 pm

driverblock,
Thank you for the suggestion. After commenting out the call to analogRead() (not commenting out the #define) it still crashes. This is consistent with your expectations.

I appreciate your suggestion, since it is consistent with the fact that the code works in parts, but not in total. I'm not sure it is the answer yet, since I can undefine BM085_ATTACHED, THRMCPL_ATTACHED, DHT_ATTACHED, leaving only
RCT_ATTACHED,
THRMISTOR_ATTACHED, and
DISPLAY_ATTACHED
and this still crashes. Is there any way to measure/estimate the amount of RAM in use/remaining?

Using my Fluke 79 multimeter, I made the further observations that the 5V line is rock steady at 5.07V. However, the 3v3 line is unsteady and depends on the software that is running. I cut the line from 3v3 to AREF, and am using the DEFAULT analogReference(), and moved the thermistor over to the 5V line.

Here's the funky thing, with DHT and thermistor enabled in software (these each seem to cause the crash), and with logging off, 3v3 is around 4.0 V--seems high to me??? Before I cut the AREF line, 3v3 was at 5.07 (rather suggests a short).

Does that provide any insight?
park
 
Posts: 13
Joined: Wed Dec 28, 2011 4:12 pm

Re: Reset caused by data logger + thermistor + serial I2C backpack?

by adafruit_support_rick on Sat Dec 29, 2012 8:17 pm

Hmm…
Looking at your schematic a little closer, you're mixing 3.3V and 5V I2C devices. This could be how you're getting 5V feeding back onto the 3.3V pin.

The I2C backpack and the DS1307 are both 5V devices.

The BMP085 and the TSL7561 are both 3.3V devices. The BMP is "5V friendly" if you've powering it on V2 instead of V1. The TSL is strictly 3.3.

According to the TSL tutorial, you can still use it with the datalogger IF you remove the SCL and SDA pullup resistors from the DS1307. Have you done this?

The same would apply to the 4.7K pullups on the I2C backpack. Removing the pullups on 5V devices protects the 3.3V devices from 5V.

You would then also have to run the BMP on 3.3 on the V1 line.

One question remains - can the I2C LCD backpack data lines run at 3.3V? I don't know. You will still have to run the backpack at 5V, but you would have only 3.3V logic levels on the data lines.

You may want to splice in an I2C logic-level shifter, to separate the 5V and 3.3V segments of the bus.

adafruit_support_rick
 
Posts: 12938
Joined: Tue Mar 15, 2011 11:42 am
Location: Buffalo, NY

Re: Reset caused by data logger + thermistor + serial I2C backpack?

by park on Sun Dec 30, 2012 12:43 am

driverblock,

I'll order a level shifter and see if I can work that out. I did have the data logger configured without the pullup resistors, but did not connect the dots on the LCD backpack. I am nearly certain you've identified the problem. I'll pull the display off the I2C and see if that works.

I will post back when I have more to update--thanks so much for your advice.
park
 
Posts: 13
Joined: Wed Dec 28, 2011 4:12 pm

Re: Reset caused by data logger + thermistor + serial I2C backpack?

by park on Sun Dec 30, 2012 11:16 pm

I removed the i2c lines from the serial backpack, and oddly the 3v3 line is still hovering around 4V (dips to 3.7V momentarily, synchronous with some process in the program).
Does this voltage seem problematic for the 3v3 line?

I moved all the string constants into flash by enclosing them in the "F()" macro/function.

While the LCD isn't working (of course), the rest is. This is pretty convincing evidence that I was running out of RAM. I'll still put a level shifter in the line for added stability, but there may be more than one problem at work here.
park
 
Posts: 13
Joined: Wed Dec 28, 2011 4:12 pm

Re: Reset caused by data logger + thermistor + serial I2C backpack?

by adafruit_support_bill on Mon Dec 31, 2012 7:44 am

Looking at your source code, I see this:
Code: Select all | TOGGLE FULL SIZE
      #ifdef THERMISTOR_ATTACHED
      // Assumming you follow the adafruit tutorial for the 3.3 V hookup, and reduced noise
      analogReference( EXTERNAL);
      pinMode( thrmstr_pin, INPUT);
      #endif // THERMISTOR_ATTACHED

There is a caution regarding analogReference(EXTERNAL) here: http://arduino.cc/en/Reference/AnalogReference
If you're using an external reference on the AREF pin, you must set the analog reference to EXTERNAL before calling analogRead(). Otherwise, you will short together the active reference voltage (internally generated) and the AREF pin, possibly damaging the microcontroller on your Arduino board.

If you un-defined THERMISTOR_ATTACHED, but did not disconnect the AREF pin, it is possible you may have damaged something.
User avatar
adafruit_support_bill
 
Posts: 30887
Joined: Sat Feb 07, 2009 10:11 am

Re: Reset caused by data logger + thermistor + serial I2C backpack?

by park on Tue Jan 01, 2013 12:02 am

I may well have done that, having read the cautions much too late. I get normal function except for the taps. Any way to test?

If something is cooked, should I pursue replacing just the Atmega, or the voltage regulators too?
park
 
Posts: 13
Joined: Wed Dec 28, 2011 4:12 pm