Skip to content

Commit 964bd60

Browse files
jonnygrahamcrankyoldgit
authored andcommitted
Add support for Fujitsu (#259)
Qudos to @jonnygraham for this.
1 parent 6456015 commit 964bd60

File tree

9 files changed

+539
-17
lines changed

9 files changed

+539
-17
lines changed

.github/Contributors.md

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
## Contributors of this project
2-
### Main contributors & maintainers
3-
- [Mark Szabo](https://github.com/markszabo/) : Initial IR sending on ESP8266
4-
- [Sébastien Warin](https://github.com/sebastienwarin/) (http://sebastien.warin.fr) : Initial IR receiving on ESP8266
5-
- [David Conran](https://github.com/crankyoldgit/)
6-
- [Roi Dayan](https://github.com/roidayan/)
7-
- [Marcos de Alcântara Marinho](https://github.com/marcosamarinho/)
8-
- [Massimiliano Pinto](https://github.com/pintomax/)
9-
- [Darsh Patel](https://github.com/darshkpatel/)
10-
11-
All contributors can be found on the [contributors site](https://github.com/markszabo/IRremoteESP8266/graphs/contributors).
12-
13-
### Contributors of the [original project](https://github.com/z3t0/Arduino-IRremote) can be found on the [original project's contributors page](https://github.com/z3t0/Arduino-IRremote/blob/master/Contributors.md)
1+
## Contributors of this project
2+
### Main contributors & maintainers
3+
- [Mark Szabo](https://github.com/markszabo/) : Initial IR sending on ESP8266
4+
- [Sébastien Warin](https://github.com/sebastienwarin/) (http://sebastien.warin.fr) : Initial IR receiving on ESP8266
5+
- [David Conran](https://github.com/crankyoldgit/)
6+
- [Roi Dayan](https://github.com/roidayan/)
7+
- [Marcos de Alcântara Marinho](https://github.com/marcosamarinho/)
8+
- [Massimiliano Pinto](https://github.com/pintomax/)
9+
- [Darsh Patel](https://github.com/darshkpatel/)
10+
- [Jonny Graham](https://github.com/jonnygraham/)
11+
12+
All contributors can be found on the [contributors site](https://github.com/markszabo/IRremoteESP8266/graphs/contributors).
13+
14+
### Contributors of the [original project](https://github.com/z3t0/Arduino-IRremote) can be found on the [original project's contributors page](https://github.com/z3t0/Arduino-IRremote/blob/master/Contributors.md)
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright 2017 Jonny Graham
2+
#include <IRsend.h>
3+
#include <ir_Fujitsu.h>
4+
5+
IRFujitsuAC fujitsu(5); // IR led controlled by Pin D1.
6+
7+
void printState() {
8+
// Display the settings.
9+
Serial.println("Fujitsu A/C remote is in the following state:");
10+
Serial.printf(" Command:%d, Mode: %d, Temp: %dC, Fan Speed: %d," \
11+
" Swing Mode: %d\n",
12+
fujitsu.getCmd(), fujitsu.getMode(), fujitsu.getTemp(),
13+
fujitsu.getFanSpeed(), fujitsu.getSwing());
14+
// Display the encoded IR sequence.
15+
unsigned char* ir_code = fujitsu.getRaw();
16+
Serial.print("IR Code: 0x");
17+
for (uint8_t i = 0; i < FUJITSU_AC_STATE_LENGTH; i++)
18+
Serial.printf("%02X", ir_code[i]);
19+
Serial.println();
20+
}
21+
22+
void setup() {
23+
fujitsu.begin();
24+
Serial.begin(115200);
25+
delay(200);
26+
27+
// Set up what we want to send. See ir_Mitsubishi.cpp for all the options.
28+
Serial.println("Default state of the remote.");
29+
printState();
30+
Serial.println("Setting desired state for A/C.");
31+
fujitsu.setCmd(FUJITSU_AC_CMD_TURN_ON);
32+
fujitsu.setSwing(FUJITSU_AC_SWING_BOTH);
33+
fujitsu.setMode(FUJITSU_AC_MODE_COOL);
34+
fujitsu.setFanSpeed(FUJITSU_AC_FAN_HIGH);
35+
fujitsu.setTemp(24);
36+
}
37+
38+
void loop() {
39+
// Now send the IR signal.
40+
Serial.println("Sending IR command to A/C ...");
41+
fujitsu.send();
42+
printState();
43+
delay(5000);
44+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[platformio]
2+
lib_extra_dirs = ../../
3+
src_dir=.
4+
5+
[common]
6+
build_flags =
7+
lib_deps_builtin =
8+
lib_deps_external =
9+
10+
[env:nodemcuv2]
11+
platform = espressif8266
12+
framework = arduino
13+
board = nodemcuv2
14+
build_flags = ${common.build_flags}
15+
lib_deps =
16+
${common.lib_deps_builtin}
17+
${common.lib_deps_external}

src/IRremoteESP8266.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
*
3232
* Updated by sillyfrog for Daikin, adopted from
3333
* (https://github.com/mharizanov/Daikin-AC-remote-control-over-the-Internet/)
34-
*
34+
* Fujitsu A/C code added by jonnygraham
3535
* GPL license, all text above must be included in any redistribution
3636
****************************************************/
3737

@@ -107,6 +107,9 @@
107107
#define DECODE_MITSUBISHI_AC false // Not written.
108108
#define SEND_MITSUBISHI_AC true
109109

110+
#define DECODE_FUJITSU_AC false // Not written.
111+
#define SEND_FUJITSU_AC true
112+
110113
#define DECODE_DAIKIN false // Not finished.
111114
#define SEND_DAIKIN true
112115

@@ -179,6 +182,7 @@ enum decode_type_t {
179182
#define MITSUBISHI_MIN_REPEAT 1U // Based on marcosamarinho's code.
180183
#define MITSUBISHI_AC_STATE_LENGTH 18U
181184
#define MITSUBISHI_AC_MIN_REPEAT 1U
185+
#define FUJITSU_AC_MIN_REPEAT 0U
182186
#define NEC_BITS 32U
183187
#define PANASONIC_BITS 48U
184188
#define PANASONIC_MANUFACTURER 0x4004ULL

src/IRsend.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,11 @@ class IRsend {
140140
uint16_t nbytes = MITSUBISHI_AC_STATE_LENGTH,
141141
uint16_t repeat = MITSUBISHI_AC_MIN_REPEAT);
142142
#endif
143+
#if SEND_FUJITSU_AC
144+
void sendFujitsuAC(unsigned char data[],
145+
uint16_t nbytes,
146+
uint16_t repeat = FUJITSU_AC_MIN_REPEAT);
147+
#endif
143148
#if SEND_GLOBALCACHE
144149
void sendGC(uint16_t buf[], uint16_t len);
145150
#endif

src/ir_Fujitsu.cpp

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
// Copyright 2017 Jonny Graham
2+
#include "ir_Fujitsu.h"
3+
#include <algorithm>
4+
#include "IRsend.h"
5+
6+
7+
// Fujitsu A/C support added by Jonny Graham
8+
9+
10+
// Fujitsu A/C
11+
// Ref:
12+
// These values are based on averages of measurements
13+
#define FUJITSU_AC_HDR_MARK 3224U
14+
#define FUJITSU_AC_HDR_SPACE 1574U
15+
#define FUJITSU_AC_BIT_MARK 448U
16+
#define FUJITSU_AC_ONE_SPACE 1182U
17+
#define FUJITSU_AC_ZERO_SPACE 367U
18+
#define FUJITSU_AC_TRL_MARK 448U
19+
#define FUJITSU_AC_TRL_SPACE 8100U
20+
21+
#if SEND_FUJITSU_AC
22+
// Send a Fujitsu A/C message.
23+
//
24+
// Args:
25+
// data: An array of bytes containing the IR command.
26+
// nbytes: Nr. of bytes of data in the array. (typically either
27+
// FUJITSU_AC_STATE_LENGTH or FUJITSU_AC_STATE_LENGTH_SHORT)
28+
// repeat: Nr. of times the message is to be repeated.
29+
// (Default = FUJITSU_AC_MIN_REPEAT).
30+
//
31+
// Status: BETA / Appears to be working.
32+
//
33+
void IRsend::sendFujitsuAC(unsigned char data[], uint16_t nbytes,
34+
uint16_t repeat) {
35+
// Set IR carrier frequency
36+
enableIROut(38);
37+
for (uint16_t r = 0; r <= repeat; ++r) {
38+
// Header
39+
mark(FUJITSU_AC_HDR_MARK);
40+
space(FUJITSU_AC_HDR_SPACE);
41+
// Data
42+
for (uint16_t i = 0; i < nbytes; i++)
43+
sendData(FUJITSU_AC_BIT_MARK, FUJITSU_AC_ONE_SPACE,
44+
FUJITSU_AC_BIT_MARK, FUJITSU_AC_ZERO_SPACE,
45+
data[i], 8, false);
46+
// Footer
47+
mark(FUJITSU_AC_TRL_MARK);
48+
space(FUJITSU_AC_TRL_SPACE);
49+
}
50+
}
51+
52+
// Code to emulate Fujitsu A/C IR remote control unit.
53+
54+
// Warning: Consider this very alpha code. Seems to work, but not validated.
55+
//
56+
// Equipment it seems compatible with:
57+
// * Fujitsu ASYG30LFCA with remote AR-RAH2E
58+
// * <Add models (A/C & remotes) you've gotten it working with here>
59+
// Initialise the object.
60+
IRFujitsuAC::IRFujitsuAC(uint16_t pin) : _irsend(pin) {
61+
stateReset();
62+
}
63+
64+
// Reset the state of the remote to a known good state/sequence.
65+
void IRFujitsuAC::stateReset() {
66+
_temp = 24;
67+
_fanSpeed = FUJITSU_AC_FAN_HIGH;
68+
_mode = FUJITSU_AC_MODE_COOL;
69+
_swingMode = FUJITSU_AC_SWING_BOTH;
70+
_cmd = FUJITSU_AC_CMD_TURN_ON;
71+
}
72+
73+
// Configure the pin for output.
74+
void IRFujitsuAC::begin() {
75+
_irsend.begin();
76+
}
77+
78+
// Send the current desired state to the IR LED.
79+
void IRFujitsuAC::send() {
80+
getRaw();
81+
uint8_t len = getCommandLength();
82+
_irsend.sendFujitsuAC(remote_state, len);
83+
}
84+
85+
uint8_t IRFujitsuAC::getCommandLength() {
86+
if (remote_state[5] != 0xFE)
87+
return FUJITSU_AC_STATE_LENGTH_SHORT;
88+
else
89+
return FUJITSU_AC_STATE_LENGTH;
90+
}
91+
92+
// Return a pointer to the internal state date of the remote.
93+
uint8_t* IRFujitsuAC::getRaw() {
94+
remote_state[0] = 0x14;
95+
remote_state[1] = 0x63;
96+
remote_state[2] = 0x00;
97+
remote_state[3] = 0x10;
98+
remote_state[4] = 0x10;
99+
bool fullCmd = false;
100+
switch (_cmd) {
101+
case FUJITSU_AC_CMD_TURN_OFF:
102+
remote_state[5] = 0x02;
103+
break;
104+
case FUJITSU_AC_CMD_STEP_HORIZ:
105+
remote_state[5] = 0x79;
106+
break;
107+
case FUJITSU_AC_CMD_STEP_VERT:
108+
remote_state[5] = 0x6C;
109+
break;
110+
default:
111+
remote_state[5] = 0xFE;
112+
fullCmd = true;
113+
break;
114+
}
115+
if (fullCmd) {
116+
remote_state[6] = 0x09;
117+
remote_state[7] = 0x30;
118+
uint8_t tempByte = _temp - FUJITSU_AC_MIN_TEMP;
119+
remote_state[8] = (_cmd == FUJITSU_AC_CMD_TURN_ON) | (tempByte << 4);
120+
remote_state[9] = _mode | 0 << 4; // timer off
121+
remote_state[10] = _fanSpeed | _swingMode << 4;
122+
remote_state[11] = 0; // timerOff values
123+
remote_state[12] = 0; // timerOff/on values
124+
remote_state[13] = 0; // timerOn values
125+
remote_state[14] = 0x20;
126+
// Checksum is the sum of the 8th to 16th bytes (ie remote_state[7]
127+
// thru remote_state[15]).
128+
// The checksum itself is stored in the 16th byte (ie remote_state[15]).
129+
// So we sum bytes 8th-15th...
130+
uint8_t checksum = 0;
131+
for (uint8_t i = 7 ; i < 15; ++i) {
132+
checksum += remote_state[i];
133+
}
134+
// and then do 0 - sum and store it in 16th.
135+
remote_state[15] = 0 - checksum;
136+
} else {
137+
// For the short codes, byte 7 is the inverse of byte 6
138+
remote_state[6] = ~remote_state[5];
139+
for (uint8_t i = 7; i < FUJITSU_AC_STATE_LENGTH; ++i) {
140+
remote_state[i] = 0;
141+
}
142+
}
143+
return remote_state;
144+
}
145+
146+
// Set the requested power state of the A/C to off.
147+
void IRFujitsuAC::off() {
148+
_cmd = FUJITSU_AC_CMD_TURN_OFF;
149+
}
150+
151+
void IRFujitsuAC::stepHoriz() {
152+
_cmd = FUJITSU_AC_CMD_STEP_HORIZ;
153+
}
154+
155+
void IRFujitsuAC::stepVert() {
156+
_cmd = FUJITSU_AC_CMD_STEP_VERT;
157+
}
158+
159+
// Set the requested command of the A/C.
160+
void IRFujitsuAC::setCmd(uint8_t cmd) {
161+
switch (cmd) {
162+
case FUJITSU_AC_CMD_TURN_OFF:
163+
case FUJITSU_AC_CMD_TURN_ON:
164+
case FUJITSU_AC_CMD_STAY_ON:
165+
case FUJITSU_AC_CMD_STEP_HORIZ:
166+
case FUJITSU_AC_CMD_STEP_VERT:
167+
break;
168+
default:
169+
cmd = FUJITSU_AC_CMD_STAY_ON;
170+
break;
171+
}
172+
_cmd = cmd;
173+
}
174+
175+
uint8_t IRFujitsuAC::getCmd() {
176+
return _cmd;
177+
}
178+
179+
// Set the temp. in deg C
180+
void IRFujitsuAC::setTemp(uint8_t temp) {
181+
temp = std::max((uint8_t) FUJITSU_AC_MIN_TEMP, temp);
182+
temp = std::min((uint8_t) FUJITSU_AC_MAX_TEMP, temp);
183+
_temp = temp;
184+
}
185+
186+
uint8_t IRFujitsuAC::getTemp() {
187+
return _temp;
188+
}
189+
190+
// Set the speed of the fan
191+
void IRFujitsuAC::setFanSpeed(uint8_t fanSpeed) {
192+
if (fanSpeed > FUJITSU_AC_FAN_QUIET)
193+
fanSpeed = FUJITSU_AC_FAN_HIGH; // Set the fan to maximum if out of range.
194+
_fanSpeed = fanSpeed;
195+
}
196+
uint8_t IRFujitsuAC::getFanSpeed() {
197+
return _fanSpeed;
198+
}
199+
200+
// Set the requested climate operation mode of the a/c unit.
201+
void IRFujitsuAC::setMode(uint8_t mode) {
202+
if (mode > FUJITSU_AC_MODE_HEAT)
203+
mode = FUJITSU_AC_MODE_HEAT; // Set the mode to maximum if out of range.
204+
_mode = mode;
205+
}
206+
207+
uint8_t IRFujitsuAC::getMode() {
208+
return _mode;
209+
}
210+
// Set the requested swing operation mode of the a/c unit.
211+
void IRFujitsuAC::setSwing(uint8_t swingMode) {
212+
if (swingMode > FUJITSU_AC_SWING_BOTH)
213+
swingMode = FUJITSU_AC_SWING_BOTH; // Set the mode to max if out of range
214+
_swingMode = swingMode;
215+
}
216+
217+
uint8_t IRFujitsuAC::getSwing() {
218+
return _swingMode;
219+
}
220+
221+
#endif

0 commit comments

Comments
 (0)