Senseair Sunrise S11 I2C communication

Moderators: grovkillen, Stuntteam, TD-er

Post Reply
Message
Author
fluppie
Normal user
Posts: 89
Joined: 09 Oct 2015, 13:23

Senseair Sunrise S11 I2C communication

#1 Post by fluppie » 11 Feb 2020, 13:07

Hi all,

I'm looking for a working I2C code example for the Sunrise S11 CO2 sensor from Senseair. I'm able to run an UART sample code, but I want to use I2C.

Not working example (for me):

Code: Select all

#include <Wire.h>
char FIND_ADDRESS = 'F';
char READ_CO2 = 'R';
byte address = 0x68;
//byte address = 104; //slave address

void setup() {
// put your setup code here, to run once:
Wire.begin();
Wire.setClock(10000);
Serial.begin(115200);
Serial.println("Type F to find all devices on I2C bus and type R to read CO2 from S-11");
}

void sendDataAndReadToAddress(byte reg, byte address, int bufferSize, int readCount) {
Wire.beginTransmission(address);
for (int k = 0; k < bufferSize; k++) {
Wire.write(reg);
}
Wire.endTransmission(false);
delay(24);
Wire.requestFrom(address, readCount);
delay(12);
int nBytes = Wire.available();
byte buff[nBytes];
int i = 0;
while (Wire.peek() != -1) {
buff[i] = Wire.read();
Serial.print(buff[i],HEX);
Serial.print(" ");
i++;
}
//Serial.write(buff, nBytes);
Serial.print('\n');
int co2 = (buff[0] << 8) | buff[1];
Serial.print("CO2 Concentration: ");
Serial.print(co2);
Serial.print("\n");
}

void getAllAddress() {
//Serial.println("Looking for addresses");
byte error, address;
for (address = 1; address < 128; address++) {
Wire.beginTransmission(address);
error = Wire.endTransmission();
delay(5);
if (error == 0) {
Serial.print(address, HEX);
Serial.print(" ");
}
}
}

void loop() {
// put your main code here, to run repeatedly:
while (Serial.available() == 0) { }
//Delay 10ms to ensure we get the whole message
delay(15);
int serialBufferSize = Serial.available();
byte buff[serialBufferSize];
int i = 0;
while (Serial.peek() != -1 && i < serialBufferSize) {
buff[i] = (byte)Serial.read();
i++;
}
char command = (char)buff[0];
if (command == FIND_ADDRESS) {
getAllAddress();
} else if (command == READ_CO2) {
//The LSB nibble of the second byte contains the number of data bytes being read
//Add 2 for the Command byte and Checksum
int bufferSize = 1;
int readCount = 2;
sendDataAndReadToAddress(0x06, address, bufferSize, readCount);
} else {
Serial.println("Invalid Command... Type F to find all devices on I2C bus and type R to read CO2 from S-11");
}
}
2nd non working snippet I found:

Code: Select all

#include <Wire.h>

const int       SUNRISE_EN         = 8;     //serial EN pin
const uint8_t   SUNRISE_ADDR       = 0x68;  // communication address
const int       ATTEMPTS           = 5;     // Amount of wakeup attempts before time-out

/* Delays in milliseconds*/
const int STABILIZATION_MS         = 35;

//¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
void  reInitI2C() { // Initialize I2C
  Wire.begin();
  Wire.setClock(100000);  // Setup I2C clock to 100kHz
}
//¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
bool _wakeup(uint8_t target) // Wakes up the sensor by initializing a write operation with no data.
{
  int attemps = ATTEMPTS;
  int error;

  do {
    Wire.beginTransmission(target);
    error = Wire.endTransmission(true);
    Serial.print("Error  ");
    Serial.println(error);
  } while (((error != 0 /*success */) && (error != 2 /*Received NACK on transmit of address*/)) && (--attemps > 0));
  if (error == 4) {
    reInitI2C();
    return false;
  }
  return (attemps > 0);
}
//¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
void setup()
{
  pinMode(SUNRISE_EN, OUTPUT);
  digitalWrite(SUNRISE_EN, HIGH);

  delay(STABILIZATION_MS); // Wait for sensor start-up and stabilization

  reInitI2C(); // Initialize I2C

  Serial.begin(115200);

  _wakeup(SUNRISE_ADDR);
}
//¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
void loop() {
}
Working UART code:

Code: Select all

//Limitations
//
//The library has the following known limitations:
//
//    If using multiple software serial ports, only one can receive data at a time.
//    Not all pins on the Mega and Mega 2560 support change interrupts, so only the following can be used for RX: 10, 11, 12, 13, 14, 15, 50, 51, 52, 53, A8 (62), A9 (63), A10 (64), A11 (65), A12 (66), A13 (67), A14 (68), A15 (69).
//    Not all pins on the Leonardo and Micro support change interrupts, so only the following can be used for RX: 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI).
//    On Arduino or Genuino 101 the current maximum RX speed is 57600bps
//    On Arduino or Genuino 101 RX doesn't work on Pin 13 

