I2C Inter IC Communication – ESP8266

In this tutorial, I will show you how to interface I2C Inter IC Communication with ESP8266, EEPROM AT24C256, and 12-bit 2-channel ADC MCP3202.  This protocol mainly used for onboard IC to IC communication. In this tutorial, we not working dedicated SCL, SDA pins, and no library. now We code from scratch to make a clear knowledge and make it easy to interface with any I2C device.


≡I2C Signalling


CLOCK and DATA TRANSITIONS: The SDA pin is usually picked high with an external device. Data on the SDA pin is only during SCL low time periods. Data settings during SCL high periods will show a start or stop condition as shown below.

START CONDITION: A high-to-low transition of SDA with SCL high is a start position which must precede any other command.

STOP CONDITION: A low-to-high transition of SDA with SCL high is a stop position. After a read sequence, the stop command will place the EEPROM in a standby power mode.


≡ I2C Start Stop Condition Sample Code:


void i2c_start(void)
{
  RELEASE_I2C_BUS();
  delayMicroseconds(I2C_DELAY);
  SDA_0();
  delayMicroseconds(I2C_DELAY);
  SCL_0();
  delayMicroseconds(I2C_DELAY);
return;
}
void i2c_stop(void)
{
  SDA_0();
  SCL_1();
  delayMicroseconds(I2C_DELAY);
  SDA_1();
  delayMicroseconds(I2C_DELAY);
  SCL_0();
  delayMicroseconds(I2C_DELAY);
return;
}

≡ Interfacing AT24C256 with ESP8266


First We have to need rede datasheet on AT24C256


≡ Pin Overview of AT24C256


I2C Inter Communication ESP8266

SERIAL CLOCK (SCL): The SCL input is utilized to positive side clock data into each EEPROM device and negative side clock data out of all devices.

SERIAL DATA (SDA): The SDA pin is bidirectional for serial data transfer. This pin open-drain driven and maybe a wire with any number of other open-drain or open-collector devices.

DEVICE/ADDRESSES (A1, A0): The A1 and A0 pins are device address inputs that are hardwired or left not joined for hardware compatibility with other AT24CXX devices. When the pins hardwired, as many as four 256K devices may write on a single bus system.

WRITE PROTECT (WP): The write protects input during connected to GND, allows normal write operations. If WP  connected high to VCC, all write operations to the memory hindered.


≡ 24C256 Connections with NodeMCU for I2C Inter Communication ESP8266


Attach D6 (GPIO 12) to SDA (pin 5) of 24C256 and D7(GPIO 13) to SCL (pin 6). and  Also, attach a pull up of 10KOhm on SCL and SDA line. Attach the power supply of 3.3V, GND as shown in the circuit.

I2C Inter Communication ESP8266


≡ Program for EEPROM 24C256 interface:


//----------------------------------------------------

//Enter your hardware connections here
#define SDA_PIN     12         /* The SDA port pin */
#define SCL_PIN     13         /* The SCL port pin */

//----------------------------------------------------

#define I2C_DELAY     5      //5 micro seconds = 200KHz
#define I2C_TIMEOUT   1000
#define I2C_READ  1
#define I2C_WRITE 0
#define I2C_QUIT  0
#define I2C_CONTINUE  1
#define I2C_NO_ERROR       0
#define I2C_ERROR_DEVICE_BUSY    1
#define I2C_ERROR_DEVICE_NOT_RESPONDING  2
/* Macro definitions */

 

#define I2C_START(ADDRESS)     { i2c_start(); i2c_transmit(ADDRESS); }
#define I2C_START_TX(ADDRESS)  I2C_START(ADDRESS)
#define I2C_START_RX(ADDRESS)  I2C_START(ADDRESS | I2C_READ)
//------------------------------------
#define SCL_1() { pinMode(SCL_PIN,0); }
#define SCL_0() { pinMode(SCL_PIN,1); }
#define SDA_1() { pinMode(SDA_PIN,0); }
#define SDA_0() { pinMode(SDA_PIN,1); }
#define RELEASE_I2C_BUS() { SCL_1(); SDA_1(); }

