Sharp/IVT support, heatpumps should use 38 kHz carrier frequency

This commit is contained in:
ToniA
2015-11-03 19:40:48 +02:00
parent 21d05ca048
commit a8cd8956de
13 changed files with 236 additions and 37 deletions
+1 -1
View File
@@ -141,7 +141,7 @@ void CarrierHeatpumpIR::sendCarrier(IRSender& IR, uint8_t operatingMode, uint8_t
sendBuffer[8] = IR.bitReverse(checksum); sendBuffer[8] = IR.bitReverse(checksum);
// 40 kHz PWM frequency // 40 kHz PWM frequency
IR.setFrequency(40); IR.setFrequency(38);
// Header // Header
IR.mark(CARRIER_AIRCON1_HDR_MARK); IR.mark(CARRIER_AIRCON1_HDR_MARK);
+1 -1
View File
@@ -176,7 +176,7 @@ void FujitsuHeatpumpIR::sendFujitsuTestRun(IRSender& IR)
void FujitsuHeatpumpIR::sendFujitsuMsg(IRSender& IR, uint8_t msgSize, uint8_t *msg) void FujitsuHeatpumpIR::sendFujitsuMsg(IRSender& IR, uint8_t msgSize, uint8_t *msg)
{ {
// 40 kHz PWM frequency // 40 kHz PWM frequency
IR.setFrequency(40); IR.setFrequency(38);
// Header // Header
IR.mark(FUJITSU_AIRCON1_HDR_MARK); IR.mark(FUJITSU_AIRCON1_HDR_MARK);
+1 -1
View File
@@ -118,7 +118,7 @@ void MideaHeatpumpIR::sendMidea(IRSender& IR, uint8_t operatingMode, uint8_t fan
void MideaHeatpumpIR::sendMidearaw(IRSender& IR, uint8_t sendBuffer[]) void MideaHeatpumpIR::sendMidearaw(IRSender& IR, uint8_t sendBuffer[])
{ {
// 40 kHz PWM frequency // 40 kHz PWM frequency
IR.setFrequency(40); IR.setFrequency(38);
// Header // Header
IR.mark(MIDEA_AIRCON1_HDR_MARK); IR.mark(MIDEA_AIRCON1_HDR_MARK);
@@ -188,7 +188,7 @@ void MitsubishiHeatpumpIR::sendMitsubishi(IRSender& IR, uint8_t powerMode, uint8
MitsubishiTemplate[17] = checksum; MitsubishiTemplate[17] = checksum;
// 40 kHz PWM frequency // 40 kHz PWM frequency
IR.setFrequency(40); IR.setFrequency(38);
// The Mitsubishi data is repeated twice // The Mitsubishi data is repeated twice
for (int j=0; j<2; j++) { for (int j=0; j<2; j++) {
@@ -163,7 +163,7 @@ void PanasonicCKPHeatpumpIR::sendPanasonicCKP(IRSender& IR, uint8_t operatingMod
void PanasonicCKPHeatpumpIR::sendPanasonicCKPraw(IRSender& IR, uint8_t sendBuffer[]) void PanasonicCKPHeatpumpIR::sendPanasonicCKPraw(IRSender& IR, uint8_t sendBuffer[])
{ {
// 40 kHz PWM frequency // 40 kHz PWM frequency
IR.setFrequency(40); IR.setFrequency(38);
// Header, two first uint8_ts repeated // Header, two first uint8_ts repeated
IR.mark(PANASONIC_AIRCON1_HDR_MARK); IR.mark(PANASONIC_AIRCON1_HDR_MARK);
@@ -228,7 +228,7 @@ void PanasonicCKPHeatpumpIR::sendPanasonicCKPOnOffTimerCancel(IRSender& IR, bool
} }
// 40 kHz PWM frequency // 40 kHz PWM frequency
IR.setFrequency(40); IR.setFrequency(38);
for (int i=0; i<6; i++) { for (int i=0; i<6; i++) {
IR.mark(PANASONIC_AIRCON1_HDR_MARK); IR.mark(PANASONIC_AIRCON1_HDR_MARK);
+1 -1
View File
@@ -208,7 +208,7 @@ void PanasonicHeatpumpIR::sendPanasonic(IRSender& IR, uint8_t operatingMode, uin
panasonicTemplate[26] = checksum; panasonicTemplate[26] = checksum;
// 40 kHz PWM frequency // 40 kHz PWM frequency
IR.setFrequency(40); IR.setFrequency(38);
// Header // Header
IR.mark(PANASONIC_AIRCON2_HDR_MARK); IR.mark(PANASONIC_AIRCON2_HDR_MARK);
+1
View File
@@ -12,6 +12,7 @@ Currently supports at least these models
* Fujitsu Nocria AWYZ14 (remote control P/N AR-PZ2) * Fujitsu Nocria AWYZ14 (remote control P/N AR-PZ2)
* Mitsubishi MSZ FD-25, probably also FD-35 (remote control P/N KM09D 0052376) * Mitsubishi MSZ FD-25, probably also FD-35 (remote control P/N KM09D 0052376)
* Hisense AUD (remote control Y-H1-01, Y-H1-02(E), Y-J1, Y-E4-07) probably AUC model * Hisense AUD (remote control Y-H1-01, Y-H1-02(E), Y-J1, Y-E4-07) probably AUC model
* Sharp AY-ZP40KR (remote control P/N CRMC-A788JBEZ), possibly also IVT
## Instructions ## Instructions
+6 -6
View File
@@ -90,8 +90,8 @@ void SamsungHeatpumpIR::send(IRSender& IR, uint8_t powerModeCmd, uint8_t operati
void SamsungHeatpumpIR::sendSamsung(IRSender& IR, uint8_t powerMode, uint8_t operatingMode, uint8_t fanSpeed, uint8_t temperature, uint8_t swingV) void SamsungHeatpumpIR::sendSamsung(IRSender& IR, uint8_t powerMode, uint8_t operatingMode, uint8_t fanSpeed, uint8_t temperature, uint8_t swingV)
{ {
uint8_t SamsungTemplate[] = { 0x02, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, // Header part uint8_t SamsungTemplate[] = { 0x02, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, // Header part
0x01, 0xD2, 0x0F, 0x00, 0x00, 0x00, 0x00, // Always the same data on POWER messages 0x01, 0xD2, 0x0F, 0x00, 0x00, 0x00, 0x00, // Always the same data on POWER messages
0x01, 0x00, 0xFE, 0x71, 0x00, 0x00, 0x00 }; // The actual data is in this part, on uint8_ts 14-20 0x01, 0x00, 0xFE, 0x71, 0x00, 0x00, 0x00 }; // The actual data is in this part, on uint8_ts 14-20
uint8_t SamsungChecksum = 0; uint8_t SamsungChecksum = 0;
@@ -114,15 +114,15 @@ void SamsungHeatpumpIR::sendSamsung(IRSender& IR, uint8_t powerMode, uint8_t ope
// Set the vertical swing mode on the template message // Set the vertical swing mode on the template message
SamsungTemplate[16] = swingV; SamsungTemplate[16] = swingV;
// Calculate the uint8_t 15 checksum // Calculate the byte 15 checksum
// Count the number of ONE bits on message uint8_ts 15-20 // Count the number of ONE bits on message uint8_ts 15-20
for (uint8_t j=15; j<21; j++) { for (uint8_t j=15; j<21; j++) {
uint8_t Samsunguint8_t = SamsungTemplate[j]; uint8_t Samsungbyte = SamsungTemplate[j];
for (uint8_t i=0; i<8; i++) { for (uint8_t i=0; i<8; i++) {
if ( (Samsunguint8_t & 0x01) == 0x01 ) { if ( (Samsungbyte & 0x01) == 0x01 ) {
SamsungChecksum++; SamsungChecksum++;
} }
Samsunguint8_t >>= 1; Samsungbyte >>= 1;
} }
} }
+122
View File
@@ -0,0 +1,122 @@
#include <SharpHeatpumpIR.h>
SharpHeatpumpIR::SharpHeatpumpIR() : HeatpumpIR()
{
static const char PROGMEM model[] PROGMEM = "sharp";
static const char PROGMEM info[] PROGMEM = "{\"mdl\":\"sharp\",\"dn\":\"Sharp AY-ZP40KR\",\"mT\":18,\"xT\":32,\"fs\":3,\"maint\":[10]}}";
_model = model;
_info = info;
}
void SharpHeatpumpIR::send(IRSender& IR, uint8_t powerModeCmd, uint8_t operatingModeCmd, uint8_t fanSpeedCmd, uint8_t temperatureCmd, uint8_t swingVCmd, uint8_t swingHCmd)
{
// Sensible defaults for the heat pump mode
uint8_t powerMode = SHARP_AIRCON1_MODE_ON;
uint8_t operatingMode = SHARP_AIRCON1_MODE_HEAT;
uint8_t fanSpeed = SHARP_AIRCON1_FAN_AUTO;
uint8_t temperature = 23;
if (powerModeCmd == 0)
{
powerMode = SHARP_AIRCON1_MODE_OFF;
}
switch (operatingModeCmd)
{
case MODE_HEAT:
operatingMode = SHARP_AIRCON1_MODE_HEAT;
break;
case MODE_COOL:
operatingMode = SHARP_AIRCON1_MODE_COOL;
break;
case MODE_DRY:
operatingMode = SHARP_AIRCON1_MODE_DRY;
temperatureCmd = 10;
break;
case MODE_FAN:
operatingMode = SHARP_AIRCON1_MODE_COOL;
// Temperature needs to be set to 32 degrees for 'simulated' FAN mode
temperatureCmd = 32;
break;
case MODE_MAINT: // Maintenance mode is just the heat mode at +8 or +10, FAN5
operatingMode |= SHARP_AIRCON1_MODE_HEAT;
temperature = 10;
fanSpeedCmd = FAN_5;
break;
}
switch (fanSpeedCmd)
{
case FAN_AUTO:
fanSpeed = SHARP_AIRCON1_FAN_AUTO;
break;
case FAN_1:
fanSpeed = SHARP_AIRCON1_FAN1;
break;
case FAN_2:
fanSpeed = SHARP_AIRCON1_FAN2;
break;
case FAN_3:
fanSpeed = SHARP_AIRCON1_FAN3;
break;
}
if ( temperatureCmd > 16 && temperatureCmd < 32)
{
temperature = temperatureCmd;
}
sendSharp(IR, powerMode, operatingMode, fanSpeed, temperature);
}
void SharpHeatpumpIR::sendSharp(IRSender& IR, uint8_t powerMode, uint8_t operatingMode, uint8_t fanSpeed, uint8_t temperature)
{
uint8_t SharpTemplate[] = { 0xAA, 0x5A, 0xCF, 0x10, 0x00, 0x00, 0x00, 0x06, 0x08, 0x80, 0x04, 0xF0, 0x01 };
// 0 1 2 3 4 5 6 7 8 9 10 11 12
uint8_t checksum = 0x00;
// Set the power mode on the template message
SharpTemplate[5] = powerMode;
// Set the fan speed & operating mode on the template message
SharpTemplate[6] = fanSpeed | operatingMode;
// Set the temperature on the template message
if (temperature == 10) {
SharpTemplate[4] = 0x00; // Maintenance mode temperature
} else {
SharpTemplate[4] = (temperature - 17);
}
// Calculate the checksum
for (int i=0; i<12; i++) {
checksum ^= SharpTemplate[i];
}
checksum ^= SharpTemplate[12] & 0x0F;
checksum ^= (checksum >> 4);
checksum &= 0x0F;
SharpTemplate[12] |= (checksum << 4);
// 38 kHz PWM frequency
IR.setFrequency(38);
// Header
IR.mark(SHARP_AIRCON1_HDR_MARK);
IR.space(SHARP_AIRCON1_HDR_SPACE);
// Data
for (unsigned int i=0; i<sizeof(SharpTemplate); i++) {
IR.sendIRbyte(SharpTemplate[i], SHARP_AIRCON1_BIT_MARK, SHARP_AIRCON1_ZERO_SPACE, SHARP_AIRCON1_ONE_SPACE);
}
// End mark
IR.mark(SHARP_AIRCON1_BIT_MARK);
IR.space(0);
}
+42
View File
@@ -0,0 +1,42 @@
/*
Sharp AY-ZP40KR heatpump control (remote control P/N CRMC-A788JBEZ)
Probably also works on IVT (as those are Sharp units with different branding)
Also see: https://github.com/skarlsso/IRRemoteIVT/blob/master/IRRemoteIVT.ino
*/
#ifndef SharpHeatpumpIR_h
#define SharpHeatpumpIR_h
#include <HeatpumpIR.h>
// Sharp timing constants
#define SHARP_AIRCON1_HDR_MARK 3540 // 3820
#define SHARP_AIRCON1_HDR_SPACE 1720 // 1680
#define SHARP_AIRCON1_BIT_MARK 460 // 420
#define SHARP_AIRCON1_ONE_SPACE 1400 // 1250
#define SHARP_AIRCON1_ZERO_SPACE 430 // 330
// Sharp codes
#define SHARP_AIRCON1_MODE_HEAT 0x01
#define SHARP_AIRCON1_MODE_COOL 0x02
#define SHARP_AIRCON1_MODE_DRY 0x03
#define SHARP_AIRCON1_MODE_OFF 0x21 // Power OFF
#define SHARP_AIRCON1_MODE_ON 0x31 // Power ON
#define SHARP_AIRCON1_FAN_AUTO 0x20 // Fan speed
#define SHARP_AIRCON1_FAN1 0x30
#define SHARP_AIRCON1_FAN2 0x50
#define SHARP_AIRCON1_FAN3 0x70
class SharpHeatpumpIR : public HeatpumpIR
{
public:
SharpHeatpumpIR();
void send(IRSender& IR, uint8_t powerModeCmd, uint8_t operatingModeCmd, uint8_t fanSpeedCmd, uint8_t temperatureCmd, uint8_t swingVCmd, uint8_t swingHCmd);
private:
void sendSharp(IRSender& IR, uint8_t powerMode, uint8_t operatingMode, uint8_t fanSpeed, uint8_t temperature);
};
#endif
@@ -7,6 +7,7 @@
#include <MideaHeatpumpIR.h> #include <MideaHeatpumpIR.h>
#include <MitsubishiHeatpumpIR.h> #include <MitsubishiHeatpumpIR.h>
#include <SamsungHeatpumpIR.h> #include <SamsungHeatpumpIR.h>
#include <SharpHeatpumpIR.h>
IRSender irSender(3); // IR led on Duemilanove digital pin 3 IRSender irSender(3); // IR led on Duemilanove digital pin 3
@@ -14,7 +15,7 @@ IRSender irSender(3); // IR led on Duemilanove digital pin 3
HeatpumpIR *heatpumpIR[] = {new PanasonicCKPHeatpumpIR(), new PanasonicDKEHeatpumpIR(), new PanasonicJKEHeatpumpIR(), HeatpumpIR *heatpumpIR[] = {new PanasonicCKPHeatpumpIR(), new PanasonicDKEHeatpumpIR(), new PanasonicJKEHeatpumpIR(),
new PanasonicNKEHeatpumpIR(), new CarrierHeatpumpIR(), new MideaHeatpumpIR(), new PanasonicNKEHeatpumpIR(), new CarrierHeatpumpIR(), new MideaHeatpumpIR(),
new FujitsuHeatpumpIR(), new MitsubishiFDHeatpumpIR(), new MitsubishiFEHeatpumpIR(), new FujitsuHeatpumpIR(), new MitsubishiFDHeatpumpIR(), new MitsubishiFEHeatpumpIR(),
new SamsungHeatpumpIR(), NULL}; new SamsungHeatpumpIR(), new SharpHeatpumpIR(), NULL};
void setup() void setup()
{ {
+1
View File
@@ -11,6 +11,7 @@ MitsubishiHeatpumpIR KEYWORD1
MitsubishiFDHeatpumpIR KEYWORD1 MitsubishiFDHeatpumpIR KEYWORD1
MitsubishiFEHeatpumpIR KEYWORD1 MitsubishiFEHeatpumpIR KEYWORD1
SamsungHeatpumpIR KEYWORD1 SamsungHeatpumpIR KEYWORD1
SharpHeatpumpIR KEYWORD1
IRSender KEYWORD1 IRSender KEYWORD1
@@ -1,6 +1,38 @@
#include <Arduino.h> /**
* The MySensors Arduino library handles the wireless radio link and protocol
* between your home built sensors/actuators and HA controller of choice.
* The sensors forms a self healing radio network with optional repeaters. Each
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
* network topology allowing messages to be routed to nodes.
*
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
* Copyright (C) 2013-2015 Sensnology AB
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
*
* Documentation: http://www.mysensors.org
* Support Forum: http://forum.mysensors.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
*******************************
*
* REVISION HISTORY
* Version 1.0 - Toni A - https://github.com/ToniA/arduino-heatpumpir
*
* DESCRIPTION
* Heatpump controller
*/
// HeatpumpIR libraries, https://github.com/ToniA/arduino-heatpumpir // Enable debug prints to serial monitor
#define MY_DEBUG
// Enable and select radio type attached
#define MY_RADIO_NRF24
//#define MY_RADIO_RFM69
// HeatpumpIR libraries,
#include <FujitsuHeatpumpIR.h> #include <FujitsuHeatpumpIR.h>
#include <PanasonicCKPHeatpumpIR.h> #include <PanasonicCKPHeatpumpIR.h>
#include <PanasonicHeatpumpIR.h> #include <PanasonicHeatpumpIR.h>
@@ -8,19 +40,19 @@
#include <MideaHeatpumpIR.h> #include <MideaHeatpumpIR.h>
#include <MitsubishiHeatpumpIR.h> #include <MitsubishiHeatpumpIR.h>
#include <SamsungHeatpumpIR.h> #include <SamsungHeatpumpIR.h>
#include <SharpHeatpumpIR.h>
// Timer library, https://github.com/JChristensen/Timer // Timer library, https://github.com/JChristensen/Timer
#include <Timer.h> #include <Timer.h>
// MySensors libraries // MySensors libraries
#include <MySensor.h>
#include <SPI.h> #include <SPI.h>
#include <MySensor.h>
// Child ID's of this node // Child ID's of this node
#define CHILD_1 1 #define CHILD_1 1
// MySensors definitions // MySensors definitions
MySensor gw;
MyMessage irMsg(CHILD_1, V_IR_RECEIVE); MyMessage irMsg(CHILD_1, V_IR_RECEIVE);
// -- Hacks for Domoticz start // -- Hacks for Domoticz start
@@ -41,7 +73,8 @@ HeatpumpIR *heatpumpIR[] = { new PanasonicCKPHeatpumpIR(), // 0, keep this if yo
new FujitsuHeatpumpIR(), // 6 new FujitsuHeatpumpIR(), // 6
new MitsubishiFDHeatpumpIR(), // 7 new MitsubishiFDHeatpumpIR(), // 7
new MitsubishiFEHeatpumpIR(), // 8 new MitsubishiFEHeatpumpIR(), // 8
new SamsungHeatpumpIR() // 9 new SamsungHeatpumpIR(), // 9
new SharpHeatpumpIR() // 10
}; };
// IR led on PWM output-capable digital pin 3 // IR led on PWM output-capable digital pin 3
@@ -54,6 +87,7 @@ int8_t panasonicCKPTimer = 0;
// Number of supported models // Number of supported models
byte models = 0; byte models = 0;
void setup() void setup()
{ {
Serial.begin(115200); Serial.begin(115200);
@@ -63,33 +97,31 @@ void setup()
models = sizeof(heatpumpIR) / sizeof(HeatpumpIR*); models = sizeof(heatpumpIR) / sizeof(HeatpumpIR*);
Serial.print(F("Number of supported models: ")); Serial.println(models); Serial.print(F("Number of supported models: ")); Serial.println(models);
// Auto-assign the node ID, do not forward messages
gw.begin(incomingMessage, AUTO, false);
// Send the sketch version information to the gateway and Controller
gw.sendSketchInfo("Heatpump Sensor", "1.0");
// Register a sensors to the MySensors Gateway
gw.present(CHILD_1, S_IR, "IR sender");
// -- Hacks for Domoticz start
gw.present(CHILD_2, S_INFO, "IR data");
gw.present(CHILD_3, S_LIGHT, "IR send");
// The TEXT sensor is not created in Domoticz before data is sent // The TEXT sensor is not created in Domoticz before data is sent
gw.send(textMsg.setSensor(CHILD_2).set("00000000")); send(textMsg.setSensor(CHILD_2).set("00000000"));
// -- Hacks for Domoticz end // -- Hacks for Domoticz end
} }
void presentation() {
// Send the sketch version information to the gateway and Controller
sendSketchInfo("Heatpump Sensor", "1.0");
// Register a sensors to the MySensors Gateway
present(CHILD_1, S_IR, "IR sender");
// -- Hacks for Domoticz start
present(CHILD_2, S_INFO, "IR data");
present(CHILD_3, S_LIGHT, "IR send");
}
void loop() void loop()
{ {
gw.process();
timer.update(); timer.update();
} }
// Handle incoming messages from the MySensors Gateway // Handle incoming messages from the MySensors Gateway
void incomingMessage(const MyMessage &message) { void receive(const MyMessage &message) {
const char *irData; const char *irData;
@@ -105,7 +137,7 @@ void incomingMessage(const MyMessage &message) {
else if (message.type==V_LIGHT) { else if (message.type==V_LIGHT) {
// When the button is pressed on Domoticz, request the value of the TEXT sensor // When the button is pressed on Domoticz, request the value of the TEXT sensor
Serial.println(F("Requesting IR code from Domoticz...")); Serial.println(F("Requesting IR code from Domoticz..."));
gw.request(CHILD_2, V_TEXT, 0); request(CHILD_2, V_TEXT, 0);
} else if (message.type==V_TEXT) { } else if (message.type==V_TEXT) {
// TEXT sensor value is received as a result of the previous step // TEXT sensor value is received as a result of the previous step
Serial.println(F("IR code received from Domoticz...")); Serial.println(F("IR code received from Domoticz..."));
@@ -117,7 +149,7 @@ void incomingMessage(const MyMessage &message) {
sendHeatpumpIRCommand(irData); sendHeatpumpIRCommand(irData);
// Set the Domoticz switch back to 'OFF' state // Set the Domoticz switch back to 'OFF' state
gw.send(sendMsg.setSensor(CHILD_3).set(0)); send(sendMsg.setSensor(CHILD_3).set(0));
} }
// -- Hacks for Domoticz end // -- Hacks for Domoticz end
} }