Need to reduce code size for Arduino UNO

Good afternoon. I'm a graduate student working on building an autonomous system that measures gas components of a water column. We're utilizing arduinos due to their cost and the semi-disposable nature of these systems once they are deployed. I have written code to read in 2 serial sensors and 3 analog sensors as well as switch a FET and use a DS18B20 temp probe. Then I write the lines of data to an SD card in a .txt file. I'm looking for help in reducing code size, as I need to add in GSM/GPRS capability and I'm out of room. Right now I have a lot of Serial.print lines for troubleshooting on the benchtop, and I know that removing those will help. I also tried this originally with an Arduion Mega but was unable to get the GSM shield modem to work with it despite extensive troubleshooting with Robotshop (the vendor). Other help would be greatly appreciated! Thank you!!

#include <SoftwareSerial.h>
#include <OneWire.h>
#include <Metro.h>
#include <SD.h>
#include <GSM.h>

#define pump A3
const int chipSelect = 10;
OneWire ds(4);
File dataFile;

SoftwareSerial co2Serial(19,18);
SoftwareSerial gpsSerial(9,8);  

byte readCO2[] = {0xFE, 0X44, 0X00, 0X08, 0X02, 0X9F, 0X25}; //Command packet to read Co2 (see app note) 
byte response[] = {0,0,0,0,0,0,0}; //create an array to store the response 
//multiplier for value. default is 1. set to 3 for K-30 3% and 10 for K-33 ICB 
int valMultiplier = 1; 
char inChar;
int index;
String inData;
String gpsString;
int pumpstate = LOW;
int pumpcycle = 0;
Metro pumpMetro = Metro(250);

void setup(){ 
  Serial.begin(9600); 
  pinMode(pump,OUTPUT);
  digitalWrite(pump,pumpstate);
  pinMode(10,OUTPUT);
  analogReference(DEFAULT);
  //initialize SD card and generate .txt file to store data
  Serial.print("Initializing SD card...");  
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    while (1) ;
  }
  Serial.println("card initialized.");
  dataFile = SD.open("datalog.txt",FILE_WRITE);

}
void loop() {
  delay(2000);  //change to vary sampling frequency in milliseconds

  if (pumpMetro.check() == 1){
    if (pumpstate == LOW) {
      pumpstate = HIGH;
      pumpMetro.interval(5000);
      pumpcycle ++;
    }
    else {
      pumpMetro.interval(5000);
      pumpstate = LOW;
    }
    digitalWrite (pump,pumpstate);
  }
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;
  
  if ( !ds.search(addr)) {
    ds.reset_search();
    delay(250);
    return;
  }
  
  ds.reset();
  ds.select(addr);
  ds.write(0x44,1);         // start conversion, with parasite power on at the end
  
  delay(750);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.
  
  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad

  for (i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
  }

  unsigned int raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // count remain gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    if (cfg == 0x00) raw = raw << 3;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms
    // default is 12 bit resolution, 750 ms conversion time
  }
  float wTemp = (float)raw / 16.0;
  Serial.print(wTemp);
  Serial.write(44);
  
  co2Serial.begin(9600);
  sendRequest(readCO2); 
  unsigned long trueCO2 = getValue(response); 
  Serial.print(trueCO2);
  Serial.write(44); 
  co2Serial.end();

  int rawstemp = analogRead (A1);
  float stempmv = (rawstemp * (5.0 / 1023));
  float iTemp = (((stempmv * 1000) - 500) / 100);
  Serial.print(iTemp);
  Serial.write(44);
  int rawpressure = analogRead(A0);
  float pressure = ((rawpressure * (5.0 / 1023.0)) * 125 + 572.75);
  Serial.print(pressure);
  Serial.write(44);
  float rawcond = analogRead(A1);
  float mv_cond = rawcond * (5.0 / 1023.0);
  float inv_cond = (1 / mv_cond);
  float lin_cond = (inv_cond * 18147) + 4968.6;
  //float pow_cond = 25017 * (Pow(5,-0.664));
  //float conductivity = (lin_cond + pow_cond) / 2;
  float conductivity = lin_cond;
  Serial.print(conductivity);
  Serial.write(44);
  Serial.print(mv_cond);
  Serial.write(44);
  
  gpsSerial.begin(4800);
    gpsString = "";
    index = 0;
    inData = 0;
    inChar = 0;
    delay(800);
    while(gpsSerial.available()>0) {
    inChar = gpsSerial.read();
    inData[index] = inChar;
    index++;
    gpsString += inChar;
    
    if (inChar == 42){
      //36 = $, 42 = *
      index = 0;
      Serial.println(gpsString);    
    }  }
    gpsSerial.end();
    
  uint32_t m = millis();
  
  dataFile.print(m);
  dataFile.print(", ");
  dataFile.print(wTemp);
  dataFile.print(", ");    
  dataFile.print(trueCO2);
  dataFile.print(", ");
  dataFile.print(iTemp);
  dataFile.print(", ");
  dataFile.print(pressure);
  dataFile.print(", ");
  dataFile.print(conductivity);
  dataFile.print(", ");
  dataFile.print(mv_cond);
  dataFile.print(", ");
  dataFile.print(pumpstate);
  dataFile.print(", ");
  dataFile.print(gpsString);

  dataFile.flush();
}

void sendRequest(byte packet[]) 
{ 
 while(!co2Serial.available()) //keep sending request until we start to get a response 
 { 
 co2Serial.write(readCO2,7); 
 delay(50); 
 } 
 int timeout=0; //set a timeoute counter 
 while(co2Serial.available() < 7 ) //Wait to get a 7 byte response 
 { 
 timeout++; 
 if(timeout > 10) //if it takes to long there was probably an error 
 { 
 while(co2Serial.available()) //flush whatever we have 
 co2Serial.read(); 
 break; //exit and try again 
 } 
 delay(50); 
 } 
 for (int i=0; i < 7; i++) 
 { 
 response[i] =  co2Serial.read(); 
 } 
} 
unsigned long getValue(byte packet[]) 
{ 
 int high = packet[3]; //high byte for value is 4th byte in packet in the packet 
 int low = packet[4]; //low byte for value is 5th byte in the packet 
 unsigned long val = high*256 + low; //Combine high byte and low byte with this formula to get value 
 return val* valMultiplier; 
}

You should not be calling begin() and end() in loop(). Use listen() to change the active instance.

and I'm out of room.

In SRAM or in Flash?

Ditching the String class would help.

    inChar = gpsSerial.read();
    inData[index] = inChar;
    index++;
    gpsString += inChar;

Not keeping two copies of the same data would too.

    }  }

ONE } per line. Never more than one.

You can also save room by using data type byte instead of int for many things.

Thanks for the help! I'm putting in your recommendations now and have gotten the size down a little bit, but really hoping for more so I can put in the GSM code. Any and all help is most appreciated!

V/R
cwall

Yuo might have to go into the libraries and simplify functions you don't utilize all of. i.e., rewrite the OneWire functions to handle only your hardware.

Otherwise, you may need a Mega.

Thanks KeithRB. I think I am going to have to go Mega. My earlier failure with getting the GSM to work is frustrating, but we'll see. I just put in an order for an Arduino Mega 2560, the one I had was an ADK, and I'm hoping that that was the reason it failed to work with the GSM Shield. We'll see next week. Thanks!

V/R
cwall