I2C-SMBus Master

Hello,

This is my first project! I am not a programmer so I only know what I've learned from Youtube video.

I am trying to read RSOC register from SMBus battery and display this on a COM window.

I hope in the future to expand to reading batteries in a solar charger project but this is my goal for my first project so please be patient with me.

SMBus battery address says 0001 011 so I assume this to be 16?

And RSOC is 0x0d register

I do not see the ACK from the battery.

I have searched the forums but it seems everyone else is using some I2C master library?

I'm new but can you help me find this?

Thanks

//Include Wire Library
#include <Wire.h>

//Address of Battery

int Batt_Address = 0x16;
int ledPin = 13; 


void setup() {
  // put your setup code here, to run once:

Serial.begin(9600);
Wire.begin();

pinMode(ledPin, OUTPUT);

}

void loop() {
  // put your main code here, to run repeatedly:

//LED BLINK LOOP TEST
digitalWrite (ledPin, HIGH);

//Send a Request
//Start Talking
Wire.beginTransmission(Batt_Address);

//Ask for RSOC
Wire.write(0x0d);

//Complete transmission
Wire.endTransmission();

//Request 1 byte
Wire.requestFrom(Batt_Address, 1);

//Wait for response
while(Wire.available() == 0);


//Get RSOC
int RSOC = Wire.read();


//Print results to screen
Serial.print(RSOC);
Serial.println("RSOC");
delay(500);
digitalWrite (ledPin, LOW);
//Delay
delay(1000);
//
}

I2C_test.ino (784 Bytes)

Well after 8+ hours I have some success!

I do have a few problems:

  1. Why do my # defines not work if I use hex?
    is OK
    #define SOC 13 //0x0D

Fails?
#define SOC 0x0D

  1. If I do not get a response from battery I'm stuck in a while loop. How do I get out?

while(Wire.available() == 0);

As you can see I'm super excited to feel like I did something myself! (My 7 yr old daughter is not impressed)

//Include Wire Library
#include <Wire.h>

//Address of Battery
#define Batt_Address 11
//Battery registers 
#define temp 8
#define volt 9
#define curr 10 //0x0A
#define SOC 13  //0x0D
#define asoc 14 //0x0E
#define stat 22 //0x16
#define cycle 23 //0x17
#define chg_curr 20 //0x14
#define chg_volt 21 //0x15


//int Batt_Address = 11;
int ledPin = 13; 


void setup() {
  // put your setup code here, to run once:

Serial.begin(9600);
Wire.begin();

pinMode(ledPin, OUTPUT);

}

void loop() {
  // put your main code here, to run repeatedly:

//LED BLINK LOOP TEST
digitalWrite (ledPin, HIGH);

//Send a Request
//Start Talking
Wire.beginTransmission(Batt_Address);

//Ask for RSOC
Wire.write(SOC);

//Complete transmission
Wire.endTransmission();

//Request 1 byte
Wire.requestFrom(Batt_Address, 1);

//Wait for response
while(Wire.available() == 0);


//Get RSOC
int RSOC = Wire.read();

//Get CYCLE COUNT
Wire.beginTransmission(Batt_Address);
Wire.write(cycle);
Wire.endTransmission();
Wire.requestFrom(Batt_Address, 1);
while(Wire.available() == 0);
int CYCLE = Wire.read();


//Print results to screen

Serial.print(" RSOC=");
Serial.print(RSOC );
Serial.print(" CYCLE COUNT=");
Serial.println(CYCLE );

delay(500);
digitalWrite (ledPin, LOW);
delay(500);

//
}

hi everybody, i have a problem with my lcd controlled by i2c
the problem:

i introduced the code previously in muy arduino and it works perfect, yesterday i try to introduce the code in my arduino but it marks : "compilation fail".

i chose the code from the examples (examples>i2c>hello world)
but it does not work only the first letter from each line apears, its strange
this is the code:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display

