IRremote
ac_LG.hpp
Go to the documentation of this file.
1 /*
2  * ac_LG.hpp
3  *
4  * Contains functions for sending LG air conditioner IR Protocol
5  * There is no state plausibility check, e.g. you can send fan speed in Mode D and change temperature in mode F
6  *
7  * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
8  *
9  ************************************************************************************
10  * MIT License
11  *
12  * Copyright (c) 2021-2022 Armin Joachimsmeyer
13  *
14  * Permission is hereby granted, free of charge, to any person obtaining a copy
15  * of this software and associated documentation files (the "Software"), to deal
16  * in the Software without restriction, including without limitation the rights
17  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18  * copies of the Software, and to permit persons to whom the Software is furnished
19  * to do so, subject to the following conditions:
20  *
21  * The above copyright notice and this permission notice shall be included in all
22  * copies or substantial portions of the Software.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
25  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
26  * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
27  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
28  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
29  * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30  *
31  ************************************************************************************
32  */
33 #ifndef _AC_LG_HPP
34 #define _AC_LG_HPP
35 #include <Arduino.h>
36 
37 // This block must be located after the includes of other *.hpp files
38 //#define LOCAL_INFO // This enables info output only for this file
39 //#define LOCAL_DEBUG // This enables debug output only for this file - only for development
40 #include "LocalDebugLevelStart.h"
41 
42 #include "IRremoteInt.h"
43 #include "ac_LG.h" // useful constants
44 #include "LongUnion.h"
45 
49 /*
50  * LG remote measurements: Type AKB73315611, Ver1.1 from 2011.03.01
51  * Internal crystal: 4 MHz
52  * Header: 8.9 ms mark 4.15 ms space
53  * Data: 500 / 540 and 500 / 1580;
54  * Clock is nor synchronized with gate so you have 19 and sometimes 19 and a spike pulses for mark
55  * Duty: 9 us on 17 us off => around 33 % duty
56  * NO REPEAT: If value like temperature has changed during long press, the last value is send at button release
57  * If you do a double press -tested with the fan button-, the next value can be sent after 118 ms
58  */
59 #define SIZE_OF_FAN_SPEED_MAPPING_TABLE 4
60 const int AC_FAN_TOWER[SIZE_OF_FAN_SPEED_MAPPING_TABLE] = { 0, 4, 6, 6 }; // last dummy entry to avoid out of bounds access
61 const int AC_FAN_WALL[SIZE_OF_FAN_SPEED_MAPPING_TABLE] = { 0, 2, 4, 5 }; // 0 -> low, 4 high, 5 -> cycle
62 
63 void Aircondition_LG::setType(bool aIsWallType) {
64  ACIsWallType = aIsWallType;
65  INFO_PRINT(F("Set wall type to "));
66  INFO_PRINTLN(aIsWallType);
67 }
68 
69 void Aircondition_LG::printMenu(Print *aSerial) {
70  aSerial->println();
71  aSerial->println();
72  aSerial->println(F("Type command and optional parameter without a separator"));
73  aSerial->println(F("0 Off"));
74  aSerial->println(F("1 On"));
75  aSerial->println(F("s Swing <0 or 1>"));
76  aSerial->println(F("a Auto clean <0 or 1>"));
77  aSerial->println(F("j Jet on"));
78  aSerial->println(F("e Energy saving <0 or 1>"));
79  aSerial->println(F("l Lights toggle"));
80  aSerial->println(F("f Fan speed <0 to 2 or 3 for cycle>"));
81  aSerial->println(F("t Temperature <18 to 30> degree"));
82  aSerial->println(F("+ Temperature + 1"));
83  aSerial->println(F("- Temperature - 1"));
84  aSerial->println(F("m <c(ool) or a(uto) or d(ehumidifying) or h(eating) or f(an) mode>"));
85  aSerial->println(F("S Sleep after <0 to 420> minutes"));
86  aSerial->println(F("T Timer on after <0 to 1439> minutes"));
87  aSerial->println(F("O Timer off after <0 to 1439> minutes"));
88  aSerial->println(F("C Clear all timer and sleep"));
89  aSerial->println(F("e.g. \"s1\" or \"t23\" or \"mc\" or \"O60\" or \"+\""));
90  aSerial->println(F("No plausibility check is made!"));
91  aSerial->println();
92 }
93 
94 /*
95  * Send repeat
96  * Repeat commands should be sent in a 110 ms raster.
97  * @param aCommand one of LG_COMMAND_OFF, LG_COMMAND_ON etc.
98  */
99 bool Aircondition_LG::sendCommandAndParameter(char aCommand, int aParameter) {
100  // Commands without parameter
101  switch (aCommand) {
102  case LG_COMMAND_OFF: // off
104  PowerIsOn = false;
105  return true;
106 
107  case LG_COMMAND_ON: // on
108  PowerIsOn = false; // set to false in order to suppress on bit
110  return true;
111 
112  case LG_COMMAND_JET:
113  DEBUG_PRINTLN(F("Send jet on"));
115  return true;
116 
117  case LG_COMMAND_LIGHT:
119  return true;
120 
123  return true;
124 
126  if (18 <= Temperature && Temperature <= 29) {
127  Temperature++;
129  } else {
130  return false;
131  }
132  return true;
133 
135  if (19 <= Temperature && Temperature <= 30) {
136  Temperature--;
138  } else {
139  return false;
140  }
141  return true;
142 
143  }
144 
145  PowerIsOn = true;
146 
147  /*
148  * Now the commands which require a parameter
149  */
150  if (aParameter < 0) {
151  DEBUG_PRINT(F("Error: Parameter is less than 0"));
152  return false;
153  }
154  switch (aCommand) {
155 
156  case LG_COMMAND_MODE:
157  Mode = aParameter + '0';
159  break;
160 
161  case LG_COMMAND_SWING:
162  DEBUG_PRINT(F("Send air swing="));
163  DEBUG_PRINTLN(aParameter);
164  if (ACIsWallType) {
165  if (aParameter) {
167  } else {
169  }
170  } else {
171  if (aParameter) {
173  } else {
175  }
176  }
177  break;
178 
180  DEBUG_PRINT(F("Send auto clean="));
181  DEBUG_PRINTLN(aParameter);
182  if (aParameter) {
184  } else {
186  }
187  break;
188 
189  case LG_COMMAND_ENERGY:
190  DEBUG_PRINT(F("Send energy saving on="));
191  DEBUG_PRINTLN(aParameter);
192  if (aParameter) {
194  } else {
196  }
197  break;
198 
200  if (aParameter < SIZE_OF_FAN_SPEED_MAPPING_TABLE) {
201  FanIntensity = aParameter;
203  } else {
204  return false;
205  }
206  break;
207 
209  if (18 <= aParameter && aParameter <= 30) {
210  Temperature = aParameter;
212  } else {
213  return false;
214  }
215  break;
216 
217  case LG_COMMAND_SLEEP:
218  // 420 = maximum I have recorded
219  if (aParameter <= 420) {
220  sendIRCommand(LG_SLEEP + aParameter);
221  } else {
222  return false;
223  }
224  break;
225 
226  case LG_COMMAND_TIMER_ON:
227  // 1440 = minutes of a day
228  if (aParameter <= 1439) {
229  sendIRCommand(LG_TIMER_ON + aParameter);
230  } else {
231  return false;
232  }
233  break;
234 
236  if (aParameter <= 1439) {
237  sendIRCommand(LG_TIMER_OFF + aParameter);
238  } else {
239  return false;
240  }
241  break;
242 
243  default:
244  return false;
245  }
246  return true;
247 }
248 
249 void Aircondition_LG::sendIRCommand(uint16_t aCommand) {
250 
251  INFO(F("Send code=0x"));
252  INFO_PRINT(aCommand, HEX);
253  INFO_PRINT(F(" | 0b"));
254  INFO_PRINTLN(aCommand, BIN);
255 
256 
257  IrSender.sendLG2((uint8_t) LG_ADDRESS, aCommand, 0);
258 }
259 
260 /*
261  * Takes values from static variables
262  */
264 
265  uint8_t tTemperature = Temperature;
266  INFO_PRINT(F("Send temperature="));
267  INFO_PRINT(tTemperature);
268  INFO_PRINT(F(" fan intensity="));
270  INFO_PRINT(F(" mode="));
271  INFO_PRINTLN((char )Mode);
272 
273 
274  WordUnion tIRCommand;
275  tIRCommand.UWord = 0;
276 
277  // Temperature is coded in the upper nibble of the LowByte
278  tIRCommand.UByte.LowByte = ((tTemperature - 15) << 4); // 16 -> 0x00, 18 -> 0x30, 30 -> 0xF0
279 
280  // Fan intensity is coded in the lower nibble of the LowByte
281  if (ACIsWallType) {
282  tIRCommand.UByte.LowByte |= AC_FAN_WALL[FanIntensity];
283  } else {
284  tIRCommand.UByte.LowByte |= AC_FAN_TOWER[FanIntensity];
285  }
286 
287  switch (Mode) {
288  case AC_MODE_COOLING:
289  tIRCommand.UByte.HighByte = LG_MODE_COOLING >> 8;
290  break;
291  case AC_MODE_HEATING:
292  tIRCommand.UByte.HighByte = LG_MODE_HEATING >> 8;
293  break;
294  case AC_MODE_AUTO:
295  tIRCommand.UByte.HighByte = LG_MODE_AUTO >> 8;
296  break;
297  case AC_MODE_FAN:
298  tTemperature = 18;
299  tIRCommand.UByte.HighByte = LG_MODE_FAN >> 8;
300  break;
302  tIRCommand.UWord = LG_MODE_DEHUMIDIFIYING;
303  break;
304  default:
305  break;
306  }
307  if (!PowerIsOn) {
308  // switch on requires masked bit
309  tIRCommand.UByte.HighByte &= ~(LG_SWITCH_ON_MASK >> 8);
310  }
311  PowerIsOn = true;
312 
313  sendIRCommand(tIRCommand.UWord);
314 }
315 
317 #include "LocalDebugLevelEnd.h"
318 
319 #endif // _AC_LG_HPP
LG_COMMAND_AUTO_CLEAN
#define LG_COMMAND_AUTO_CLEAN
Definition: ac_LG.h:77
Aircondition_LG::Temperature
uint8_t Temperature
Definition: ac_LG.h:132
LG_COMMAND_LIGHT
#define LG_COMMAND_LIGHT
Definition: ac_LG.h:80
LG_COMMAND_TEMPERATURE
#define LG_COMMAND_TEMPERATURE
Definition: ac_LG.h:82
DEBUG_PRINT
#define DEBUG_PRINT(...)
Definition: LocalDebugLevelStart.h:79
INFO_PRINT
#define INFO_PRINT(...)
Definition: LocalDebugLevelStart.h:90
WordUnion
Union to specify parts / manifestations of a 16 bit Word without casts and shifts.
Definition: LongUnion.h:36
LG_WALL_SWING_OFF
#define LG_WALL_SWING_OFF
Definition: ac_LG.h:59
LG_AUTO_CLEAN_ON
#define LG_AUTO_CLEAN_ON
Definition: ac_LG.h:68
LG_COMMAND_FAN_SPEED
#define LG_COMMAND_FAN_SPEED
Definition: ac_LG.h:81
WordUnion::UByte
struct WordUnion::@2 UByte
WordUnion::HighByte
uint8_t HighByte
Definition: LongUnion.h:39
Aircondition_LG::setType
void setType(bool aIsWallType)
Definition: ac_LG.hpp:63
LG_COMMAND_TIMER_OFF
#define LG_COMMAND_TIMER_OFF
Definition: ac_LG.h:88
LG_ENERGY_SAVING_OFF
#define LG_ENERGY_SAVING_OFF
Definition: ac_LG.h:56
Aircondition_LG::ACIsWallType
bool ACIsWallType
Definition: ac_LG.h:127
LG_COMMAND_ENERGY
#define LG_COMMAND_ENERGY
Definition: ac_LG.h:79
LG_MODE_FAN
#define LG_MODE_FAN
Definition: ac_LG.h:52
AC_MODE_DEHUMIDIFIYING
#define AC_MODE_DEHUMIDIFIYING
Definition: ac_LG.h:95
LG_MODE_HEATING
#define LG_MODE_HEATING
Definition: ac_LG.h:54
Aircondition_LG::sendTemperatureFanSpeedAndMode
void sendTemperatureFanSpeedAndMode()
Definition: ac_LG.hpp:263
Aircondition_LG::Mode
uint8_t Mode
Definition: ac_LG.h:133
LG_WALL_SWING_ON
#define LG_WALL_SWING_ON
Definition: ac_LG.h:58
ac_LG.h
LG_COMMAND_SWING
#define LG_COMMAND_SWING
Definition: ac_LG.h:76
LocalDebugLevelStart.h
SIZE_OF_FAN_SPEED_MAPPING_TABLE
#define SIZE_OF_FAN_SPEED_MAPPING_TABLE
Definition: ac_LG.hpp:59
LG_COMMAND_MODE
#define LG_COMMAND_MODE
Definition: ac_LG.h:85
Aircondition_LG::sendIRCommand
void sendIRCommand(uint16_t aCommand)
Definition: ac_LG.hpp:249
LG_SLEEP
#define LG_SLEEP
Definition: ac_LG.h:64
LG_COMMAND_JET
#define LG_COMMAND_JET
Definition: ac_LG.h:78
LG_SWITCH_ON_MASK
#define LG_SWITCH_ON_MASK
Definition: ac_LG.h:49
AC_FAN_TOWER
const int AC_FAN_TOWER[SIZE_OF_FAN_SPEED_MAPPING_TABLE]
Definition: ac_LG.hpp:60
INFO_PRINTLN
#define INFO_PRINTLN(...)
Definition: LocalDebugLevelStart.h:91
LG_LIGHT
#define LG_LIGHT
Definition: ac_LG.h:67
Aircondition_LG::sendCommandAndParameter
bool sendCommandAndParameter(char aCommand, int aParameter)
Definition: ac_LG.hpp:99
AC_MODE_HEATING
#define AC_MODE_HEATING
Definition: ac_LG.h:98
LG_COMMAND_CLEAR_ALL
#define LG_COMMAND_CLEAR_ALL
Definition: ac_LG.h:89
LongUnion.h
LG_COMMAND_TIMER_ON
#define LG_COMMAND_TIMER_ON
Definition: ac_LG.h:87
Aircondition_LG::FanIntensity
uint8_t FanIntensity
Definition: ac_LG.h:131
LG_MODE_AUTO
#define LG_MODE_AUTO
Definition: ac_LG.h:53
LG_MODE_DEHUMIDIFIYING
#define LG_MODE_DEHUMIDIFIYING
Definition: ac_LG.h:51
LG_ENERGY_SAVING_ON
#define LG_ENERGY_SAVING_ON
Definition: ac_LG.h:55
LG_COMMAND_SLEEP
#define LG_COMMAND_SLEEP
Definition: ac_LG.h:86
AC_MODE_FAN
#define AC_MODE_FAN
Definition: ac_LG.h:96
LG_SWING_OFF
#define LG_SWING_OFF
Definition: ac_LG.h:61
LG_AUTO_CLEAN_OFF
#define LG_AUTO_CLEAN_OFF
Definition: ac_LG.h:69
LG_CLEAR_ALL
#define LG_CLEAR_ALL
Definition: ac_LG.h:65
DEBUG_PRINTLN
#define DEBUG_PRINTLN(...)
Definition: LocalDebugLevelStart.h:80
IrSender
IRsend IrSender
Definition: IRSend.hpp:62
AC_MODE_AUTO
#define AC_MODE_AUTO
Definition: ac_LG.h:97
LG_COMMAND_TEMPERATURE_MINUS
#define LG_COMMAND_TEMPERATURE_MINUS
Definition: ac_LG.h:84
LG_ADDRESS
#define LG_ADDRESS
Definition: ac_LG.h:42
LG_MODE_COOLING
#define LG_MODE_COOLING
Definition: ac_LG.h:50
LG_TIMER_ON
#define LG_TIMER_ON
Definition: ac_LG.h:62
Aircondition_LG::PowerIsOn
bool PowerIsOn
Definition: ac_LG.h:128
LG_COMMAND_TEMPERATURE_PLUS
#define LG_COMMAND_TEMPERATURE_PLUS
Definition: ac_LG.h:83
AC_FAN_WALL
const int AC_FAN_WALL[SIZE_OF_FAN_SPEED_MAPPING_TABLE]
Definition: ac_LG.hpp:61
LG_SWING_ON
#define LG_SWING_ON
Definition: ac_LG.h:60
AC_MODE_COOLING
#define AC_MODE_COOLING
Definition: ac_LG.h:94
WordUnion::LowByte
uint8_t LowByte
Definition: LongUnion.h:38
LG_TIMER_OFF
#define LG_TIMER_OFF
Definition: ac_LG.h:63
WordUnion::UWord
uint16_t UWord
Definition: LongUnion.h:47
LG_COMMAND_OFF
#define LG_COMMAND_OFF
Definition: ac_LG.h:74
IRremoteInt.h
Contains all declarations required for the interface to IRremote. Could not be named IRremote....
Aircondition_LG::printMenu
void printMenu(Print *aSerial)
Definition: ac_LG.hpp:69
LocalDebugLevelEnd.h
IRsend::sendLG2
void sendLG2(uint8_t aAddress, uint16_t aCommand, int_fast8_t aNumberOfRepeats)
LG2 uses a special repeat.
Definition: ir_LG.hpp:168
LG_JET_ON
#define LG_JET_ON
Definition: ac_LG.h:57
LG_POWER_DOWN
#define LG_POWER_DOWN
Definition: ac_LG.h:66
LG_COMMAND_ON
#define LG_COMMAND_ON
Definition: ac_LG.h:75