PiSupply / PiJuice

Resources for PiJuice HAT for Raspberry Pi - use your Pi Anywhere
https://uk.pi-supply.com/collections/pijuice/products/pijuice-portable-power-raspberry-pi
GNU General Public License v3.0
440 stars 104 forks source link

Documentation for i2c interface #891

Open PhillippOhlandt opened 2 years ago

PhillippOhlandt commented 2 years ago

Hello,

I looked through this repo and could not find the documentation for the i2c interface. I am porting the python lib to a different language but not every function in the python lib is documented (like GetRsocEstimationConfig) so I wanted to look directly into the i2c interface documentation. Also, any other documentation which might help me, would be good.

tvoverbeek commented 2 years ago

The actual i2c commands you will have to deduce from pijuice.py (https://github.com/PiSupply/PiJuice/blob/master/Software/Source/pijuice.py). Here is the snippet for GetRsocEstimationConfig:

    rsocEstimationOptions = ['AUTO_DETECT', 'DIRECT_BY_MCU']
    def GetRsocEstimationConfig(self):
        result = self.interface.ReadData(self.BATTERY_TEMP_SENSE_CONFIG_CMD, 1)
        if result['error'] != 'NO_ERROR':
            return result
        else:
            d = result['data']
            if ((d[0]&0x30)>>4) < len(self.rsocEstimationOptions):
                return {'data':self.rsocEstimationOptions[(d[0]&0x30)>>4], 'error':'NO_ERROR'}
            else:
                return {'error':'UNKNOWN_DATA'}

Elsewhere in pijuice.py you find BATTERY_TEMP_SENSE_CONFIG_CMD = 0x5D.

Hope this helps with the porting.

PhillippOhlandt commented 2 years ago

Ah ok, that's unfortunate. The only hint that this function has something to do with battery temperature sensing is the command name. I hoped there would be an in-depth documentation so some code parts from the python lib can be better understood.

For example, when retrieving the battery temperature:

    def GetBatteryTemperature(self):
        result = self.interface.ReadData(self.BATTERY_TEMPERATURE_CMD, 2)
        if result['error'] != 'NO_ERROR':
            return result
        else:
            d = result['data']
            temp = d[0]
            if (d[0] & (1 << 7)):
                temp = temp - (1 << 8)
            return {'data': temp, 'error': 'NO_ERROR'}

It is requesting two bytes (because the checksum is on the third byte) but only the first byte is used. And then there is this check:

            if (d[0] & (1 << 7)):
                temp = temp - (1 << 8)

I don't know what it is doing. If I just use the first byte without that check, I get e.g. 35 but when I implement that check, I end up with -220.

Having this documented somewhere would have been nice.

tvoverbeek commented 2 years ago

That is converting from unsigned to signed byte (1 << 8 = 256)

PhillippOhlandt commented 2 years ago

Ah, got it. Actually, my code was buggy and the if-condition was always executed, leading to above mentioned output which was obviously not correct.