Bug in code. Please help!

Hi All,

Nice little community you have here.

I'm having problems with reliability in a program that I have written. It will run fine for a while - anywhere from a couple hours to 19 hours almost to the tee. After that, sometimes it just freezes and sometimes it turns on pump1 indefinitely. Not sure what the problem is but I need a solution!

I'm fairly new to C and I'm hoping the problem is straight forward. Can you guys take a look at my code? Thanks!

//Initialize Global Variablles
  //include libraries
    #include <Wire.h>
    #include <Time.h>
    #include <TimeAlarms.h>
  //define varibles
    int i;                           //working variable
    int co2_lower_limit = 1200;       //parts per million
    float dwell_start_up = 2;        //seconds
    float dwell_idle = 3;            //seconds, time between samples
    float dwell_co2_on = 1.25;       //seonds
    float dwell_co2_disperson = 30;  //seconds
    float dwell_pump1_on = 65;
    float dwell_pump_trasition_delay = 10;
    float dwell_pump2_on = 65;
    int tempValue;
    int pHValue;
  //define outputs
    int pump1 = 3;
    int pump2 = 4;
    int ACunit = 5;
    int light = 6;
    int co2_valve = 7;
    int co2sensorpower = 8;          // This is the default address of the CO2 sensor, 7bits shifted left.
  // Address for co2 Meter
    int co2Addr = 0x68; 
