Giter Club home page Giter Club logo

Comments (44)

dennisfrett avatar dennisfrett commented on August 13, 2024 1

@shmizan Here is a sample I've made to reproduce what I'm seeing.
This is meant to be an IR "relay" that just forwards what it's seeing. (My main project relies on this being possible to translate certain IR codes):

#include <Arduino.h>

#define IRSND_PROTOCOL_NAMES 1
#define IRMP_PROTOCOL_NAMES 1

#define USE_ONE_TIMER_FOR_IRMP_AND_IRSND
#define IRMP_IRSND_ALLOW_DYNAMIC_PINS
#define IRSND_IR_FREQUENCY 38000

// Only enable needed protocols.
#define IRMP_SUPPORT_NEC_PROTOCOL 1
#define IRSND_SUPPORT_NEC_PROTOCOL 1

#include <irmp.c.h>
#include <irsnd.c.h>

#define IR_RECEIVE_PIN 6
#define IR_SEND_PIN 8

IRMP_DATA irmp_data;

void setup()
{
    irmp_init(IR_RECEIVE_PIN);
    irsnd_init(IR_SEND_PIN);

    Serial.begin(115200);
    Serial.println("Starting");
}

void loop()
{
    if (irmp_get_data(&irmp_data)) {
        const bool isRepeat = irmp_data.flags & IRSND_REPETITION_MASK;

        if (isRepeat) {
            irmp_data.flags = IRSND_RAW_REPETITION_FRAME;
        }

        // irsnd_send_data(&irmp_data, false);
        // irsnd_send_data(&irmp_data, true);
        // irsnd_send_data(&irmp_data, !isRepeat);
        irsnd_send_data(&irmp_data, isRepeat);
    }
}

I've tried with allcombinations of irsnd_send_data(&irmp_data, X); but I'm always getting the following behavior:

result

So all the codes are forwarded, but the timing between the "main command" and the first repeat is wrong at transmit side. The receiver sees a 40ms delay between both (which matches the standard), but my sender has ~90ms delay. All the other repeats are correctly spaced.

@ArminJo Is there something obviously wrong that you see with my code?

from irmp.

dennisfrett avatar dennisfrett commented on August 13, 2024 1

I have debugged this further with the following code:

long lastTime = 0;
void loop()
{
    const auto loopStartTime = millis();

    if (irmp_get_data(&irmp_data)) {
        Serial.println("Time since last IR code seen: " + String(loopStartTime - lastTime));
        lastTime = millis();
    }
}

I pressed the button on the remote and held it down, and got the following output:

Time since last IR code seen: 3477
Time since last IR code seen: 51
Time since last IR code seen: 106
Time since last IR code seen: 107
Time since last IR code seen: 106
Time since last IR code seen: 106
Time since last IR code seen: 108
Time since last IR code seen: 107
Time since last IR code seen: 108
Time since last IR code seen: 107
Time since last IR code seen: 108

I checked the time of the loop if I only do the serial printing, and it doesn't seem to be relevant here.
It seems to me like it takes at least ~50ms for irmp_get_data to parse a new incoming IR code, which would explain why I am unable to get the send delay down to 40ms.

@ArminJo Would the correct usage here be to buffer the first IR command and see if it is immediately followed by a repeat? In that case I could probably just send with repeats set to 1, and then use the new flag to send all following repeats (~110ms delays). I've been trying this, but even if I send the first repeat together with the main code (just set flags to 1), the timing between the first repeat and the second repeat becomes too large.

I also don't really see a difference between sending with do_wait set to false or true.

from irmp.

ukw100 avatar ukw100 commented on August 13, 2024 1

I have found a solution to the problem. With the next version there is a new flag IRSND_SUPPRESS_TRAILER, which suppresses the longer pause after sending the data. This way you can send a repetition frame immediately afterwards. However, you then have to make the pause between the original frame and the repetition frame yourself.

The flag should only be set when sending the main frame.

Example:

irsnd_send_data(&irmp_data, IRSND_SUPPRESS_TRAILER);
delay (40);
irsnd_send_data(&irmp_data, IRSND_RAW_REPETITION_FRAME);
irsnd_send_data(&irmp_data, IRSND_RAW_REPETITION_FRAME);
...

I will send the necessary changes to Armin today so that he can issue a new version.

from irmp.

ArminJo avatar ArminJo commented on August 13, 2024

What is the reason for requiring a repeat directly? Is the repeat parameter (flags) not sufficient?

from irmp.

dennisfrett avatar dennisfrett commented on August 13, 2024

