ToniA / arduino-heatpumpir

An Arduino library to control split-unit heatpumps over Infrared
GNU General Public License v2.0
389 stars 141 forks source link

ESP8266 support #11

Closed opeRaptor closed 8 years ago

opeRaptor commented 8 years ago

I have used your library before and it worked very well so thank you for that.

I was wondering if you would consider implementing support for the ESP8266 on Arduino?

Thank you for your hard work.

ToniA commented 8 years ago

I have no idea how to create 38 kHz signal on ESP8266. Maybe we could make a version which would support IR blasters, i.e. devices which create the 38 kHz signal, and ESP8266 would just add the modulation to the carrier wave produced by the blaster?

opeRaptor commented 8 years ago

Thank you for your reply, there is another library that I unfortunately could not get to work but has support on the ESP8266. I am using a Japanese Panasonic unit for reference.

Your work is appreciated.

https://github.com/r45635/HVAC-IR-Control/blob/master/HVAC_ESP8266/HVAC_ESP8266.ino

Here is how it appears to be done:

/****************************************************************************
/* enableIROut : Set global Variable for Frequency IR Emission
/***************************************************************************/ 
void enableIROut(int khz) {
  // Enables IR output.  The khz value controls the modulation frequency in kilohertz.
  halfPeriodicTime = 500/khz; // T = 1/f but we need T/2 in microsecond and f is in kHz
}

/****************************************************************************
/* mark ( int time) 
/***************************************************************************/ 
void mark(int time) {
  // Sends an IR mark for the specified number of microseconds.
  // The mark output is modulated at the PWM frequency.
  long beginning = micros();
  while(micros() - beginning < time){
    digitalWrite(IRpin, HIGH);
    delayMicroseconds(halfPeriodicTime);
    digitalWrite(IRpin, LOW);
    delayMicroseconds(halfPeriodicTime); //38 kHz -> T = 26.31 microsec (periodic time), half of it is 13
  }
}

/****************************************************************************
/* space ( int time) 
/***************************************************************************/ 
/* Leave pin off for time (given in microseconds) */
void space(int time) {
  // Sends an IR space for the specified number of microseconds.
  // A space is no output, so the PWM output is disabled.
  digitalWrite(IRpin, LOW);
  if (time > 0) delayMicroseconds(time);
}

/****************************************************************************
/* sendRaw (unsigned int buf[], int len, int hz)
/***************************************************************************/ 
void sendRaw (unsigned int buf[], int len, int hz)
{
  enableIROut(hz);
  for (int i = 0; i < len; i++) {
    if (i & 1) {
      space(buf[i]);
    } 
    else {
      mark(buf[i]);
    }
  }
  space(0); // Just to be sure
}

A similar technic seems to be used in this library: https://github.com/markszabo/IRremoteESP8266/blob/master/IRremoteESP8266.cpp

void IRsend::mark(int time) {
  // Sends an IR mark for the specified number of microseconds.
  // The mark output is modulated at the PWM frequency.
  long beginning = micros();
  while(micros() - beginning < time){
    digitalWrite(IRpin, HIGH);
    delayMicroseconds(halfPeriodicTime);
    digitalWrite(IRpin, LOW);
    delayMicroseconds(halfPeriodicTime); //38 kHz -> T = 26.31 microsec (periodic time), half of it is 13
  }
}

/* Leave pin off for time (given in microseconds) */
void IRsend::space(int time) {
  // Sends an IR space for the specified number of microseconds.
  // A space is no output, so the PWM output is disabled.
  digitalWrite(IRpin, LOW);
  if (time > 0) delayMicroseconds(time);
}

void IRsend::enableIROut(int khz) {
  // Enables IR output.  The khz value controls the modulation frequency in kilohertz.
  halfPeriodicTime = 500/khz; // T = 1/f but we need T/2 in microsecond and f is in kHz
}
ToniA commented 8 years ago

Interesting... I certainly thought PWM would be required to create reliable 38 kHz carrier on ESP8266. I was also worried about the WiFi stack priority, as I had understood it runs on a higher priority, and might cause issues with timings on the Arduino software.

I'll certainly give this a try. I think all it needs is a third implementation of the IRSender class, basically an extended version of the IRSenderBlaster.cpp. And some compiler flags to not compile the Arduino-dependent parts if the hardware is ESP8266. The best part is that I already have some ESP8266's, and have programmed those using the Arduino IDE.

Thanks for the tip :)

opeRaptor commented 8 years ago

Great to hear, sounds like you know exactly what needs to be tweaked. It is your library after all haha. I can test the library out on my side when you get it working and give you some feedback.

Thanks again for your hard work.

