New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for IST8310 compass #12917
Conversation
Do you want to test this code? You can flash it directly from Betaflight Configurator:
WARNING: It may be unstable. Use only for testing! |
I did a try in the past #5397 but the i2c bus of Betaflight was not reliable in the timing. For inav I did similar code and it worked. |
Thanks @McGiverGim did not know. Also cannot test without hardware. |
I've some, I will try to test it but I will be out until monday. |
Confirmed, I've an IST8310 and an IST8308, but I need to do some soldering to test it. |
AUTOMERGE: (FAIL)
|
I've informed by Discord, but I think is good to have here the problems I've found. Maybe others can help here and not in Discord. |
With the latest changes it's going better. Now it's detected correctly. But it does not read any value from the mag (the values are always zero). |
Tested latest code. The mag is detected but again no values read. |
@McGiverGim IST8310 supports standard speed (100kHz) and fast speed (400Khz). Default we use a clock speed of 800Khz, please try:
We could also try getting axis data from their respective registers (having a low and high byte) |
I tested all the different i2c speed with your earlier code, without luck, but I will recheck it later. |
Strange. Using 100 and 400 clockspeed makes the MAG and the BARO not found. Pushing it at 800 again makes them found again. |
The return false, if I'm not wrong, is to say that there is not new data in the MAG variables. When returns true, is because there is new data. |
Yes. But it also means 'try again 1ms later'. You want IST8310_ODR_SINGLE just before returning true, so that MAG has enough time to prepare data (100ms) |
Some tests:
with the three states:
EDIT: I forgot that the problem is not the states, is that this version does not have the read without blocking.... |
Tested the current @haslinghuis version with the static fix, adding the PULSE_NORMAL (but it seems it does not affect) and the asynchronous buffer read and... IT WORKS!
I will do a review with the changes I have :) |
Done a tests using the async write too (we don't care about the result so I suppose it will be better) and it works too:
The times are far better... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some are optional, but with this seems to work and use very few times :)
switch (state) { | ||
default: | ||
case STATE_REQUEST_DATA: | ||
busReadRegisterBuffer(dev, IST8310_REG_DATA, buf, sizeof(buf)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Asyncrhonous
busReadRegisterBuffer(dev, IST8310_REG_DATA, buf, sizeof(buf)); | |
busReadRegisterBufferStart(dev, IST8310_REG_DATA, buf, sizeof(buf)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But code shall check that operation is finished before using received data
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose that the worst that can happen is that it will contain old data, that is the same that will happen if the data is not ready.
I don't know neither how to know if the read has finished. Do we have some method that gives this information?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Worst case is that there is race between I2C and data processing, mixing low and high byte from different measurements. Probability of this is very low ..
Sorry, my knowledge of I2C driver is very limited. Maybe grep code for busReadRegisterBufferStart and see how odher drivers handle it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Returns status from (drivers/stm32/bus_i2c_hal.c):
// Non-blocking read
bool i2cReadBuffer(I2CDevice device, uint8_t addr_, uint8_t reg_, uint8_t len, uint8_t* buf)
{
if (device == I2CINVALID || device >= I2CDEV_COUNT) {
return false;
}
I2C_HandleTypeDef *pHandle = &i2cDevice[device].handle;
if (!pHandle->Instance) {
return false;
}
HAL_StatusTypeDef status;
status = HAL_I2C_Mem_Read_IT(pHandle, addr_ << 1, reg_, I2C_MEMADD_SIZE_8BIT, buf, len);
if (status == HAL_BUSY) {
return false;
}
if (status != HAL_OK) {
return i2cHandleHardwareFailure(device);
}
return true;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe grep code for busReadRegisterBufferStart and see how odher drivers handle it
Other drivers seem to ignore it, when they use "Start" method. At least the QMC5883 that is very similar. I don't say that this is correct, but is what is being done at this moment.
@McGiverGim : Ideally implement nonblocking version. 2 states may do:
Some check shall make sure that receive is finished (1ms should be enough at 400kHz) and some state handling may be necessary to handle startup (no data received yet) |
39337d9
to
aed434a
Compare
switch (state) { | ||
default: | ||
case STATE_REQUEST_DATA: | ||
busReadRegisterBufferStart(dev, IST8310_REG_DATA, buf, sizeof(buf)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Problem is that this will fail if some other transaction is pending.
Maybe just :
busReadRegisterBufferStart(dev, IST8310_REG_DATA, buf, sizeof(buf)); | |
if (!busReadRegisterBufferStart(dev, IST8310_REG_DATA, buf, sizeof(buf))) return false; |
69ac8dc
to
3111694
Compare
@McGiverGim @ledvinap function |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested with the cloud build from the Configurator, and now it works, as is. It can go better, but now it works.
I have an IST8308 sample too, if you want to start again :P |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good enough. Someone shall look at asynchronous reads eventually, it may cause hard-to-catch bugs (for example, it will probably fail is DRDY interrupt is used and I2C collision occurs)
* Add support for IST8310 compass * fix read * Using states * Fixes after review
* Add support for IST8310 compass * fix read * Using states * Fixes after review
https://intofpv.com/attachment.php?aid=8104