I2C sensor with Yun

Hi!

I have a I2C sensor that I try to use with my Yun Rev2, but so far no luck.

This is the code, which is meant for Uno/Mega. But as long as its I2C it should also work with Yun? Or do I need to change something?

//This code will work on an Arduino Uno and Mega
//This code was written to be easy to understand.
//Modify this code as you see fit.
//This code will output data to the Arduino serial monitor.
//Type commands into the Arduino serial monitor to control the EZO Co2 sensor.
//This code was written in the Arduino 1.8.9 IDE
//This code was last tested 7/2019


#include <Wire.h>                //enable I2C.
#define address 105              //default I2C ID number for EZO Co2 sensor.



char computerdata[20];           //we make a 20 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 Co2_data[20];               //we make a 20-byte character array to hold incoming data from the Co2 sensor.
byte in_char = 0;                //used as a 1 byte buffer to store inbound bytes from the Co2 sensor.
byte i = 0;                      //counter used for Co2_data array.
int time_ = 250;                 //used to set the delay needed to process the command sent to the EZO Co2 sensor.
int Co2_int;                     //int var used to hold the value of the Co2.


void setup()                    //hardware initialization.
{
  Serial.begin(9600);           //enable serial port.
  Wire.begin();                 //enable I2C port.
}


void serialEvent() {                                                              //this interrupt will trigger when the data coming from the serial monitor(pc/mac/other) is received.
  received_from_computer = Serial.readBytesUntil(13, computerdata, 20);           //we read the data sent from the serial monitor(pc/mac/other) until we see a <CR>. We also count how many characters have been received.
  computerdata[received_from_computer] = 0;                                       //stop the buffer from transmitting leftovers or garbage.
  serial_event = true;                                                            //set the serial event flag.
}


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"
    }
    i=0;                                                                          //reset i, we will need it later 
   
    
    Wire.beginTransmission(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 Co2 sensor.

      delay(time_);                                                               //wait the correct amount of time for the circuit to complete its instruction. 
       
      Wire.requestFrom(address, 20, 1);                                           //call the circuit and request 20 bytes (this may be more than we need)
      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("Success");        //means the command was successful.
          break;                            //exits the switch case.

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

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

        case 255:                           //decimal 255.
          Serial.println("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.
      Co2_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.
      }
    }

    Serial.println(Co2_data);               //print the data.
  }
  serial_event = false;                     //reset the serial event flag
}
  //Uncomment this section if you want to take the Co2 value and convert it into integer number.
  //Co2_int=atoi(Co2_data);
}

Is your sensor detected by one of the I2C scanners?

markd833:
Is your sensor detected by one of the I2C scanners?

The serial monitor is empty if thats what you mean?

No. The I2C scanner is a separate sketch that scans the I2C bus to see what I2C devices it can see and it then reports back what it found.

Have a read of this thread where the author describes what it is etc. I'm not familiar with the Yun, so I don't know if the code will be compatible with it. Give it a go and see what it prints out.

markd833:
No. The I2C scanner is a separate sketch that scans the I2C bus to see what I2C devices it can see and it then reports back what it found.

Have a read of this thread where the author describes what it is etc. I'm not familiar with the Yun, so I don't know if the code will be compatible with it. Give it a go and see what it prints out.

Sorry, yes I have. It finds the device and names it 0x69, which is suposed to be the same as "105" I think...

Ok, so from the code you posted, I'm guessing that the sensor is an EZO Co2 sensor, and that it's the one made by Atlas Scientific.

If you go to the Atlas Scientific website by following the link, then have a look down the right hand side of the web page. Expand Documents & Downloads and you will find some sample code to interface with the sensor using Arduino.

markd833:
Ok, so from the code you posted, I'm guessing that the sensor is an EZO Co2 sensor, and that it's the one made by Atlas Scientific.

If you go to the Atlas Scientific website by following the link, then have a look down the right hand side of the web page. Expand Documents & Downloads and you will find some sample code to interface with the sensor using Arduino.

Yes that is correct and this code is from that page.

This may not help solve your problem but in setup(), just after you initialize the serial port, add in the line:

while (!Serial);

This is apparently needed to make sure that the serial port connection had been established before you try to use it.

markd833:
This may not help solve your problem but in setup(), just after you initialize the serial port, add in the line:

while (!Serial);

This is apparently needed to make sure that the serial port connection had been established before you try to use it.

markd833:
This may not help solve your problem but in setup(), just after you initialize the serial port, add in the line:

while (!Serial);