void i2c_start(void);
void i2c_init(void);
void i2c_stop(void);
unsigned char i2c_transmit(unsigned char data);
unsigned char i2c_receive(unsigned char ack);
void i2c_init(void)
{
  digitalWrite(SDA_PIN,0);
 digitalWrite(SCL_PIN,0);
  RELEASE_I2C_BUS();
  delayMicroseconds(I2C_TIMEOUT);
  i2c_start();
  delayMicroseconds(I2C_TIMEOUT);
  i2c_stop();
  delayMicroseconds(I2C_TIMEOUT);
return;
}
/*###########################################*/
void i2c_start(void)
{
  RELEASE_I2C_BUS();
  delayMicroseconds(I2C_DELAY);
  SDA_0();
  delayMicroseconds(I2C_DELAY);
  SCL_0();
  delayMicroseconds(I2C_DELAY);
return;
}
/*###########################################*/
void i2c_stop(void)
{
  SDA_0();
  SCL_1();
  delayMicroseconds(I2C_DELAY);
  SDA_1();
  delayMicroseconds(I2C_DELAY);
  SCL_0();
  delayMicroseconds(I2C_DELAY);
return;
}
/*###########################################*/
unsigned char i2c_transmit(unsigned char data)
{
register unsigned char bit=0;
  for(bit=0; bit<=7; bit++)
    {
        if( data & 0x80 ) { SDA_1(); } else { SDA_0(); }
        SCL_1();
        delayMicroseconds(I2C_DELAY);
        SCL_0();
        delayMicroseconds(I2C_DELAY);
        data = (data<<1);
    }
  /* Look for AKNOWLEDGE */
  RELEASE_I2C_BUS();
  delayMicroseconds(I2C_DELAY);
  if(digitalRead(SDA_PIN)==0)
   {
       SCL_0();
       delayMicroseconds(I2C_DELAY);
   }
  else{
     delayMicroseconds(I2C_TIMEOUT);
     if(digitalRead(SDA_PIN)==0)
      {
         SCL_0();
         delayMicroseconds(I2C_DELAY);
      }

     else { return(I2C_ERROR_DEVICE_NOT_RESPONDING); }

      }
  if(digitalRead(SDA_PIN)==0)
   {
        delayMicroseconds(I2C_TIMEOUT);
         if(digitalRead(SDA_PIN)==0)
         { return(I2C_ERROR_DEVICE_BUSY); }
   }  
return(I2C_NO_ERROR);  
}
/*###########################################*/
unsigned char i2c_receive(unsigned char ack)
{
register unsigned char bit=0, data=0;
  SDA_1();
  for(bit=0; bit<=7; bit++)
    {
       SCL_1();
        delayMicroseconds(I2C_DELAY);
        data = (data<<1);
        if(digitalRead(SDA_PIN)==1)
        { data++; }
        SCL_0();
        delayMicroseconds(I2C_DELAY);
    }
  /* if CONTINUE then send AKNOWLEDGE else if QUIT do not send AKNOWLEDGE (send Nack) */      
  if(ack==I2C_CONTINUE) { SDA_0(); }  else { SDA_1(); }
  SCL_1();
  delayMicroseconds(I2C_DELAY);
  SCL_0();
  delayMicroseconds(I2C_DELAY);
return data;
}
void setup() {
  delay(1);
  Serial.begin(115200);
  Serial.println("");
  //Pin SCL and SDA Connections are defined in header file
  i2c_init();   //Initialize I2C
  Serial.println("I2C Initialized");
  Serial.println("Writing Data: 123");
  Write_EEPROM(0,123); //Data to write
}
void loop() {
  Serial.print("Reading Data: ");
  Serial.println(Read_EEPROM(0));
  delay(1000); 
}
void Write_EEPROM(int add, char data)
{
  int temp1,addH,addL;
  addH = (add & 0xFF00);
  addH = addH >> 8;
  addL = (add & 0x00FF);
  I2C_START_TX(0b10100000); //Device address with read command
  i2c_transmit(addH);       //Send Word Address
  i2c_transmit(addL);
  i2c_transmit(data);       //Send data to write 
  i2c_stop();
  delay(20);     //Wait for EEPROM to write data
}
int Read_EEPROM(int add)
{
  int data,addH,addL;
  //Dummy Write for addressing
  addH = (add & 0xFF00);
  addH = addH >> 8;
  addL = (add & 0x00FF);
  I2C_START_TX(0b10100000); //Device address with read command
  i2c_transmit(addH);       //Send Word Address
  i2c_transmit(addL);
  //Read Data byte
  I2C_START_TX(0b10100001); //Device address with read command
  data = i2c_receive(0);
  i2c_stop(); 
  return data;
}

I2C Inter Communication ESP8266

Visit to get more tutorials on IoT project

INTERNET OF THINGS

 163 total views,  1 views today