Go Down

Topic: Trying to control Mitsubishi Heat Pump Air Conditioning Unit (Read 10327 times) previous topic - next topic

iisfaq

Hi all

I am trying to control a Mitsubishi Heat Pump Air Conditioning Unit. I am using Ken Sherrif's latest experimental IRRemote library.

I have increased the constant RAWBUF because the heat pump remote seems to send 180 values with each button press.

#define RAWBUF 255 // Length of raw duration buffer - IRRemote.H

I can reliababily capture button sequences but when I try to play back it does not work - ie Nothing happens on the heat pump.

Here is my sketch


Quote


#include <IRremote.h>

int RECV_PIN = 11;

// ON
//Unknown encoding: 3DF7796E (32 bits)
//Raw (180): -8014 3200 -1550 450 -350 450 -1150 400 -400 400 -400 400 -1150 450 -350 450 -1150 400 -400 400 -350 450 -1150 400 -1200 400 -1150 450 -350 400 -1200 400 -350 450 -1150 400 -1200 400 -1150 450 -350 450 -350 400 -400 400 -400 400 -1150 450 -1150 400 -400 400 -1150 450 -1150 400 -400 400 -400 400 -1150 450 -350 400 -400 400 -1200 400 -350 450 -350 400 -1200 400 -1150 450 -350 450 -1150 400 -1150 450 -350 450 -1150 400 -1200 400 -1150 450 -350 400 -1200 400 -350 450 -1150 400 -1200 400 -400 400 -350 450 -350 400 -1200 400 -400 400 -1150 450 -350 400 -1200 400 -1150 450 -1150 400 -1200 400 -350 450 -1150 400 -1200 400 -350 450 -350 450 -350 400 -400 400 -400 400 -1150 450 -350 400 -400 400 -1200 400 -1150 450 -1150 400 -400 400 -350 450 -1150 400 -1200 400 -400 400 -1150 450 -350 400 -400 400 -1150 450 -1150 400 -400 400 -400 400 -1150 450 -350 400

// OFF
// Unknown encoding: 364B214A (32 bits)
// Raw (180): -13552 3200 -1550 450 -350 400 -1150 450 -350 450 -350 450 -1150 400 -350 450 -1150 450 -350 400 -400 400 -1150 450 -1150 400 -1200 400 -350 450 -1150 450 -350 400 -1200 400 -1150 450 -1150 400 -400 400 -350 450 -350 450 -350 400 -1200 400 -1150 450 -350 450 -1150 400 -1150 450 -350 450 -350 400 -1200 400 -350 450 -350 450 -1150 400 -400 400 -400 400 -1150 450 -1150 400 -400 400 -1150 450 -1150 400 -400 400 -1150 450 -1150 400 -1200 400 -350 450 -1150 400 -400 400 -1150 450 -1150 450 -350 400 -400 400 -400 400 -1150 450 -350 400 -1200 400 -350 450 -1150 400 -1200 400 -1150 450 -1150 400 -400 400 -1150 450 -1150 400 -400 400 -400 400 -350 450 -350 450 -350 450 -1150 400 -400 400 -350 450 -1150 400 -1200 400 -1150 450 -350 400 -1200 400 -1150 450 -1150 400 -400 400 -1150 450 -350 450 -350 400 -1200 400 -350 450 -350 450 -350 450 -1150 400 -400 400



unsigned int powerOn[] = {
   3200,1550,400,400,400,1200,400,350,400,400,400,1200,400,400,400,1150,400,400,400,400,400,1200,350,1200,400,1200,400,400,400,1150,
   400,400,400,1200,400,1150,400,1200,400,400,400,400,350,400,400,400,400,1200,400,1150,400,400,400,1200,400,1200,350,400,400,400,
   400,1200,400,400,400,350,400,1200,400,400,400,400,400,1150,400,1200,400,400,400,1150,400,1200,400,400,400,1150,400,1200,400,1200,
   400,400,350,1200,400,400,400,1200,400,1150,400,400,400,400,400,400,400,1150,400,400,400,1200,400,400,350,1200,400,1200,400,1200,
   350,1200,400,400,400,1200,350,1200,400,1200,400,400,400,350,400,400,400,400,400,1200,400,400,350,400,400,400,400,1200,400,1150,
   400,400,400,1200,400,1200,350,400,400,400,400,1200,400,400,350,400,400,1200,400,400,400,400,400,1150,400,1200,400,400,400};

