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);
// 40 kHz PWM frequency
IR.setFrequency(40);
IR.setFrequency(38);
// Header
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)
{
// 40 kHz PWM frequency
IR.setFrequency(40);
IR.setFrequency(38);
// Header
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[])
{
// 40 kHz PWM frequency
IR.setFrequency(40);
IR.setFrequency(38);
// Header
IR.mark(MIDEA_AIRCON1_HDR_MARK);
@@ -188,7 +188,7 @@ void MitsubishiHeatpumpIR::sendMitsubishi(IRSender& IR, uint8_t powerMode, uint8
MitsubishiTemplate[17] = checksum;
// 40 kHz PWM frequency
IR.setFrequency(40);
IR.setFrequency(38);
// The Mitsubishi data is repeated twice
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[])
{
// 40 kHz PWM frequency
IR.setFrequency(40);
IR.setFrequency(38);
// Header, two first uint8_ts repeated
IR.mark(PANASONIC_AIRCON1_HDR_MARK);
@@ -228,7 +228,7 @@ void PanasonicCKPHeatpumpIR::sendPanasonicCKPOnOffTimerCancel(IRSender& IR, bool
}
// 40 kHz PWM frequency
IR.setFrequency(40);
IR.setFrequency(38);
for (int i=0; i<6; i++) {
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;
// 40 kHz PWM frequency
IR.setFrequency(40);
IR.setFrequency(38);
// Header
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)
* 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
* Sharp AY-ZP40KR (remote control P/N CRMC-A788JBEZ), possibly also IVT
## 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)
{
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, 0x00, 0xFE, 0x71, 0x00, 0x00, 0x00 }; // The actual data is in this part, on uint8_ts 14-20
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
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
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
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++) {
if ( (Samsunguint8_t & 0x01) == 0x01 ) {
if ( (Samsungbyte & 0x01) == 0x01 ) {
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 <MitsubishiHeatpumpIR.h>
#include <SamsungHeatpumpIR.h>
#include <SharpHeatpumpIR.h>
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(),
new PanasonicNKEHeatpumpIR(), new CarrierHeatpumpIR(), new MideaHeatpumpIR(),
new FujitsuHeatpumpIR(), new MitsubishiFDHeatpumpIR(), new MitsubishiFEHeatpumpIR(),
new SamsungHeatpumpIR(), NULL};
new SamsungHeatpumpIR(), new SharpHeatpumpIR(), NULL};
void setup()
{
+1
View File
@@ -11,6 +11,7 @@ MitsubishiHeatpumpIR KEYWORD1
MitsubishiFDHeatpumpIR KEYWORD1
MitsubishiFEHeatpumpIR KEYWORD1
SamsungHeatpumpIR KEYWORD1
SharpHeatpumpIR 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 <PanasonicCKPHeatpumpIR.h>
#include <PanasonicHeatpumpIR.h>
@@ -8,19 +40,19 @@
#include <MideaHeatpumpIR.h>
#include <MitsubishiHeatpumpIR.h>
#include <SamsungHeatpumpIR.h>
#include <SharpHeatpumpIR.h>
// Timer library, https://github.com/JChristensen/Timer
#include <Timer.h>
// MySensors libraries
#include <MySensor.h>
#include <SPI.h>
#include <MySensor.h>
// Child ID's of this node
#define CHILD_1 1
// MySensors definitions
MySensor gw;
MyMessage irMsg(CHILD_1, V_IR_RECEIVE);
// -- Hacks for Domoticz start
@@ -41,7 +73,8 @@ HeatpumpIR *heatpumpIR[] = { new PanasonicCKPHeatpumpIR(), // 0, keep this if yo
new FujitsuHeatpumpIR(), // 6
new MitsubishiFDHeatpumpIR(), // 7
new MitsubishiFEHeatpumpIR(), // 8
new SamsungHeatpumpIR() // 9
new SamsungHeatpumpIR(), // 9
new SharpHeatpumpIR() // 10
};
// IR led on PWM output-capable digital pin 3
@@ -54,6 +87,7 @@ int8_t panasonicCKPTimer = 0;
// Number of supported models
byte models = 0;
void setup()
{
Serial.begin(115200);
@@ -63,33 +97,31 @@ void setup()
models = sizeof(heatpumpIR) / sizeof(HeatpumpIR*);
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
gw.send(textMsg.setSensor(CHILD_2).set("00000000"));
send(textMsg.setSensor(CHILD_2).set("00000000"));
// -- 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()
{
gw.process();
timer.update();
}
// Handle incoming messages from the MySensors Gateway
void incomingMessage(const MyMessage &message) {
void receive(const MyMessage &message) {
const char *irData;
@@ -105,7 +137,7 @@ void incomingMessage(const MyMessage &message) {
else if (message.type==V_LIGHT) {
// When the button is pressed on Domoticz, request the value of the TEXT sensor
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) {
// TEXT sensor value is received as a result of the previous step
Serial.println(F("IR code received from Domoticz..."));
@@ -117,7 +149,7 @@ void incomingMessage(const MyMessage &message) {
sendHeatpumpIRCommand(irData);
// 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
}
@@ -207,4 +239,4 @@ void panasonicCancelTimer()
panasonicCKPHeatpumpIR->sendPanasonicCKPCancelTimer(irSender);
Serial.println(F("The TIMER led should now be OFF"));
}
}