0

I did some research of my own before asking this question, and stumbled across this Arduino forum discussion. In case it was indeed a memory issue, I tried converting what I thought were my own string variables in the program with the c_str() function. I immediately realized that the variables I'm sending to the serial monitor are actually chars.

For this reason, I come to you, mighty StackExchange. Is this really a memory issue, or is my Arduino just somehow faulty? What can I change to fix my problem?

#include <Ezo_i2c.h>
#include <Ezo_i2c_util.h>
#include <iot_cmd.h>
#include <sequencer1.h>
#include <sequencer2.h>
#include <sequencer3.h>
#include <sequencer4.h>
#include <Wire.h>                //enable I2C.
#define HUM_address 111          //default I2C ID number for EZO Humidity sensor.
#define O2_address 108           //default I2C ID number for EZO O2 sensor.
#define CO2_address 105          //default I2C ID number for EZO CO2 sensor.

#define printtab(x) Serial.print(String(x) + "\t ");
#define printline Serial.println();

//EZO-HUM vars
//   | |
//   V V
char computerdata[32];           //we make a 32 byte character array to hold incoming data from a pc/mac/other.
byte received_from_computer = 0; //we need to know how many characters have been received.
byte serial_event = false;       //a flag to signal when data has been received from the pc/mac/other.
byte code = 0;                   //used to hold the I2C response code.
char Humidity_data[22];          //we make a 22-byte character array to hold incoming data from the Humidity sensor.
byte in_char = 0;                //used as a 1 byte buffer to store inbound bytes from the Humidity  sensor.
byte i = 0;                      //counter used for Humidity_data array.
int time_ = 1000;                 //used to set the delay needed to process the command sent to the EZO Humidity sensor.

//EZO-CO2 vars
//   | |
//   V V
byte CO2_code = 0;                   //used to hold the I2C response code.
char CO2_data[20];               //we make a 20-byte character array to hold incoming data from the Co2 sensor.
byte CO2_in_char = 0;                //used as a 1 byte buffer to store inbound bytes from the Co2 sensor.
int CO2_time_ = 1000;                 //used to set the delay needed to process the command sent to the EZO Co2 sensor.

//EZO-O2 vars
//   | |
//   V V
byte O2_code = 0;                   //used to hold the I2C response code.
char O2_data[20];                //we make a 20-byte character array to hold incoming data from the o2 sensor.
byte O2_in_char = 0;                //used as a 1 byte buffer to store inbound bytes from the o2 sensor.
int O2_time_ = 1000;                 //used to set the delay needed to process the command sent to the EZO o2 sensor.

char *HUM;                       //char pointer used in string parsing.
char *TMP;                       //char pointer used in string parsing.
char *NUL;                       //char pointer used in string parsing (the sensor outputs some text that we don't need).
char *DEW;                       //char pointer used in string parsing.
char *O2_reading;



void setup()                    //hardware initialization.
{
  Serial.begin(9600);           //enable serial port.
  Wire.begin();                 //enable I2C port.
  while (!Serial);           //wait for serial monitor to be open
}




