Saturday 19 December 2015

Arduino I2C Tutorial

As I have explained my understanding about I2C Communication before, how to deal and make a communication between microcontroller and I2C device. Here I would like to share a little tutorial about Arduino I2C.

Today, there are literally thousands of devices using I2C interface. Many application like RTC, digital compass, temperature and so on using I2C. It is because, I2C provide simplicity in wiring and communication. Even within 2 pins, SDA and SCL, we can control with up to 128 devices as slaves. Here, Arduino gives us an easy way to communicate with these I2C devices.

On Arduino boards, depends on Arduino type, there are two pins out that are used for I2C. For Arduino UNO, I2C pins out using Analog pin 4 (A4) as SDA and Analog pin 5 (A5) as SCL. But Arduino Mega, This board use another pin as I2C pins, pin 20 as SDA and pin 21 as SCL. So this will deferent too with other Arduino board.


Arduino Board I2C pins
UNO, Ethernet A4(SDA), A5(SCL)
Mega 20(SDA), 21(SCL)
Leonardo 2(SDA), 3(SCL)
Due 20(SDA), 21(SCL), SDA1, SCL1

To communicate with I2C devices, Arduino has spoiled us with it's library. With this Arduino's library, we can communicate easily with all I2C devices. The Arduino's library that allow us to communicate with I2C devices called Wire.h. In this library, there are some functions to help us to make an I2C communication.

In this opportunity, I would like to make a tutorial how to use these functions. In this library, I separate the functions into 4 sections: Initiating, Transmitting, Receiving, and Responding in Slave Mode. 

Initiating

This section is to initiate the Wire.h library and to define our Arduino as a master or a slave.

Wire.begin()
Initiating the Arduino in a master mode, with this function we can control the data transfer when connecting with other I2C devices.

Wire.begin(address)
Initiating the Arduino in a slave mode, filled with 7-bit slave address. We can define our I2C unique address here. For more detail about I2C addressing you can find it here.

Transmitting

This section is to communicate (starting, writing, and stopping) between master and slave. Used at master side.

Wire.beginTransmission(address)
Begin a transmission to I2C slave device with device's unique address.

Wire.write(data)
Write data from I2C slave device in response to a master's request, or queue bytes for transmission from master to slave. Place it between beginTransmission() and endTransmission().

Wire.endTransmission()
End a transmission to I2C slave device, and transmit the queue data.

Receiving

This section is to receive the buffered bytes of data from slave to master.

Wire.requestFrom(address, count)
Request "count" of data from I2C slave device at "address". Used at master side

Wire.available()
Return the number of bytes available to be retrieved by read(). This function should be called after function requestFrom() at master side or inside onReceive() handler at slave side.

Wire.read()
Read bytes of data that was transmitted from slave to master after asking for request in requestFrom() function or transmitted from master to slave.

Responding in Slave Mode

This section is only used at I2C slave device to communicate with master device (if we want to make our other Arduino act as a slave).

Wire.onReceive(handler)
Register a function to be called when a slave device receives a transmission from master or when master sends data. handler is the function to be called when the slave receives data, this should take a single int parameter and return nothing.

Wire.onRequest(handler)
Register a function to be called when a slave device sends a transmission to master or when master request for data. handler is the function to be called, takes no parameters and return nothing.

Reliable Sources

Thursday 17 December 2015

I2C Communication

What is I2C?

I2C is an acronym of Inter-IC or Inter-Integrated Circuit designed by Philips in the early '80s. This bus allows easy communication between multiple modules (IC). Like Serial Peripheral Interface (SPI), this protocol just serves in short distance communications within a single device. This communication only requires two wires (sometimes called Two Wire Interface) to exchange data or information, like Asynchronous Serial Interface (RS-232 or UART's).

I2C is a simple, low bandwidth, short-distance protocol (about 2 meters) with standard clock speed up to 100kHz. But in Fast mode, I2C can reach 400kHz and 3.4MHz in High-Speed mode. Most of the modules can operate up to 100kHz. If we force it up to 1MHz, there will be a uS (micro-second) delay between transferring process.

