IRMP-org / IRMP

Infrared Multi Protocol Decoder
GNU General Public License v3.0
267 stars 43 forks source link

Not all pins working on Arduino Nano (dynamic sending pins) #38

Closed dennisfrett closed 3 years ago

dennisfrett commented 3 years ago

Bug Report

Arduino Platform

IDE

IR-Protocol

Example to reproduce the issue

Pin(s) used for IR-receive, if not default

Version

Current behavior

In my project I noticed some IR leds were not detected well by receivers. I created a test project where I loop over D2 - D12 on my Arduino Nano and send some predefined NEC code on it. On the pins themselves I just attach a logic analyzer to test. In the logic analyzer I use an IR NEC decoder to verify what is sent.

This is the code I use:

...
constexpr IRMP_DATA irData= {IRMP_NEC_PROTOCOL, 0xFF00, 0x7};

void loop() {
  for (int pin = 0; pin <= 12; pin++) {
    irsnd_init(pin);
    irsnd_send_data(&irData, true);
    irsnd_data_print(&Serial, &irData);
    delay(100);
  }
...

I notice that for some pins I get the correct output, for other pins I get invalid output. The pins that work are: D2, D4, D8 and D12.

For the other pins I get different behavior, for some pins it just detects part of the protocol: the AGC pulse and the long pause, but nothing else. For other pins parts of the code seem to be messed up. For other pins nothing can be decoded.

The behavior seems consistent: for the 'working' pins it always works, for the failing pins it always fails. The IR pulses seem "right enough" to be picked up by a receiver sometimes though.

I've flashed the same code to a second Arduino Nano board to verify and get the same result.

ArminJo commented 3 years ago

Thanks for reporting (the copy/paste programming bug, I have to confess). 🥇 I did not set the pin to output, I used a constant as pin number in line 49 in irsndArduinoExt.cpp.h.

Maybe you can test it again and report? Thank you very much Armin

dennisfrett commented 3 years ago

Sadly this does not fix the issue for me. I also tried manually setting the pin mode to output, but to no avail. I have attached the Sigrok Pulseview file here: irmp_pin_issue.zip, this contains output for pins D2 to D5.

From the NEC decoding you can see that only pin D2 and D4 are correctly recognized. D1 doesn't get recognized at all and D5 is all 1s (recognized wrong).

Could there be something off with the timing on the different pins? I don't know how to easily compare pulses in Pulseview, but if we could see the difference between the raw pulses between a failing output and a working output, it might be more clear what is going on.

ArminJo commented 3 years ago
void setup(){
    irsnd_data.protocol = IRMP_NEC_PROTOCOL;
    irsnd_data.address = 0x0707;
    irsnd_data.command = 0x23;
    irsnd_data.flags = 1; // repeat frame 1 time
}
void loop(){
    for (int pin = 2; pin <= 12; pin++)    {
        irsnd_init(pin);
        irsnd_send_data(&irsnd_data, true);
        irsnd_data_print(&Serial, &irsnd_data);
        delay(100);
    }
}

works like a charm!

dennisfrett commented 3 years ago

The complete code I'm using now to verify is:

#include <Arduino.h>

#define IRMP_IRSND_ALLOW_DYNAMIC_PINS

#include <irsndSelectAllProtocols.h>

#include <irsnd.c.h>

IRMP_DATA irsnd_data;

void setup() {
  irsnd_data.protocol = IRMP_NEC_PROTOCOL;
  irsnd_data.address = 0x00FF;
  irsnd_data.command = 0x23;
  irsnd_data.flags = 0;
}
void loop() {
  irsnd_init(3);
  irsnd_send_data(&irsnd_data, true);
  irsnd_data_print(&Serial, &irsnd_data);
  delay(100);
}

This sends on pin 3 always. It seems this pin just gives very unstable results, as you can see in the screenshot failing

The results with the green bar at the bottom are correct, the rest are not.

It seems that around 1/10 to 1/5 pulses on pin 3 are failing randomly. When I run the same test with pin 2 or 4 they are all consistently correct.

Verified on an Arduino Uno and an Arduino Nano

dennisfrett commented 3 years ago

I've went back and rechecked lots of pins with this code, my current conclusion seems to be: PWM pins tend to be less stable. Does that make sense?

ArminJo commented 3 years ago

Is the signal taken at the arduino pins or at the receiver device? And what is your exact definition of failing? Do you have one sender circuit for all pins? Why do you send no repeat? I checked the example on my oscilloscope and all output signals are the same! Ther is no knowledge of PWM or other special functions for digital output!

dennisfrett commented 3 years ago

The signal is taken directly at the Arduino pins, there is no actual IR led / receiver involved in my test setup.

Do you have one sender circuit for all pins? What do you mean by this? Currently I just recompile for each pin, and connect only this pin to the analyzer.

"failing" here means the following: my devices sometimes don't pick up the IR code sent from my project, the logic analyzer is sometimes unable to decode the signal.

I'm sending no repeat just to test. I can verify if it makes a difference. Should it?

Even when it fails, the logic analyzer clearly shows a signal, and visually I cannot distinguish a failing sequence from a working one, but the devices don't pick it up and the analyzer can't decode it.

In the screenshot you can see an example of this, visually, both signals look identical, but only one is correctly decoded. failing

This is why it feels like the PWM pins might have slight timing variations that visually don't show up, but make make a difference in the actual signal.

Are you checking visually on your scope? Or can it decode NEC?

dennisfrett commented 3 years ago

I re-checked with flags set to 1, no difference. On the PWM pins I get signals, but sometimes they cannot be decoded.

dennisfrett commented 3 years ago

I've compared timings for "failed" signals with correct ones, it seems that some pulses are being sent too late. I don't know the details of the NEC protocol, but a working 0 gets encoded as a 565µs pulse and a 604µs pause. The failed 0s get detected as a 570µs pulse and a 612µs pause. (According to my logic analyzer)

According to the spec, the pulse and the pause (for 0) should take 562.5µs. Could it be that somehow they are taking a bit too long in general and the PWM pins add a slight delay (~13µs) causing the signal to become incorrect?

This is all using version 3.3.5 of the library. Weirdly, if I go back to 3.3.4, the failed signals sent on pin 3 occur much less frequently.