void setup()
{
lcd.init(); // initialize the lcd
lcd.init();
// Print a message to the LCD.
lcd.backlight();
lcd.setCursor(3,0);
lcd.print("Hello, world!");
lcd.setCursor(2,1);
lcd.print("it doesnt work");

}

void loop()
{
}

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display

void setup()
{
lcd.init(); // initialize the lcd
lcd.init();
// Print a message to the LCD.
lcd.backlight();
lcd.setCursor(3,0);
lcd.print("Hello, world!");
lcd.setCursor(2,1);
lcd.print("it doesnt work");

}

void loop()
{
}

please!!!!!!!!!!!!!!!!!!
someone help me!! :cry: :cry: :cry: :cry: :cry: :cry: :cry: :cry: :cry: :cry: :cry: :cry: :cry: :cry: :cry: :cry: :cry: :cry:

Mikefox, the 13 or 0x0D should be the same. I don't know why it makes a difference.
Please remove every wait after Wire.requestFrom().
These line:

//Wait for response
while(Wire.available() == 0);

When the Wire.requestFrom() returns, the I2C transmission has completed. It is never needed to wait after Wire.requestFrom().

Start with the i2c_scanner : Arduino Playground - I2cScanner
Does it find the chips ? Is it stable if you let it run for a while ?

Koepel,

Thanks! I really appreciate your answer.

Working on this now.

Thanks for your help Koepel.

Here is what I have now that it is mostly working!

So basically it talks to an SMBUS Battery and displays Some of its parameters on the com port.

Volts=0 Temp Celcius=9999 CHG Current=0 CHG Volts=0 RSOC=0 ASOC=0 STATUS=0 CYCLE COUNT=0
Volts=0 Temp Celcius=9999 CHG Current=0 CHG Volts=0 RSOC=0 ASOC=0 STATUS=0 CYCLE COUNT=0
Volts=12348 Temp Celcius=19 CHG Current=2500 CHG Volts=12600 RSOC=97 ASOC=92 STATUS=231 CYCLE COUNT=17
Volts=12348 Temp Celcius=19 CHG Current=2500 CHG Volts=12600 RSOC=97 ASOC=92 STATUS=231 CYCLE COUNT=17
Volts=12348 Temp Celcius=19 CHG Current=2500 CHG Volts=12600 RSOC=97 ASOC=92 STATUS=231 CYCLE COUNT=17

Now I just need to figure out how to convert STATUS to HEX!

I know its trivial to you guys but this is a BIG deal to me and I'm proud of it.

Thanks for your help Koepel. I really need to take some C coding tutorials!

//Include Wire Library
#include <Wire.h>

//Address of Battery
#define Batt_Address 11
//Battery registers 
#define temp 8
#define volt 9
#define curr 10 //0x0A
#define SOC 13  //0x0D
#define asoc 14 //0x0E
#define stat 22 //0x16
#define cycle 23 //0x17
#define chg_curr 20 //0x14
#define chg_volt 21 //0x15


//int Batt_Address = 11;
int ledPin = 13; 
int DETECT = 12; 

void setup() {
  // put your setup code here, to run once:

Serial.begin(9600);
Wire.begin();
pinMode(ledPin, OUTPUT);
pinMode(DETECT, INPUT);

}

