cocco
cocco

Reputation: 16706

Fast I2C connection, moving to new library

I need a faster communication between the ESP and the ADC, so I found this https://github.com/pasko-zh/brzo_i2c.

Original Wire Example

#include "Wire.h"
#define PCF8591 0x48
byte a0;

void setup() {
  Wire.begin(13,14);
  Serial.begin(115200);
}

void loop() {
  Wire.beginTransmission(PCF8591);
  Wire.write(0x04);
  Wire.endTransmission();
  Wire.requestFrom(PCF8591, 5);
  a0=Wire.read();
  a0=Wire.read();
  Serial.println(a0);
  delay(1000);
}

Brzo I2C example

#include "brzo_i2c.h"

uint8_t buffer[10];
uint8_t error=0;
float temp=0.0;

uint8_t ICACHE_RAM_ATTR get_temp(float *t) {
   uint8_t bcode=0;
  brzo_i2c_start_transaction(0x48,400);
  buffer[0]=0x04; 
  brzo_i2c_write(buffer,1,false);// somewhere here is the error
  brzo_i2c_read(buffer,2,false);// or here
  bcode=brzo_i2c_end_transaction();
  *t=((buffer[0]<<8)|buffer[1]);
  return bcode;
}

void setup(){
  delay(500);
  Serial.begin(115200);
  brzo_i2c_setup(13,14,2000);
}

void loop() {
  error=get_temp(&temp);
  if(error==0){
  Serial.print("Temp = ");
  Serial.println(temp, 8);
} else {
  Serial.print("Brzo error : ");
  Serial.println(error);
}
  delay(500);
}

But I always get the same error.

1 : Bus not free

I rewrote it in different ways, changing the frequency, pins and doing multiple transactions. The main reason I don't get it to work is the difference in the API.

There is no ~Wire.requestFrom();in the brzo_i2c lib. So I need to read the value withbrzo_i2c_read(buffer,2,false);`. Anyway, the brzo code does not work. I always get the same error and there is no description in the docs.

Wire reference: https://www.arduino.cc/en/reference/wire

brzo reference: https://github.com/pasko-zh/brzo_i2c/wiki

Upvotes: 0

Views: 613

Answers (1)

Paško
Paško

Reputation: 41

This is paško, the author of the library brzo_i2c.

First, for further upcoming questions may I kindly ask you to open an issue on the github repo, i.e. bzro_i2c Issues. This is the usual place where people ask questions about the library.

I made a distinction between documentation of the code and the wiki. The readme is short and the brzo_i2c wiki explains many i2c and brzo_i2c related stuff.

In general, an i2c bus is not free if either SCA or SCL is low.

I assume your wiring is correct? How big are your pull-up resistors?

I had a look at the datasheet of the PCF8591. On page 20 table 11 "dynamic characteristics" it says: SCL clock frequency MAX 100 kHz. In your code however, you are selecting 400 kHz, brzo_i2c_start_transaction(0x48,400); So, you should use 100 kHz at maximum. I guess it is a timing problem for the read command after writing the control byte.

Concerning Wire.requestFrom(PCF8591, 5): Behind the scenes this statement does read 5 bytes and puts them in a receive buffer, i.e. i2c communication takes place: START, send slave address, read first byte, ..., STOP. You can see this in the code of the wire library, where it calls twi_readFrom(.), and the actual i2c communication in the underlying esp8266Core code. Note that calls afterwards to wire.read(.) does not perform any i2c communication, instead it just returns the bytes from the receive buffer. Now, turning Wire.requestFrom(PCF8591, 5) into brzo_i2c is very simple:

brzo_i2c_start_transaction(0x48,100);
  brzo_i2c_read(buffer,5,false);
bcode = brzo_i2c_end_transaction();

However, I would not do seperate transactions for reads and writes, instead I would combine them -- as long as they belong "together". So your code above, where your writing the control byte and then afterwards reading out the corresponding data is the way to go :-)

btw: From your code I am guessing that you are using an analogue temperature sensor. You may use a digital sensor that has an i2c bus interface, e.g., an ADT7420, code snippet with brzo_i2c is here

Upvotes: 4

Related Questions