I am working on a motorized rewinder system driven where the motors are driven by SX1509 and some motor drivers.
Currently my approach works ok and the rewinder operation has been quite reliable.
My concern right now is that the PWM pin feature in sx1509.py does not implement the klipper’s MCU PWM pin’s shutdown behavior — i.e., the default_value in the config_pwm_out command. Therefore, if hypothetically my printer goes into shutdown during a rewind operation, the motor will stay running until the next power cycle or klipper reconnection — I would like to change that.
Could someone shed some light on:
Will an I2C shutdown feature be of interest to people?
Is it possible to implement it without changing the low level MCU code? I think not, but checking to make sure
I know DECL_SHUTDOWN can be used to setup a shutdown behavior for I2Cs. But, given that I2C devices vary in nature, what would be a good general interface for setting up the shutdown behavior? My current idea is to store a list of <oids, data> pairs to write to the I2C interface during shutdown. Any suggestions?
Please let me know what you think? If this looks promising at all, I will move on to do work on sx1509.py to properly support the default_value config entry, for both digital and pwm pins.
It’s possible to add support for shutdowns on pins controlled from i2c devices, but it can be a challenge to implement it correctly. For reference, you can look at the similar support in src/linux/pca9685.c (which is for an SPI device).
For what it is worth, in many cases a low-cost micro-controller is of a similar price to a GPIO expander chip. So, in the last few years, most people have just deployed a micro-controller. That has the advantage of requiring no new code, high precision timing, and better test coverage.
Thank you for your inputs! I looked into the linux/pca9685.c code and they look understandable ---- only I’m not sure if the PWM support from the C code level (as in linux/pca9685.c) is necessary for my purpose. The host module sx1509.py already satisfies my needs fairly well, and my approach seems to work so far.
Since you said it would be a challenge, here are some potential issues that I can think of and my thoughts:
The command queue can contain I2C commands that might be executed after the shutdown handler? — I looked into sched.c and don’t think this could be the case, but just checking to make sure?
Shutdown needs to clean up the data structures (a singly linked list in my code) to avoid memory leak? — I think the next reset will call alloc_init that clears up the memory
Any other thoughts? Would you like me to send a PR with my current approach?
most people have just deployed a micro-controller.
Yes, I’ve considered that as well. But I opted for SX1509 because I saw klipper supported it. Plus, using a microcontroller is a tad bit less scalable IMO — I would probably need to require anyone who wants to use my rewinder system with more than eight-ish lanes to use a USB hub or setup CAN, whereas the boards we use for our MMU already come with spare I2C pins and we can daisy chain SX1509s easily.
I also don’t need any precision timing in my case.
A big challenge is handling a shutdown that occurs while in the middle of an existing i2c transfer. Two big risks in that case: 1 - the i2c command to turn off pins may fail and lead to an infinite shutdown loop (thus not actually turning off heaters), or 2 - the shutdown i2c commands aren’t sent in that case (thus some pins not actually turned off during shutdown). It’s also very difficult to effectively test for these types of “race conditions”, so hard to have confidence that they are handled correctly.