int incomingByte = 0;

IRsend irsend;
IRrecv irrecv(RECV_PIN);

decode_results results;

void setup()
{
   Serial.begin(9600);
   irrecv.enableIRIn(); // Start the receiver

}

// Dumps out the decode_results structure.
// Call this after IRrecv::decode()
// void * to work around compiler issue
//void dump(void *v) {
//  decode_results *results = (decode_results *)v
void dump(decode_results *results) {
   int count = results->rawlen;
   if (results->decode_type == UNKNOWN) {
      Serial.print("Unknown encoding: ");
   }
   else if (results->decode_type == NEC) {
      Serial.print("Decoded NEC: ");
   }
   else if (results->decode_type == SONY) {
      Serial.print("Decoded SONY: ");
   }
   else if (results->decode_type == RC5) {
      Serial.print("Decoded RC5: ");
   }
   else if (results->decode_type == RC6) {
      Serial.print("Decoded RC6: ");
   }
   else if (results->decode_type == PANASONIC) {   
      Serial.print("Decoded PANASONIC - Address: ");
      Serial.print(results->panasonicAddress,HEX);
      Serial.print(" Value: ");
   }
   else if (results->decode_type == JVC) {
      Serial.print("Decoded JVC: ");
   }
   Serial.print(results->value, HEX);
   Serial.print(" (");
   Serial.print(results->bits, DEC);
   Serial.println(" bits)");
   Serial.print("Raw (");
   Serial.print(count, DEC);
   Serial.print("): ");

   for (int i = 0; i < count; i++) {
      if ((i % 2) == 1) {
         Serial.print(results->rawbuf*USECPERTICK, DEC);
      }
      else {
         Serial.print(-(int)results->rawbuf*USECPERTICK, DEC);
      }
      Serial.print(" ");
   }
   Serial.println("");
}


void loop() {
   if (Serial.available() > 0) {
      // read the incoming byte:
      incomingByte = Serial.read();
 
      Serial.print("Sent BIG Code");
      irsend.sendRaw(powerOn, 179,38);
      Serial.print("DONE");
   }

   if (irrecv.decode(&results)) {
      Serial.println(results.value, HEX);
      dump(&results);
      irrecv.resume(); // Receive the next value
   }
}



I really do not know what I need to do next.. Any clues?

Chris

johnwasser

What sending LED are you using and how is it connected to the Arduino?
Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

iisfaq


What sending LED are you using and how is it connected to the Arduino?


I took note of your previous comment about the output power and added a transisiter to the circuit.

The Mitsubishi Remote Control has this IR Transmitter - no idea on the specifications



The IR Sensor I am using is from JayCar in New Zealand - see http://www.jaycar.co.nz/productView.asp?ID=ZD1945&keywords=Infrared+Diode&form=KEYWORD

5MM EMITTING DIODE

5mm LED & has a blue transparent lens.

Specifications:

- Forward Current (If): 50mA max
- Peak forward current (Ip): 1.2A
- Forward Voltage (VF): 1.2V @ 20mA
- Reverse Voltage (VR): 5V max
- Power Dissipation (Pd): 100mW max
- Viewing Angle: 30°
- Peak Spectral Wavelength(IR): 940nm @ 20mA * Spectral Bandwidth (DI): 50nm@20mA
- Material: GaAs



My Arduino board showing my connections



My Arduino board schema


Chris

iisfaq

#3
Jun 23, 2012, 05:58 am Last Edit: Jun 23, 2012, 06:03 am by iisfaq Reason: 1
:)  SUCCESS :)

