[SOLVED] SMBus and I²C-Wire-Library

Hi,

working on a Smart Battery. Want to read all the interesting data like voltage, innertemperatur, current,Capacity....

All these are done in seperated sketches. Now I want to put it in one big sketch and there I get problems I can't explain (see comments). It seems that the values are switched: Getting voltage-values during reading for temperature and vice versa.

Here is the code for the first attempt (getting voltage and temperature in one sketch):

#include "Wire.h"
#define bl03_address 0x0B

void setup()
{
 Wire.begin();
 Serial.begin(9600);
 
 
}

void getvoltage()
{
 Wire.beginTransmission(bl03_address); 
 Wire.write(0x09);
 byte one,second;
 Wire.requestFrom(bl03_address, 2);
 one= Wire.read();//should get 74; got 97
 second=Wire.read();//should get 30; got B
 Serial.println(one,HEX);
 Serial.println(second,HEX);
 double c= (second*256) + one;
 Serial.println("Spannunng der BL03");
 Serial.println(((c/3)*10/1000),2);
 byte errorcode = Wire.endTransmission(bl03_address);
 Serial.print("Errorcode=");Serial.println(errorcode);
}

void gettemperature()
{
 Wire.beginTransmission(bl03_address); 
 Wire.write(0x08);
 byte one=0,second=0;
 Wire.requestFrom(bl03_address, 2);
 one= Wire.read();//should get 97; got 74
 second=Wire.read();//should get B; got 30
 Serial.println(one,HEX);
 Serial.println(second,HEX);
 int c= (second*256) + one;
 Serial.println("Temperatur der BL03");
 Serial.println(((c/10)-273.15),2);
 int errorcode = Wire.endTransmission(bl03_address);
 Serial.print("Errorcode=");Serial.println(errorcode);
}

void loop()
{
  getvoltage();
 gettemperature();
 delay(5000);
}

Would totally appreciate replies.

Would help if you provided a link to the datasheet of that BL03, whatever that is.

Sorry for the lack of information. BL03 is a LiIon battery with Battery Managment System. It's like a black box for me. There is no datasheet available. So after reverse engineering I found out thats a SMBus Communciation to read out relevant data like Capacity, Current, Voltage,.....

So after spending a few hours searching in the forum, I found that a few guys have a similar problem. The SMBus protocol requires 2 Startbits and then one Stopbit. Something like this:

Startbit
WriteaddressBattery
Registeraddress (where the data is stored)
Startbit
ReadAddressBattery
Number of Bytes to write
Stopbit

Well, for one value like temperature, there is no problem. But putting two values in one programm the wire library seems not to be able to handle it correctly.

At the moment i have switched to the i2cmaster-Library from http://homepage.hispeed.ch/peterfleury/avr-software.html . But I'm would be totally happy to keep the Wire-Library.

toonlumberjack

I haven't used either I2C or SMBus but my understanding is that they are both essentially the same, the differences being small and relating to clock speeds and voltage levels. Also SMBus has an ALERT signal.

In either case there are no start "bits", there is a single start "condition" and two acknowledge bits.

SMBus is very well documented, have you searched for the spec and other documentation?


Rob

Yeah i have the complete SMBus Documents.

What i have found for the Wire-Library was on

ARDUINO 1.0.1 - 2012.05.21
...
* Added ability to generate repeated starts in the Wire library (in
  master mode).  Extra boolean parameters to endTransmission() and
  requestFrom() control whether or not to send a stop (or a repeated
  start instead).  (Todd Krein)
  http://code.google.com/p/arduino/issues/detail?id=663
...

So it seems to work. Will study Google Code Archive - Long-term storage for Google Code Project Hosting. now.

Thanks for reply
toonlumberjack

The SMBus protocol requires 2 Startbits and then one Stopbit.

I cannot find such a definition in the SMBus description on Wikipedia:

http://en.wikipedia.org/wiki/System_Management_Bus

I also used some SMBus devices which also didn't follow your description. Maybe your device is very special in this regard and introduced something special or you misinterpreted the start and stop condition to be start and stop bits (that are not bits because the clock line is not alternated). In any case, multiple start conditions are device specific and not part of the SMBus specification (to my knowledge).

Well, for one value like temperature, there is no problem. But putting two values in one programm the wire library seems not to be able to handle it correctly.

Please describe how this is meant. What does "one program" mean in this context?

At the moment i have switched to the i2cmaster-Library from http://homepage.hispeed.ch/peterfleury/avr-software.html .

i2cmaster is a software emulation of the I2C bus while twimaster does it in hardware like the Wire library.

I cannot find such a definition in the SMBus description on Wikipedia:

A Smart Battery IC needs the following and above mentioned transmission (pseudocode) without a stopbit between the startbits. And by the way: Wikipedia is not almighty :wink:

I also used some SMBus devices which also didn't follow your description

Yeah, totally right.

Maybe your device is very special in this regard and introduced something special or you misinterpreted the start and stop condition to be start and stop bits (that are not bits because the clock line is not alternated). In any case, multiple start conditions are device specific and not part of the SMBus specification (to my knowledge).

Well, I started with a white paper. After sniffing the data between a analyzing device, whose software is not open and which i could only use for a few hours, I decided to go that way. But I don't want to ignore that I could misinterpreted something.

Well, for one value like temperature, there is no problem. But putting two values in one programm the wire library seems not to be able to handle it correctly.

Please describe how this is meant. What does "one program" mean in this context?

Sorry. I'm not a native speaker. So what i meant was:
Reading one value in one sketch (in the loop() ) was no problem at all. But reading two values in one sketch got me the problem.

At the moment i have switched to the i2cmaster-Library from http://homepage.hispeed.ch/peterfleury/avr-software.html .

i2cmaster is a software emulation of the I2C bus while twimaster does it in hardware like the Wire library.

Well, it worked for me. So the issue is SOLVED for me.

Here the change in the code:

#include <i2cmaster.h>

int dev = 0x0B<<1;
int data_low = 0;
int data_high = 0;
int pec = 0;

void setup()
{
Serial.begin(9600);
i2c_init(); //Initialise the i2c bus
}

void getvoltage()
{
  i2c_start_wait(dev+I2C_WRITE);
  i2c_write(0x09);
  i2c_rep_start(dev+I2C_READ);
  data_low = i2c_readAck(); //Read 1 byte and then send ack
  data_high = i2c_readAck(); //Read 1 byte and then send ack
  pec = i2c_readNak();
  i2c_stop();

  double tempDataVoltage = 0x0000;
  tempDataVoltage = (data_high) *256 + data_low;
  double voltage = tempDataVoltage/3*10;
  //Serial.print("Spannung=");Serial.println(tempDataVolatge,HEX);
  Serial.print("Spannung in mV =");Serial.println(voltage,0);
}

void gettemperature()
{
  i2c_start_wait(dev+I2C_WRITE);
  i2c_write(0x08);
  i2c_rep_start(dev+I2C_READ);
  data_low = i2c_readAck(); //Read 1 byte and then send ack
  data_high = i2c_readAck(); //Read 1 byte and then send ack
  pec = i2c_readNak();
  i2c_stop();

  double tempDataTemperature = 0x0000;
  tempDataTemperature = (data_high) *256 + data_low;
  //Serial.print("Temperatur=");Serial.println(tempDataTemperature,HEX);
  double temperature=((tempDataTemperature/10)-273.15);
  Serial.print("Temperatur in Grad Celsius=");Serial.println(temperature,2);
}

void loop()
{

getvoltage();
gettemperature();
Serial.println("--------------------------------------------");
}