Bit banging a CO2 sensor with an arduino

Post here about your Arduino projects, get help - for Adafruit customers!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
User avatar
daemach
 
Posts: 146
Joined: Fri Feb 13, 2009 2:07 pm

Bit banging a CO2 sensor with an arduino

Post by daemach »

I recently discovered a self-calibrating CO2 sensor that uses an interface similar to I2C: http://www.epluse.com/en/products/co2-m ... ons/ee892/ They sent me a couple of samples and said the price would be ~$58 in quantities of 5-10K. The sensor returns temperature, relative humidity and a CO2 measurement (apparently), and possibly air velocity too, though the documentation seems to be conflicting on that one.

The datasheet for the E2 interface, (their protocol), has code for interfacing with the processor that must be modified to work with specific processors: http://www.epluse.com/uploads/tx_EplusE ... sch_33.pdf (see the section that says "// adapt this code for your target processor !!!")

I've attempted to do this using pinMode and digitalWrite in the .h file I'm trying to create but the compiler is throwing errors saying the Arduino functions (pinMode, etc) aren't declared. I'm not a C coder so I've probably screwed up the file structure somehow. I would really appreciate some help with this. I'll post the library on the Arduino site if I can get it working.

The problem functions are at the very end. See below:

Code: Select all

/***************************************************************************/
// definitions

#define DELAY_FAKTOR 10
#define ACK 1
#define NAK 0

int SDA = 4;
int SCL = 5;

/***************************************************************************/
// variables

unsigned char rh_low;
unsigned char rh_high;
unsigned char temp_low;
unsigned char temp_high;
unsigned char checksum_03;
unsigned int rh_ee03= 0;
unsigned int temp_ee03= 0;
float rh = 0;
float temperature = 0;

/***************************************************************************/
// functions

char check_ack(void);
void send_ack(void);
void send_nak(void);
void E2Bus_start(void);
void E2Bus_stop(void);
void E2Bus_send(unsigned char);
void set_SDA(void);
void clear_SDA(void);
int read_SDA(void);
void set_SCL(void);
void clear_SCL(void);
unsigned char E2Bus_read(void);
void e2Delay(unsigned int value);

/***************************************************************************/


float RH_read(void);
float Temp_read(void);
unsigned char EE03_status(void);

int sdaPin = 9;
int sclPin = 10;
int ledPin = 13;

float Temp_read(void)
{

  E2Bus_start();
  E2Bus_send(0xA1);

  if (check_ack()==ACK)
  {
    temp_low = E2Bus_read();
    send_ack();
    checksum_03 = E2Bus_read();
    send_nak();
    // terminate communication
    E2Bus_stop();

    if (((0xA1 + temp_low) % 256) == checksum_03) // checksum OK?
    {
      E2Bus_start();
      E2Bus_send(0xB1);        // MW2-high request
      check_ack();
      temp_high = E2Bus_read();
      send_ack();        // terminate communication
      checksum_03 = E2Bus_read();
      send_nak();
      E2Bus_stop();

      // default value (error code)

      // MW2-low request

      if (((0xB1 + temp_high) % 256) == checksum_03) // checksum OK?
      { 
        temp_ee03=temp_low+256*temp_high; //yes->calculate temperature
        temperature=((float)temp_ee03/100) - 273.15;
        // overwrite default (error) value
      }

    }
    E2Bus_stop();

  }
  return temperature;

}

float RH_read(void)

{
  rh = -1;

  E2Bus_start();
  E2Bus_send(0x81);    // MW1-low request

  if (check_ack()==ACK)
  {
    rh_low = E2Bus_read();
    send_ack();
    checksum_03 = E2Bus_read();
    send_nak();    // terminate communication
    E2Bus_stop();

    if (((0x81 + rh_low) % 256) == checksum_03)     // checksum OK?
    {
      E2Bus_start();
      E2Bus_send(0x91);      // MW1-high request
      check_ack();
      rh_high = E2Bus_read();
      send_ack();
      checksum_03 = E2Bus_read();
      send_nak();      // terminate communication
      E2Bus_stop();

      if (((0x91 + rh_high) % 256) == checksum_03)      // checksum OK?
      { 
        rh_ee03=rh_low+256*(unsigned int)rh_high;       // yes-> calculate humidity value
        rh=(float)rh_ee03/100;        // overwrite default (error) value
      }

    }
    E2Bus_stop();

  }
  return rh;

}

unsigned char EE03_status(void)