I2C Speed Mode Speed (Hz) Distance (meter)
Standard Speed 100k 2
Fast Mode 400k 100
High-Speed 3.4M 0.5

The Physical of I2C

Physically I2C bus can be seen in two wires called  SCL and SDA. SCL is the clock line is used to synchronize all data transfers over I2C bus. SDA is the data line. Both SCL and SDA lines are "open drain" drivers or the chip only can drive the output low and cannot drive it high. To be able to go high, we must provide pull-up resistor (usually above 1000 ohm) to the voltage source.


If we don't provide these pull-up resistor, these two lines (SCL and SDA) will always on low logic, about nearby 0V, and these line won't work well. If you buy an I2C module such as HMCL5883L or BMP180 and read the datasheet carefully, the datasheet usually mentions the requirement pull-up resistor to be attached.

Master and Slaves

The I2C bus communication must, at least, has two devices or more, one device as master and the other as slaves. The master is always the device that drives the SCL clock line and the slaves are the devices that respond to the master. Only master device can initiate the transfer process. I2C is a half-duplex serial transmission and the data flow only in a direction at a time. the data transfer rate of this bus depends on crystal frequency of slave devices. the rate of data transfer refers to the clock frequency of SCL bus must be 1/16th of slave frequency.

Addressing

I2C is multi-point protocol. There can be more than two slaves in a line, but normally there is only one master. To distinguish one slave to another, each slave device has their unique address.



All I2C addresses are either 7 bits or 10 bits. But the common address will have 7-bit addresses. So, the I2C can control up to 128 slaves in a line with one master. There is an extra bit or eighth bit that is used to inform the slave if the master is writing or reading from it.

Start and Stop Condition

There are two conditions needed to communicate between I2C devices, START and STOP condition. START and STOP condition are two special sequence defined for I2C bus. These two conditions are defined by the master side. Both condition is signed by high logic of SCL. The different is START condition is the SDA logic transition from high to low and STOP condition is when SDA in transition from low to high.



After the START condition the bus is considered as busy and the data can be used by master after STOP condition is detected. After that the master can re-initiate the START condition to get the data and then send STOP condition to use the data, and soon. The START condition usually followed by the slave I2C address.

Exchange Data Procedure

The first thing before the data transaction is that the master begins the communication by initiating the START condition followed by sending the 7-bit unique slave device address. The address is started with the Most Significant Bit (MSB). Continue to the next extra bit (eighth bit) to determine the device status, READ or WRITE, by logic low (0) and high (1). The slave that matches with the address will continue with the transaction, any other will ignore the transaction and wait for the next. 

The logic low (0) means that the status of the master is on WRITE or the slave is on receive status. The other side, the high logic (1), determine the master is on READ or the slave is on transmit status. This is followed by an ACK bit issued by the receiver to acknowledge the receipt of previous byte. Then master must now send the byte of internal register address inside the slave that it wishes to read or write. At the end of byte, the receiver issues a new ACK bit. For every 8 bit of data, the receiver sends the ACK bit. The master can continue to send data bytes to the slave and this will normally be placed in the following register because slave will automatically increment the internal register address after each byte. This sequence pattern is repeated if there is more byte needed to be transferred.



In WRITE procedure, logic low (0), when the master is done transmitting all of the data bytes it wants to send, it issues the last ACK then starting the STOP condition. In READ procedure, logic high (1), the master acknowledge the final byte it receives. This will tells the slave that its transmission is done. Then the master sends the STOP condition.

Sequences

So generally, we have the conclusion of the communication procedure to get the data from the slave device.
  1. Send the START condition
  2. Send the unique 7-bit slave I2C address with extra Write bit
  3. Send internal register address where we want to read from
  4. Send repeat START condition
  5. Send the unique 7-bit slave I2C address with extra Write bit
  6. Receive data from slave device
  7. Send STOP condition

How To Deal With I2C Device

