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

Frequency accuracy #32

Open
waj opened this issue Jul 3, 2017 · 13 comments
Open

Frequency accuracy #32

waj opened this issue Jul 3, 2017 · 13 comments

Comments

@waj
Copy link

waj commented Jul 3, 2017

I was looking for a library to control my AC from an ESP8266 and this one worked on the first try. Thank you for this! (I have a Carrier compatible AC)

However, I noticed that with this library I have to point my IR led directly to the AC, otherwise the signal was ignored. I would have assumed I didn't have enough power in my circuit but I noticed something strange: while trying another library (https://github.com/markszabo/IRremoteESP8266) and sending raw codes, even though I couldn't get my AC to work properly, the AC was beeping even with my IR led pointing somewhere else.

So I did a little research and it seems that library makes a better effort with the accuracy of the signal frequency. The authors improved that some time ago to take into account rounding and the time the instructions affects the carrier periods: crankyoldgit/IRremoteESP8266@178b09d

I tested then your library but using a new implementation of the IRSender that forwards the calls to mark and space to the IRremoteESP8266 implementation:

class IRsendSender : public IRSender {
public:
  IRsendSender(uint8_t pin);
  void setFrequency(int frequency);
  void space(int spaceLength);
  void mark(int markLength);

private:
  IRsend ir;
};

IRsendSender::IRsendSender(uint8_t pin) : IRSender(pin), ir(pin) {
  ir.begin();
}

void IRsendSender::setFrequency(int frequency) {
  ir.enableIROut(frequency);
}

void IRsendSender::space(int spaceLength) {
  ir.space(spaceLength);
}

void IRsendSender::mark(int markLength) {
  ir.mark(markLength);
}

And the result was amazing :-). I was able to control my AC without having to point my IR led directly.

So, I wonder what's the best approach to improve this in your library as well. Should be shamelessly copy the implementation from IRremoteESP8266?. Should we include the wrapper I just created in your library instead?

@ToniA
Copy link
Owner

ToniA commented Jul 3, 2017

Thanks, this sounds really promising :) I've been struggling with the poor range, and haven't really had an idea why it was so poor. Seems like integrating with IRremoteESP8266 would not be that hard, but this of course brings in a dependency into another library.

@moskovskiy82
Copy link

Is it only working on esp8266? Or arduino will also be affected?

@ToniA
Copy link
Owner

ToniA commented Jul 30, 2017

I think the accuracy was poor only on ESP8266. On Arduino you are much closer to the 'bare metal'

@Muhamed-Reyad
Copy link

Hi
im a total noby and i tried replacing the default implementation with the one from IRremoteESP8266 but i kept having all kinds of compilation errors.

Can any of you guys please attach their edited versions of the IRSender.h and IRSender.cpp ( im assuming those are the ones in question)
any help would be much appreciated
thnx

@arion-p
Copy link

arion-p commented Jul 5, 2018

Hi,
What is the status of this issue?
I see that there was some implementation in dev branch but it was never merged to master. Is the dev branch working? will this be abandoned or will it eventually make it to master?

My Mitsubishi FD seems to be very sensitive to the exact frequency of the signal (apparently uses a very steep band pass filter to eliminate interference), so I would like to try this fix.

@ToniA
Copy link
Owner

ToniA commented Jul 6, 2018

I merged in the IRRemoteESP8266 change from the 'dev' branch, let me know if it works better.

@arion-p
Copy link

arion-p commented Jul 6, 2018

Thank you for your immediate response.

Unfortunately I cannot test in my current project (ESPEasy + P115) as the current version of IRRemoteESP8266 (v2.42) is incompatible with the one used in ESPEasy (patched 1.2.0).

I will have to create a test project and try that, but it will take me some time.

@ToniA
Copy link
Owner

ToniA commented Jul 9, 2018

Today I took the latest ESPEasy from the 'mega' branch, added src/_P115_HeatpumpIR.ino from the ESPEasy playground, added the latest HeatpumpIR into lib/HeatpumpIR and tried to compile (it didn't). The version of IRRemoteESP8266 is really old, so I needed to apply this change to HeatpumpIR library:

diff --git a/IRSender.h b/IRSender.h
index a6bb13c..756d654 100644
--- a/IRSender.h
+++ b/IRSender.h
@@ -7,7 +7,7 @@
 #include <Arduino.h>

 #ifdef ESP8266
-#include <IRsend.h>  // From IRremoteESP8266 library
+#include <IRremoteESP8266.h>  // From IRremoteESP8266 library
 #endif

 class IRSender

After this change the ESPEasy compiles, but it still uses the 'bitbang' method for PWM. If you change line 94 on the plugin code to this:

Plugin_115_irSender = new IRSenderIRremoteESP8266(irPin);

... it should use the IRremoteESP8266 PWM implementation. I didn't try with a real heatpump device, but at least my red led is blinking, so there's a very good chance this might work.

@arion-p
Copy link

arion-p commented Jul 9, 2018

I will be away for a couple of weeks, so I cannot test. But I will when I get back. IIRC the version in ESPEasy does not include the timing enhancements discussed here (it is a patched v1.2.0), but I will test nonetheless.

In the mean time I took a different route. I "copied" the logic from IRremoteESP8266 simplifying the code where necessary (e.g. duty cycle is always 50%). There was only a slight improvement in range. The calibrated period was 22 uS (instead of 26 uS) but that didn't make much difference. So I'm starting to think my issue might not be related.

I will post the code in case you want to include it.

@ToniA
Copy link
Owner

ToniA commented Jul 10, 2018

Latest ESPEasy Mega also works with latest IRremoteESP8266 + P115 if you delete plugin files _P015_IR.ino and _P035_IRTX.ino. So this way you can use the latest IRremoteESP8266 'as is'.

@N-Storm
Copy link
Contributor

N-Storm commented Apr 2, 2019

IRSenderESP8266 indeed are much more accurate than IRSenderBitBang.
I've measured actual period delays with working WiFi and at 38 kHz carrier it's ~30 us with BitBang method:
изображение

I've tried to improve it by replacing delayMicroseconds with ESP.getCycleCount routines which should account sub-us periods. Ended up with 29 us periods for now. Probably should take other delays into account or use an NMI (best way probably on ESP8266).

PS: IRremoteESP8266 routines show 26.5 us periods for me which is the closest one to 38 kHz (it's ~37.74 kHz) carrier.

EDIT: I've managed to compensate that by subtracting experimentally found number of cycles and was able to get a good almost exact 38 kHz carrier out of ESP8266 with getCycleCount. But later I've found that built-in ESP8266 SDK function startWaveform() which uses Timer1 and us half-period times gives almost exact and stable carrier frequency:
изображение

I'll create a pull request for my new BitBang class which uses this function once I test it deeply.

@N-Storm
Copy link
Contributor

N-Storm commented Apr 2, 2019

Added 2 new more accurate classes on my fork here N-Storm#3
Waiting on @ToniA to merge current pull requests from my fork to submit new.

@N-Storm
Copy link
Contributor

N-Storm commented Apr 2, 2019

Fixed in #73

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants