// Write start bit to the hardware I2C port
// return 0 if successful, 1 if not successful
int8_t i2c_start()
{
uint8_t result;
uint16_t timeout;
TWCR=(1<<TWINT) | (1<<TWSTA) | (1<<TWEN); //! 1) I2C start
for (timeout = 0; timeout < HW_I2C_TIMEOUT; timeout++) //! 2) START the timeout loop
{
delay(1); //Serial.println("Hello");
if (TWCR & (1 << TWINT)) break; //! 3) Check the TWINT bit in TWCR
}
result=(TWSR & 0xF8); //! 4) Mask the status //Serial.println(result);
if ((result == STATUS_START) || (result == STATUS_REPEATED_START))
return(0); //! 5) Return status
else
return(1);
}
LT_I2C contains the low level routines to communicate with devices using the
ATMega328's onboard hardware I2C port. Each routine checks the Two Wire Status
Register (TWSR) at the end of the transaction and returns 0 if successful and 1
if not successful.
I2C Frequency = (CPU Clock frequency)/(16+2(TWBR)*Prescaler)
TWBR-Two Wire Bit Rate Register
TWCR=Two Wire Control Register (TWINT TWEA TWSTA TWSTO TWWC TWEN - TWIE)
TWSR=Two Wire Status Register
Prescaler Values:
TWSR1 TWSR0 Prescaler
0 0 1
0 1 4
1 0 16
1 1 64
Examples:
CPU Frequency = 16Mhz on Arduino Uno
I2C Frequency Prescaler TWSR1 TWSR0 TWBR
1khz 64 1 1 125
10khz 64 1 1 12
50khz 16 1 0 10
100khz 4 0 1 18
400khz 1 0 0 12
Need help on this: I am working on a project for power monitoring using Linear Technology module LTC2947 and ESP32. I got results when I connected the module with arduino uno. But when I tried to communicate with ESP32, the above function is preventing from getting those outputs. Could anyone explain why this function works with arduino uno and not with ESP32?
Hi,
Thank you for the reply. Actually, the LTC2947 is designed for working with Linduino (type of arduino UNO). Since they have given predefined libraries with predefined calculations which have a major role with uno I2C library.
I need to work with ESP32, the code of reading the data is not working. I can communicate and do other things like changing the page in order to read voltage, current, power, etc. I am new to this.
I tried to read the values with the help of the wire library, but the values I am getting are different.
int8_t LTC2947_I2CRdBlock(uint8_t slvAddr, uint8_t regAddr, uint8_t length, uint8_t *values)
{
int8_t ret = 0;
if (length == 0 || i2c_start() != 0) //I2C START
return 1; //Stop and return 0 if START fail
ret |= i2c_write((slvAddr << 1) | I2C_WRITE_BIT); // Write 7 bit address with W bit
ret |= i2c_write(regAddr); // Set register address
ret |= i2c_repeated_start();
ret |= i2c_write((slvAddr << 1) | I2C_READ_BIT); // Write 7 bit address with R bit
if (ret != 0) //If NACK return 1
{
i2c_stop(); //I2C STOP
return 1;
}
length--;
while (length > 0)
{
*values = i2c_read(WITH_ACK); //Read from bus with ACK
values++;
length--;
}
*values = i2c_read(WITH_NACK); //Read from bus with NACK for the last one;
i2c_stop(); //I2C STOP
return 0; // Success!
}
There is a folder called "LT_I2C_WIRE" which uses the Arduino Wire library, and those can be used in a ESP32 as well. So if a file uses #include <LT_I2C_Wire.h> then it is okay.
However, the file "LTC2947.cpp" use the #include <LT_I2C.h which is not using the Arduino Wire library. It is not even compatible with the "LT_I2C_WIRE" !
Someone made a terrible mistake by writing code for the LTC2947 that can only be used on the Linduino (or perhaps also on a Arduino Uno).
That means you have to rewrite that code.
It should be easy. But when I look into the code, it is not easy.
I am using the same sketchbook you have given here. I have rewritten the code of LTC2947.cpp with the help of functions provided in the I2C_Wire.cpp. The only thing is I cannot read the values from the function "LTC2947_Read_I_P_V_TEMP_VCC" in LTC2947.cpp but i can read and get output from the IC with the help of function "LTC2947_GetCurrentPageSelect()" in LTC2947.cpp.
You are right, I need to rewrite the code for that. Since am new to this could you give some guidance in order to read those data.
Planning on using the ltsketchbook for my own project and ran into the same issues. Instead of reinventing the wheel I would like to check with you how far you got.
If possible can you share the changed code and let me know if there are still some open issues. Perhaps we can work together making this library compatible with the esp32.
Hi,
Am sorry for the late reply. I have my semester exams going on so I freezed the project 2 months before. I need to start it back again.
Actually I got the output with the help of wire library. But the thing is we need to convert to the real values. Since the code i have mentioned earlier is hardcorded in arduino kind of devices its easy. But for esp32 we need to build our own (from my knowledge). I am happy to help you. And starting the project back again.
One of the most important goals of Arduino is to be able to use a sketch on any Arduino board.
The ESP8266 and ESP32 are not officially supported by Arduino, but they made it possible to use a Arduino sketch.
A few years ago, the ESP8266 and ESP32 were not very compatible. They had their own special functions and many libraries were adapted to be able to run them on a ESP.
That has improved. The ESP8266 and ESP32 have become much more compatible with Arduino.
Every well written library is compatible with (almost) all platforms.
Bad code with crazy quirks might not run on all boards. Some make a library with optimizations for just one Arduino board. Some make a library that has special things to make it "better", but instead the library is made "worse" (because it is less compatible).
I'm trying to say: Don't strive to make a "special" ESP32 sketch. Find good compatible libraries and write a sketch that is as normal as possible.
The first codeline in this topic was: TWCR=(1<<TWINT) | (1<<TWSTA) | (1<<TWEN); //! 1) I2C start
Then you know that someone didn't understand how important it is to write compatible code.
Hi,
Me and my friend wrote the code and got the communication from LTC2947 back to ESP32. @Koepel Thank you for your advice to use wire library and your comments from other posts to restart communication using Wire.endTransmission(false) has also helped me.