I'm building an IR repeater box, basically.
I want to be able to relay all incoming signals to the receiver in real time.
If I would use the flags, I would need to buffer the whole command (wait until the key was depressed, and count the number of repeats), and then relay that command.

What I actually want to do is: system detects 0x00FFAB as a NEC command, send it directly. System detects a repeat command, send it directly.

If I need to buffer all the repeats first, the system cannot react in real time.

Does that make sense?

from irmp.

ArminJo avatar ArminJo commented on August 13, 2024

What is the reason to not just use an amplifier for the incoming signal?
It has the advantage that it supports all protocols.

from irmp.

dennisfrett avatar dennisfrett commented on August 13, 2024

The project I have also needs to do "translation" and routing.
The issue I have is that I have multiple devices which have an overlap in the NEC codes that they react to. So I just map all the actions I want to 1 single remote, and my Arduino project translates it to the correct one and outputs it to the correct IR LED.

It all works very well, but now when I hold down a volume button, the receiving device just sees the same IR NEC command repeated instead of receiving actual repeat codes. This slows down the speed significant that it changes the volume.

So I can't get by with purely relaying the pulses. It needs to interpret the protocol first.

from irmp.

ArminJo avatar ArminJo commented on August 13, 2024

If you only have NEC, then look at https://github.com/Arduino-IRremote/Arduino-IRremote.
There is a dedicated void IRsend::sendNECRepeat() function.
Disable all other protocols.

from irmp.

dennisfrett avatar dennisfrett commented on August 13, 2024

I saw that library, but I currently need dynamic output pins (multiple IR LEDs), and this is not supported by that library. I also need to support the Samsung protocol.

from irmp.

dennisfrett avatar dennisfrett commented on August 13, 2024

@ArminJo I have not looked through the code base in a lot of detail. But is there a (private?) API available that just takes in the protocol and the signal to be sent? In that case it would be easy to add a new public API like sendNECRepeat, that just calls this with NEC and 0xFFFFFF.

from irmp.

ArminJo avatar ArminJo commented on August 13, 2024

@ukw100
You are the core developer, do you know if there is a workaround for direct sending a NEC repeat?

from irmp.

dennisfrett avatar dennisfrett commented on August 13, 2024

Any news on this @ukw100 , @ArminJo ?

from irmp.

ukw100 avatar ukw100 commented on August 13, 2024

It is not true that you have to wait until all the repeats have been sent. You are informed of every frame, namely the original frame (flag = 0) as well as every repetition (flag = 1) in realtime, not after the n'th repetition. You could send the NEC frame again for each repetition.

The implementation of a special function sendNECRepeat() breaks the general character of IRMP. At which special request should this end?

To make the request generally available, I could provide a general repeat function for IRSND. If this function gets the NEC protocol as parameter, it creates a repeat frame - in the other cases a normal frame. Then this would be solved in general.

from irmp.

dennisfrett avatar dennisfrett commented on August 13, 2024

Thanks for you reply!

It is not true that you have to wait until all the repeats have been sent. You are informed of every frame, namely the original frame (flag = 0) as well as every repetition (flag = 1) in realtime, not after the n'th repetition. You could send the NEC frame again for each repetition.

I understand how I can get the the information about how many repeats have been received.

However, I don't see how I can "forward" the repeats?

Could you give an example of this? If I, for example, receive a NEC command, and I see it's the first repetition.
At this moment I've already sent out the NEC command (from the first time I've seen it). What do I send out, now that I've detected the repeat? It would be incorrect to send the same NEC command with repeats set to 1, since then the receiving device will have received 2 NEC commands + 1 repeat (total of 3), instead of 2.

What am I missing here?

from irmp.

ukw100 avatar ukw100 commented on August 13, 2024

If you receive an IRMP frame with flags = 0x01 (better: if (irmp.flags & IRMP_FLAG_REPETITION)), you could resend this frame with flags = 0x00. So you convert a received repetition-frame into a normal NEC frame. For example a TV accepts a volume command (e.g. 1 NEC plus 3 repetitions) just like it accepts 4 NEC volume frames.

Therefore:
receceive NEC frame with flags = 0x00 -> send frame with flags = 0x00
receceive NEC frame with flags = 0x01 -> send frame with flags = 0x00

Then, for example, one NEC frame + 3 repetition frames simply becomes 4 NEC frames on the transmitter side. However, sending a complete NEC frame takes longer than sending an NEC repetition frame, so you may not be able to send all the repetitions received. You would have to try this out.

I have now decided to solve it as follows:

A. I define a new FLAG IRSND_FLAG_ONLY_REPETITION (0x10)

B. If you set this flag in irsnd_data.flags, only the repetition frame is sent if NEC - nothing else.

