I'm a new arduino fan, and working on a project to record weather and GPS data to a SD card. I'm using the sparkfun weather shield and mini-SD shield, along with a GS407 gps receiver. I have modified the demo sketchs to get the below program. It works for a minute or two, but eventually locks. I believe I'm running out of memory on the arduino (compiled source is a little over 27K). I was hoping someone could take a look and recommend what I can do to shrink the size.
/*
Weather Shield with GPS
By: Nathan Seidle
modified to use with SD card shield
License: This code is public domain
Used with SparkFun GS407 GPS receiver
*/
#include <Wire.h> //I2C needed for sensors
#include "MPL3115A2.h" //Pressure sensor
#include "HTU21D.h" //Humidity sensor
#include <SoftwareSerial.h> //Needed for GPS
#include <TinyGPS++.h> //GPS parsing
#include <SD.h> //Micro SD card
TinyGPSPlus gps;
static const int RXPin = 5, TXPin = 4; //GPS is attached to pin 4(TX from GPS) and pin 5(RX into GPS)
SoftwareSerial ss(RXPin, TXPin);
MPL3115A2 myPressure; //Create an instance of the pressure sensor
HTU21D myHumidity; //Create an instance of the humidity sensor
//Hardware pin definitions
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// digital I/O pins
const byte WSPEED = 3;
const byte STAT1 = 7;
const byte STAT2 = 8;
const byte GPS_PWRCTL = 6; //Pulling this pin low puts GPS to sleep but maintains RTC and RAM
const int chipSelect = 8; //for the SD card
// analog I/O pins
const byte REFERENCE_3V3 = A3;
const byte LIGHT = A1;
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//Global Variables
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
long lastSecond; //The millis counter to see when a second rolls by
byte seconds; //When it hits 60, increase the current minute
byte seconds_2m; //Keeps track of the "wind speed/dir avg" over last 2 minutes array of data
byte minutes; //Keeps track of where we are in various arrays of data
byte minutes_10m; //Keeps track of where we are in wind gust/dir over last 10 minutes array of data
//We need to keep track of the following variables:
float humidity = 0; // [%]
float tempf = 0; // [temperature F]
float pressure = 0;
float light_lvl = 455; //[analog value from 0 to 1023]
void setup()
{
Serial.begin(9600);
Serial.println("Weather Shield Example");
ss.begin(9600); //Begin listening to GPS over software serial at 9600. This should be the default baud of the module.
pinMode(STAT1, OUTPUT); //Status LED Blue
pinMode(STAT2, OUTPUT); //Status LED Green
pinMode(GPS_PWRCTL, OUTPUT);
digitalWrite(GPS_PWRCTL, HIGH); //Pulling this pin low puts GPS to sleep but maintains RTC and RAM
pinMode(REFERENCE_3V3, INPUT);
pinMode(LIGHT, INPUT);
//Configure the pressure sensor
myPressure.begin(); // Get sensor online
myPressure.setModeBarometer(); // Measure pressure in Pascals from 20 to 110 kPa
myPressure.setOversampleRate(7); // Set Oversample to the recommended 128
myPressure.enableEventFlags(); // Enable all three pressure and temp event flags
//Configure the humidity sensor
myHumidity.begin();
seconds = 0;
lastSecond = millis();
// turn on interrupts
interrupts();
// make sure that the default chip select pin is set to
// output, even if you don't use it:
pinMode(chipSelect, 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("Weather Shield online!");
}
void loop()
{
//Keep track of which minute it is
if(millis() - lastSecond >= 1000)
{
digitalWrite(STAT1, HIGH); //Blink stat LED
lastSecond += 1000;
//Take a speed and direction reading every second for 2 minute average
if(++seconds_2m > 119) seconds_2m = 0;
//if(seconds_2m % 10 == 0) displayArrays(); //For testing
if(++seconds > 59)
{
seconds = 0;
if(++minutes > 59) minutes = 0;
if(++minutes_10m > 9) minutes_10m = 0;
}
//Report all readings every second
printWeather();
digitalWrite(STAT1, LOW); //Turn off stat LED
}
smartdelay(800); //Wait 1 second, and gather GPS data
}
//While we delay for a given amount of time, gather GPS data
static void smartdelay(unsigned long ms)
{
unsigned long start = millis();
do
{
while (ss.available())
gps.encode(ss.read());
} while (millis() - start < ms);
}
//Calculates each of the variables that wunderground is expecting
void calcWeather()
{
//Calc humidity
humidity = myHumidity.readHumidity();
//Calc tempf from pressure sensor
tempf = myPressure.readTempF();
//Calc pressure
pressure = myPressure.readPressure();
//Calc light level
light_lvl = get_light_level();
}
//Returns the voltage of the light sensor based on the 3.3V rail
//This allows us to ignore what VCC might be (an Arduino plugged into USB has VCC of 4.5 to 5.2V)
float get_light_level()
{
float operatingVoltage = analogRead(REFERENCE_3V3);
float lightSensor = analogRead(LIGHT);
operatingVoltage = 3.3 / operatingVoltage; //The reference voltage is 3.3V
lightSensor = operatingVoltage * lightSensor;
return(lightSensor);
}
//Prints the various variables directly to the port
//I don't like the way this function is written but Arduino doesn't support floats under sprintf
void printWeather()
{
calcWeather(); //Go calc all the various sensors
Serial.println();
Serial.print("$");
Serial.print("humidity=");
Serial.print(humidity, 1);
Serial.print(",tempf=");
Serial.print(tempf, 1);
Serial.print(",pressure=");
Serial.print(pressure, 2);
Serial.print(",light_lvl=");
Serial.print(light_lvl, 2);
Serial.print(",lat=");
Serial.print(gps.location.lat(), 6);
Serial.print(",lat=");
Serial.print(gps.location.lng(), 6);
Serial.print(",altitude=");
Serial.print(gps.altitude.meters());
Serial.print(",sats=");
Serial.print(gps.satellites.value());
char sz[32];
Serial.print(",date=");
sprintf(sz, "%02d/%02d/%02d", gps.date.month(), gps.date.day(), gps.date.year());
Serial.print(sz);
Serial.print(",time=");
sprintf(sz, "%02d:%02d:%02d", gps.time.hour(), gps.time.minute(), gps.time.second());
Serial.print(sz);
Serial.print(",");
Serial.println("#");
File dataFile = SD.open("datalog2.txt", FILE_WRITE);
//if the file is available, write to it:
if (dataFile){
dataFile.println();
dataFile.print("humidity=");
dataFile.print(humidity, 1);
dataFile.print(",tempf=");
dataFile.print(tempf, 1);
dataFile.print(",pressure=");
dataFile.print(pressure, 2);
dataFile.print(",light_lvl=");
dataFile.print(light_lvl, 2);
dataFile.print(",lat=");
dataFile.print(gps.location.lat(), 6);
dataFile.print(",lat=");
dataFile.print(gps.location.lng(), 6);
dataFile.print(",altitude=");
dataFile.print(gps.altitude.meters());
dataFile.print(",sats=");
dataFile.print(gps.satellites.value());
dataFile.print(",date=");
dataFile.print(gps.date.month());
dataFile.print("/");
dataFile.print(gps.date.day());
dataFile.print("/");
dataFile.print(gps.date.year());
dataFile.print(",time=");
dataFile.print(gps.time.hour());
dataFile.print(":");
dataFile.print(gps.time.minute());
dataFile.print(":");
dataFile.print(gps.time.second());
dataFile.println("#");
dataFile.close();
}
//if the file isn't open, print error
else {
Serial.println("SD card not present or error opening datalog.txt");
}
}