The key how to deal with I2C devices is "have the device datasheet near you". This means that we must read carefully and understand the device datasheet. Because each I2C device has unique way how to deal with and different between one to another. As example, the way you deal with HMC5883L is totally different with BMP180. Each device has their own way to be deal. So, if we want to make a communication between our microcontroller and I2C device, make sure you read and understand the datasheet first.

Reliable Sources



Friday 11 December 2015

X-Y Axis Level Indicator Using Arduino

Continuing my previous idea about 3 Axis Accelerometer (ADXL345) using Arduino, I would like to do a little improvement about this idea. When you have a smartphone and install some tools in it, you will have one of the tools is level indicator.

In this opportunity, I would like to make a simple level indicator using collaboration between Arduino and servos. This simple level indicator have two main axis, X Axis and Y Axis, that will be shown in the movement of servos as an indicator.


Step 1: Components Gathering


1x Arduino
1x Accelerometer ADXL345
2x Servos
2x Hand Made Arrows
1x ProtoBoard
~x Cable Jumper

I replaced ProtoBoard and Cable Jumper with handmade Arduino shield. I made the shield based on the wiring procedure that will be described later.

Step 2: Wiring

We already knew that ADXL345 using I2C to communicate with the microcontroller.

And if you already done with the wiring, the final product will be like this.

I used my handmade Arduino shield for easy attachment, the shield follows the wiring procedure above. There is a box I use for placing the servos.

Step 3: Coding

 #include <Wire.h>  
 #include <Servo.h>  
 Servo xservo;  
 Servo yservo;  
 int xval, yval;  
 #define DEVICE (0x53)  //ADXL345 device address  
 #define TO_READ (6)    //num of bytes we are going to read each time (two bytes for each axis)  
 byte buff[TO_READ] ;  //6 bytes buffer for saving data read from the device  
 char str[512];           //string buffer to transform data before sending it to the serial port  
 void setup()  
 {  
  Wire.begin();    // join i2c bus (address optional for master)  
  Serial.begin(9600); // start serial for output  
  xservo.attach(5);  
  yservo.attach(6);  
  //Turning on the ADXL345  
  writeTo(DEVICE, 0x2D, 0);     
  writeTo(DEVICE, 0x2D, 16);  
  writeTo(DEVICE, 0x2D, 8);  
 }  
 void loop()  
 {  
  int regAddress = 0x32;  //first axis-acceleration-data register on the ADXL345  
  int x, y, z;  
  readFrom(DEVICE, regAddress, TO_READ, buff); //read the acceleration data from the ADXL345  
   //each axis reading comes in 10 bit resolution, ie 2 bytes. Least Significat Byte first!!  
   //thus we are converting both bytes in to one int  
  x = (((int)buff[1]) << 8) | buff[0];    
  y = (((int)buff[3])<< 8) | buff[2];  
  z = (((int)buff[5]) << 8) | buff[4];  
  //we send the x y z values as a string to the serial port  
  sprintf(str, "%d %d %d", x, y, z);   
  Serial.print(str);  
  Serial.write(10);  
  xval = x;  
  xval = map(xval, -250, 250, 0, 180);  
  xservo.write(xval);  
  delay(10);   
  yval = y;  
  yval = map(yval, -250, 250, 0, 180);  
  yservo.write(yval);  
  delay(10);   
  //It appears that delay is needed in order not to clog the port  
  delay(10);  
 }  
 //---------------- Functions  
 //Writes val to address register on device  
 void writeTo(int device, byte address, byte val) {  
   Wire.beginTransmission(device); //start transmission to device   
   Wire.write(address);    // send register address  
   Wire.write(val);    // send value to write  
   Wire.endTransmission(); //end transmission  
 }  
 //reads num bytes starting from address register on device in to buff array  
 void readFrom(int device, byte address, int num, byte buff[]) {  
  Wire.beginTransmission(device); //start transmission to device   
  Wire.write(address);    //sends address to read from  
  Wire.endTransmission(); //end transmission  
  Wire.beginTransmission(device); //start transmission to device  
  Wire.requestFrom(device, num);  // request 6 bytes from device  
  int i = 0;  
  while(Wire.available())  //device may send less than requested (abnormal)  
  {   
   buff[i] = Wire.read(); // receive a byte  
   i++;  
  }  
  Wire.endTransmission(); //end transmission  
 }  