This means that the API does not have to be changed. IRSND only evaluates the lower 4 bits for repetitions anyway, the upper 4 bits are free for extensions. This change will then appear in the next release.

from irmp.

dennisfrett avatar dennisfrett commented on August 13, 2024

What you described is what I have now. Repeats are just converted to regular frames. The problem is that some devices interpret 5 NEC frames differently from 1 frame + 4 repeats.

Audio devices, will speed up volume increase / decrease when repeats are received vs regular frames.

I like the idea for the flag change! Looking forward to it, thanks.

from irmp.

ArminJo avatar ArminJo commented on August 13, 2024

I am reluctant to merge all changes from the original svn repository into the Arduino sources 😢.
It is too much effort for me now. I am not motivated any more to merge the same diffs repeatedly for every upstream change.
Sorry.

from irmp.

dennisfrett avatar dennisfrett commented on August 13, 2024

What original repository do you mean?
I will try later if I can just link against both IRMP and IRRemote at the same time without them interfering, then I can just use the repeat command from the latter, but use dynamic pins that IRMP offers.

from irmp.

ArminJo avatar ArminJo commented on August 13, 2024

Things are getting better 😀.
Today I am waiting for some minor changes upstream, then I will build a new release with the new functionality.

from irmp.

ArminJo avatar ArminJo commented on August 13, 2024

Changes are released.

from irmp.

dennisfrett avatar dennisfrett commented on August 13, 2024

Thanks! I'll give it a try later.

from irmp.

ntzb avatar ntzb commented on August 13, 2024

@dennisfrett did you manage to work it out?
I'm in the same situation but the added flag gets no response from my AVR.
on long pressing, the volume buttons were detected as:

P=NEC A=0x857A C=0x1A R
P=NEC A=0x857A C=0x1B R

so I tried to define:

avrVolP.protocol = IRMP_NEC_PROTOCOL;
avrVolP.address = 0x857A;
avrVolP.command = 0x1A;
avrVolP.flags = 0x10; <-- used the new flag

and send it in loop while the serial is not empty, but only after first sending with flags = 0.
the AVR didn't have any response to the repeat code sent with the 0x10.
what am I doing wrong?

from irmp.

dennisfrett avatar dennisfrett commented on August 13, 2024

I have not yet implemented it in my main project, but I set it up on a breadboard and measured the IR being sent with a logic analyser. The repeats get sent out correctly, but the timing is different from the NEC protocol.

Normally in NEC the main command gets sent out, and if the key is held down, after 40ms the repeat command is sent. Repeat is resent every 108ms.

The problem is that with the current implementation in this library, there is a larger gap between the main NEC command and the first repeat command. The other repeats are sent nicely with 108ms difference.

So if the receiver strictly implements NEC and ignores first repeats that come in way later than 40ms, this will not work.

I suspect that the reading of the IR command does not return fast enough to be able to send the first repeat in time.

@ArminJo Do you know by any chance if it's possible, when holding down the key on the remote, to have the first (non repeat) command completely handled and the repeat sent within 40ms?

from irmp.

ArminJo avatar ArminJo commented on August 13, 2024

UPDATED.
You must send the first command with irsnd_send_data(&irsnd_data, true); and wait 40ms or send it with irsnd_send_data(&irsnd_data, false); and wait 110ms.
Then you set the flag and send the repeat with irsnd_send_data(&irsnd_data, false); and wait 110ms, and so on...

from irmp.

ntzb avatar ntzb commented on August 13, 2024

that's what I was trying, but to no avail. I tried a very basic code:

avrVolP.flags = 0;
irsnd_send_data(&avrVolP, true);
avrVolP.flags = 0x10;
delay(40);
irsnd_send_data(&avrVolP, true);
delay(40);
irsnd_send_data(&avrVolP, true);
delay(40);
irsnd_send_data(&avrVolP, true);

avrVolP is the command I'm sending, with the same address and command as I wrote above, and flags = 0.
I only get the first volume change, then nothing.

@dennisfrett would you mind sharing your code as reference?

edit: not sure about the significance of this but using IRRemote, I got this info:

Protocol=NEC Address=0x7A Command=0x1B Raw-Data=0xE41B857A (32 bits) LSB first //first event
Protocol=NEC Address=0x7A Command=0x1B Repeat gap=28000us //first repeat
Protocol=NEC Address=0x7A Command=0x1B Repeat gap=17364us //next repeat
Protocol=NEC Address=0x7A Command=0x1B Repeat gap=17314us
Protocol=NEC Address=0x7A Command=0x1B Repeat gap=17364us

not quite sure what the repeat gap means for practical purposes

from irmp.

