
Software Serial Esp8266 I2c
Dec 14, 2016 Software serial can be implemented on any GPIO pin of ESP8266. For this you need SoftwareSerial Library for ESP. Download from here Link. To add library in Arduino IDE, Library path is different for ESP8266. C:Program FilesArduinoportablepackagesesp8266hardwareesp82662.1.0libraries. Software serial. The I2C driver code of the Non-OS SDK 1.5.1 in driver folder uses bit-bang method. Usually, some dedicated registers for I2C stored in the chip, and software will control the register to communicate with peripherals. If ESP8266 adopts similar manner, some kind of access method should be specified in datasheet.
Introduction: ESP8266: I2C PORT and Address Scanner
Here I present the i2c_port_address_scanner.ino sketch for the ESP8266. The i2c_port_address_scanner.ino will not only discover the address of your I2C device but also the PORT numbers to which SLA and SLC are connected.
For a newbie adding an I2C device can be frustrating. Several things need to line up properly for things to work. Various boards have different mappings between port number and GPIO number. Additionally, the stated ports in the program need to match the connected ports on the board. Additionally, the SLA and the SLC pair needs to properly line up with what is stated in the code.
To test and take some of that mystery out there is a i2c_scanner.ino program floating around on Arduino.cc and GIThub. But to get it to work the wiring should match the definition’s in a program. That program is to discover the I2C address only.
Teacher Notes
Teachers! Did you use this instructable in your classroom?
Add a Teacher Note to share how you incorporated it into your lesson.
Step 1: What Is the I2C Bus?
What is I2C Bus?
I2C bus is a means of connecting several peripheral input and output devices that support I2C on two wires. One of those wires is the DATA line called the SDA, whereas the other is the CLOCK line called the SCL. The information is sent on these two lines using what is called the I2C communication protocol. I will not go into the details of I2C, but for clarity purpose you can get additional information here and here.
Step 2: Things You Need
You will need an ESP8266 NodeMCU, ESP8266
WeMos, or ESP8266MOD module on an adapter board and a USB-UART dongle like the one described here.
Additionally, you will also need a couple of I2C devices to test. I had a real-time clock module DS1307 and a 0.96-inch OLED SSD1306 which I will use for the test and demonstration.
A set of hook up wires.
Step 3: Setups
I will present two setups for the
purpose of demonstration.
Setup 1:
In this setup, we will connect two I2C devices on the same bus. The i2c_port_address_scanner.ino will discover on which port the SDA and the SCL lines are connected. Additionally, it will also discover the I2C address of the two devices.
Setup 2:
In this setup, we will connect the two I2C devices on two separate buses. The i2c_port_address_scanner.ino will discover the two buses and the I2C address of each device on their respective bus.
Step 4: SETUP 1 Details
In this setup, we will connect two I2C
devices on the same bus. The i2c_port_address_scanner.ino will discover on which port the SDA and the SCL lines are connected. Additionally, it will also discover the I2C address of the two devices.
I used a NodeMCU board since that was handily available, you can use any other board. I picked D1(GPIO5), and D2(GPIO4) as my bus ports.
The connections were as follows:
NodeMCU GPIO0 -> SCL (RTC) -> SCL (OLED)
NodeMCU GPIO4 -> SDA (RTC) -> SDA (OLED)
NodeMCU +3.3 -> VCC (RTC) -> VCC (OLED)
NodeMCU GND -> GND (RTC) -> GND (OLED)
Step 5: Results of SETUP 1
The image above is self evident. There are three addresses on SDA:SCL pair GPIO4:GPIO0; 0x3C, 0x50, and 0x68. You see three addresses while you have connected two devices because the RTC board has an EEPROM at address 0x50. It is accessible to the program for read and write.
Step 6: SETUP 2 Details
In this setup, we will connect the two I2C
devices on two separate busses. The i2c_port_address_scanner.ino will discover the two busses and the I2C address of each device on their respective bus.
The connections were as follows:
NodeMCU D1 GPIO0 -> SCL (RTC)
ramzan ul mubarak ke mahine ke sawal jawab. kesi ye judai hai dj mazamp3. maum hall vakah le heran be mp3 song. jo masriq ko dekhta hai to maghrib se ghafil ni hota. mujhe tum jaan se bhi aziz ho poetry. O sanam o sanam kash hota agar mp3 free download skull.
NodeMCU GPIO4 -> SDA (RTC)
NodeMCU +3.3 -> VCC (RTC)
NodeMCU GND -> GND (RTC)
NodeMCU GPIO13 -> SCL (OLED)
NodeMCU GPIO5 -> SDA (OLED)
RTC (opposite header) +3.3 -> VCC (OLED)
RTC (opposite header) GND -> GND (OLED)
Step 7: Results of SETUP 2
The image above is self evident.
There are two addresses on SDA:SCL pair GPIO4:GPIO0; they being 0x50, and 0x68. You see three addresses while you have connected two devices because the RTC board has an EEPROM at address 0x50. It is accessible to the program for read and write.
There is one address at the GPIO5:GPIO13; it being 0x3C.
Step 8: The Code of I2c_post_address_scanner.ino
The main code of the i2c_port_address_scanner.ino consists of
two functions. The void scanPorts() has two for loops that pick the SDA and SCL pairs and calls the void check_if_exist_I2C() function to scan through the 127 possible I2C addresses. If it finds one, then it publishes it on the Serial Monitor.
void scanPorts() {
for (uint8_t i = 0; i < sizeof(portArray); i++) {
for (uint8_t j = 0; j < sizeof(portArray); j++) {
if (i != j){
Serial.print('Scanning (SDA : SCL) - ' + portMap[i] + ' : ' + portMap[j] + ' - ');
Wire.begin(portArray[i], portArray[j]);
check_if_exist_I2C();
}
}
}
}
//This code is a modified version of the code posted on the Arduino forum and other places
void check_if_exist_I2C() {
byte error, address;
int nDevices;
nDevices = 0;
for (address = 1; address < 127; address++ ) {
// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the address.
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error 0){
Serial.print('I2C device found at address 0x');
if (address < 16)
Serial.print('0');
Serial.print(address, HEX);
Serial.println(' !');
nDevices++;
} else if (error 4) {
Serial.print('Unknow error at address 0x');
if (address < 16)
Serial.print('0');
Serial.println(address, HEX);
}
} //for loop
if (nDevices 0)
Serial.println('No I2C devices found');
else
Serial.println('**********************************n');
}
An updated GITHub source code can be downloaded here. In any case you can downloaded the code here:
Be the First to Share
Recommendations
Arduino Contest 2020
First Time Author Contest
Space Challenge
Brzo i2c implements an i2c master and is written in assembly language for the esp8266. The core features are:
- Fast mode plus speeds
- 800 KHz @ 80 MHz CPU frequency
- 1 MHz @ 160 MHz CPU frequency
- Precise timing for SCL and SDA, including removal of spikes
- i2c transactions: Group any combination of i2c writes or reads together, either with or without repeated start.
For further information you may refer to the wiki
HW and Tool Chain Support
- Brzo i2c supports only esp8266 modules because it is implented in Xtensa assembly language.
- The code is tested for the Arduino tool chain
- And thanks to valkuc it works for the native tool chain, too! Make sure to use the correct compiler flags.
- Tested Arduino versions:
- ESP8266 Arduino Core 2.4.1
- ESP8266 Arduino Core 2.3.0
- ESP8266 Arduino Core 2.2.0
- ESP8266 Arduino Core 2.1.0
- Tested Native SDK versions:
- SDK Version 3.0.1
- SDK Version 2.0.0
Brzo i2c was tested with several i2c devices. If you find one which is not working, please open an issue.
NOTE for AM2320 Sensor: The wake-up sequence is not compatible with brzo_i2c
, see analysis here
How to install the Brzo I2C Library
Use the Library Manager:
- If you are using the ArduinoIDE, you can install via library manager
- If you are developing with PlatformIO then simply use the library manager to install brzo_i2c
Pull it from github
And then just include brzo_i2c in your sketch as any other library with #include 'brzo_i2c.h'
.
Disabling or enabling Interrupts during i2c reads or writes
In brzo_i2c.h you can set the behaviour how interrupts during i2c reads or writes are handled: Setting BRZO_I2C_DISABLE_INTERRUPTS
to 1
will disable all interrupts during i2c read or writes. The default is all interrupts are disabled. For further information about disabling or enabling interrupts refer to the wiki
I2C Setup
To setup the i2c bus you need to call at least once brzo_i2c_setup
.
brzo_i2c_setup(uint8_t sda, uint8_t scl, uint32_t clock_stretch_time_out_usec)
.
Input
- The number of your SDA Pin
- The number of your SCL Pin
- The timeout for an i2c slave clock stretch in micro seconds. Be careful when using i2c devices with a very long clock stretching, please read the wiki.
Returns
- None
Example:brzo_i2c_setup(5, 12, 200);
I2C Transactions
The motivation for i2c transactions is found on the wiki. An i2c transactions always begins with brzo_i2c_start_transaction
and ends with brzo_i2c_end_transaction
. Within a transaction you can combine any number i2c commands with or without a repeated start, i.e. brzo_i2c_write
or brzo_i2c_read
.A transaction is bound to one i2c slave and all commands are executed at the same SCL speed. Thus, brzo_i2c_start_transaction takes the slave address and SCL speed in KHz as input parameters.
Begin a transaction
brzo_i2c_start_transaction(uint8_t slave_address, uint16_t SCL_frequency_KHz)
Input
- I2c slave address (7 bit encoded)
- SCL speed to be used for the entire transaction in KHz (SCL speed is rounded to the next 100-level, e.g., 651 will be rounded up to 700)
Returns
- None
Example: Start a transaction to an i2c slave at 0x20 with 1 MHz SCL speed.brzo_i2c_start_transaction(0x20, 1000);
End a Transaction
uint8_t brzo_i2c_end_transaction()
Note:
- The last i2c command before calling
brzo_i2c_end_transaction()
must not contain a repeated start, therefore usebrzo_i2c_read/write(., ., false)
to send a STOP sequence instead of another repeated START. - Refer to the i2c specification about repeated starts and how to 'end' them
Input
- None
Returns
- 0 : All i2c commands were executed without errors
- errors
- 1 : Bus not free, i.e. either SDA or SCL is low
- 2 : Not ACK ('NACK') by slave during write: Either the slave did not respond to the given slave address; or the slave did not ACK a byte transferred by the master.
- 4 : Not ACK ('NACK') by slave during read, i.e. slave did not respond to the given slave address
- 8 : Clock Stretching by slave exceeded maximum clock stretching time. Most probably, there is a bus stall now!
- 16 : Read was called with 0 bytes to be read by the master. Command not sent to the slave, since this could yield to a bus stall
- 32 : ACK Polling timeout exceeded
I2C Commands
The following i2c commands shall only be used within a transaction!
I2C write
brzo_i2c_write(uint8_t *data, uint8_t no_of_bytes, boolean repeated_start)
Note:
- You can only call
brzo_i2c_write
inside a transaction! - Of course, there is error checking inside the write command. However, errors are only reported at the end of a transaction.
Input
- A pointer to an array of bytes: Either use the base address, e.g.,
brzo_i2c_write(buffer, 2, .)
or use the address of a specific array element, e.g.brzo_i2c_write(&buffer[4], 2, .);
. The former writesbuffer[0]
andbuffer[1]
, the latterbuffer[4]
andbuffer[5]
- The number of bytes to be written
- Repeated start if needed
Returns
- None
Example
- From (the previously defined)
uint8_t buffer[4]
write 2 bytes (buffer[0]
,buffer[1]
) and finish the command with a STOP, i.e. no repeated start.brzo_i2c_write(buffer, 2, false);
I2C Read
brzo_i2c_read(uint8_t *data, uint8_t no_of_bytes, boolean repeated_start)
Note:
- You can only call
brzo_i2c_read
inside a transaction! - Of course, there is error checking inside the read command. However, errors are only reported at the end of a transaction.
Input
- A pointer to an array of bytes: Either use the base address, e.g.,
brzo_i2c_read(buffer, 2, .)
or use the address of a specific array element, e.g.brzo_i2c_read(&buffer[4], 2, .);
. The former receives two bytes and saves them tobuffer[0]
andbuffer[1]
, the latter tobuffer[4]
andbuffer[5]
- The number of bytes to be read
- Repeated start if needed
Returns
- None
Example
- Into (the previously defined)
uint8_t buffer[4]
store 3 bytes (buffer[0]
,buffer[1]
,buffer[2]
) and finish the read with a repeated start, i.e. do not send a STOP.brzo_i2c_read(buffer, 3, true);
I2C Acknowledge Polling
Please see the wiki for further information about ACK Polling.
brzo_i2c_ACK_polling(uint16_t ACK_polling_time_out_usec)
Note:
- You can only call
brzo_i2c_ACK_polling
inside a transaction! - There is error checking inside the ACK polling command. However, errors are only reported at the end of a transaction.
Input
- The timeout for ACK polling in micro seconds
Returns
- None
Example
- Perform an ACK polling with 10 msec timeout
brzo_i2c_ACK_polling(10000)
Example of I2C Transactions
Examples of sketches are located in /examples folder.