Step 4: Testing

After all wiring and coding are done, here we come with the testing.

Thank you for your time to visit my blog and I am very sorry for the dirty pillow behind :p. hahaha

Tuesday 1 December 2015

3 Axis Accelerometer (ADXL345) using Arduino

Accelerometer is a device to measure the rate of change of velocity, or to measure acceleration. The unit of this acceleration is meter per second squared (m/s2) or in G-Forces (g). One G-Force is equal to 9.8m/s2. Accelerometer is useful enough to make a device that utilize earth gravitation. Accelerometer is usually measured in 3-axis (X Axis, Y Axis, and Z Axis). The common device module to measure the acceleration is ADXL345.

ADXL345 is a small, thin, ultralow power, 3-axis accelerometer with 13 bit resolution measurement up to ±16g. The acceleration measurement system can be selected from ±2g±4g±8g, or ±16g. ADXL345 is well suited for mobile applications.




In this opportunity, I would like to share about how to make accelerometer (ADXL345) using Arduino.


Step 1: Component Preparation

To Make an accelerometer using Arduino, here are some component that required to make a simple accelerometer.


1x Arduino UNO
1x Accelerometer ADXL345 (the datasheet can be downloaded here)
4x Cable Jumper

Step 2: Wiring

ADXL345 module has I2C address of 0x53 as you can see from the datasheet. It can share I2C bus with other devices as long as each device has unique address.



Only 4 connection we need to make an I2C communication.
ADXL345 ↔ Arduino
  • VIN ↔ 5V
  • GND ↔ GND
  • SDA ↔ SDA (Analog pin 4)
  • SCL ↔ SCL (Analog pin 5)

Here I made my own Arduino shield for ADXL345, but the connection follow the wiring diagram above.


Step 3: Coding

To understand more about ADXL345 I2C address and how to access the ADXL345, I suggest you read the datasheet.
 #include <Wire.h>  
 #define DEVICE (0x53)    //ADXL I2C device address  
 #define TO_READ (6)     //Total bytes to be read (2 bytes each axis)  
 byte buff[TO_READ];     //Save read data to buffer  
 char value[512];  
 void setup(){  
  Wire.begin();       //Start I2C communication  
  Serial.begin(9600);    //Start serial communication to   
                //show read output from ADXL  
  //Turning on ADXL  
  writeTo(DEVICE, 0x02, 0);  
  writeTo(DEVICE, 0x02, 16);  
  writeTo(DEVICE, 0x02, 8);  
 }  
 void loop(){  
  int regAddress = 0x32;  //First data from ADXL  
  int Axis_X, Axis_Y, Axis_Z; //Defining three Axis from ADXL  
  readFrom(DEVICE, regAddress, TO_READ, buff); //Read data from ADXL  
  //Read data from ADXL is bytes so must convert it to int  
  Axis_X = (((int)buff[1]) << 8) | buff[0];  
  Axis_Y = (((int)buff[3]) << 8) | buff[2];  
  Axis_Z = (((int)buff[5]) << 8) | buff[4];  
  //Print the values to PC  
  sprintf(value, "X Axis = %d, Y Axis = %d, Z Axis = %d", Axis_X, Axis_Y, Axis_Z);  
  Serial.println(value);  
  delay(500);  
 }  
 //Write value to ADXL  
 void writeTo(int device, byte address, byte val){  
  Wire.beginTransmission(device); //Start communicating ADXL  
  Wire.write(address);       //Send register address0x03  
  Wire.write(val) ;        //Send value to write  
  Wire.endTransmission();     //End communication  
 }  
 void readFrom(int device, byte address, int num, byte buff[]){  
  Wire.beginTransmission(device); //Start communicating ADXL  
  Wire.write(address);       //Send register address  
  Wire.endTransmission();     //End communication  
  Wire.beginTransmission(device); //Start communicating ADXL  
  Wire.requestFrom(device, num);  //Request number of byte from ADXL  
  int i = 0;  
  while(Wire.available()){      
   buff[i] = Wire.read();     //Receive value  
   i++;  
  }  
  Wire.endTransmission();     //End communication  
 }               