dennisfrett avatar dennisfrett commented on August 13, 2024

@ukw100 Thanks! Once that is in, I can create an Arduino example for a simple IR repeater that does the repeats correctly and create a pull request for it, if you want.

Might be a good starting point for others trying to do something similar.

from irmp.

ArminJo avatar ArminJo commented on August 13, 2024

@ukw100 the call with irsnd_send_data(x,false) does exactly the same as the flag IRSND_SUPPRESS_TRAILER!
We should decide if we do it via flag or call parameter.
If I could start from scratch, I would always skip the trailng space and provide the possibility to enable it with a call parameter.

from irmp.

ukw100 avatar ukw100 commented on August 13, 2024

@ArminJo did you overwrite irsnd_send_data()?
irsnd_send_data (&data, 0) always sends a trailer, but returns immediateley. If you overwote this function, I cannot accept this, because you make then this incomapatibe with the standard C version.

In the past, IRSND did not add a trailer, which caused various problems. That's why I added it a few years ago.

from irmp.

ArminJo avatar ArminJo commented on August 13, 2024

@ukw100 No I did not overwrite it! I only changed the behavior for Arduino not to wait for the trailing space if the last parameter was false, since this was not possible before!

from irmp.

ukw100 avatar ukw100 commented on August 13, 2024

@ArminJo the second parameter do_wait controls wether irsnd_send_data() returns immediately or if it waits until the complete frame incl. trailer has been sent. In the first case the application can do somethin other while the ISR is sending the frame (incl. trailer) in the background. Please do not change the previous behaviour. This will lead to incompatibilities and loss of certain features.

I have sent you the necessary changes by e-mail.

from irmp.

ArminJo avatar ArminJo commented on August 13, 2024

@dennisfrett
You can not use irsnd_send_data(&irmp_data, true); because its implementation is wrong if you send a repeat.
This is a global problem with the difference between gaps and period with codes with different code send times.
AFAIK NEC is specifies a period of 110 ms, but irsnd implements only one gap length, which is incompatible for codes having different code length. 😞

from irmp.

ukw100 avatar ukw100 commented on August 13, 2024

I wrote:

irsnd_send_data(&irmp_data, IRSND_SUPPRESS_TRAILER);
delay (40);
irsnd_send_data(&irmp_data, IRSND_RAW_REPETITION_FRAME);
irsnd_send_data(&irmp_data, IRSND_RAW_REPETITION_FRAME);
...

This is incorrect. I meant:

irmp_data.flags = IRSND_SUPPRESS_TRAILER;
irsnd_send_data(&irmp_data, 1);
delay (40);
irmp_data.flags = IRSND_RAW_REPETITION_FRAME;
irsnd_send_data(&irmp_data, 1);
irsnd_send_data(&irmp_data, 1);
...

Please excuse the misunderstanding.

from irmp.

ArminJo avatar ArminJo commented on August 13, 2024

irsnd_send_data(&irmp_data, 1);
irsnd_send_data(&irmp_data, 1);

This gives 40 ms gaps between the repeats, not resulting in 110 ms period 🙁

from irmp.

ukw100 avatar ukw100 commented on August 13, 2024

This gives 40 ms gaps between the repeats, not resulting in 110 ms period 🙁

Dennis uses IRMP & IRSND as an IR relais. IRSND sends out what IRMP gets.

Lets's suppose IRMP gets one NEC frame and two NEC repetition frames. These frames already have the correct time distance, so Dennis can immediately send them all without trailers:

irmp_data.flags = IRSND_SUPPRESS_TRAILER;
irsnd_send_data(&irmp_data, 1);
irmp_data.flags = IRSND_SUPPRESS_TRAILER | IRSND_RAW_REPETITION_FRAME;
irsnd_send_data(&irmp_data, 1);
irsnd_send_data(&irmp_data, 1);

Here we don't need to insert any delay calls, because we already get the frames with the correct time distance.

from irmp.

ArminJo avatar ArminJo commented on August 13, 2024

The solution is to look at the NEC timing https://www.sbprojects.net/knowledge/ir/nec.php and always send with false and do the delay manually to match the timing.
I.e. delay the first NEC repeat by 48 ms and all other repeats by 98 ms.

from irmp.

dennisfrett avatar dennisfrett commented on August 13, 2024

@ArminJo @ukw100 I am confused here. I am trying multiple different things.
As @ukw100 said, in principle I should not need to care about the timing, if I just relay the exact thing that comes in.
The sending device already ensures the timing is correct.

But even if I'm trying to manually send them:

void loop()
{
  irmp_data.protocol = IRMP_NEC_PROTOCOL;
  irmp_data.flags = IRSND_RAW_REPETITION_FRAME;
  irsnd_send_data(&irmp_data, false);
}

