-
-
Notifications
You must be signed in to change notification settings - Fork 5.4k
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 ICM20948 accelerometer #6756
base: master
Are you sure you want to change the base?
Conversation
Thank you for submitting a PR, please be aware that you need to sign off to accept the developer certificate of origin, please see point 3 in https://github.com/Klipper3d/klipper/blob/master/docs/CONTRIBUTING.md#what-to-expect-in-a-review Thanks |
Sign-off added |
We can certainly add support for a new accelerometer, but it should be done by refactoring the existing mpu9250 code, not duplicating it. (Or, if no code changes are needed, by updating the documentation to indicate that the icm20948 is supported by the mpu9250 config.) Thanks, |
1170904
to
a78b650
Compare
Hi @KevinOConnor, Thanks for taking a look at the PR.
Around 90% of the register addresses and values are different, so ICM20948 is not supported by the MPU9250 config. The sample frequency is also different: 4.5 kHz instead of 4 kHz.
There are two ways this could be addressed on the front-end:
The branch as of 020f250 does work, at least for the ICM20948. I don't have an MPU9250 to test. The data are here: In the spirit of not copy-pasting, I took a poke at Option A: a78b650 However, something is lacking in my understanding of how I2C is accessed through klipper. It doesn't work. I'll concede that I'm stuck.
|
Ah, I thought your earlier comment was indicating that this chip was mostly compatible with the mpu9250. If they are totally different chips with different protocols then it would not make sense to use the same code for both. Cheers, |
I see - I should have been more precise! It was a copy paste but one followed by quite a few breaking changes. I'd agree that the incompatibility justifies a new file.
|
@phansel you might want to take a look at my recent changes in #6715 - the situation is similar there. There is a lot of difference between the registers of these chips, but many of the functions are similar or the same... I am not sure if it is truly desirable to try to consolidate the code in this case, but is probably doable? |
@Wulfsta Thanks for the comments! In the specific case of the ICM20948 vs. MPUxxxx, the max sample rate isn't even the same, so a few sequence-dependent components of the init are broken by having to probe the I2C to identify the device. To make matters worse, the DEVICE_ID register doesn't even have the same address. Someone more familiar with the klipper codebase could probably figure that first issue out, but the net savings are only a few hundred lines of Python. Since these drivers generally will only be used once or twice, and there are only so many accelerometers, I generally prefer to keep them in separate files to (a) reduce risk of breaking behavior of Chip A by modifying Chip B's driver and (b) improve readability. A bunch of switches in the middle of the driver can be quite confusing, e.g. gpio-pca953x.c. It's ultimately up to the owners of the repo. I'm happy to help but don't have access to an MPU9250 for regression testing and don't have unlimited time to figure out how klippy/extras/bus.py works. |
The only reason I see to consolidate these is if we are concerned about binary size (irrelevant to the Python side, of course) - which should not be an issue anyways, since there is a mechanism in place to optionally include sensors for chips that are sensitive to this. As I said, I am not sure it is desirable to consolidate in this case, I just wanted to provide another resource to consider. 🙂 |
4f2c65d
to
f9dcf11
Compare
@KevinOConnor I've updated this PR to match the new CONFIG_WANT_[sensor] format. |
Thank you for your contribution to Klipper. Unfortunately, a reviewer has not assigned themselves to this GitHub Pull Request. All Pull Requests are reviewed before merging, and a reviewer will need to volunteer. Further information is available at: https://www.klipper3d.org/CONTRIBUTING.html There are some steps that you can take now:
Unfortunately, if a reviewer does not assign themselves to this GitHub Pull Request then it will be automatically closed. If this happens, then it is a good idea to move further discussion to the Klipper Discourse server. Reviewers can reach out on that forum to let you know if they are interested and when they are available. Best regards, PS: I'm just an automated script, not a human being. |
self.set_reg(REG_PWR_MGMT_1, SET_PWR_MGMT_1_WAKE) | ||
self.set_reg(REG_PWR_MGMT_2, SET_PWR_MGMT_2_ACCEL_ON) | ||
# Add 20ms pause for accelerometer chip wake up | ||
self.read_reg(REG_DEVID) # Dummy read to ensure queues flushed |
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.
there are i2c_write_wait_ack
which can be used above
Which ensures that that request is acknowledged by the device
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'll swap that in. Thanks for the suggestion @nefelim4ag
systime = self.printer.get_reactor().monotonic() | ||
next_time = self.mcu.estimated_print_time(systime) + 0.020 | ||
self.set_reg(REG_ACCEL_SMPLRT_DIV1, SAMPLE_RATE_DIVS[self.data_rate]) | ||
self.set_reg(REG_ACCEL_SMPLRT_DIV2, SAMPLE_RATE_DIVS[self.data_rate], |
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.
Those will reorder writes, cause your next set_reg will execute with minclock=0
BTW, you should be able to just write 2 bytes at address of DIV1
Same for power management
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.
This is ultimately duplicated from klippy/extras/mpu9250.py. I can change icm20948.py to import functions from there where they're unchanged.
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.
Yes, I already found that, but this is your code now :D
I just suggest you not mindlessly copy things
minclock=0/reqclock=0 is the default behavior anyway
With wait_ack() you can just add a pause there, before write, or order other writes by minclock
If you merge coupled registers write, that will also make things cleaner, like:
SAMPLE_RATE_DIVS = { 4500: [0x00, 0x0] }
i2c_write_wait_ack([REG_ACCEL_SMPLRT_DIV1] + SAMPLE_RATE_DIVS[self.data_rate])
# or
set_reg(REG_ACCEL_SMPLRT_DIV1, SAMPLE_RATE_DIVS[self.data_rate])
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.
According to the datasheet, there is a 20ms delay between the chip wake and accelerometer ready (how ready, what does it mean?) but looks like all registers can be just written
default_addr=ICM20948_ADDR, | ||
default_speed=400000) | ||
self.mcu = mcu = self.i2c.get_mcu() | ||
self.oid = oid = mcu.create_oid() |
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.
oid
is not used anywhere
By popular request, adding support for the non-obsolete ICM20948 accelerometer by porting the MPU9250 codebase. There are several register changes which obstruct integration with the MPU9250 driver, e.g. automatically detecting that a chip is ICM20948 before initializing it.
Seems to work with an RP2040 Pico:
I'm not sure if these values are scaled correctly. Are they?
Signed-off-by: Paul Hansel [email protected]