Step 4: Testing

Connect the ADXL345 to Arduino using I2C communication, then open Arduino serial monitor (Ctrl+Shift+M) to see the result.



Thank you, I hope this will help you.





Tuesday 24 November 2015

Simple RF Device

You want to have a remote control device but you don't have enough money and you are the creative one? Why don't you create your own remote control device? Here I would like to share about my simple idea to create a simple remote control device. I made a simple remote LED controlller using components that I think are not expensive and easy to find.

Step 1: Gather some needed components


1x a pair of RF Module (xd-fst (transmitter) and xd-rf-5v (receiver))
2x Arduino (I used Arduino UNO as receiver and Mega2560 as transmitter)
1x LED
1x Push Button
1x 10k Resistor
1x ProtoBoard
~x Cable Jumper (I used cable UTP)

Step 2: Wiring 

We will be create two devices for this project, one for receiver device and another for transmitter device.

Receiver:

1x RF Receiver Module (xd-rf-5v)
1x Arduino (I used Arduino UNO)
1x LED
~x Cable Jumper

Transmitter:

1x RF Transmitter Module (xd-fst)
1x Arduino (I used Arduino Mega2560)
1x Push Button
1x 10k Resistor
~x Cable Jumper

And after combine all components, the result will be like:

Step 3: Coding

There will be two types of code we will use, one for receiver and another for transmitter.

Receiver:
 #include <VirtualWire.h>  
 void setup()  
 {  
   Serial.begin(9600);     // Configure the serial connection to the computer  
   vw_set_ptt_inverted(true); // Required by the RF module  
   vw_setup(2000);      // bps connection speed  
   vw_set_rx_pin(3);     // Arduino pin to connect the receiver data pin  
   vw_rx_start();      // Start the receiver  
   pinMode(12, OUTPUT);  // Set LED to pin 13 in UNO  
 }  
 void loop()  
 {  
  uint8_t buf[VW_MAX_MESSAGE_LEN];  
  uint8_t buflen = VW_MAX_MESSAGE_LEN;  
  if (vw_get_message(buf, &buflen))   // We check if we have received data  
  {  
   int i;  
   // Message with proper check    
   for (i = 0; i < buflen; i++)  
   {  
    //Serial.write(buf[i]); // The received data is stored in the buffer  
                // and sent through the serial port to the computer  
    if (buf[i] == 'a'){  
     digitalWrite(12, HIGH);  
     Serial.write(buf[i]); // If you want to see the received message  
    }  
    else{  
     digitalWrite(12, LOW);  
     Serial.write("No message is received");  
    }  
   }  
   Serial.println();  
  }  
 }  

Transmitter:
 #include <VirtualWire.h>  
 int button = 2;  
 void setup()  
 {  
   pinMode(button, INPUT);   // Setting A0 as Input  
   vw_set_ptt_inverted(true); // Required by the RF module  
   vw_setup(2000);      // bps connection speed  
   vw_set_tx_pin(3);     // Arduino pin to connect the receiver data pin  
 }  
 void loop()  
 {  
   if(digitalRead(button) == HIGH){  
    // Message to send:  
    const char *msg = "a";  
    vw_send((uint8_t *)msg, strlen(msg));  
    vw_wait_tx();    // We wait to finish sending the message  
   }  
   else{  
    // Message to send:  
    const char *msg = "b";  
    vw_send((uint8_t *)msg, strlen(msg));  
    vw_wait_tx();     // We wait to finish sending message  
   }  
   delay(10);     // We wait to send the message again          
 }  

I used Arduino virtual wire library, #include <VirtualWire.h>, to call functions that required for wireless communication. You can see the complete guide for this library here.

Step 4: Testing

After all code and wiring are done. Let's try our device.


You can improve this project as you wish with your own creative idea.