Closed nbigaouette closed 3 years ago
I've pushed the code to a new repo, might be clearer than out of context snippets above.
See https://github.com/nbigaouette/robot-car/blob/343b89bc397dc99761de583d744ebe8d/rust/spot/src/main.rs
Hi and thanks for testing this on AVR!
If my parsing of the output from IRrecvDump correctly it seems to be standard NEC, so Infrared should be able to handle it. And as it looks like both command and repeats are recognized, but the data is incorrectly parsed. Weird.
My initial guess was that the avr-hal's delay_us()
were to inaccurate (sometimes they only guarantee that they will delay for at least that amount of time), but as the Headers for the command for both Repat and Command are recognized, that seems to be ok.
My second guess is that Infrared's tolerances is too tight, but then again, then you wouldn't have gotten a Ok(Some(cmd)) response from poll()
.
So it could be a bug in Infrared, I'm gonna write some test code with the data you posted and see if I can figure out what is going on.
Fantastic! Thanks for your help 👍
I'm attaching all the IR codes of my remote I've dumped from IRrecvDump. In the file, I've put the button I've pressed to get the dumped value. For example:
Left
Decoded NEC: FD9867 (32 bits)
Raw (68): 4142 9000 -4400 600 -550 600 -550 550 -550 600 -550 550 -550 550 -600 550 -550 550 -600 550 -1600 600 -1650 550 -1650 600 -1600 600 -1650 550 -1650 600 -550 550 -1650 600 -1650 550 -550 550 -600 550 -1650 550 -1650 550 -600 550 -550 550 -600 550 -550 550 -1650 600 -1650 550 -550 550 -600 550 -1650 550 -1650 550 -1700 550
is the output I got when pressing the Left
button on the remote. The following two lines are the output of IRrecvDump.
ir_codes.txt. The file is also on github.
Hopefully that should help you out...
Thanks again!
If I look at the IR receiver initialization from the original C++ code: https://github.com/nbigaouette/robot-car/blob/343b89bc397dc99761de583d744ebe8d47dfd135/initial_code/sdk/Smart%20robot%20car%20comprehensive_Experiment/Comprehensive_Experiment/IRremote.cpp#L272-L294 there some interrupt and timers initialization... Should I be setting those too in my Rust code? Or is infrared supposed to be initializing things by itself?
I did a quick test with the data you posted above and in the text file, and Infrared seems to parse it just right - https://gist.github.com/jkristell/4abf47e36a789c1be05ae579be71dd6b
So it's probably some kind of timing problem, with running the code in the main loop. Could you try the next-branch of Infrared? That should work better with the AVR as I removed some costly operations in the hot path.
Setting up the interrupt and calling poll()
from a periodic interrupt is probably the way to go. Unfortunately timers in AVR-hal is not that great :).
As a side note: I started a project where I tried to get an AVR based remote control up and running with Infrared as the IR driver. https://github.com/jkristell/rustyremote
But the project stalled when I needed to setup a timer and realized there was no infrastructe in avr-hal to do it. My plan was to get back to it and at least implement my own timer that I could use in the project.
Example of using the "next" branch:
https://github.com/jkristell/infrared-examples/blob/infrared-r0.11/stm32f103-bluepill/Cargo.toml
Don't forget to change the infrared version in dependency list.
After consulting with an expert friend, using a sleep is not ok to do what I wanted to do. I needed to go down the interrupt route.
After some head scratching (and some help from https://github.com/Rahix/avr-hal/blob/bfc950428919af96030e66e9b44af2b4574a1ec1/boards/arduino-uno/examples/uno-millis.rs) I came up with this: https://github.com/nbigaouette/robot-car/blob/343560dbacca67d643a6cb6c17ad5eaf/rust/spot/src/main.rs
Now it "seems" to work.
With the code above, I get the following output when I press the buttons one after the other (1, 2, 3, 4, 5, 6, 7, 8, 9, *, 0, #, Up, Left, Ok, Right, Down):
Initializing Arduino Uno...
6 161 true
6 161 true
134 161 true
78 161 true
134 161 true
78 161 true
54 161 true
78 161 true
38 161 true
46 161 true
78 161 true
54 161 true
54 161 true
30 161 true
38 161 true
30 161 true
46 161 true
What surprised me (except that I get something! 😂 ) is that:
addr
value changes while the cmd
stays at 161.I'm not sure I can say that "it works" yet...
Hi
I bought an Arduino Uno to test this as well. The example code I wrote is here: https://github.com/jkristell/infrared-examples/blob/add-arduino-example/arduino_uno/src/main.rs
And I get the same error as you. The reason for the weird result is that Infrared successfully parse some bits in the command, then fails because of some timing issue, but, the bits are saved in the bitbuf and returned as a command when Infrared sees the repeat code, on the next button press.
So this is a Infrared bug (the bitbuf should be cleared on error), but a bug that at least helps us to understand what's happening.
I am gonna add some infrastructure to Infrared to do capturing of the pulses, and do offline print/debug of them, that should help figuring out why this fails.
Another thing I found. Rc5 works fine, but none of the other protocols :)
Another live update. If I only do capture on the pin and print the data "offline", after the receive, the data looks Ok.
But if i then create a BufferReceiver
and try to parse the buffer, it fails too. I think this indicates some problem with the AVR Rustc AVR backend, I'm gonna try changing all internal u32 types to usize/u16 and see what happens.
My suspicion is that my use of Range
somehow creates this problem.
Wow thanks for your investigation!! I do hope it's not the AVR backend, as that's quite deep in the stack :S
Please let me know of your investigation!
Thanks again ;)
Ok, so a small update.
If I just capture the pulses in the interrupt and do the decoding in the main-loop, it seems to work on my hacked up version.
I could try to polish up this and create a example for you to use. Not ideal, but a solution :).
That'd be great!
Possible related: https://github.com/rust-lang/rust/issues/82242
I finally found the problem. It was the shift of the u32 as described in the rust-lang bug. And that was the reason rc5 worked the whole time, but not the other protocols, as Rc5 used u16 internally to save the received data.
I have created a branch https://github.com/jkristell/infrared/tree/avr with a hacky version that supports Nec (only the standard variant) as well as Rc5 and Rc6.
Example on how to use it can be found here: https://github.com/jkristell/infrared-examples/tree/add-arduino-example/arduino_uno
Hi! Thanks for this crate. I am new to embedded rust and thus bought this kit: https://www.amazon.ca/-/fr/gp/product/B07CVS1LBT
It's an Arduino Uno controlling the car. While the original C code is fully functional, I want to write my own Rust firmware.
My first step is to read infrared commands from the remote but I am having issues. I struggled to even get something since your example uses a bluepill instead of an arduino so I am trying to understand how the infrared receiver works. The
avr-hal
crate I am using (https://github.com/Rahix/avr-hal) does not seems to be handle interupts which you example uses...It seems that the
PeriodicReceiver::new()
's sample rate must match the delay between two successive calls topoll()
. So for a 20kHz rate, I need toarduino_uno::delay_us(50);
in my loop (1 / 20kHz = 50 mus):If I change the delay by 1 mus,
poll()
returns anErr
... Is that expected?Using the arduino's "IRremote" library's IRrecvDump example I see the following in the serial console when I press the button "1" of the remote:
From this I understand the protocol is NEC. I thus define my receiver as:
I tried both Nec and NecDebug: The
cmd
+addr
andbits
are always 0. :(The
NecDebug::repeat
does seems to work though; a short press gives me false while a long press gives true.Am I missing something obvious?
Thanks a lot!!