OK I have found what the problem was - not hardware just software.

I had been looking at the values that I receive and thought that generally they look like multiples of 400 but they are not all multiples of 400.  Some values are 1550, 1150, 350 etc.

Quote
unsigned int powerOn[] = {
  3200,1550,400,400,400,1200,400,350,400,400,400,1200,400,400,400,1150,400,400,400,400,400,1200,350,1200,400,1200,400,400,400,1150,
  400,400,400,1200,400,1150,400,1200,400,400,400,400,350,400,400,400,400,1200,400,1150,400,400,400,1200,400,1200,350,400,400,400,
  400,1200,400,400,400,350,400,1200,400,400,400,400,400,1150,400,1200,400,400,400,1150,400,1200,400,400,400,1150,400,1200,400,1200,
  400,400,350,1200,400,400,400,1200,400,1150,400,400,400,400,400,400,400,1150,400,400,400,1200,400,400,350,1200,400,1200,400,1200,
  350,1200,400,400,400,1200,350,1200,400,1200,400,400,400,350,400,400,400,400,400,1200,400,400,350,400,400,400,400,1200,400,1150,
  400,400,400,1200,400,1200,350,400,400,400,400,1200,400,400,350,400,400,1200,400,400,400,400,400,1150,400,1200,400,400,400};


So I modified the code in irremote.cpp and modified the interrupt code added a funtion

so in the interrupt function I added

Quote
irparams.rawbuf[irparams.rawlen++] = fixTimer(irparams.timer);


Quote
case STATE_MARK: // timing MARK
   if (irdata == SPACE) {   // MARK ended, record time
     irparams.rawbuf[irparams.rawlen++] = fixTimer(irparams.timer);
     irparams.timer = 0;
     irparams.rcvstate = STATE_SPACE;
   }
   break;
 case STATE_SPACE: // timing SPACE
   if (irdata == MARK) { // SPACE just ended, record it
     irparams.rawbuf[irparams.rawlen++] = fixTimer(irparams.timer);
     irparams.timer = 0;
     irparams.rcvstate = STATE_MARK;
   }
   else { // SPACE
     if (irparams.timer > GAP_TICKS) {
       // big SPACE, indicates gap between codes
       // Mark current code as ready for processing
       // Switch to STOP
       // Don't reset timer; keep counting space width
       irparams.rcvstate = STATE_STOP;
     }
   }
   break;


In the fixTimer function I just hard coded some values.

Since the code was using the value t * 50ms so my code really just enforces a return value of 1600,1200,400 or something > 1600 (not sure I need this)

Quote

unsigned int fixTimer(unsigned int t)
{
   if (t < 20)
      return 8;
   else if (t  < 31)
      return 24;
   else if (t  < 33)
      return 32;
   else
      return t;

}



Now I have two IR Raw arrays that I can use.

Quote
unsigned int powerOn[] = { // 65214,
3200,1600,400,400,400,1200,400,400,400,400,400,1200,400,400,400,1200,400,400,400,400,
400,1200,400,1200,400,1200,400,400,400,1200,400,400,400,1200,400,1200,400,1200,400,400,
400,400,400,400,400,400,400,1200,400,1200,400,400,400,1200,400,1200,400,400,400,400,
400,1200,400,400,400,400,400,1200,400,400,400,400,400,1200,400,1200,400,400,400,1200,
400,1200,400,1200,400,1200,400,1200,400,1200,400,1200,400,1200,400,1200,400,1200,400,400,
400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,1200,400,1200,400,1200,
400,1200,400,1200,400,1200,400,1200,400,1200,400,400,400,400,400,400,400,400,400,400,
400,400,400,400,400,400,400,400,400,1200,400,1200,400,400,400,1200,400,1200,400,1200,
400,400,400,1200,400,400,400,400,400,1200,400,400,400,400,400,400,400,1200,400};