ToniA commented 8 years ago

OK, would you try out the 'dev' branch. I only tested that it compiles, but the implementation was really straightforward.

opeRaptor commented 8 years ago

Tested it with my Japanese Panasonic unit and it works like a charm! Thank you very much for this!

ToniA commented 8 years ago

Nice to hear, and thanks for verifying this :) I'll merge to master, and close this issue.

adrianmihalko commented 8 years ago

Hi ToniA,

I am waiting for my first ESP8266 module and I would like to control my AC unit with ESP EASY. I have here an Arduino Uno so I tried your app: IR Raw decoder for Arduino.

The result:

Number of symbols: 115
Symbols:
Hh1100010011010011011001001000000000000001001001001000000011000000101000100000000000000000000000000000000001000000
Bytes:
23,CB,26,01,80,24,01,03,45,00,00,00,00,02
Timings (in us): 
PAUSE SPACE:  0
HEADER MARK:  3820
HEADER SPACE: 1560
BIT MARK:     457
ZERO SPACE:   318
ONE SPACE:    1321
Decoding known protocols...
Looks like a Fuego etc. protocol
Checksum matches
POWER ON
MODE HEAT
Temperature: 28
FAN: 3
Vertical air direction: UP

It looks fine, it is successfully recognized my remote. I tried in all mode 1-2-3-4 and my remote is recognized in every mode. I don't know it's good or not?

Interesting, that sometimes I see signals like:

Number of symbols: 1
Symbols:

Bytes:

Timings (in us): 
PAUSE SPACE:  0
HEADER MARK:  0
HEADER SPACE: 0
BIT MARK:     80
ZERO SPACE:   0
ONE SPACE:    0
Decoding known protocols...
Unknown protocol

...when no remote is used.

Back to my real question(s):

Best regards, Adrian

ToniA commented 8 years ago

I was working with the Fuego (etc.) protocol earlier this year, to the point where I can decode it. Would you help me in finishing this, I just need protocol samples to be able to write the send part of the code?

adrianmihalko commented 8 years ago

Superb, I scanned all functions on my remote:

sintech_air_conditioner_ir_code.txt

ToniA commented 8 years ago

Thank you :) I'll try to get some progress on this next week.

ToniA commented 8 years ago

Please try out the master branch now (with the one called 'FuegoHeatpumpIR'). The vertical swing is still not fixed, I'll do that later.

adrianmihalko commented 8 years ago

Hey, what a great news for Sunday. :)

I am on ESP8266 (Wemos D1 mini).

Here is what I did:

1, cloned arduino-heatpumpir to my Arudino/libraries folder.

2, edited _P115_HeatpumpIR.ino from the playground:

added #include <FuegoHeatpumpIR.h> and new FuegoHeatpumpIR()

I tried to compile, but I get error:

(error log included)

So I removed #include <CarrierHeatpumpIR.h> and new CarrierHeatpumpIR(), after that compiling was success.

3, curl http://192.168.1.7/control?cmd=heatpumpir,fuego,1,1,0,23,0,0

...and my AC is turned on. Yeeeaah. :) But I am unable to turn it off, this command is missing?

carrierheatpump.error.txt

ToniA commented 8 years ago

How about now, there was a quite obvious error in (not) sending the OFF code? I also added another Carrier model, so generic 'Carrier' instances cannot be created. Need to fix that in the ESPEasy code...

adrianmihalko commented 8 years ago

It is possible that OFF code is still not working? I can turn on my AC 100x, but cannot turn it OFF.

//turns on
curl http://192.168.1.7/control?cmd=heatpumpir,fuego,1,1,0,23,0,0
Heatpump IR code transmitted

//nothing happens
curl http://192.168.1.7/control?cmd=heatpumpir,fuego,0,0,0,23,0,0
Heatpump IR code transmitted
ToniA commented 8 years ago

Can you scan the OFF signal from the real remote?

adrianmihalko commented 8 years ago

Of course:

power_on_off.txt

ToniA commented 8 years ago

I wonder if it only accepts the OFF code if the operatingmode is the same as the last mode sent... Please try the latest version, and send both the ON and OFF commands in the same operatingmode. If this is the case, turning it off might require first sending an ON command so that you can be sure the mode is correct for turning it off.

adrianmihalko commented 8 years ago

Still nothing. Interesting, that If I turn off AC via remote and after that I send a turn off request trough Arduino, the AC beeps once (=received the code).

And one more thing, which may be important: after turning on the AC, I can't send any command to it anymore -> I can't change heat, mode, fan etc.

ToniA commented 8 years ago

Let's continue this in email, you'll find my email address on my Github front page.