PROBLEM SAVING A STRING TO SD IN ULTIMATE GPS SHIELD

Post here about your Arduino projects, get help - for Adafruit customers!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
lechetrezna
 
Posts: 5
Joined: Fri Jun 06, 2014 1:18 pm

PROBLEM SAVING A STRING TO SD IN ULTIMATE GPS SHIELD

Post by lechetrezna »

Hi there. First of all: I am an absolute beginner so please forgive me in advance for my akward question and my poor scripting practice. I am trying to develop a science project where the idea is to gather GPS data along with temperature and humidity data from a suite of five DHT22 sensors connected to digital pins 2, 3, 4, 5 and 6 (i'll leave pin 9 for another sensor and one analog pin for another sensor, but for now I want to make it work with just the DHT22). Then I want to store all that information in an SD card. I have purchased an Ultimate GPS datalogger shield. My strategy is to first build a character string containing all the data, and then store that string in a file in the SD card. To achieve that, I adapted the 'leo_parsing' sketch from the Adafruit_GPS library. Up to this point, the code does what I want it to do., and I obtain a nice clean string with all the desired data which I visualize in the Serial port. If you try it with an Ultimate GPS shield without DHT22 sensors you will receive zeroes instead of temperature and humidity readings. Here is the sketch:

Code: Select all

#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
#include "DHT.h"
SoftwareSerial mySerial(8, 7);
Adafruit_GPS GPS(&mySerial);
#define GPSECHO  true
#define DHTTYPE DHT22   // DHT 22  (AM2302)
uint32_t timer = millis();
 
void setup()  
  { 
  Serial.begin(9600);
  delay(5000);
  Serial.println("Adafruit GPS library basic test!");
  GPS.begin(9600);
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);   // 1 Hz update rate
  GPS.sendCommand(PGCMD_ANTENNA);
  delay(1000);
  mySerial.println(PMTK_Q_RELEASE);
   }