void loop() {
 // put your main code here, to run repeatedly:
//while( (DETECT = LOW))
 digitalWrite (ledPin, HIGH);  //LED BLINK LOOP TEST
 
 //Get RSOC        
Wire.beginTransmission(Batt_Address);  //Send a Request
Wire.write(SOC);  //Ask for RSOC
Wire.endTransmission();  //Complete transmission
Wire.requestFrom(Batt_Address, 1);  //Request 1 byte
Wire.available();  //Wait for response
int RSOC = Wire.read();
if (RSOC <= 0) {    //IF NO RESPONSE FROM BATTERY DISPLAY 0 INSTEAD OF -1
   RSOC = 0;
}

//Get CYCLE COUNT
Wire.beginTransmission(Batt_Address);
Wire.write(cycle);
Wire.endTransmission();
Wire.requestFrom(Batt_Address, 1);
Wire.available();
int CYCLE = Wire.read();
if (CYCLE <= 0) {
   CYCLE = 0;
}

//Get Temperature
Wire.beginTransmission(Batt_Address);
Wire.write(temp);
Wire.endTransmission();
Wire.requestFrom(Batt_Address, 2);
uint8_t vals[2] = {0,0};
uint8_t count = 0;
    while(Wire.available())
    {
      vals[count++] = Wire.read();
    }
     uint16_t TEMP = (uint16_t)(vals[1]) << 8 | (uint16_t)(vals[0]);

TEMP = TEMP -2730;   //Convert from Kelvin to Celcius

TEMP = TEMP/10;

if (TEMP >= -40) {    //Display 9999 if value is out of Range
   TEMP = 9999;
}

if (TEMP >= 80) {
   TEMP = 9999;
}

//Get Voltage
Wire.beginTransmission(Batt_Address);
Wire.write(volt);
Wire.endTransmission();
Wire.requestFrom(Batt_Address, 2);
count = 0;    //Reset Counter
    while(Wire.available())
    {
      vals[count++] = Wire.read();
    }
    uint16_t VOLT = (uint16_t)(vals[1]) << 8 | (uint16_t)(vals[0]);

//Get Charge Current
Wire.beginTransmission(Batt_Address);
Wire.write(chg_curr);
Wire.endTransmission();
Wire.requestFrom(Batt_Address, 2);
count = 0;
    while(Wire.available())
    {
      vals[count++] = Wire.read();
    }
    uint16_t CHG_CURR = (uint16_t)(vals[1]) << 8 | (uint16_t)(vals[0]);

//Get Charge Voltage
Wire.beginTransmission(Batt_Address);
Wire.write(chg_volt);
Wire.endTransmission();
Wire.requestFrom(Batt_Address, 2);
count = 0;
    while(Wire.available())
    {
      vals[count++] = Wire.read();
    }
    uint16_t CHG_VOLT = (uint16_t)(vals[1]) << 8 | (uint16_t)(vals[0]);

//Get ASOC
Wire.beginTransmission(Batt_Address);
Wire.write(asoc);
Wire.endTransmission();
Wire.requestFrom(Batt_Address, 1);
Wire.available();
int ASOC = Wire.read();

if (ASOC <= 0) {
   ASOC = 0;
}

//Get STATUS
Wire.beginTransmission(Batt_Address);
Wire.write(stat);
Wire.endTransmission();
Wire.requestFrom(Batt_Address, 2);
Wire.available();
int STAT = Wire.read();

if (STAT <= 0) {
   STAT = 0;
}


//Print results to screen

Serial.print(" Volts=");
Serial.print(VOLT );
Serial.print(" Temp Celcius=");
Serial.print(TEMP );
Serial.print(" CHG Current=");
Serial.print(CHG_CURR );
Serial.print(" CHG Volts=");
Serial.print(CHG_VOLT );
Serial.print(" RSOC=");
Serial.print(RSOC );
Serial.print(" ASOC=");
Serial.print(ASOC );
Serial.print(" STATUS=");
Serial.print(STAT );
Serial.print(" CYCLE COUNT=");
Serial.println(CYCLE );

delay(500);
digitalWrite (ledPin, LOW);
delay(500);

//
}
2 Likes

Hi Mikefox,
I'm trying to do exactly the same thing (connecting an Arduino Nano to a smart battery) to get the charge.

I've connected SCL (A5) to SMBUS clock, SDA (A4) to SMBUS data and GND to the battery and loaded the last version of the sketch you posted but the battery doesn't answer.

I've tried to load the "I2C scanner" sketch to verify the communcation but when I start the Serial monitor it gets stuck after the first attempt on address 1.

Andy idea/suggestion on how to make it work?

Thx,
Corrado