{
  unsigned char stat_ee03;

  E2Bus_start();
  E2Bus_send(0x71); //main command for STATUS request
  if (check_ack()==ACK)
  {
    stat_ee03 = E2Bus_read();
    send_ack();
    checksum_03 = E2Bus_read();
    send_nak();

    E2Bus_stop();

    if (((stat_ee03 + 0x71) % 256) == checksum_03)
      return stat_ee03;
  }
  return 0xFF;

}












void E2Bus_start(void)
// send Start condition to E2 Interface
{
  set_SDA();
  set_SCL();
  e2Delay(30*DELAY_FAKTOR);
  clear_SDA();
  e2Delay(30*DELAY_FAKTOR);
}
/*-------------------------------------------------------------------------*/

void E2Bus_stop(void)
// send Stop condition to E2 Interface
{
  clear_SCL();
  e2Delay(20*DELAY_FAKTOR);
  clear_SDA();
  e2Delay(20*DELAY_FAKTOR);
  set_SCL();
  e2Delay(20*DELAY_FAKTOR);
  set_SDA();
  e2Delay(20*DELAY_FAKTOR);
}
/*-------------------------------------------------------------------------*/

void E2Bus_send(unsigned char value)
{
  unsigned char i;
  unsigned char maske = 0x80;

  for (i=8;i>0;i--)
  {
    clear_SCL();
    e2Delay(10*DELAY_FAKTOR);
    if ((value & maske) != 0)
    {
      set_SDA();
    }
    else
    {
      clear_SDA();
    }
    e2Delay(20*DELAY_FAKTOR);
    set_SCL();
    maske >>= 1;
    e2Delay(30*DELAY_FAKTOR);
    clear_SCL();
  }
  set_SDA();

}
/*-------------------------------------------------------------------------*/

unsigned char E2Bus_read(void)
{
  unsigned char data_in = 0x00;
  unsigned char maske = 0x80;

  for (maske=0x80;maske>0;maske >>=1)
  {
    clear_SCL();
    e2Delay(30*DELAY_FAKTOR);
    set_SCL();
    e2Delay(15*DELAY_FAKTOR);
    if (read_SDA())
    {
      data_in |= maske;
    }
    e2Delay(15*DELAY_FAKTOR);
    clear_SCL();
  }
  return data_in;

}
/*-------------------------------------------------------------------------*/

char check_ack(void)// check for acknowledge
{
  int input;

  e2Delay(30*DELAY_FAKTOR);
  set_SCL();
  e2Delay(15*DELAY_FAKTOR);
  input = read_SDA();
  e2Delay(15*DELAY_FAKTOR);
  if(input == 1)
    return NAK;
  else
    return ACK;

}
/*-------------------------------------------------------------------------*/

void send_ack(void)
// send acknowledge
{ 
  clear_SCL();
  e2Delay(15*DELAY_FAKTOR);
  clear_SDA();
  e2Delay(15*DELAY_FAKTOR);
  set_SCL();
  e2Delay(30*DELAY_FAKTOR);
  clear_SCL();
  set_SDA();
}
/*-------------------------------------------------------------------------*/

void send_nak(void)
// send NOT-acknowledge
{ 
  clear_SCL();
  e2Delay(15*DELAY_FAKTOR);
  set_SDA();
  e2Delay(15*DELAY_FAKTOR);
  set_SCL();
  e2Delay(30*DELAY_FAKTOR);
  clear_SCL();
  set_SDA();
}
/*-------------------------------------------------------------------------*/

void e2Delay(unsigned int value)
// delay- routine
{ 
  while (--value != 0); 
}
/*-------------------------------------------------------------------------*/


// adapt this code for your target processor !!!

void set_SDA(void)    // set port-pin (SDA)
{ 
  pinMode(sdaPin,OUTPUT);
  digitalWrite(sdaPin,HIGH);
  //  SDA = 1; 
}

void clear_SDA(void)  // clear port-pin (SDA)
{ 
  pinMode(sdaPin,OUTPUT);
  digitalWrite(sdaPin,LOW);
  //  SDA = 0; 
}

int read_SDA(void)    // read SDA-pin status
{ 
  pinMode(sdaPin,INPUT);
  return digitalRead(sdaPin); 
}

void set_SCL(void)    // set port-pin (SCL)
{ 
  pinMode(sclPin,OUTPUT);
  digitalWrite(sclPin,HIGH);
  //  SCL = 1; 
}

