I2C library for the sw6115 lithium chip

Hi guys, this is a call for help to build an I2C library for the SW6115 chip thats found on most of the 18650 battery modules (Like those from DIYmore).

The library should allow the user to read various info about the batteries via I2C (stuff like charging status, temp, capacity, and so on)

I have been searching around and it looks like the problem until now has been the lack of a datasheet for the chip in english.

Great news is I made it my personal mission to find the neccesary information.

After weeks of searching the all the dark corners of the internet, signing up to a bunch of chinese forums, and selling my soul to the devil, I have found an english copy of the datasheet, and the I2C protocol !!!

I am able to offer the technical information I have aquired, and carry out testing of the library.

I hope someone with adequate knowlage of I2C and building libraries could help with the writing of the library. Its probably super easy for someone who knows what they are doing. And Im sure it would be very usefull to alot of other people :slight_smile:

And together we can produce something cool for the community!!

SW6115.zip (2.2 MB)

Hello,

It seems to be easy enough to write a library for this chip, but will it be useful ? Battery modules using this chip probably doesn’t give easy access to the I2C pins and use LEDs to indicate charge status, disallowing the use of the I2C interface (as said in the datasheet).

The led pins are also the I2c pins, so by removing the leds there are some pads available to solder to.

I believe it would be useful for a lot of people, things like wifi or Bluetooth servers could also send info about the battery status for example.

It’s a bit too complicated for me to write myself, I’d be really thankful for some guidance :blush:

Before writing a library, try simpler things

Here is an example that should read registers 0x14 and 0x15 to calculate the battery voltage

Wire.beginTransmission( 0x3C );
Wire.write( 0x14 );
Wire.endTransmission();
Wire.requestFrom( 0x3C, 2 );
uint8_t r14 = Wire.read();
uint8_t r15 = Wire.read();  
float vBat = (((r15 << 8) | r14) & 0xFFF) * 1.2;

(edit: oops… fixed)

1 Like

I have tested it out but Im not getting any usable data.

Both r14 and r15 are showing 255

Here is my sketch:

#include <Wire.h>

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Wire.begin();

}

void loop() {
  // put your main code here, to run repeatedly:
  Wire.beginTransmission( 0x3C );
Wire.write( 0x14 );
Wire.write( 0x15 );
Wire.endTransmission();
Wire.requestFrom( 0x3c, 2 );
uint8_t r14 = Wire.read();
uint8_t r15 = Wire.read();  
float vBat = (((r15 << 8) | r14) & 0xFFF) * 1.2;

Serial.println(vBat,5);

Serial.println(r14);
Serial.println(r15);
delay(1000);

}

I have pin 20 on the chip grounded, as per diagram in the datasheet.
I have tested with and without pullups, no difference.
With pullups (12k) I measured with a multimeter and I am reading ~3.3v (unfortunately no oscilloscope at hand). The signal wires are not getting pulled down by the chip or MCU??

Am I maybe missing some initialization steps in my code?

Heheh a bit sneaky there mate :wink:

I am now getting usable info from r14, but r15 shows constant 255

Any ideas?

If I write the code like this, it works (it works so thanks by the way :slight_smile: )

#include <Wire.h>

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Wire.begin();

}

void loop() {
  // put your main code here, to run repeatedly:
Wire.beginTransmission( 0x3C );
Wire.write( 0x14 );
Wire.endTransmission();
Wire.requestFrom( 0x3C, 1 );
uint8_t r14 = Wire.read();
Wire.beginTransmission( 0x3C );
Wire.write( 0x15 );
Wire.endTransmission();
Wire.requestFrom( 0x3C, 1 );
uint8_t r15 = Wire.read();  
float vBat = (((r15 << 8) | r14) & 0xFFF) * 0.0012;

Serial.println(vBat,5);

Serial.println(r14);
Serial.println(r15);
delay(1000);

}

It just seems a bik kinda clunky, like it should be written better? Or do you need to begin a new transmission for each register?

Many I2C devices allow to read multiple registers at once because they have an automatic address increment feature, maybe this chip doesn’t have this feature (nothing about it in the datasheet) so you will need to read each registers separately

To be honest I don’t know much about I2C, maybe there is another way

Ok, well thankyou for your help so far. We have established that the i2c for this chip works :raised_hands:

I would like to take it a step further and start work on a library so it can be useful to anyone.
I have never built a library from scratch though :roll_eyes:

It would be a nice learning experience for me, I just need to find a victim who will help with it :grimacing:

:+1:

Look at other libraries for I2C devices, like this one for example

https://github.com/blemasle/arduino-mcp23017/tree/master/src

Good luck, if you have questions I will answer if I can :slight_smile:

:+1: I could see this being really useful, go for it .

Try this page;

https://www.arduino.cc/en/reference/libraries

Has a link to a tutorial on writing libraries.

I have started building the library but I cant get it working…

I cant figure out how to get it working though :frowning:

I get the following error message:

C:\Users\MickW\Documents\Arduino\libraries\arduino_sw6115-main\src\SW6115.cpp: In member function 'float SW6115::readVoltage()':
C:\Users\MickW\Documents\Arduino\libraries\arduino_sw6115-main\src\SW6115.cpp:13:14: error: 'ADC_VDATA_1' was not declared in this scope
  _bus->write(ADC_VDATA_1);
              ^
C:\Users\MickW\Documents\Arduino\libraries\arduino_sw6115-main\src\SW6115.cpp:18:14: error: 'ADC_VDATA_2' was not declared in this scope
  _bus->write(ADC_VDATA_2);
              ^
Using library arduino_sw6115-main at version 0.0.1 in folder: C:\Users\MickW\Documents\Arduino\libraries\arduino_sw6115-main 
Using library Wire at version 1.0.1 in folder: C:\Users\MickW\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\libraries\Wire 
exit status 1
Error compiling for board ESP32 Dev Module.

Hi guys, just a bump.

I tried a few different things and still can’t get it working.

I was hoping someone could take a quick look at the repo and tell me where I am going wrong?

Thanks :pray:

(post withdrawn by author, will be automatically deleted in 24 hours unless flagged)

??.

I can’t seem to properly reference the register addresses that I have stored in the .h file. It’s probably a simple mistake but I can’t figure it out.

It’s my first time properly building a library from scratch, could someone take a look at it ?

Seems like probably nobody cares, but I finally got the library working.

If anyone needs it, it can be found here:

I have built a few functions, but there is still alot of things the chip is capable of, so if anyone wants to help out, feel free.

Good job :slight_smile:

Few suggestions:

  • Unlike with the MCP23017, your chip address is always 0x3C and cannot be changed, so you don’t need the address parameter in the constructor, just replace uint8_t _deviceAddr; by const uint8_t _deviceAddr = 0x3C;

  • Because the address can’t be changed, you can only have one SW6115 on the I2C bus (or you need additional hardware), so you could create a SW6115 object directly in your class (for example add SW6115 Battery; at the end of .h, after the class definition), so that you don’t have to do it everytime in the sketch (like Wire, Serial, etc).

  • You could simplify all readXX functions by making a generic readRegister function (just like in the MCP23017 library I linked)

float SW6115::readVbatt()
{
  uint8_t r14 = readRegister(SW6115Register::ADC_VDATA_1);
  uint8_t r15 = readRegister(SW6115Register::ADC_VDATA_2);
  return (((r15 << 8) | r14) & 0xFFF) * 1.2;
  //VBAT = ((Reg0x15[3:0]<<8)+ Reg0x14[7:0]) *1.2 mV
}

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.