This is apparently needed to make sure that the serial port connection had been established before you try to use it.

Yes but this is just to make sure that a serial connection is opened? It should not effect the rest of code as far as I can see.
If I just wanted to upload the value to some website/cloud service and NOT use serial monitor then this would even stop the code and it would not work.

@drfish

Other post/duplicate DELETED
Please do NOT cross post / duplicate as it wastes peoples time and efforts to have more than one post for a single topic.

Continued cross posting could result in a time out from the forum.

Could you also take a few moments to Learn How To Use The Forum.

Other general help and troubleshooting advice can be found here.
It will help you get the best out of the forum in the future.

I think you should concentrate on getting the example code working locally before introducing more functionality such as trying to upload information to the cloud.

markd833:
I think you should concentrate on getting the example code working locally before introducing more functionality such as trying to upload information to the cloud.

Well I have tried that as well. I would think the code would work but it does not.
With an I2C scanner I find the device identified as 0x69
I have now tried with Wemos D1 Mini Pro and same problem. I tried putting in some debugging code

//This code will work on an Arduino Uno and Mega
//This code was written to be easy to understand.
//Modify this code as you see fit.
//This code will output data to the Arduino serial monitor.
//Type commands into the Arduino serial monitor to control the EZO Co2 sensor.
//This code was written in the Arduino 1.8.9 IDE
//This code was last tested 7/2019


#include <Wire.h>                //enable I2C.
#define address 105              //default I2C ID number for EZO Co2 sensor.



char computerdata[20];           //we make a 20 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 Co2_data[20];               //we make a 20-byte character array to hold incoming data from the Co2 sensor.
byte in_char = 0;                //used as a 1 byte buffer to store inbound bytes from the Co2 sensor.
byte i = 0;                      //counter used for Co2_data array.
int time_ = 250;                 //used to set the delay needed to process the command sent to the EZO Co2 sensor.
int Co2_int;                     //int var used to hold the value of the Co2.


void setup()                    //hardware initialization.
{
  Serial.begin(9600);           //enable serial port.
  Wire.begin();                 //enable I2C port.
}


void serialEvent() {                                                              //this interrupt will trigger when the data coming from the serial monitor(pc/mac/other) is received.
  received_from_computer = Serial.readBytesUntil(13, computerdata, 20);           //we read the data sent from the serial monitor(pc/mac/other) until we see a <CR>. We also count how many characters have been received.
  computerdata[received_from_computer] = 0;                                       //stop the buffer from transmitting leftovers or garbage.
  serial_event = true;                                                            //set the serial event flag.
}


void loop() {                                                                     //the main loop.

  Serial.print("Serial ok");

  
  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"
    }
    i=0;                                                                          //reset i, we will need it later 
   
    
    Wire.beginTransmission(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 Co2 sensor.

      delay(time_);                                                               //wait the correct amount of time for the circuit to complete its instruction. 
       
      Wire.requestFrom(address, 20, 1);                                           //call the circuit and request 20 bytes (this may be more than we need)
      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("Success");        //means the command was successful.
          break;                            //exits the switch case.

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

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

        case 255:                           //decimal 255.
          Serial.println("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.
      Co2_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.
      }
    }

    Serial.println(Co2_data);               //print the data.
  }
  serial_event = false;                     //reset the serial event flag
}

      Serial.println("loop finished");

  //Uncomment this section if you want to take the Co2 value and convert it into integer number.
  //Co2_int=atoi(Co2_data);
}

I can see the “Serial ok” in the serial monitor. I can also see the “loop finished”. And after some research I can see that its probably the

  if (serial_event == true) {                                                     //if a command was sent to the EZO device.

this part that messes up my code. Anyone have a good idea to solve it?

I can see this guys had the same problem and solved it, but I dont quite understand his solution

I think the general point of the thread you linked to is that serialEvent() is no longer used.

From my quick skim of the solution, it seems that you should take the code that is inside the serialEvent() function and put it at the end of your loop() function.

I’m guessing that you then end up with something like this:

void loop() {                              //the main loop.
  Serial.print("Serial ok");

  // the rest of the code in loop()

  received_from_computer = Serial.readBytesUntil(13, computerdata, 20);           //we read the data sent from the serial monitor(pc/mac/other) until we see a <CR>. We also count how many characters have been received.
  computerdata[received_from_computer] = 0;                                       //stop the buffer from transmitting leftovers or garbage.
  serial_event = true;                                                            //set the serial event flag.
}

And delete the whole of the serialEvent() function.