void clear_SCL(void)  // clear port-pin (SCL)
{ 
  pinMode(sclPin,OUTPUT);
  digitalWrite(sclPin,LOW);
  //  SCL = 0; 
}


User avatar
zener
 
Posts: 4567
Joined: Sat Feb 21, 2009 2:38 am

Re: Bit banging a CO2 sensor with an arduino

Post by zener »

I am guessing this is a simple problem having to do with file paths or something. Those built in functions are supposed to be included auromatically when you compile. I would try searching in that error message. It is probably a common problem. But I have not programmed in Arduino lately. I know that you don't have to manually include or declare for those functions to work. That is one of the helpful features of Arduino.

User avatar
daemach
 
Posts: 146
Joined: Fri Feb 13, 2009 2:07 pm

Re: Bit banging a CO2 sensor with an arduino

Post by daemach »

I tried including wiring.h and it stopped complaining about the missing arduino functions but it's giving me new errors:

_NewTemp.cpp.o:(.data.SDA+0x0): multiple definition of `SDA'
E2_Interface.cpp.o:(.data.SDA+0x0): first defined here
_NewTemp.cpp.o:(.data.SCL+0x0): multiple definition of `SCL'
E2_Interface.cpp.o:(.data.SCL+0x0): first defined here
_NewTemp.cpp.o: In function `loop':

etc...

I also tried splitting the functions into a .cpp file and left the definitions in the .h file. I'm not a c coder so I'm sure my structure is part of the problem.

e2_interface.h:

Code: Select all


/***************************************************************************/
// definitions

#define DELAY_FAKTOR 10
#define ACK 1
#define NAK 0

int SDA = 4;
int SCL = 5;

/***************************************************************************/
// variables

unsigned char rh_low;
unsigned char rh_high;
unsigned char temp_low;
unsigned char temp_high;
unsigned char checksum_03;
unsigned int rh_ee03= 0;
unsigned int temp_ee03= 0;
float rh = 0;
float temperature = 0;

/***************************************************************************/
// private functions

char check_ack(void);
void send_ack(void);
void send_nak(void);
void E2Bus_start(void);
void E2Bus_stop(void);
void E2Bus_send(unsigned char);
void set_SDA(void);
void clear_SDA(void);
int read_SDA(void);
void set_SCL(void);
void clear_SCL(void);
unsigned char E2Bus_read(void);
void e2Delay(unsigned int value);

//public functions

float RH_read(void);
float Temp_read(void);
unsigned char EE03_status(void);

/***************************************************************************/

e2_interface.cpp:

Code: Select all

#include "Wiring.h"
#include "E2_Interface.h"


int sdaPin = 9;
int sclPin = 10;
int ledPin = 13;

float Temp_read(void)
{

  E2Bus_start();
  E2Bus_send(0xA1);

  if (check_ack()==ACK)
  {
    temp_low = E2Bus_read();
    send_ack();
    checksum_03 = E2Bus_read();
    send_nak();
    // terminate communication
    E2Bus_stop();

    if (((0xA1 + temp_low) % 256) == checksum_03) // checksum OK?
    {
      E2Bus_start();
      E2Bus_send(0xB1);        // MW2-high request
      check_ack();
      temp_high = E2Bus_read();
      send_ack();        // terminate communication
      checksum_03 = E2Bus_read();
      send_nak();
      E2Bus_stop();

      // default value (error code)

      // MW2-low request

      if (((0xB1 + temp_high) % 256) == checksum_03) // checksum OK?
      { 
        temp_ee03=temp_low+256*temp_high; //yes->calculate temperature
        temperature=((float)temp_ee03/100) - 273.15;
        // overwrite default (error) value
      }

    }
    E2Bus_stop();

  }
  return temperature;

}

float RH_read(void)

{
  rh = -1;

  E2Bus_start();
  E2Bus_send(0x81);    // MW1-low request

  if (check_ack()==ACK)
  {
    rh_low = E2Bus_read();
    send_ack();
    checksum_03 = E2Bus_read();
    send_nak();    // terminate communication
    E2Bus_stop();

    if (((0x81 + rh_low) % 256) == checksum_03)     // checksum OK?
    {
      E2Bus_start();
      E2Bus_send(0x91);      // MW1-high request
      check_ack();
      rh_high = E2Bus_read();
      send_ack();
      checksum_03 = E2Bus_read();
      send_nak();      // terminate communication
      E2Bus_stop();

      if (((0x91 + rh_high) % 256) == checksum_03)      // checksum OK?
      { 
        rh_ee03=rh_low+256*(unsigned int)rh_high;       // yes-> calculate humidity value
        rh=(float)rh_ee03/100;        // overwrite default (error) value
      }

    }
    E2Bus_stop();

  }
  return rh;

}

unsigned char EE03_status(void)

{
  unsigned char stat_ee03;

  E2Bus_start();
  E2Bus_send(0x71); //main command for STATUS request
  if (check_ack()==ACK)
  {
    stat_ee03 = E2Bus_read();
    send_ack();
    checksum_03 = E2Bus_read();
    send_nak();

    E2Bus_stop();

    if (((stat_ee03 + 0x71) % 256) == checksum_03)
      return stat_ee03;
  }
  return 0xFF;

}












void E2Bus_start(void)
// send Start condition to E2 Interface
{
  set_SDA();
  set_SCL();
  e2Delay(30*DELAY_FAKTOR);
  clear_SDA();
  e2Delay(30*DELAY_FAKTOR);
}
/*-------------------------------------------------------------------------*/

void E2Bus_stop(void)
// send Stop condition to E2 Interface
{
  clear_SCL();
  e2Delay(20*DELAY_FAKTOR);
  clear_SDA();
  e2Delay(20*DELAY_FAKTOR);
  set_SCL();
  e2Delay(20*DELAY_FAKTOR);
  set_SDA();
  e2Delay(20*DELAY_FAKTOR);
}
/*-------------------------------------------------------------------------*/

void E2Bus_send(unsigned char value)
{
  unsigned char i;
  unsigned char maske = 0x80;

  for (i=8;i>0;i--)
  {
    clear_SCL();
    e2Delay(10*DELAY_FAKTOR);
    if ((value & maske) != 0)
    {
      set_SDA();
    }
    else
    {
      clear_SDA();
    }
    e2Delay(20*DELAY_FAKTOR);
    set_SCL();
    maske >>= 1;
    e2Delay(30*DELAY_FAKTOR);
    clear_SCL();
  }
  set_SDA();

}
/*-------------------------------------------------------------------------*/

unsigned char E2Bus_read(void)
{
  unsigned char data_in = 0x00;
  unsigned char maske = 0x80;

  for (maske=0x80;maske>0;maske >>=1)
  {
    clear_SCL();
    e2Delay(30*DELAY_FAKTOR);
    set_SCL();
    e2Delay(15*DELAY_FAKTOR);
    if (read_SDA())
    {
      data_in |= maske;
    }
    e2Delay(15*DELAY_FAKTOR);
    clear_SCL();
  }
  return data_in;

}
/*-------------------------------------------------------------------------*/

char check_ack(void)// check for acknowledge
{
  int input;

  e2Delay(30*DELAY_FAKTOR);
  set_SCL();
  e2Delay(15*DELAY_FAKTOR);
  input = read_SDA();
  e2Delay(15*DELAY_FAKTOR);
  if(input == 1)
    return NAK;
  else
    return ACK;

}
/*-------------------------------------------------------------------------*/

void send_ack(void)
// send acknowledge
{ 
  clear_SCL();
  e2Delay(15*DELAY_FAKTOR);
  clear_SDA();
  e2Delay(15*DELAY_FAKTOR);
  set_SCL();
  e2Delay(30*DELAY_FAKTOR);
  clear_SCL();
  set_SDA();
}
/*-------------------------------------------------------------------------*/

void send_nak(void)
// send NOT-acknowledge
{ 
  clear_SCL();
  e2Delay(15*DELAY_FAKTOR);
  set_SDA();
  e2Delay(15*DELAY_FAKTOR);
  set_SCL();
  e2Delay(30*DELAY_FAKTOR);
  clear_SCL();
  set_SDA();
}
/*-------------------------------------------------------------------------*/

void e2Delay(unsigned int value)
// delay- routine
{ 
  while (--value != 0); 
}
/*-------------------------------------------------------------------------*/


// adapt this code for your target processor !!!

void set_SDA(void)    // set port-pin (SDA)
{ 
  pinMode(sdaPin,OUTPUT);
  digitalWrite(sdaPin,HIGH);
  //  SDA = 1; 
}

void clear_SDA(void)  // clear port-pin (SDA)
{ 
  pinMode(sdaPin,OUTPUT);
  digitalWrite(sdaPin,LOW);
  //  SDA = 0; 
}

int read_SDA(void)    // read SDA-pin status
{ 
  pinMode(sdaPin,INPUT);
  return digitalRead(sdaPin); 
}

void set_SCL(void)    // set port-pin (SCL)
{ 
  pinMode(sclPin,OUTPUT);
  digitalWrite(sclPin,HIGH);
  //  SCL = 1; 
}

void clear_SCL(void)  // clear port-pin (SCL)
{ 
  pinMode(sclPin,OUTPUT);
  digitalWrite(sclPin,LOW);
  //  SCL = 0; 
}

The test sketch:

Code: Select all

#include "E2_Interface.h"

void setup() {        
  dummy = EE03_status();
}

void loop() {
  humidity = RH_read();
  //  status = EE03_status();
}


User avatar
zener
 
Posts: 4567
Joined: Sat Feb 21, 2009 2:38 am

Re: Bit banging a CO2 sensor with an arduino

Post by zener »

I am sorry I'm the only one here answering you since I am least qualified! Hopefully the smart people show up soon! I think you have a very simple error probably.

Looking at your code I can only come up with a couple of ideas: First of all maybe you split it up too much. I am not sure the fine points of that. I do notice you have "#include "E2_Interface.h"" in two seperate parts, so maybe that is causing the multiple defines error. Just a guess. It is interesting that wiring.h fixed your first problem since I don't think I ever had to include that specifically. Anyway, you know how computers are about error messages, sometimes they are not 'exactly' right.

User avatar
opossum
 
Posts: 636
Joined: Fri Oct 26, 2007 12:42 am

Re: Bit banging a CO2 sensor with an arduino

Post by opossum »

The header file should only have the public functions. Put everything else in the cpp file.

User avatar
daemach
 
Posts: 146
Joined: Fri Feb 13, 2009 2:07 pm

Re: Bit banging a CO2 sensor with an arduino

Post by daemach »

I am making more progress with this. At this point it looks like it's spitting out data but the clock is not consistent at all when using the arduino functions. I tried using some bit shifting functions instead but the pulse trains look even worse.

See the attachment to see the Arduino function pulse train. Clock is on the bottom.

I have the arduino and bit-shifting functions below. I have a hunch the bit-shifting functions would work better but I'm having problems writing LOWs.

Thanks in advance!

Code: Select all

// adapt this code for your target processor !!!

void set_SDA(void)    // set port-pin (SDA)
{ 
  pinMode(sdaPin,OUTPUT);
   if(DEBUG==1){
    PORTD |= 1<<4;
  } else {
    digitalWrite(sdaPin,HIGH);
  } 
}

void clear_SDA(void)  // clear port-pin (SDA)
{ 
  pinMode(sdaPin,OUTPUT);
   if(DEBUG==1){
    PORTD &= !1<<4;
  } else {
    digitalWrite(sdaPin,LOW);
  } 
}

int read_SDA(void)    // read SDA-pin status
{ 
  pinMode(sdaPin,INPUT);
  return digitalRead(sdaPin); 
}

void set_SCL(void)    // set port-pin (SCL)
{ 
  if(DEBUG==1){
    PORTD |= 1<<5;
  } else {
    digitalWrite(sclPin,HIGH);
  } 
}

void clear_SCL(void)  // clear port-pin (SCL)
{ 
  if(DEBUG==1){
    PORTD &= !1<<5;
  } else {
    digitalWrite(sclPin,LOW);
  } 
}
Attachments
EE892_Logic.JPG
EE892_Logic.JPG (49.87 KiB) Viewed 4300 times

User avatar
opossum
 
Posts: 636
Joined: Fri Oct 26, 2007 12:42 am

Re: Bit banging a CO2 sensor with an arduino

Post by opossum »

This will not work...

Code: Select all

    PORTD &= !1<<4;
Use the bitwise compliment to invert individual bits...

Code: Select all

    PORTD &= ~(1<<4);
The jitter you are seeing may be due to the ISR that handles timing, PWM and such. Is it causing communication problems?

User avatar
daemach
 
Posts: 146
Joined: Fri Feb 13, 2009 2:07 pm

Re: Bit banging a CO2 sensor with an arduino

Post by daemach »

Thanks very much - I figured I had that expression wrong. At this point it's not communicating at all still, unfortunately.

I included two screenshots - the one named _Native uses the bitwise functions. _Arduino is the arduino functions. The Arduino pulsetrain looks more correct although, like you said, something is causing jitter. I assumed that was the Arduino function overhead which is why I'm trying to figure out the bitwise stuff. The native train looks very broken which means I probably still don't have those functions right. Thats the only thing that changes.

The entire sketch, with the new bitwise functions, is below. Moving everything into one file got me past the compiling errors. I figure I'll try to break everything out into a library once I get it working. The block I posted before is at the bottom.

Code: Select all

/***************************************************************************/
// definitions

#define DELAY_FAKTOR 5
#define ACK 1
#define NAK 0
#define DEBUG 0

int SDA = 4;
int SCL = 5;
int sdaPin = 4;
int sclPin = 5;
int ledPin = 13;
int dummy = 0xFF;

/***************************************************************************/
// variables

unsigned char rh_low;
unsigned char rh_high;
unsigned char temp_low;
unsigned char temp_high;
unsigned char checksum_03;
unsigned int rh_ee03= 0;
unsigned int temp_ee03= 0;
float rh = 0;
float temperature = 0;
float humidity = 0;

/***************************************************************************/
// private functions

char check_ack(void);
void send_ack(void);
void send_nak(void);
void E2Bus_start(void);
void E2Bus_stop(void);
void E2Bus_send(unsigned char);
void set_SDA(void);
void clear_SDA(void);
int read_SDA(void);
void set_SCL(void);
void clear_SCL(void);
unsigned char E2Bus_read(void);
void e2Delay(unsigned int value);

//public functions

float RH_read(void);
float Temp_read(void);
unsigned char EE03_status(void);

/***************************************************************************/



void setup() {
  Serial.begin(9600);  
  dummy = EE03_status();
  // pinMode(13, OUTPUT); 
  pinMode(sclPin,OUTPUT);
}

void loop() {
  //humidity = RH_read();
  temperature = Temp_read();
  dummy = EE03_status();
  /*
  digitalWrite(13, HIGH);   // set the LED on
   delay(100);              // wait for a second
   digitalWrite(13, LOW);    // set the LED off
   delay(50);              // wait for a second
   */

  Serial.print("Temperature: ");
  serialPrintFloat(temperature);
  //Serial.print("  F, Humidity: ");
  //serialPrintFloat(humidity);
  Serial.println();
  delay(1000);
  //  status = EE03_status();
}

void serialPrintFloat(float f){
  Serial.print((int)f);
  Serial.print(".");
  int decplace = (f - (int)f) * 100;
  Serial.print(abs(decplace));
}

float Temp_read(void)
{

  E2Bus_start();
  E2Bus_send(0xA1);

  if (check_ack()==ACK)
  {
    temp_low = E2Bus_read();
    send_ack();
    checksum_03 = E2Bus_read();
    send_nak();
    // terminate communication
    E2Bus_stop();

    if (((0xA1 + temp_low) % 256) == checksum_03) // checksum OK?
    {
      E2Bus_start();
      E2Bus_send(0xB1);        // MW2-high request
      check_ack();
      temp_high = E2Bus_read();
      send_ack();        // terminate communication
      checksum_03 = E2Bus_read();
      send_nak();
      E2Bus_stop();

      // default value (error code)

      // MW2-low request

      if (((0xB1 + temp_high) % 256) == checksum_03) // checksum OK?
      { 
        temp_ee03=temp_low+256*temp_high; //yes->calculate temperature
        temperature=((float)temp_ee03/100) - 273.15;
        // overwrite default (error) value
      }

    }
    E2Bus_stop();

  }
  return temperature;

}

float RH_read(void)

{
  rh = -1;

  E2Bus_start();
  E2Bus_send(0x81);    // MW1-low request

  if (check_ack()==ACK)
  {
    rh_low = E2Bus_read();
    send_ack();
    checksum_03 = E2Bus_read();
    send_nak();    // terminate communication
    E2Bus_stop();

    if (((0x81 + rh_low) % 256) == checksum_03)     // checksum OK?
    {
      E2Bus_start();
      E2Bus_send(0x91);      // MW1-high request
      check_ack();
      rh_high = E2Bus_read();
      send_ack();
      checksum_03 = E2Bus_read();
      send_nak();      // terminate communication
      E2Bus_stop();

      if (((0x91 + rh_high) % 256) == checksum_03)      // checksum OK?
      { 
        rh_ee03=rh_low+256*(unsigned int)rh_high;       // yes-> calculate humidity value
        rh=(float)rh_ee03/100;        // overwrite default (error) value
      }

    }
    E2Bus_stop();

  }
  return rh;

}

unsigned char EE03_status(void)

{
  unsigned char stat_ee03;

  E2Bus_start();
  E2Bus_send(0x71); //main command for STATUS request
  if (check_ack()==ACK)
  {
    stat_ee03 = E2Bus_read();
    send_ack();
    checksum_03 = E2Bus_read();
    send_nak();

    E2Bus_stop();

    if (((stat_ee03 + 0x71) % 256) == checksum_03)
      return stat_ee03;
  }
  return 0xFF;

}












void E2Bus_start(void)
// send Start condition to E2 Interface
{
  set_SDA();
  set_SCL();
  e2Delay(30*DELAY_FAKTOR);
  clear_SDA();
  e2Delay(30*DELAY_FAKTOR);

}
/*-------------------------------------------------------------------------*/

void E2Bus_stop(void)
// send Stop condition to E2 Interface
{
  clear_SCL();
  e2Delay(20*DELAY_FAKTOR);
  clear_SDA();
  e2Delay(20*DELAY_FAKTOR);
  set_SCL();
  e2Delay(20*DELAY_FAKTOR);
  set_SDA();
  e2Delay(20*DELAY_FAKTOR);
}
/*-------------------------------------------------------------------------*/

void E2Bus_send(unsigned char value)
{
  unsigned char i;
  unsigned char maske = 0x80;

  for (i=8;i>0;i--)
  {
    clear_SCL();
    e2Delay(10*DELAY_FAKTOR);
    if ((value & maske) != 0)
    {
      set_SDA();
    }
    else
    {
      clear_SDA();
    }
    e2Delay(20*DELAY_FAKTOR);
    set_SCL();
    maske >>= 1;
    e2Delay(30*DELAY_FAKTOR);
    clear_SCL();
  }
  set_SDA();

}
/*-------------------------------------------------------------------------*/

unsigned char E2Bus_read(void)
{
  unsigned char data_in = 0x00;
  unsigned char maske = 0x80;

  for (maske=0x80;maske>0;maske >>=1)
  {
    clear_SCL();
    e2Delay(30*DELAY_FAKTOR);
    set_SCL();
    e2Delay(15*DELAY_FAKTOR);
    if (read_SDA())
    {
      data_in |= maske;
    }
    e2Delay(15*DELAY_FAKTOR);
    clear_SCL();
  }
  return data_in;

}
/*-------------------------------------------------------------------------*/

char check_ack(void)// check for acknowledge
{
  int input;

  e2Delay(30*DELAY_FAKTOR);
  set_SCL();
  e2Delay(15*DELAY_FAKTOR);
  input = read_SDA();
  e2Delay(15*DELAY_FAKTOR);
  if(input == 1)
    return NAK;
  else
    return ACK;

}
/*-------------------------------------------------------------------------*/

void send_ack(void)
// send acknowledge
{ 
  clear_SCL();
  e2Delay(15*DELAY_FAKTOR);
  clear_SDA();
  e2Delay(15*DELAY_FAKTOR);
  set_SCL();
  e2Delay(30*DELAY_FAKTOR);
  clear_SCL();
  set_SDA();
}
/*-------------------------------------------------------------------------*/

void send_nak(void)
// send NOT-acknowledge
{ 
  clear_SCL();
  e2Delay(15*DELAY_FAKTOR);
  set_SDA();
  e2Delay(15*DELAY_FAKTOR);
  set_SCL();
  e2Delay(30*DELAY_FAKTOR);
  clear_SCL();
  set_SDA();
}
/*-------------------------------------------------------------------------*/

void e2Delay(unsigned int value)
// delay- routine
{ 
  while (--value != 0); 
}
/*-------------------------------------------------------------------------*/


// adapt this code for your target processor !!!

void set_SDA(void)    // set port-pin (SDA)
{ 
  pinMode(sdaPin,OUTPUT);
   if(DEBUG==1){
    PORTD |= 1<<4;
  } else {
    digitalWrite(sdaPin,HIGH);
  } 
}

void clear_SDA(void)  // clear port-pin (SDA)
{ 
  pinMode(sdaPin,OUTPUT);
   if(DEBUG==1){
    PORTD &= ~(1<<4);
  } else {
    digitalWrite(sdaPin,LOW);
  } 
}

int read_SDA(void)    // read SDA-pin status
{ 
  pinMode(sdaPin,INPUT);
  return digitalRead(sdaPin); 
}

void set_SCL(void)    // set port-pin (SCL)
{ 
  if(DEBUG==1){
    PORTD |= 1<<5;
  } else {
    digitalWrite(sclPin,HIGH);
  } 
}

void clear_SCL(void)  // clear port-pin (SCL)
{ 
  if(DEBUG==1){
    PORTD &= ~(1<<5);
  } else {
    digitalWrite(sclPin,LOW);
  } 
}
Attachments
EE892_Arduino.JPG
EE892_Arduino.JPG (45.85 KiB) Viewed 4294 times
EE892_Native.JPG
EE892_Native.JPG (41.82 KiB) Viewed 4294 times

gromain
 
Posts: 9
Joined: Mon Jul 04, 2011 10:32 am

Re: Bit banging a CO2 sensor with an arduino

Post by gromain »

Hi there!

I know this is a bit old, and I hope that you solved your problem already!
But anyway, I was faced with the same one, and decided to tackle it hard, so I wrote my own arduino library to go on with the E2 protocol.
In case anyone is interested (because this thread is the only one I found when "googling arduino E2 protocol", so it's kinda reference), the code (and lib) is available on github: http://www.github.com/gromain/E2
As of today, it's completely functional.
I just need to add the function to read from a custom adress (currently it reads from the custom memory address 0x00, and the pointer is incremented by one after each read, so not really easy to access a particular memory address!) and the function to write in custom memory.
But otherwise, it's functionnal with the humidity,temperature and CO2 measurement from the E+E Elektronics sensors (http://www.epluse.com).
(I didn't code the air velocity function yet, mainly because I don't have access to an air velocity sensor. But it shouldn't be hard to do once you have the library with the rest of the code).


Well, that's it.

Cheers,

gromain

User avatar
daemach
 
Posts: 146
Joined: Fri Feb 13, 2009 2:07 pm

Re: Bit banging a CO2 sensor with an arduino

Post by daemach »

I did get it worked out finally. I wish I had posted the library here now to save you the trouble!

I do need to figure out an easy way to check for the sensors existence before trying to use it though. It would be great if they would have stuck to the i2c protocol instead of rolling their own...

User avatar
michaay11
 
Posts: 8
Joined: Sun Dec 20, 2015 12:29 pm

Re: Bit banging a CO2 sensor with an arduino

Post by michaay11 »

Hello,

can anyone who made the sensor work with an arduino please help me? I'm really desperately trying to read CO2 from an arduino and i have both the EE892 and EE891 sensor. I don't what is wrong but I am a complete arduino newby. Thanks to everyone who can help me.

Kind regards
Michael

User avatar
Franklin97355
 
Posts: 23910
Joined: Mon Apr 21, 2008 2:33 pm

Re: Bit banging a CO2 sensor with an arduino

Post by Franklin97355 »

Did you try the code in the link above?

User avatar
daemach
 
Posts: 146
Joined: Fri Feb 13, 2009 2:07 pm

Re: Bit banging a CO2 sensor with an arduino

Post by daemach »

Put the attached files into a folder called ee892 within your libraries folder, then use the following info to get it running:

Code: Select all

#include <ee892.h>

int _co2PinData = A3;
int _co2PinClock = A2;

ee892 co2Sensor = ee892(_co2PinData, _co2PinClock);

//for measurement:

co2Sensor.getMeasurement(0xC1,0xD1)  //real-time
co2Sensor.getMeasurement(0xE1,0xF1)  //average



Attachments
ee892.zip
(2.89 KiB) Downloaded 54 times

User avatar
michaay11
 
Posts: 8
Joined: Sun Dec 20, 2015 12:29 pm

Re: Bit banging a CO2 sensor with an arduino

Post by michaay11 »

Thank you very much for you answer!
It still doesn't work though. I implemented the code as the following:

Code: Select all

#include <ee892.h>

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

void loop() {
  int _co2PinData = A4;
  int _co2PinClock = A5;
  ee892 co2Sensor = ee892(_co2PinData, _co2PinClock);
  int co2test;
  //for measurement:

  co2test = co2Sensor.getMeasurement(0xC1,0xD1);  //real-time
  co2Sensor.getMeasurement(0xE1,0xF1);  //average
  Serial.println(co2test);

  delay(1000);

}
and I put the files into my library folder, but on my serial monitor all it prints is -1. How can that be? I'm sorry if I made something completely obvious wrong.

Kind regards
Michael

User avatar
daemach
 
Posts: 146
Joined: Fri Feb 13, 2009 2:07 pm

Re: Bit banging a CO2 sensor with an arduino

Post by daemach »

Are you certain you have 5v going to the vcc pin, that the device is grounded and that data and clock are connected to A4 and A5? If so, it should work.

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino”