This time, I2C communication with an ultrasonic sensor to Arduino.
Among them, the Wire function is especially convenient.
First, I will give an overview of I2C communication.
What is I2C communication?
I2C (Inter-Integrated Circuit) is a method of serial communication with peripheral devices advocated by Philips, and is a method that mainly realizes high-speed communication with EEPROM memory ICs.
In the basic configuration, the master side and the slave side are clearly separated, and the master side has the initiative of all controls. Only one master can be connected, but many slaves can be connected.
I2C connects all the same lines (SDA, SCL) in parallel. Even though they are in parallel, they can communicate with each other because they are assigned addresses, just like Internet networks.
The address can be binary, hexadecimal, or decimal. For example, when writing in hexadecimal, write in the form of 0x70 or 0x56. Also, the master has no address.
When communicating, be sure to first declare the Slave destination (address) before sending the data. Even when the destination changes, the destination is said one by one.
Even in human life, you always write the address in letters and courier services. It’s the same. Speaking of course, it’s natural.
Main commands of the Wire library
#include<Wire.h>
When communicating with I2C, it is necessary to declare it first. This is a statement that says “use the Wire library” and is written at the beginning of the program.
Wire.begin();
Initialize the wire library. If you are a Slave, enter the address in parentheses. Master does not need to enter an address.
Wire.beginTransmission(slave address);
Prepares to start communication with the Slave at the address specified in parentheses. Be sure to declare it when you start communication.
Wire.write( data );
The data in parentheses of “Wire.write” is sent to the address specified in “Wire.beginTransmission”. Basically, the data is within 1 byte.
Wire.endTransmission();
Completes the process of sending data to Slave. In the Wire library, the data buffer from “begin Transmission” to “end Transmission” is 32 bytes, so if there is a lot of data to be transmitted, it is necessary to divide it by “end Transmission” sequentially.
Wire.requestFrom(address, byte);
When the Master requests data from Slave, it declares it first. Write the request destination address and the amount of data you want.
Wire.available()
Returns the number of bytes that can be read by read ().
Wire.read()
On the master device, it is also used when reading the data sent from the slave after executing “requestFrom ()” and when the slave receives the data from the master.
I2C programs for ultrasonic sensors
Here is the ultrasonic sensor program I talked about in my previous blog. In my last blog, I’ll focus on the areas of communication that I didn’t really touch on.
#include <Wire.h>
void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial communication at 9600bps
pinMode(11,OUTPUT);
}
int reading = 0;
int SPEAKER = 11;
int TIME=100;
int m[9]={262,294,330,349,392,440,494,524,0 };
int melody=0;
void loop()
{
// step 1: instruct sensor to read echoes
Wire.beginTransmission(112); // transmit to device #112 (0x70)
Wire.write(byte(0x00)); // sets register pointer to the command register (0x00)
Wire.write(byte(0x51)); // command sensor to measure in "centimeters" (0x51)
Wire.endTransmission(); // stop transmitting
// step 2: wait for readings to happen
delay(20); // datasheet suggests at least 65 milliseconds
// step 3: instruct sensor to return a particular echo reading
Wire.beginTransmission(112); // transmit to device #112
Wire.write(byte(0x02)); // sets register pointer to echo #1 register (0x02)
Wire.endTransmission(); // stop transmitting
// step 4: request reading from sensor
Wire.requestFrom(112, 2); // request 2 bytes from slave device #112
// step 5: receive reading 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("cm");
if(reading>105){
}else if(reading>95){
melody=m[7];
tone(11,melody) ;
delay(TIME);
}else if(reading>85){
melody=m[6];
tone(11,melody) ;
delay(TIME);
}else if(reading>75){
melody=m[5];
tone(11,melody) ;
delay(TIME);
}else if(reading>65){
melody=m[4];
tone(11,melody) ;
delay(TIME);
}else if(reading>55){
melody=m[3];
tone(11,melody) ;
delay(TIME);
}else if(reading>45){
melody=m[2];
tone(11,melody) ;
delay(TIME);
}else if(reading>35){
melody=m[1];
tone(11,melody) ;
delay(TIME);
}else if(reading>25){
melody=m[0];
tone(11,melody) ;
delay(TIME);
}else if(reading>15){
melody=m[8];
tone(11,melody) ;
delay(TIME);
}
tone(11,melody) ;
}
delay(5); // wait a bit since people have to read the output :)
}
First, “#include ” and “Wire.begin ();” are included in “voidsetup () {“. Reads the Wire library and initializes the Wire library.
#include <Wire.h>
void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial communication at 9600bps
pinMode(11,OUTPUT);
}
The main program consists of 5 stages.
First, specify the address (112) of the Slave device in “Wire.beginTransmission (112);”.
Next, send 0x00 with “Wire.write”. This is a signal to start communication with an ultrasonic sensor. Then write 0x51. This sets the distance of the ultrasonic sensor to be read out later to be returned in centimeters. Send by “Wire.end Transmission”.
After waiting for 20 milliseconds, send 0x02. It requires the sensor to send an ultrasound reading. Then, use “Wire.requestForm” to prepare for reception. The capacity is 2 bytes. Finally, the flow is to read the measured value with “Wire.read ()”.
// step 1: instruct sensor to read echoes
Wire.beginTransmission(112); // transmit to device #112 (0x70)
// the address specified in the datasheet is 224 (0xE0)
// but i2c adressing uses the high 7 bits so it's 112
Wire.write(byte(0x00)); // sets register pointer to the command register (0x00)
Wire.write(byte(0x51)); // command sensor to measure in "centimeters" (0x51)
// use 0x51 for centimeters
// use 0x52 for ping microseconds
Wire.endTransmission(); // stop transmitting
// step 2: wait for readings to happen
delay(20); // datasheet suggests at least 65 milliseconds
// step 3: instruct sensor to return a particular echo reading
Wire.beginTransmission(112); // transmit to device #112
Wire.write(byte(0x02)); // sets register pointer to echo #1 register (0x02)
Wire.endTransmission(); // stop transmitting
// step 4: request reading from sensor
Wire.requestFrom(112, 2); // request 2 bytes from slave device #112
// step 5: receive reading 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("cm");
That’s all for today.