//Run Setup
void setup() { 
  //setup pins- water, light, and temperature pins as outputs
    pinMode(pump1, OUTPUT); 
    pinMode(pump2, OUTPUT);
    pinMode(light, OUTPUT); 
    pinMode(ACunit, OUTPUT);
    pinMode(co2_valve, OUTPUT);
  //initial values of pins
    digitalWrite (pump1, LOW);
    digitalWrite (pump2, LOW);
    digitalWrite(light, HIGH);
    digitalWrite(ACunit, HIGH);
    digitalWrite(co2_valve, LOW);
    digitalWrite(13, LOW);
  //set time
     setTime(14,58,0,16,4,10); // set time to 8:29:40am Jan 1 2010 
    //would like to auto sync eventually
  //setup light cycle times
    Alarm.alarmRepeat(8,47,0, Daytime);    // 6:30am daytime starts every day
    //Alarm.alarmRepeat(2,00,0, Nighttime);  // 12:30am nighttime starts every day
  //setup water cycle times
    Alarm.alarmRepeat(0,00,0, Water);  // 8:00am water starts every day
    Alarm.alarmRepeat(1,00,0, Water);  // 8:00am water starts every day
    Alarm.alarmRepeat(2,00,0, Water);  // 8:00am water starts every day
    Alarm.alarmRepeat(3,00,0, Water);  // 8:00am water starts every day
    Alarm.alarmRepeat(4,00,0, Water);  // 8:00am water starts every day
    Alarm.alarmRepeat(5,00,0, Water);  // 8:00am water starts every day
    Alarm.alarmRepeat(6,00,0, Water);  // 8:00am water starts every day
    Alarm.alarmRepeat(7,00,0, Water);  // 8:00am water starts every day
    Alarm.alarmRepeat(8,00,0, Water);  // 8:00am water starts every day
    Alarm.alarmRepeat(9,0,0, Water);  // 10:00pm water starts every day 
    Alarm.alarmRepeat(10,0,0, Water);  // 12:00pm water starts every day
    Alarm.alarmRepeat(11,0,0, Water);  // 2:00pm water starts every day 
    Alarm.alarmRepeat(12,0,0, Water);  // 4:00pm water starts every day
    Alarm.alarmRepeat(13,0,0, Water);  // 6:00pm water starts every day 
    Alarm.alarmRepeat(14,0,0, Water);  // 8:00pm water starts every day
    Alarm.alarmRepeat(15,0,0, Water);  // 10:00pm water starts every day 
    Alarm.alarmRepeat(16,0,0, Water);  // 12:00pm water starts every day
    Alarm.alarmRepeat(17,0,0, Water);  // 2:00am water starts every day 
    Alarm.alarmRepeat(18,0,0, Water);  // 2:00am water starts every day
    Alarm.alarmRepeat(19,0,0, Water);  // 2:00am water starts every day
    Alarm.alarmRepeat(20,0,0, Water);  // 2:00am water starts every day
    Alarm.alarmRepeat(21,0,0, Water);  // 2:00am water starts every day
    Alarm.alarmRepeat(22,0,0, Water);  // 2:00am water starts every day
    Alarm.alarmRepeat(23,0,0, Water);  // 2:00am water starts every day
    Alarm.alarmRepeat(24,0,0, Water);  // 2:00am water starts every day
  //open serial port
    Serial.begin(9600);
    Wire.begin ();
    pinMode(13, OUTPUT);             // We will use this pin as a read-indicator
    Serial.println("What a wonderful day to grow tomatotoes!");
    Serial.println("Initializing");
    for (i = 0; i < dwell_start_up; i ++){
      Serial.println(i);
      Alarm.delay(1000);
    }
}
//Run Loop
void loop() {
Serial.println("-------------------------------------");
//Display time
  digitalClockDisplay();
  if(light = 1){
    Serial.println("(Daytime)");
  }
  else{
    Serial.println("(Nighttime)");
  }

//Print co2 value to serial
int co2Value = readCO2();
if(co2Value > 0) {
  Serial.print("co2(ppm): ");
  Serial.println(co2Value);
}
else {
  Serial.print("co2(ppm): ");
  Serial.println("checksum failed");
}
if(tempValue > 0) {
  Serial.print("temp(F): ");
  Serial.println(tempValue);
}
else {
  Serial.print("temp(F): ");
  Serial.println("checksum failed");
}
if(pHValue > 0) {
  Serial.print("pH: ");
  Serial.println(pHValue);
}
else {
  Serial.print("pH: ");
  Serial.println("checksum failed");
}
Serial.println("-------------------------------------");

delay(dwell_idle * 1000); //second
//co2 valve logic
if (co2Value < co2_lower_limit && co2Value > 0) {
  Serial.println("***low co2 value detected***");
  Serial.print(co2Value);
  Serial.print("(detected) < ");
  Serial.print(co2_lower_limit);
  Serial.println("(limit)");
  
  Alarm.delay(500);// Solenoid dwell
  Serial.print("co2 valve actuated for ");
  digitalWrite(co2_valve, HIGH);
  digitalWrite(13, HIGH);
  Serial.print(dwell_co2_on);
  Serial.println(" second(s)");
  Alarm.delay((dwell_co2_on * 1000));  // Solenoid dwell, dwell_co2_on given in seconds
  digitalWrite(co2_valve, LOW);
  digitalWrite(13, LOW);
  Serial.print("dispersion delay for ");
  Serial.print(dwell_co2_disperson);
  Serial.println(" second(s)");
  Alarm.delay(dwell_co2_disperson * 1000);// Delay dwell,dwell_co2_dispersion given in seconds
}
//if (co2Value > 1000);
//{
//digitalWrite(co2_valve, LOW);
//digitalWrite(13, LOW);
//}

Alarm.delay(1000);
}

// functions to be called when an alarm triggers:
void Daytime(){
  Serial.print("Alarm: - Daytime");    
  digitalWrite(co2_valve, LOW);
  digitalWrite(light, HIGH);
  digitalWrite(ACunit, HIGH);
}
void Nighttime(){
  Serial.print("Alarm: - Nighttime");    
  digitalWrite(co2_valve, LOW);
  digitalWrite(light, LOW);
  digitalWrite(ACunit, LOW);
}
void Water(){
  Serial.println("Time to Water");
  //pump1  
    Serial.print("pump1 actuated for ");
    Serial.println(dwell_pump1_on);
    digitalWrite(co2_valve, LOW);
    digitalWrite(pump1, HIGH);
    Alarm.delay(dwell_pump1_on * 1000);  
    digitalWrite(pump1, LOW);
    Alarm.delay(dwell_pump_trasition_delay * 1000);
  //pump2  
    Serial.print("pump2 actuated for ");
    Serial.println(dwell_pump2_on); 
    digitalWrite(pump2, HIGH);
    Alarm.delay(dwell_pump2_on * 1000);
    digitalWrite(pump2, LOW);
}
void digitalClockDisplay(){
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.println(" ");
  Serial.print(dayStr(weekday()));
  Serial.print(" ");
  Serial.print(day());
  Serial.print(" ");
  Serial.print(monthShortStr(month()));
  Serial.print(" ");
  Serial.print(year()); 
  Serial.println(); 
}