#include <SoftwareSerial.h>
#define S11_TX A2 // 12
#define S11_RX A3 // 11
SoftwareSerial s11(S11_TX, S11_RX);

void setup() {
// put your setup code here, to run once:
s11.begin(9600);
Serial.begin(115200);
}

void loop() {
// put your main code here, to run repeatedly:
byte co2Read[] = { 0xfe, 0x04, 0x00, 0x03, 0x00, 0x01, 0xd5, 0xc5 };
s11.write(co2Read, 8);
int millisec = 0;
while(s11.available() <= 0) {
delay(1);
millisec++;
if (millisec > 1500) break;
}
delay(50);
if (s11.available() <= 0) {
Serial.println("no data available");
return;
}
int s11ResponseSize = s11.available();
byte s11Response[s11ResponseSize];
int count = 0;
while (count < s11ResponseSize) {
s11Response[count] = s11.read();
count++;
}
int co2 = (s11Response[3] << 8) | s11Response[4];
Serial.print("CO2 Concentration: ");
Serial.print(co2);
Serial.print("\n");
delay(2000);
}

User avatar
grovkillen
Core team member
Posts: 3621
Joined: 19 Jan 2017, 12:56
Location: Hudiksvall, Sweden
Contact:

Re: Senseair Sunrise S11 I2C communication

#2 Post by grovkillen » 11 Feb 2020, 13:09

I got this from a user:

Code: Select all


#include <Wire.h>

void setup() {
  Wire.begin();                // join i2c bus (address optional for master)
  Serial.begin(9600);          // start serial communication at 9600bps
}

int reading = 0;
float temp=0;

void loop() {
  // step 1: wake sensor
  Wire.beginTransmission(byte(0x68)); // transmit to device 0x68=104
  Wire.endTransmission();      // stop transmitting

  delay(5);       //max 15ms            

  // step 3: instruct sensor to return a particular echo reading
  Wire.beginTransmission(byte(0x68)); // transmit to device #104
  Wire.write(byte(0x06));      // sets register pointer to echo #1 register (0x06)
  Wire.endTransmission();      // stop transmitting

  // step 4: request reading from sensor
  Wire.requestFrom(byte(0x68), 2);    // request 2 bytes from slave device #104

  // step 5: receive reading CO2 from sensor
  if (2 <= Wire.available()) { // if two bytes were received
    reading = Wire.read();    // receive high byte (overwrites previous reading)
    reading = reading << 8;    // shift high byte to be high 8 bits
    reading |= Wire.read();   // receive low byte as lower 8 bits
    Serial.print(reading);   // print the reading
    Serial.println(" CO2");
  }
  
 // step 6: read temperature
  Wire.beginTransmission(byte(0x68)); // transmit to device 
  Wire.write(byte(0x08));      // sets register pointer to echo #1 register (0x08)
  Wire.endTransmission();      // stop transmitting
  Wire.requestFrom(byte(0x68), 2);    // request 2 bytes from slave device 
   if (2 <= Wire.available()) { // if two bytes were received
    reading = Wire.read();    // receive high byte (overwrites previous reading)
    reading = reading << 8;    // shift high byte to be high 8 bits
    reading |= Wire.read();   // receive low byte as lower 8 bits
    temp=reading;
    Serial.print((temp/100));   // print the reading
    Serial.println(" C");
  }
  delay(5000);                  // wait a bit since people have to read the output :)
}
ESP Easy Flasher [flash tool and wifi setup at flash time]
ESP Easy Webdumper [easy screendumping of your units]
ESP Easy Netscan [find units]
Official shop: https://firstbyte.shop/
Sponsor ESP Easy, we need you :idea: :idea: :idea:

fluppie
Normal user
Posts: 89
Joined: 09 Oct 2015, 13:23

Re: Senseair Sunrise S11 I2C communication

#3 Post by fluppie » 11 Feb 2020, 13:47

13:46:31.041 -> 488 CO2
13:46:31.041 -> 19.15 C
13:46:36.063 -> 488 CO2
13:46:36.063 -> 19.15 C
13:46:41.061 -> 489 CO2
13:46:41.061 -> 19.16 C
13:46:46.055 -> 489 CO2
13:46:46.055 -> 19.16 C
13:46:51.065 -> 489 CO2
13:46:51.065 -> 19.16 C
13:46:56.084 -> 490 CO2
13:46:56.084 -> 19.16 C

That sample code works right-away :). Many thanks!

User avatar
grovkillen
Core team member
Posts: 3621
Joined: 19 Jan 2017, 12:56
Location: Hudiksvall, Sweden
Contact:

Re: Senseair Sunrise S11 I2C communication

#4 Post by grovkillen » 11 Feb 2020, 13:51

Great!
ESP Easy Flasher [flash tool and wifi setup at flash time]
ESP Easy Webdumper [easy screendumping of your units]
ESP Easy Netscan [find units]
Official shop: https://firstbyte.shop/
Sponsor ESP Easy, we need you :idea: :idea: :idea:

Post Reply

Who is online

Users browsing this forum: No registered users and 28 guests