Skip to content
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

fixed length PWM #94

Open
PsychicNoodles opened this issue Aug 20, 2021 · 5 comments
Open

fixed length PWM #94

PsychicNoodles opened this issue Aug 20, 2021 · 5 comments

Comments

@PsychicNoodles
Copy link

PsychicNoodles commented Aug 20, 2021

This is about an issue that I've encountered while working on my first project involving GPIO and PWM, so apologies if the terminology is a bit off. I'm currently trying to implement an air conditioner IR remote and wanted to use set_pwm on an OutputPin, but unfortunately there doesn't seem to be a way to specify the number of pulses and precisely interject with extended spaces (which as far as I can tell is a necessary technique). Is there a specific reason why the current implementation can only loop infinitely until given another input, or is it just a feature that hasn't been added yet?
(the hardware PWM seems a bit harder to manipulate like that, but at least the software PWM should be able to?)

@golemparts
Copy link
Owner

Thanks for opening this issue. Basically, the hardware PWM exposes all functionality available through the underlying linux PWM driver in a user-friendly way. The software PWM tries to copy that interface as much as possible. Unfortunately, neither implementation offers anything that specifically fits your needs.

While a complete IR remote implementation would be out of scope for RPPAL, being able to pulse a specific number of times should make it a lot easier to use RPPAL in this specific use-case, so I'll add that as a ToDo for a future release. Until then, you have a few options. Toggling pins in RPPAL is relatively fast compared to other GPIO libraries, so you could try manually implementing the correct protocol and see if the results are accurate enough. However, any software-based implementation is inherently inaccurate on a multi-threaded OS due to scheduling/preemption. Alternatively, you could look into something like LIRC (Linux Infrared Remote Control). I haven't used it myself, but apparently it's an easy way to implement IR remotes in Raspberry Pi OS.

@golemparts
Copy link
Owner

Another option would be to (ab)use the hardware PWM and have it pulse the correct number of times, disable it, sleep, send the next set of pulses by reconfiguring PWM, etc.

@PsychicNoodles
Copy link
Author

The Linux PWM driver certainly seems low level, and I can understand wanting to keep the software PWM as close to that as possible. I had some free time yesterday so I whipped together a modified version of the current software PWM that accepts an iterator of waves so that you can have both a fixed output like I want as well as a repeating signal like it is now. It's probably still a bit rough, and if it were to be included in the main branch it may make more sense to split it off into a separate software PWM module, but it worked in my tests and keeps the time sensitive work in its tight loop. If you'd rather not include it, at least this might be a useful reference for anyone else with a similar issue.

https://github.com/PsychicNoodles/rppal

@golemparts
Copy link
Owner

Thanks for providing a link to your changes! I'm currently of two minds on including this in the base crate. On the one hand, it's great being able to offer support for IR remote control protocols and similar use-cases that require PWM sequences. On the other, it goes a bit beyond basic peripheral support and leans more towards a specific implementation, and as you pointed out, expanding the software PWM code this much would fit better in a separate module. I did notice some other libraries, namely pigpio, offer similar functionality though.

In either case I think it makes sense to at least provide the bare minimum to implement something like this. Since the current API wouldn't help you in this case, I plan to split off the busywait/sleep code currently used by softpwm into its own function in a public utilities module (since it's also needed for embedded-hal's Delay trait implementation, and might be useful elsewhere), and add something like a blocking pulse method, similar to the existing softpwm methods but with an additional parameter to specify how many times a cycle should be repeated. Combined with the relatively accurate busywait/sleep method, that would allow the manual implementation of a PWM sequence. It might also be an interesting idea for an external crate.

Either way, I'll keep this issue open until this has been addressed, and will keep you updated if adding your implementation ends up being the right way forward.

@PsychicNoodles
Copy link
Author

Thanks for the follow up! Looking forward to however you decide to implement this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Feature requests
  
Awaiting triage
Development

No branches or pull requests

2 participants