[SMBus] A smart battery emulator

when battery of my laptop, a very old DELL E5400, stoped working, i start to investigate to find what was the problem.
first i build the I2C sniffer you can found here: [I2C] Yet another I2C logging program.

with use of I2C sniffer i found that my battery say it has a negative total capacity, for this reason PC ignore it at all, and don’t charge it anymore.
after hours of search on the web, i wasn’t able to find a way to fix the battery, so i decided to build a Smart Battery emulator with Arduino.

first, i tried the good work made by @General_Victm posted here: Trying to simulate a SMBus from an Smart Battery accu pack with the Arduino Uno.

the original sketch was partially working on my PC, but i done a lot of changes to make it fully working on my DELL laptop.
sincerly is not 100% working, because DELL battery have a kind of authentication mechanim that i don’t know, but this don’t let the sketch unusable, because authentication code change only when AC charger is connected with PC turned off, so the workaround is simple, first turn on PC then connect AC charger.

you can find the sketch as attachment.

SMBusBatteryEmulator.ino (18.3 KB)


First of all thanks a lot for having posted your code here!
I'm interested too in emulating the smartbattery slave part (just trying to play with a drone battery)

I already succed in reading the battery parameters from an arduino. Now I want to emulate the smart battery.

From what I see in the I2C frames between the drone's board and the smart battery, the protocol is "checksumed" with some PEC bytes which are specific to SMBus protocol (wrt to I2C).

I did not see in your code if you emulate the PEC bytes ?


smart battery of my laptop don’t use PEC.

if you are searching for a way to calculate PEC, you can try the algorithm written at the end of this document:

i don’t checked it, just found on web

* Bulk buffer CRC8 calculation without a lookup table
* (size optimized). Generic data types used.
* @param const void* data
* @param unsigned size
* @return unsigned char
static unsigned char crc8(const void *data, unsigned size)
 const unsigned char *p = data;
 unsigned crc = 0;
 int i, j;
 for(j = size; j != 0; --j, ++p) {
 crc ^= ((*p) << 8);
 for(i = 8; i > 0; --i) {
 crc = ((crc & 0x8000) ? (crc ^ (0x1070 << 3)) : (crc)) << 1;
 return (unsigned char) (crc >> 8);

Thanks a lot !