void loop()                     // run over and over again
  {
  char c = GPS.read();
  if ((c) && (GPSECHO))
//    Serial.write(c); 
  if (GPS.newNMEAreceived())
    {
    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();
  if (millis() - timer > 1000)
    {
    timer = millis(); // reset the timer
    Serial.println(GPS.fix); // THIS IS TO DEBUG
    if (GPS.fix)
      {
      String dataString = "";

// THIS SECTION ADDS TIME TO THE DATASTRING
      dataString += 'H';
      dataString += ',';
      dataString += String(GPS.hour, DEC);
      dataString += ',';
      dataString += String(GPS.minute, DEC);
      dataString += ',';
      dataString += String(GPS.seconds, DEC);
      dataString += ',';
      dataString += String(GPS.milliseconds, DEC);
      dataString += ',';
      dataString += 'F';
      dataString += ',';
      dataString += String(GPS.day, DEC);
      dataString += ',';
      dataString += String(GPS.month, DEC);      
      dataString += ',';      
      dataString += String(GPS.year, DEC);  
      dataString += ',';      
      dataString += 'Q';
      dataString += ',';  
      dataString += String((int)GPS.fix);            
      dataString += ',';  
      dataString += String((int)GPS.fixquality);
      dataString += ',';
  
// THIS ADDS LATITUDE TO THE STRING  
      dataString += "LAT";
      dataString += ',';
      int gradoslat = int((GPS.latitude) / 100); // EXTRACTS THE DEGREES
      dataString += String(gradoslat); // ADDS DEGREES TO THE STRING
      dataString += ',';
      int minutoslat = (GPS.latitude - gradoslat * 100); // EXTTRACTS MINUTES
      dataString += String(minutoslat); // ADDS MINUTES TO THE STRING
      dataString += '.';
      int decimlat = (GPS.latitude - int(GPS.latitude)) * 1000; // EXTRCTS MINUTE DECIMALS
      dataString += String(decimlat); // ADDS MINUTE DECIMALS TO THE STRING
      dataString += ',';
      dataString += String(GPS.lat); // ADDS THE HEMISPHERE TO THE STRING
      dataString += ',';

// THIS ADDS LONGITUDE TO THE STRING
      dataString += "LONG";
      dataString += ',';
      int gradoslong = int((GPS.longitude) / 100); // EXTRACTS DEGREES
      dataString += String(gradoslong); // ADDS DEGREES TO THE STRING
      dataString += ',';
      int minutoslong = (GPS.longitude - gradoslong * 100); // EXTRCTS MINUTES
      dataString += String(minutoslong); // ADDS MINUTES TO THE STRING
      dataString += '.';
      int decimlong = (GPS.longitude - int(GPS.longitude)) * 1000; // EXTRACTS MINUTE DECIMALS
      dataString += String(decimlong); // ADDS MINUTE DECIMALS TO THE STRING
      dataString += ',';
      dataString += String(GPS.lon); // ADDS W_E LONGITUDE TO THE STRING
      dataString += ',';

// THIS SECTION ADDS THE ALTITUDE TO THE STRING
      dataString += "ALT";
      dataString += ',';
      dataString += String(int(GPS.altitude)); // ADDS THE INTEGER PART OF THE ALTITUDE
      dataString += '.';// 
      unsigned int altura = (GPS.altitude - int(GPS.altitude)) * 10; // EXTRACTS THE DECIMAL PART
      dataString += String(altura); // ADDS THE DECIMAL PART TO THE STRING
      dataString += ',';

// THIS SECTION ADDS THE NUMBER OF SATELLITES TO THE STRING
      dataString += "SAT";
      dataString += ',';
      dataString += String(int(GPS.satellites)); // ADDS THE NUMBER OF SATELLITES TO THE STRING
      dataString += ',';
      
// THIS SECTION ADDS TO THE STRING THE DATA FROM FIVE DHT22 TEMPERATURE AND HUMIDITY SENSORS HOOKED TO PINS 2, 3, 4, 5 AND 6
      dataString += "DHT22";
      dataString += ',';
      int dhtPins[] = {2, 3, 4, 5, 6}; // DEFINE THE PINS
      for (int i = 0; i <  4; i++)
        {
        #define DHTPIN dhtPins[i]
        DHT dht(DHTPIN, DHTTYPE);
        dht.begin();
        float h = dht.readHumidity();// READS HUMIDITY
        unsigned int frach;
        dataString += String(int(h)); // ADDS INTEGER PART OF THE HUMIDITY TO THE STRING
        dataString += '.';// ADDS THE DECIMAL POINT
        frach = (h - int(h)) * 10; // EXTRACTS THE DECIMAL PART OF THE HUMIDITY
        dataString += String(int(frach));// ADDS THE DECIMALS TO THE STRING
        dataString += ',';
        float t = dht.readTemperature();// READS TEMPERATURE FROM THE DHT22
        unsigned int fract;
        dataString += String(int(t));// ADDS THE INTEGER PART OF THE TEMPERATURE TO THE STRING
        dataString += '.';
        if (t >= 0)// IS TEMPERATURE POSITIVE?
          {
          fract = (t - int(t)) * 10; // CREATES A FLOAT VARIABLE WITH THE DECIMAL PART
          dataString += String(int(fract)); // ADDS THE DECIMAL PART TO THE STRING
          }
        else
          {
          fract = (int(t) - t) *10;
          dataString += String(int(fract));
          }
        dataString += ',';   
        }
           Serial.println(dataString);
       }
     }
   }
Now I am trying to make it store that string in the SD card, by incorporating a modified version of an example in the ARDUINO reference page (http://arduino.cc/en/Tutorial/Datalogger) where they show how to store data from three different sensors. The point is, this expanded sketch fails to produce a nice, complete string, particularly the part to do with the DHT sensors. Below, I am presenting the code with all the lines belonging to the ARDUINO SD example sketch commented out, ready to play with them. The thing is that as soon as uncomment the lines

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

the string starts doing weird things. I suspect it has to do with some kind of interaction with the DHT22 sensors, because their data are the first to fail, apparently. Including more lines just makes it worse.

Code: Select all

#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
#include "DHT.h"
// #include <SPI.h> // ARDUINO DATALOGGER SKETCH
// #include <SD.h> // ARDUINO DATALOGGER SKETCH
// const int chipSelect = 10; // ARDUINO DATALOGGER SKETCH
// File dataFile; // ARDUINO DATALOGGER SKETCH
SoftwareSerial mySerial(8, 7);
Adafruit_GPS GPS(&mySerial);
#define GPSECHO  true
#define DHTTYPE DHT22   // DHT 22  (AM2302)
uint32_t timer = millis();
 
void setup()  
  { 
  Serial.begin(9600);
  delay(5000);
  Serial.println("Adafruit GPS library basic test!");
  GPS.begin(9600);
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);   // 1 Hz update rate
  GPS.sendCommand(PGCMD_ANTENNA);
  delay(1000);
  mySerial.println(PMTK_Q_RELEASE);
//   Serial.print("Initializing SD card..."); // ARDUINO DATALOGGER SKETCH
//   pinMode(SS, OUTPUT); // ARDUINO DATALOGGER SKETCH
//   if (!SD.begin(chipSelect)) { // ARDUINO DATALOGGER SKETCH
//     Serial.println("Card failed, or not present"); // ARDUINO DATALOGGER SKETCH
//     while (1) ; // ARDUINO DATALOGGER SKETCH
//   } // ARDUINO DATALOGGER SKETCH
//   Serial.println("card initialized."); // ARDUINO DATALOGGER SKETCH
//   dataFile = SD.open("datalog.txt", FILE_WRITE); // ARDUINO DATALOGGER SKETCH
//   if (! dataFile) { // ARDUINO DATALOGGER SKETCH
//     Serial.println("error opening datalog.txt"); // ARDUINO DATALOGGER SKETCH
//     while (1) ; // ARDUINO DATALOGGER SKETCH
//   } // ARDUINO DATALOGGER SKETCH
   }

void loop()                     // run over and over again
  {
  char c = GPS.read();
  if ((c) && (GPSECHO))
//    Serial.write(c); 
  if (GPS.newNMEAreceived())
    {
    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();
  if (millis() - timer > 1000)
    {
    timer = millis(); // reset the timer
    Serial.println(GPS.fix); // THIS IS TO DEBUG
    if (GPS.fix)
      {
      String dataString = "";

// THIS SECTION ADDS TIME TO THE DATASTRING
      dataString += 'H';
      dataString += ',';
      dataString += String(GPS.hour, DEC);
      dataString += ',';
      dataString += String(GPS.minute, DEC);
      dataString += ',';
      dataString += String(GPS.seconds, DEC);
      dataString += ',';
      dataString += String(GPS.milliseconds, DEC);
      dataString += ',';
      dataString += 'F';
      dataString += ',';
      dataString += String(GPS.day, DEC);
      dataString += ',';
      dataString += String(GPS.month, DEC);      
      dataString += ',';      
      dataString += String(GPS.year, DEC);  
      dataString += ',';      
      dataString += 'Q';
      dataString += ',';  
      dataString += String((int)GPS.fix);            
      dataString += ',';  
      dataString += String((int)GPS.fixquality);
      dataString += ',';
  
// THIS ADDS LATITUDE TO THE STRING  
      dataString += "LAT";
      dataString += ',';
      int gradoslat = int((GPS.latitude) / 100); // EXTRACTS THE DEGREES
      dataString += String(gradoslat); // ADDS DEGREES TO THE STRING
      dataString += ',';
      int minutoslat = (GPS.latitude - gradoslat * 100); // EXTTRACTS MINUTES
      dataString += String(minutoslat); // ADDS MINUTES TO THE STRING
      dataString += '.';
      int decimlat = (GPS.latitude - int(GPS.latitude)) * 1000; // EXTRCTS MINUTE DECIMALS
      dataString += String(decimlat); // ADDS MINUTE DECIMALS TO THE STRING
      dataString += ',';
      dataString += String(GPS.lat); // ADDS THE HEMISPHERE TO THE STRING
      dataString += ',';

// THIS ADDS LONGITUDE TO THE STRING
      dataString += "LONG";
      dataString += ',';
      int gradoslong = int((GPS.longitude) / 100); // EXTRACTS DEGREES
      dataString += String(gradoslong); // ADDS DEGREES TO THE STRING
      dataString += ',';
      int minutoslong = (GPS.longitude - gradoslong * 100); // EXTRCTS MINUTES
      dataString += String(minutoslong); // ADDS MINUTES TO THE STRING
      dataString += '.';
      int decimlong = (GPS.longitude - int(GPS.longitude)) * 1000; // EXTRACTS MINUTE DECIMALS
      dataString += String(decimlong); // ADDS MINUTE DECIMALS TO THE STRING
      dataString += ',';
      dataString += String(GPS.lon); // ADDS W_E LONGITUDE TO THE STRING
      dataString += ',';

// THIS SECTION ADDS THE ALTITUDE TO THE STRING
      dataString += "ALT";
      dataString += ',';
      dataString += String(int(GPS.altitude)); // ADDS THE INTEGER PART OF THE ALTITUDE
      dataString += '.';// 
      unsigned int altura = (GPS.altitude - int(GPS.altitude)) * 10; // EXTRACTS THE DECIMAL PART
      dataString += String(altura); // ADDS THE DECIMAL PART TO THE STRING
      dataString += ',';

// THIS SECTION ADDS THE NUMBER OF SATELLITES TO THE STRING
      dataString += "SAT";
      dataString += ',';
      dataString += String(int(GPS.satellites)); // ADDS THE NUMBER OF SATELLITES TO THE STRING
      dataString += ',';
      
// THIS SECTION ADDS TO THE STRING THE DATA FROM FIVE DHT22 TEMPERATURE AND HUMIDITY SENSORS HOOKED TO PINS 2, 3, 4, 5 AND 6
      dataString += "DHT22";
      dataString += ',';
      int dhtPins[] = {2, 3, 4, 5, 6}; // DEFINE THE PINS
      for (int i = 0; i <  4; i++)
        {
        #define DHTPIN dhtPins[i]
        DHT dht(DHTPIN, DHTTYPE);
        dht.begin();
        float h = dht.readHumidity();// READS HUMIDITY
        unsigned int frach;
        dataString += String(int(h)); // ADDS INTEGER PART OF THE HUMIDITY TO THE STRING
        dataString += '.';// ADDS THE DECIMAL POINT
        frach = (h - int(h)) * 10; // EXTRACTS THE DECIMAL PART OF THE HUMIDITY
        dataString += String(int(frach));// ADDS THE DECIMALS TO THE STRING
        dataString += ',';
        float t = dht.readTemperature();// READS TEMPERATURE FROM THE DHT22
        unsigned int fract;
        dataString += String(int(t));// ADDS THE INTEGER PART OF THE TEMPERATURE TO THE STRING
        dataString += '.';
        if (t >= 0)// IS TEMPERATURE POSITIVE?
          {
          fract = (t - int(t)) * 10; // CREATES A FLOAT VARIABLE WITH THE DECIMAL PART
          dataString += String(int(fract)); // ADDS THE DECIMAL PART TO THE STRING
          }
        else
          {
          fract = (int(t) - t) *10;
          dataString += String(int(fract));
          }
        dataString += ',';   
        }
           Serial.println(dataString);
//   dataFile.println(dataString); // ARDUINO DATALOGGER SKETCH
//   dataFile.flush(); // ARDUINO DATALOGGER SKETCH
//   delay(5000); // ARDUINO DATALOGGER SKETCH
       }
     }
   }
Thanks in advance, and apologies!!!

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

Re: PROBLEM SAVING A STRING TO SD IN ULTIMATE GPS SHIELD

Post by adafruit_support_rick »

Please see this thread, where I solve the identical problem
http://forums.adafruit.com/viewtopic.php?f=25&t=55380

lechetrezna
 
Posts: 5
Joined: Fri Jun 06, 2014 1:18 pm

Re: PROBLEM SAVING A STRING TO SD IN ULTIMATE GPS SHIELD

Post by lechetrezna »

Wooohooo!!! That code is certainly beyond my present level of comprehension... thanks for your patience. I will give it a try and see if I can integrate the rest of sensors. Once I am done with the DHT22's my next stop is to hook a DECAGON 5TM soil and temperature probe to pin 9. This will mean blending their SDI-12 communication protocol with my code. It also seems to work with interrupts so I am wondering whether I will have trouble. My bet is: yes, I will. SO far I have managed to get hold of a piece of code that seems to render nice readings from the 5TM.

Code: Select all

#include <SDISerial.h>


/*
I used a few devices with no problem using a MEGA 2560 as well as an UNO.
Sketch was built with Arduino 1.0.4, however I also tested it under 1.0.0
Place the SDISerial folder in    "<ARDUINO_ROOT>/libraries"

with the 5TE 
the WHITE wire is power. 
   - I hooked it up to the arduino 5v output pin, however you could also connect it to a pin and drive power only when you wanted it
the RED wire is the DATA_LINE.
   - you must hook it up to a pin that can process interrupts (see link below)
   
the remaining wire must be connected to ground
*/

//in order to recieve data you must choose a pin that supports interupts
#define DATALINE_PIN 2
#define INVERTED 1
//see:   http://arduino.cc/en/Reference/attachInterrupt
//for pins that support interupts (2 or 3 typically)


SDISerial sdi_serial_connection(DATALINE_PIN, INVERTED);

char* get_measurement(){
	char* service_request = sdi_serial_connection.sdi_query("?M!",1000);
	//you can use the time returned above to wait for the service_request_complete
	char* service_request_complete = sdi_serial_connection.wait_for_response(1000);
	//dont worry about waiting too long it will return once it gets a response
	return sdi_serial_connection.sdi_query("?D0!",1000);
}

void setup(){
  sdi_serial_connection.begin(); // start our SDI connection 
  Serial.begin(9600); // start our uart
  Serial.println("OK INITIALIZED"); // startup string echo'd to our uart
  delay(3000); // startup delay to allow sensor to powerup and output its DDI serial string
}

int j=0;
void loop(){
  uint8_t wait_for_response_ms = 1000;
  char* response = get_measurement(); // get measurement data
  //if you you didnt need a response you could simply do
  //         sdi_serial_connection.sdi_cmd("0A1") 
  Serial.print("RECV:");Serial.println(response!=NULL&&response[0] != '\0'?response:"No Response!"); //just a debug print statement to the serial port
  delay(5000);
}
To top it up, I will try to bring back to life an old and presumably analogic pyranometer that I found in the trash, and integrate it in my project. So I anticipate further problems, but for the time being thanks a lot, this is a fantastic job you are doing here.

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

Return to “Arduino”