void printDigits(int digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

///////////////////////////////////////////////////////////////////
// Function : int readCO2()
// Returns : CO2 Value upon success, 0 upon checksum failure
// Assumes : - Wire library has been imported successfully.
// - LED is connected to IO pin 13
// - CO2 sensor address is defined in co2_addr
///////////////////////////////////////////////////////////////////
int readCO2() {
    int co2_value = 0;      // We will store the CO2 value inside this variable.
  /* Begin Write Sequence */ 
    Wire.beginTransmission(co2Addr);  
    Wire.send(0x22);
    Wire.send(0x00);
    Wire.send(0x08);
    Wire.send(0x2A);
    Wire.endTransmission();
  /* End Write Sequence. */
  /*
  We wait 10ms for the sensor to process our command.
  The sensors's primary duties are to accurately
  measure CO2 values. Waiting 10ms will ensure the
  data is properly written to RAM
  */
  Alarm.delay(10);
  /* Begin Read Sequence */
  /*
  Since we requested 2 bytes from the sensor we must
  read in 4 bytes. This includes the payload, checksum,
  and command status byte.
  */
  Wire.requestFrom(co2Addr, 4);
  byte i = 0;
  byte buffer[4] = {0, 0, 0, 0};
  /*
  Wire.available() is not nessessary. Implementation is obscure but we leave
  it in here for portability and to future proof our code
  */
  while(Wire.available()) {
    buffer[i] = Wire.receive();
    i++;
  }
  /* End Read Sequence */
  /*
  Using some bitwise manipulation we will shift our buffer
  into an integer for general consumption
  */
  co2_value = 0;
  co2_value |= buffer[1] & 0xFF;
  co2_value = co2_value << 8;
  co2_value |= buffer[2] & 0xFF;
  byte sum = 0; //Checksum Byte
  sum = buffer[0] + buffer[1] + buffer[2]; //Byte addition utilizes overflow
  if(sum == buffer[3]) {
  // Success!
    return co2_value;
  }
  else {
  return 0;
  }
}
if(light = 1)

Probably should be ==.

Have you modified the Alarm library to support that number of alarms you have set?

Quick response :slight_smile:

I had already changed the alarm library to support 26 alarms:
#define dtNBR_ALARMS 26

But after you pointed out:
if(light = 1) {

I changed it to:
if(digitalRead(light) == 1) {

Another good reason to define pin numbers as constants.

Another good reason to define pin numbers as constants.

I'm still pretty new to C. Could you show the syntax and maybe a brief explanation? (though I do understand the difference between = and ==)

Thanks!

** Or should this thread belong in the 'troubleshooting' section? :slight_smile:

  //define outputs
const    int pump1 = 3;
const    int pump2 = 4;
const    int ACunit = 5;
const    int light = 6;
const    int co2_valve = 7;
const    int co2sensorpower = 8;

Now, writing "if (light = 1)" actually gives you an error, instead of just a warning.

It's unlikely that you're going to reassign the functions of these pins, so tell the compiler that they're constants, and it'll tell you if you try to assign anything to them.

I don't know if this is your problem, but in a program I wrote I found that repeated calls (i.e., thousands) to the Wire functions locked up my Arduino.

I could never pin down the problem, but it went away once I changed my program to access the I2C bus less frequently.