unsigned int powerOff[] = { // 32284,
3200,1600,400,400,400,1200,400,400,400,400,400,1200,400,400,400,1200,400,400,400,400,
400,1200,400,1200,400,1200,400,400,400,1200,400,400,400,1200,400,1200,400,1200,400,400,
400,400,400,400,400,400,400,1200,400,1200,400,400,400,1200,400,1200,400,400,400,400,
400,1200,400,400,400,400,400,1200,400,400,400,400,400,1200,400,1200,400,400,400,1200,
400,1200,400,1200,400,1200,400,1200,400,1200,400,1200,400,1200,400,1200,400,1200,400,400,
400,400,400,400,400,400,400,400,400,400,400,400,400,400,400,1200,400,1200,400,1200,
400,1200,400,1200,400,1200,400,1200,400,1200,400,400,400,400,400,400,400,400,400,400,
400,400,400,400,400,400,400,400,400,1200,400,1200,400,1200,400,1200,400,1200,400,1200,
400,400,400,1200,400,400,400,400,400,400,400,400,400,400,400,400,400,1200,400};


So it looked like the Mitsubishi Heat Pump was quite particular about exactly what it saw.

So in this case it is also not Power On / Power Off - the heat pump sets all parameters at once.

So my powerOn actually sets it to Power On with the Mode set to Cooling, the temperature set to 25c, Auto fan mode, and no airflow controls set.

My powerOff actually sets it to Power Off with the Mode set to Cooling, the temperature set to 25c, Auto fan mode, and no airflow controls set.

I have spent hours and hours on this. But thanks for your help and I hope this saves some times for somone else!

chris

wirenate

Thanks for posting this! I am thinking of trying to automate our Mitsubishi heat pump with an Arduino as well! Did you ever go through and try to decode the full IR protocol (e.g. what the individual codes are for each parameter)?

How are you using the Arduino?

-nate

iisfaq


Thanks for posting this! I am thinking of trying to automate our Mitsubishi heat pump with an Arduino as well! Did you ever go through and try to decode the full IR protocol (e.g. what the individual codes are for each parameter)?

How are you using the Arduino?


Hi Nate

I have started to document what I have done in order to decode the bit pattern from the Heat Pump - still a work in progress but should be of value to you.

See http://wiki.crowe.co.nz/Mitsubishi%20Heat%20Pump.ashx

Chris

zefix

#6
Apr 09, 2013, 03:04 pm Last Edit: Apr 09, 2013, 03:41 pm by zefix Reason: 1
Hi Chris,