void loop() {                                                                     //the main loop.
  //  if (serial_event == true) {                                                     //if a command was sent to the EZO device.
  //    for (i = 0; i <= received_from_computer; i++) {                               //set all char to lower case, this is just so this exact sample code can recognize the "sleep" command.
  //      computerdata[i] = tolower(computerdata[i]);                                 //"Sleep" ≠ "sleep"
  //      //computerdata[i] = "r";
  //    }
  //    i=0;                                                                          //reset i, we will need it later
  computerdata[0] = 'r';
  //---------------------------------------------------------EZO-HUM Sensor-----------------------------------------------------------------------------//
  Wire.beginTransmission(HUM_address);                                              //call the circuit by its ID number.
  Wire.write(computerdata);                                                     //transmit the command that was sent through the serial port.
  Wire.endTransmission();                                                       //end the I2C data transmission.



  // Need to talk to each sensor separately. Because they're all Atlas Scientific EZO sensors, they all respond to the same commands

  if (strcmp(computerdata, "sleep") != 0) {                                     //if the command that has been sent is NOT the sleep command, wait the correct amount of time and request data.
    //if it is the sleep command, we do nothing. Issuing a sleep command and then requesting data will wake the Humidity  sensor.

    delay(time_);                                                               //wait the correct amount of time for the circuit to complete its instruction.

    Wire.requestFrom(HUM_address, 23, 1);                                           //call the circuit and request 22 bytes.
    code = Wire.read();                                                         //the first byte is the response code, we read this separately.

    switch (code) {                       //switch case based on what the response code is.
      case 1:                             //decimal 1.
        //Serial.println("HUM Success");        //means the command was successful.
        break;                            //exits the switch case.

      case 2:                             //decimal 2.
        Serial.println("HUM Failed");         //means the command has failed.
        break;                            //exits the switch case.

      case 254:                           //decimal 254.
        Serial.println("HUM Pending");        //means the command has not yet been finished calculating.
        break;                            //exits the switch case.

      case 255:                           //decimal 255.
        Serial.println("HUM No Data");        //means there is no further data to send.
        break;                            //exits the switch case.
    }


    while (Wire.available()) {              //are there bytes to receive.
      in_char = Wire.read();                //receive a byte.
      Humidity_data[i] = in_char;           //load this byte into our array.
      i += 1;                               //incur the counter for the array element.
      if (in_char == 0) {                   //if we see that we have been sent a null command.
        i = 0;                              //reset the counter i to 0.
        break;                              //exit the while loop.
      }
    }
    HUM = strtok(Humidity_data, ",");         //let's pars the string at each comma.
    TMP = strtok(NULL, ",");                  //let's pars the string at each comma.
    NUL = strtok(NULL, ",");                  //let's pars the string at each comma (the sensor outputs the word "DEW" in the string, we dont need it.
    DEW = strtok(NULL, ",");                  //let's pars the string at each comma.

//    HUM.c_str();
//    TMP.c_str();
//    NUL.c_str();
//    DEW.c_str();


    printtab(HUM);
    printtab(TMP);
    printtab(DEW);


    //    if (computerdata[0] == 'r') string_pars();    //uncomment this function if you would like to break up the comma separated string into its individual parts.
  }

  //---------------------------------------------------------EZO-O2 Sensor-----------------------------------------------------------------------------//

  Wire.beginTransmission(O2_address);                                           //call the circuit by its ID number.
  Wire.write(computerdata);                                                     //transmit the command that was sent through the serial port.
  Wire.endTransmission();                                                       //end the I2C data transmission.

  if (strcmp(computerdata, "sleep") != 0) {                                     //if the command that has been sent is NOT the sleep command, wait the correct amount of time and request data.
    //if it is the sleep command, we do nothing. Issuing a sleep command and then requesting data will wake the Humidity  sensor.

    delay(O2_time_);                                                               //wait the correct amount of time for the circuit to complete its instruction.

    Wire.requestFrom(O2_address, 22, 1);                                           //call the circuit and request 22 bytes.
    O2_code = Wire.read();                                                         //the first byte is the response code, we read this separately.

    switch (O2_code) {                       //switch case based on what the response code is.
      case 1:                             //decimal 1.
        //Serial.println("O2 Sensor Success");        //means the command was successful.
        break;                            //exits the switch case.

      case 2:                             //decimal 2.
        Serial.println("O2 Sensor Failed");         //means the command has failed.
        break;                            //exits the switch case.

      case 254:                           //decimal 254.
        Serial.println("O2 Sensor Pending");        //means the command has not yet been finished calculating.
        break;                            //exits the switch case.

      case 255:                           //decimal 255.
        Serial.println("O2 Sensor No Data");        //means there is no further data to send.
        break;                            //exits the switch case.
    }


    while (Wire.available()) {              //are there bytes to receive.
      O2_in_char = Wire.read();                //receive a byte.
      O2_data[i] = (int)O2_in_char;           //load this byte into our array.
      i += 1;                               //incur the counter for the array element.
      if (O2_in_char == 0) {                   //if we see that we have been sent a null command.
        i = 0;                              //reset the counter i to 0.
        break;                              //exit the while loop.
      }
    }
    O2_reading = strtok(O2_data, ",");         //let's pars the string at each comma.

    printtab(O2_reading);
    //if (computerdata[0] == 'r') O2_string_pars();             //This code also doesn't output any information.
  }












  //---------------------------------------------------------EZO-CO2 Sensor-----------------------------------------------------------------------------//

  Wire.beginTransmission(CO2_address);                                          //call the circuit by its ID number.
  Wire.write(computerdata);                                                     //transmit the command that was sent through the serial port.
  Wire.endTransmission();                                                       //end the I2C data transmission.

  if (strcmp(computerdata, "sleep") != 0) {                                     //if the command that has been sent is NOT the sleep command, wait the correct amount of time and request data.
    //if it is the sleep command, we do nothing. Issuing a sleep command and then requesting data will wake the Humidity  sensor.

    delay(CO2_time_);                                                               //wait the correct amount of time for the circuit to complete its instruction.

    Wire.requestFrom(CO2_address, 22, 1);                                           //call the circuit and request 22 bytes.
    CO2_code = Wire.read();                                                         //the first byte is the response code, we read this separately.

    switch (CO2_code) {                       //switch case based on what the response code is.
      case 1:                             //decimal 1.
        //Serial.println("CO2 Sensor Success");        //means the command was successful.
        break;                            //exits the switch case.

      case 2:                             //decimal 2.
        Serial.println("CO2 Sensor Failed");         //means the command has failed.
        break;                            //exits the switch case.

      case 254:                           //decimal 254.
        Serial.println("CO2 Sensor Pending");        //means the command has not yet been finished calculating.
        break;                            //exits the switch case.

      case 255:                           //decimal 255.
        Serial.println("CO2 Sensor No Data");        //means there is no further data to send.
        break;                            //exits the switch case.
    }


    while (Wire.available()) {              //are there bytes to receive.
      CO2_in_char = Wire.read();                //receive a byte.
      CO2_data[i] = CO2_in_char;           //load this byte into our array.
      //Serial.println((int)CO2_in_char);
      i += 1;                               //incur the counter for the array element.
      if (CO2_in_char == 0) {                   //if we see that we have been sent a null command.
        i = 0;                              //reset the counter i to 0.
        break;                              //exit the while loop.
      }
    }
    printtab(CO2_data);
    printline;
  }

  serial_event = false;                     //reset the serial event flag

}
9
  • 1
    It may be Wire locking up from bad communication. Add debug prints to your code to find out exactly where it stops...
    – Majenko
    Jun 22 at 14:47
  • You do not appear to have a hard guarantee that i cannot be incremented to the point where Humidity_data[i] = in_char; overflows.
    – timemage
    Jun 22 at 15:04
  • You have the same problem with O2_data[i] = (int)O2_in_char; You're relying on i having made it back to a zero value in both places, which also does not seem to be guaranteed for the same reason.
    – timemage
    Jun 22 at 15:11
  • sounds like an I2C problem for me. Please check with debug prints where it halts and also check the return values of Wire.endTransmission() and Wire.requestFrom(). They might indicate an error in the I2C communication. Are you using additional pullup resistors on the I2C lines? How long is the cable to the sensor?
    – chrisl
    Jun 22 at 15:31
  • Hi @timemage - I added debug prints in each section after each of the Wire.begin, wire.write, and wire.end commands and debug prints before and after each switch block. The program hung up after around 20-25 minutes on the wire.write() in the EZO-HUM block, then eventually pushed through to get a "HUM No Data" reading, and finally got stuck on EZO-HUM Wire.EndTransmission. Even now, it will hang for a minute or two on one of the sensors' Wire commands and then continue to the next block.
    – czar1249
    Jun 22 at 16:09

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.