Then everything is spaced 40ms apart, but I would expect this to just not work, since I'm requesting irsnd_send_data to return immediately.

It seems like the sending and / or receiving functions have some delay in them somewhere and don't return immediately.

from irmp.

dennisfrett avatar dennisfrett commented on August 13, 2024

The reason why we can probably not just do an instant-relay of the incoming signal, is that the first repeat is received while the main command is being sent:
result

This means the first repeat is never received by the application, so the first repeat being sent is the second repeat received, and this will break the timing. (In the screen you see 6 repeats received, only 5 sent).

I guess the only way to do this is to buffer the main command for a short while to see if a repeat will come in, and then it can be sent right between the first and the second repeat come in.

from irmp.

dennisfrett avatar dennisfrett commented on August 13, 2024

It seems that irmp_get_data just returns true too slow now.
result

The first line is the received IR signal (from the IR receiver itself).
The second line is the sent signal (see code below).
The third line is the pulse that goes high whenever irmp_get_data returns true. (D9)

This code buffers the main command until one repeat is received.

IRMP_DATA main_cmd = {IRMP_NEC_PROTOCOL, 0xFF00, 0x40};
bool mainFrameSent = false;

...

void loop()
{
  if (irmp_get_data(&test)) {
      if(test.flags == 0){
        mainFrame = test;
        mainFrameSent = false;
        return;
      }

      digitalWrite(9, HIGH);
      if(mainFrameSent){
        irsnd_send_data(&repeat, false);
      } else {
        irsnd_send_data(&mainFrame, false);
        mainFrameSent = true;
      }
      digitalWrite(9, LOW);
  }
}

As you can see it takes much longer to get back into the irmp_get_data if-body after the main command was sent.

Is this expected?

from irmp.

ArminJo avatar ArminJo commented on August 13, 2024

As you can see it takes much longer to get back into the irmp_get_data if-body after the main command was sent.

No this was a bug! I just corrected it. Thanks for reporting 👍 .

from irmp.

dennisfrett avatar dennisfrett commented on August 13, 2024

@ArminJo I've tested latest master and I'm still seeing the same behavior. (I've made absolutely sure I'm using this version of the library).

Could it be that something else is causing the wait?

from irmp.

dennisfrett avatar dennisfrett commented on August 13, 2024

@ArminJo is this something that is being looked into? Can I help somehow to debug it? Or is it actually expected?

from irmp.

ArminJo avatar ArminJo commented on August 13, 2024

It is currently as designed, but not as required. I am going to change this behavior.
The current version 3.x of IRremote now supports variable output pins 😀 .

from irmp.

ArminJo avatar ArminJo commented on August 13, 2024

Ok I changed the behavior as promised. No wait after send any more 😀 .

from irmp.

ntzb avatar ntzb commented on August 13, 2024

@ArminJo Hi,
I still think there's an issue with IRMP regarding the waiting and NEC repeat.
I tried with and without waiting, but the timing has these problems:

  1. not consistent. with one Arduino (IRMP) sending, and another (IRMP) receiving, I see that most command are sent in a similar delay (not identical), but some commands are send after 20ms, or after 180ms...
  2. cannot get delay of less than 45ms between the FIRST command and the next (first repeat) command.

e.g. running this (test) code:

IRMP_DATA avrVolP;

avrVolP.protocol = IRMP_NEC_PROTOCOL;
avrVolP.address = 0x857A;
avrVolP.command = 0x1A;

IRMP_DATA avrRepeat;

avrRepeat.protocol = IRMP_NEC_PROTOCOL;
avrRepeat.address = 0x857A;
avrRepeat.command = 0x0;
avrRepeat.flags = IRSND_RAW_REPETITION_FRAME;

irsnd_send_data(&avrVolP, false);
delay(48);
irsnd_send_data(&avrRepeat, false);
delay(98);
irsnd_send_data(&avrRepeat, false);
delay(98);
irsnd_send_data(&avrRepeat, false);
delay(98);
irsnd_send_data(&avrRepeat, false);
delay(98);

does not work, not matter how much I play with the timing (40 <= t1 <=48 or 95 <= t2 <= 105, or the waiting (true/false).

on the other hand, it works on the first try on IRremote with this (practical) code:

IrSender.sendNEC(avrVolP.address, avrVolP.command, 0);
delay(40);
while (Serial.read() != -1) {
  IrSender.sendNECRepeat();
  delay(98);
}

since I have a working solution on IRremote, I switched to that, but I thought I should update on this, in case anyone is interested.

from irmp.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.