Hey Guys! @pra @ScruffR
I was trying all kinds of stuff last night so some of it may not make sense or look right. I was basically testing out what was returned when I used 2 vs 2+1.
It looks like your latest code changes might have solved the issues. Lets take a look.
Here is the 32 byte Block Read code with your latest suggested changes.
uint32_t BQ20Z45::read32u(uint8_t address)
{
uint32_t registerValue;
Wire.beginTransmission(BQ20Z45_Address);
Wire.write(address);
Wire.endTransmission(false);
Wire.requestFrom(BQ20Z45_Address,5+1,true);
Wire.read();
registerValue = Wire.read();
registerValue |= (Wire.read()<<8);
registerValue |= (Wire.read() << 16);
registerValue |= (Wire.read() << 24);
return registerValue;
}
Here is the scan of the communication between the Micro Controller <> Fuel Gauge. Iām reading Register 0x50 which returns 4+1 Bytes Hex.
Here is the Serial return:----
So all bits are set to 0-OFF. Lets see what the PC Software Says now.
Yea!!! Its correct!!!
Lets read from the same register 0x50 via the PC Software now and compare the communication.
On the Left is the communication via the uController and on the right is the PC Software communication.
Bingo! Identical!
Lets try that again!
Iām going to read register 0x51 SafetyStatus which returns 4+1 Bytes Hex just like the last read.
Here is the Serial Return:-----
Lets see if that lines up with the bit map in the PC software real quick:
Perfect
The communication is exactly the same:
///////////////////////////////////////////////////////////////////////////////
Now I changed the function Code to read a register that returns 2 Bytes +1 instead of 4 Bytes +1. After a few unsuccessful code changes and looking at the data communication logs I got it right.
uint16_t BQ20Z45::read16u2(uint8_t address)
{
uint16_t registerValue;
Wire.beginTransmission(BQ20Z45_Address);
Wire.write(address);
Wire.endTransmission(false);
Wire.requestFrom(BQ20Z45_Address,3+1,true);
Wire.read();
registerValue = Wire.read();
registerValue |= (Wire.read()<<8);;
return registerValue;
}
So now I can pull data from all the HEX registers also!!! :collision:
I couldnāt have done it without your help guys! Thank you very much.
I also now see how valuable the Saleae Logic 4 analyzer is when it comes to troubleshooting this type of communication. It really helps you understand whats going on in a way you can visualize.
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Now the next type of register type I need to read returns a string anywhere from 10 to 32 byes in size +1.
@pra Can you look over the code below that is a stripped down version of what @ScruffR threw together to try to help out awhile back for reading from the registers that return strings.
Most of it makes sense to me. Iām just having trouble understanding how to tie this function together with with the code that calls this function in the .ino & .h files.
Here is the code Iām working with to try to return string data from registers that return anywhere from 4+1 up to 32+1.
// pass a pointer to a char[] that can take up to 33 chars
// will return the length of the string received
int readString(uint8_t address, char* result)
{
int pos = 0;
int len;
Wire.beginTransmission(BQ20Z45_Address);
Wire.write(address);
Wire.endTransmission(false);
Wire.requestFrom(BQ20Z45_Address, 1, true);
len = Wire.read();
if (len > 0)
{
// then request the rest
Wire.requestFrom(BQ20Z45_Address, len, true);
for (pos = 0; pos < len; pos++)
result[pos] = Wire.read();
}
result[pos] = '\0'; // append the zero terminator
Here is the communication recording between the PC Software <> Fuel Gauge when reading register 0x20 ManufacturerName which returns 16+1 Bytes of ASCII data because the data in that register is: Texas Instruments . I guess this register could be holding up to 32 bytes + 1 which is why @ScruffR is telling me to "pass a pointer to a Char that can hold up to 33 bytes.
I need help understanding how to pass a pointer. I think I know what you want me to do but Iām not sure so Iāll ask those that know just to be sure.
Here is the string read
So I can see how the wire reads the bytes one by one unit it has read the amount of bytes the slave has told us it was holding and then it sends a NAK to end it all.
The code is really close to the other uint16_t , uint32_t block read functions except its getting the ālenā aka byte length variable filled by the data returned when the 1st byte is read. That all makes sense.
Iām not 100% sure how I should write the rest of the code that calls this function into action from the .ino & .h files. Iāll post code for a block read function to show you what that looks like which hopefully will provide the info you need to help me out. Iām sure itās really simple but over my head at the moment.
Here is how the library code is written now for the 4+1 Byte Hex read of the SafetyAlert Register 0x50:
.ino file code
// Include the Wire library for I2C access.
#include <Wire.h>
// BQ20Z45 library.
#include <BQ20Z45.h>
// Store an instance of the BQ20Z45 Sensor
BQ20Z45 bms;
void setup()
{
// We start the serial library to output our messages.
Serial.begin(115200);
// Start i2c communication.
Wire.begin();
}
void loop()
{
Serial.print("Safety Alerts: ");
Serial.println(bms.SafetyAlert(),HEX);
Serial.println();
delay(3000); // Show new results every second.
}
.h file code for this function
#ifndef BQ20Z45_h
#define BQ20Z45_h
#include <Wire.h>
#define BQ20Z45_Address 0x0B
#define BQ20Z45_SafetyAlert 0x50
class BQ20Z45
{
public:
uint32_t SafetyAlert(void);
protected:
private:
void write(uint8_t,uint8_t);
uint8_t read(uint8_t);
uint16_t read16u(uint8_t);
int16_t read16(uint8_t);
uint32_t read32u(uint8_t);
uint16_t read16u2(uint8_t);
};
#endif
Here is the .cpp file code for this function:
#include "BQ20Z45.h"
#include "Arduino.h"
uint32_t BQ20Z45::read32u(uint8_t address)
{
uint32_t registerValue;
Wire.beginTransmission(BQ20Z45_Address);
Wire.write(address);
Wire.endTransmission(false);
Wire.requestFrom(BQ20Z45_Address,5+1,true);
Wire.read();
registerValue = Wire.read();
registerValue |= (Wire.read()<<8);
registerValue |= (Wire.read() << 16);
registerValue |= (Wire.read() << 24);
return registerValue;
}
uint32_t BQ20Z45::SafetyAlert()
{
return read32u(BQ20Z45_SafetyAlert);
}
Iām not sure what or how to properly change the variable to Char so the string function properly returns all the received data and no junk data.
Its 5:21 AM now, gotta get some sleep
Happy New Year Everybody!!