-
Notifications
You must be signed in to change notification settings - Fork 54
Description
Hello,
first of all thank you very much for providing this. I've used this software to detect, decode and clone a Mitsubishi Heavy RLA502A704A IR remote used to control SRK 20 ZS (and probably a few other models) mini split indoor units.
I don't think my changes warrant a full pull request but I thought I can share my changes and code here. I've opened this as an issue since there is no discussion tab.
First of all I had to increase the number of nedges in IR_GET, because the remote sends a lot of configuration data at once. I've had to increase it to 400 (overshooting) to detect the whole burst.
micropython_ir/ir_rx/acquire.py
Lines 15 to 16 in 08d1b61
| class IR_GET(IR_RX): | |
| def __init__(self, pin, nedges=100, twait=100, display=True): |
This "decodes" the protocol by it's timings.
if not ok and near(burst[0], 3200) and near(burst[1], 1600): # Mitsubishi Heavy
print('Mitsubishi Heavy: Start {} {} Burst length {} duration {}'.format(burst[0], burst[1], lb, duration))
ok = TrueThe remote allows you to set a lot of different things, I ignored all the calendar functions.
Operation Modes:
0 - Auto
1 - Cool
2 - Dry
3 - Fan
4 - Heat
Power:
On or Off
ACL:
This is used when there are multiple air cons in one room that need to be controlled by different remotes. I investigated what the bits the button changes but I've not investigated the feature further.
Temperature:
Can be set from 18-30°C
Fan Settings:
0 - Auto
1 - 4 set increasing fan levels
6 - HI
9 - Eco
3D Auto air flow:
On or Off, AC will ignore manual pane settings if this is set
Pane settings:
The AC offers a variety of settings for the air flow resulting from left to right, as well as up to down settings for a left set of panes and a right set of panes.
horizontal levels (left set direction / right set direction:
0 - constant movement
1 - left left
2 - left middle
3 - middle middle
4 - middle right
5 - right right
6 - right left
7 - left right
8 - offvertical levels:
0 - constant movement
2, 4, 6, 8, 10 - highest to lowest setting
12 - off
There is probably some info about the schedule, the current time, and some sort of ID for the ACL inside of the "header" and "footer" I just copied from the raw data.
This is the code that generates burst:
from ir_tx import IR
accepted_modes = list(range(5))
accepted_temperatures = list(range(18, 31))
accepted_fan_levels = [0, 1, 2, 3, 4, 6, 9]
accepted_horizontal_pane_modes = list(range(9))
accepted_vertical_pane_modes = list(range(0, 13, 2))
header = "0100101001110101110000110101100010100111"
footer = "11111111000000001111111000000001"
def invert_byte(byte_string):
# converting to int
byte_int = int(byte_string, 2)
# XORing
inverted = byte_int ^ 0xFF
return f"{inverted:08b}"
def convert_to_four_bits_LSB_first(value):
#reversing with step -1 is not supported in micropython
#return f"{value & 0b1111:04b}"[::-1]
return ''.join(f"{value & 0b1111:04b}"[i] for i in range(3, -1, -1))
def create_mitsu_bits(mode, power, acl, temp, fan_level, threed_auto, horizontal_pane_mode, vertical_pane_mode):
mitsu_bits = header
first_byte = ""
# Setting ACL - if toggled will take up entire first byte
if acl:
first_byte += "00000001"
else:
# Setting AC Mode
assert mode in accepted_modes
first_byte += ''.join(f"{mode & 0b1111:03b}"[i] for i in range(2, -1, -1))
# Setting Power
if power:
first_byte += "1"
else:
first_byte += "0"
#padding
first_byte += "0000"
# adding inverted byte first, then the real byte
mitsu_bits += invert_byte(first_byte)+first_byte
# converting temperature to corresponding bits,
# offsetting the temperature by 17 and reversing them to LSB first
assert temp in accepted_temperatures
temp_byte = convert_to_four_bits_LSB_first(temp-17)+"0000"
# adding first inverted byte and then the temperature byte
mitsu_bits += invert_byte(temp_byte)+temp_byte
# converting the fan mode to 4 bits LSB first and padding
assert fan_level in accepted_fan_levels
fan_byte = convert_to_four_bits_LSB_first(fan_level)+"0000"
# then adding the inverted byte first and then the normal one
mitsu_bits += invert_byte(fan_byte)+fan_byte
# converting the pane settings first, before the 3d auto settings, that are added before the panes
# because for some reason the seem to be mirrored if 3d auto is off
assert horizontal_pane_mode in accepted_horizontal_pane_modes
assert vertical_pane_mode in accepted_vertical_pane_modes
pane_byte = convert_to_four_bits_LSB_first(horizontal_pane_mode)
pane_byte += convert_to_four_bits_LSB_first(vertical_pane_mode)
# setting the next byte depending o nthe 3d auto feature, and taking the last 3 bits from the pane settings
if threed_auto:
threed_byte = "01001"+pane_byte[-3:]
else:
threed_byte = "00000"+pane_byte[-3:]
mitsu_bits += invert_byte(threed_byte)+threed_byte
mitsu_bits += invert_byte(pane_byte)+pane_byte
# adding the "footer" that probably contains timer/schedule settings
mitsu_bits += footer
return mitsu_bits
def convert_bits_to_times(bits):
times = [32000, 1600]
for bit in bits:
if bool(int(bit)):
times.append(400)
times.append(1200)
else:
times.append(400)
times.append(430)
times.append(400)
return times
def create_mitsu_times(*args):
return convert_bits_to_times(create_mitsu_bits(*args))
class Player(IR):
#Initiate with size 308, burst length +1 for STOP
def __init__(self, pin, freq=38000, verbose=False, asize=308):
super().__init__(pin, freq, asize, 33, verbose)
def play(self, lst):
for x, t in enumerate(lst):
self._arr[x] = t
self.aptr = x + 1
self.trigger()I can then dispatch a burst like
ir_pin = Pin(26, Pin.OUT, value = 0)
player = Player(ir_pin)
print("Creating IR Burst for Mitsubishi Heavy Indistries RLA502A704A")
print("Mode: Cool")
print("Power: On")
print("ACL: No")
print("Temp: 24")
print("Fan: Strength 3/5")
print("3D Auto Airstream: Off")
print("Airstream Horizontal: Middle/Middle")
print("Airstream Vertical: Actuating")
player.play(create_mitsu_times(1, True, False, 24, 2, False, 3, 0))