I`m trying to replicate your work(http://wiki.crowe.co.nz/Mitsubishi%20Heat%20Pump.ashx) using an arduino ethernet with a mitsubishi(heavy industries) heat pump.

My aim is to remote(LAN/http) start the "sleep" mode, which is the button left down side on the remote. In heat mode the heat pump is going to a sort of low power mode over the course of a few hours and decreases the room temperature to 13°C. Sleep mode goes for a maximum of 10 hours which is exact what I need.

My remote(RKW502A200B) is nearly the same as your's.

1. I was wondering if you had probably mixed up the fanspeed mode and the power modes of your heat pump.
These are two different settings, see your mitsu manual. There is normal mode, high power and ECO mode.
Only in normal mode I can choose the fan speed.

2. When I use the timer buttons "sleep" "on" "off" the raw code jumps from 180 to 255.
Can you replicate this?

Thanks for your awesome work on this remote code!

iisfaq

#7
Apr 09, 2013, 06:52 pm Last Edit: Apr 09, 2013, 07:36 pm by iisfaq Reason: 1
Hi

Yes I have seen the extra data bits that when uou use the timer functions, on time, off the etc.

Since I was not interested I ignored it, I was more interested in the base data functions only.

I did not look into it but the start time and end time are encoded into those bits and the sleep settings as well.

In regards to your Q1

I know I can not set fan speeds with powerful and Eco but I am unsure in what context you mention this?

Chris

iisfaq


2. When I use the timer buttons "sleep" "on" "off" the raw code jumps from 180 to 255.
Can you replicate this?


Hi

There are infact 276 bits returned.

You need to modify the IRREMOTE.H file to increase the buffer

#define RAWBUF 276

And this time you need to modify the structure in IRREMOTEINT.H

typedef struct {
  uint8_t recvpin;           // pin for IR data from detector
  uint8_t rcvstate;          // state machine
  uint8_t blinkflag;         // TRUE to enable blinking of pin 13 on IR processing
  unsigned int timer;     // state timer, counts 50uS ticks.
  unsigned int rawbuf[RAWBUF]; // raw data
  unsigned int rawlen;         // counter of entries in rawbuf

  //uint8_t rawlen;         // counter of entries in rawbuf
}
irparams_t;

Change the uint8_t rawlen to an unsigned int as shown above.

The uint8 is in fact an unsigned char = so its values are limited to 0 - 255.

This will now allow you to return the full 276 bits of binary data.

I have had a quick look but not yet decoded the additional 96 bits of data.

I will keep you posted.

Chris

iisfaq

I am not getting to far.

I have gone though 24 hours of values for the ON TIMER, with the off timer set to the same value.



So far I am not seeing a good pattern for the times.

Chris

zefix

#10
Apr 11, 2013, 02:28 pm Last Edit: Apr 15, 2013, 06:09 pm by zefix Reason: 1
Hi Chris,

I was fiddling around with this but my Mitsu won't accept any raw codes that I generated with your guide(including rasing the RAWBUF to 276), except for a peep sound but nothing else.
Then I used the standard "IRrecord" sektch from Ken Shirriff(with your changes to the config .h/.cpp) to record and send to my Mitsu and only that worked. The recorded "sleep" timer is also accepted by my Mitsu.
I do not have however tested it for the whole 10 hours and checked if it goes in low power mode an shuts itself off, but I will over the next days.  Update: Works perfect!

Code: [Select]

the "IRrecord" raw data normal on heat etc...without "sleep" timer:
m3200 s1300 m300 s500 m300 s1300 m300 s500 m300 s500 m300 s1300 m300 s500 m300 s1300 m300 s500 m300 s500 m300 s1300
m300 s1300 m300 s1300 m300 s500 m300 s1300 m300 s500 m300 s1300 m300 s1300 m300 s1300 m300 s500 m300 s500 m300 s500
m300 s500 m300 s1300 m300 s1300 m300 s500 m300 s1300 m300 s1300 m300 s500 m300 s500 m300 s1300 m300 s500 m300 s500
m300 s1300 m300 s500 m300 s500 m300 s1300 m300 s1300 m300 s500 m300 s1300 m300 s1300 m300 s500 m300 s1300 m300 s1300
m300 s1300 m300 s1300 m300 s1300 m300 s500 m300 s1300 m300 s1300 m300 s500 m300 s500 m300 s500 m300 s500 m300 s500
m300 s1300 m300 s500 m300 s1300 m300 s1300 m300 s1300 m300 s500 m300 s500 m300 s1300 m300 s500 m300 s1300 m300 s500
m300 s500 m300 s500 m300 s1300 m300 s1300 m300 s500 m300 s1300 m300 s500 m300 s1300 m300 s1300 m300 s500 m300 s500
m300 s500 m300 s1300 m300 s1300 m300 s1300 m300 s500 m300 s500 m300 s1300 m300 s1300 m300 s1300 m300 s500 m300 s500
m300 s500 m300

the "IRrecord" raw data "sleep" timer(10 hours, heating etc.):
m3200 s1300 m300 s500 m300 s1300 m300 s500 m300 s500 m300 s1300 m300 s500 m300 s1300 m300 s500
m300 s500 m300 s1300 m300 s1300 m300 s1300 m300 s500 m300 s1300 m300 s500 m300 s1300 m300 s1300
m300 s1300 m300 s500 m300 s500 m300 s500 m300 s500 m300 s1300 m300 s1300 m300 s500 m300 s1300
m300 s1300 m300 s500 m300 s500 m300 s1300 m300 s500 m300 s500 m300 s1300 m300 s500 m300 s500
m300 s1300 m300 s1300 m300 s500 m300 s1300 m300 s1300 m300 s500 m300 s1300 m300 s1300 m300
s1300 m300 s1300 m300 s1300 m300 s500 m300 s1300 m300 s1300 m300 s500 m300 s500 m300 s500 m300
s500 m300 s500 m300 s1300 m300 s500 m300 s500 m300 s1300 m300 s1300 m300 s500 m300 s500 m300
s1300 m300 s500 m300 s1300 m300 s1300 m300 s500 m300 s500 m300 s1300 m300 s1300 m300 s500 m300
s1300 m300 s500 m300 s1300 m300 s1300 m300 s500 m300 s500 m300 s500 m300 s1300 m300 s1300 m300
s1300 m300 s500 m300 s500 m300 s1300 m300 s1300 m300 s1300 m300 s500 m300 s500 m300 s500 m300
s1300 m300 s1300 m300 s1300 m300 s1300 m300 s1300 m300 s1300 m300 s1300 m300 s1300 m300 s500
m300 s500 m300 s500 m300 s500 m300 s500 m300 s500 m300 s500 m300 s500 m300 s1300 m300 s1300
m300 s1300 m300 s1300 m300 s1300 m300 s1300 m300 s1300 m300 s500 m300 s500 m300 s500 m300 s500
m300 s500 m300 s500 m300 s500 m300 s500 m300 s1300 m300 s500 m300 s1300 m300 s500 m300 s1300
m300 s1300 m300 s500 m300 s1300 m300 s1300 m300 s1300 m300 s500 m300 s1300 m300 s500 m300 s500
m300 s1300 m300 s500 m300 s500 m300



I'm no programmer at all but I looked at the numbers in excel for easier comparing them and I noticed that the normal on/off RAW code without "sleep" timer, using the "IRrecord"sketch, counts only 179 single RAW numbers. When I use the "sleep" timer this number raises to 275.
And when I use the "sleep" timer there is a change in the first 179 RAW numbers. RAW number 116 switches from 1300 to 500 and No.132 switches from 500 to 1300. This seems to be the only change.

I hope that's for some help....

vk2tds

Hi Chris...

Great work with the protocol reverse engineering. I do have some questions - I don't actually have a Mitsubishi A/C unit, but am wanting to build the capability to control it into a device I am building.

* Do you have any better idea of the timings, apart from being divisible by 400 uSec?
* Any idea what carrier frequency the Mitsubishi uses?
* What is the definition of Allergan in the spec?
* What is the difference between Up/Down Swing Manual and Up/Down Swing?
* What is the Temperature Range? Is it Temperature - 18C for the temperature field?

Anyway, great work on the protocol. FYI, I have had great success decoding IR using the USB IR Toy from DangerousPrototypes, and am having a lot of success using it, and more recently, using the Raspberry Pi running DMA and PCM

Darryl VK2TDS

sponno

Oh I have been thinking about doing this as well.
Is anyone offering the full sketch working sketch file by chance?  I have the IR emitters and ardunio. Would love to try this.

Cheers heaps, John, Auckland NZ.

iisfaq

Hi Guys

I can not longer help with any details on this project as my Mitsubishi died - $2000 NZD to fix - so it is not getting fixed.

All that for a fan and a fuse!

What is the point of a fuse if it blows you have to replace the whole circuit board- sounds like a con to me!

Chris

zefix

#14
Sep 05, 2013, 03:50 pm Last Edit: Sep 05, 2013, 04:02 pm by zefix Reason: 1
Hopefully you dont kill your Mitsu with bugged IR codes from the arduino?

Maybe a power surge?

Cant you fix this on your own for a fraction of 2000,- NSD?

All the spareparts you need you could get from "www.mrespareparts.com.au". I even used their exploded drawings to fix mine over here in germany.

Go Up