[AVR]Arduino控制格力空调 好好好



[AVR]Arduino控制格力空调硬件版本是Nano3.0。
移植自IRRemote库。部分代码百度得到。格力空调编码百度一搜也能找到。代码演示的是制冷 26度 风量最大 的开、关机操作。
红外遥控必须使用快速pwm方法。用analogWrite的话只有几十Hz的速度远远达不到38kHz的载波要求;使用程序内微秒延迟的话代码比较杂乱,独占cpu,cpu没机会做别的事情了。所以必须使用快速pwm。

因为直接使用库的话只能接一个红外LED不能控制多个空调,所以把库里面用得到的红外发射代码择出来放程序里了,然后仔细研究了代码发现,择出来也没法控制多个空调,因为使用了快速pwm的方法,内置的俩定时器当一个用啦,所以只有一组pwm输出在pwm3号端口。

没办法只好从红外管的负极想办法,把4、5脚设置为灌电流后,程序可以控制多个红外线发射管了(3共用正极,4和5接两个LED的负极)。虽然多占一个端口但是可以同时控制多台空调了。

程序基本思路是使用pwm发生器来产生38Khz的红外载波信号。通过控制pwm发生器的开关来实现红外管的0、1输出和延迟。
也未必必须使用红外管,用红色发光管也能遥控空调但有效距离只有大概1米了。白色LED只有20厘米。

—————————————————-

#define TIMER_DISABLE_INTR  (TIMSK2 = 0)
#define SYSCLOCK  16000000
#define TIMER_CONFIG_KHZ(val) ({ \
const uint8_t pwmval = SYSCLOCK / 2000 / (val); \
TCCR2A               = _BV(WGM20); \
TCCR2B               = _BV(WGM22) | _BV(CS20); \
OCR2A                = pwmval; \
OCR2B                = pwmval / 3; \
})
#define TIMER_ENABLE_PWM    (TCCR2A |= _BV(COM2B1))
#define TIMER_DISABLE_PWM   (TCCR2A &= ~(_BV(COM2B1)))

void  mark (unsigned int time)
{
TIMER_ENABLE_PWM; // Enable pin 3 PWM output
if (time > 0) custom_delay_usec(time);
}

void  space (unsigned int time)
{
TIMER_DISABLE_PWM; // Disable pin 3 PWM output
if (time > 0) custom_delay_usec(time);
}

void custom_delay_usec(unsigned long uSecs)
{
if (uSecs > 4) {
unsigned long start = micros();
unsigned long endMicros = start + uSecs – 4;
if (endMicros < start) { // Check if overflow
while ( micros() > start ) {}
}
while ( micros() < endMicros ) {}
}
}

void sendpresumable()
{
mark(9000);
space(4500);
}

void send0()
{
mark(560);
space(565);
}


void send1()
{
mark(560);
space(1690);
}

void sendGree(byte ircode, byte len)
{
byte mask = 0×01;
for(int i = 0;i < len;i++)
{
if (ircode & mask)
{   send1();   }
else
{   send0();   }
mask <<= 1;
}
}

void open1()
{
TIMER_DISABLE_INTR; //Timer2 Overflow Interrupt
pinMode(3, OUTPUT);//PWM端口
digitalWrite(3, LOW); //PWM端口
digitalWrite(4, LOW);

TIMER_CONFIG_KHZ(38);//PWM端口频率KHz

sendpresumable();
//sendGree(0×31, 8);//000自动 100制冷 010除湿 110送风 001制热; 1开;00自动 10小风 01中风 11大风;0扫风;0睡眠//关
sendGree(0×39, 8);//000自动 100制冷 010除湿 110送风 001制热; 1开;00自动 10小风 01中风 11大风;0扫风;0睡眠//开
sendGree(0x0A, 8);//温度0000-16度 1000-17度 1100-18度…. 0111-30度 低位在后
sendGree(0×20, 8);
sendGree(0×50, 8);
sendGree(0×02, 3);
mark(560);
space(10000);
space(10000);
sendGree(0×00, 8);
sendGree(0×21, 8);
sendGree(0×00, 8);
sendGree(0xF0, 8);
mark(560);
space(0);
digitalWrite(4, HIGH);
}
void close1()
{
TIMER_DISABLE_INTR; //Timer2 Overflow Interrupt
pinMode(3, OUTPUT);//PWM端口
digitalWrite(3, LOW); //PWM端口
digitalWrite(4, LOW);
TIMER_CONFIG_KHZ(38);//PWM端口频率KHz

sendpresumable();
sendGree(0×31, 8);//000自动 100制冷 010除湿 110送风 001制热; 1开;00自动 10小风 01中风 11大风;0扫风;0睡眠//关
//sendGree(0×39, 8);//000自动 100制冷 010除湿 110送风 001制热; 1开;00自动 10小风 01中风 11大风;0扫风;0睡眠//开
sendGree(0x0A, 8);//温度0000-16度 1000-17度 1100-18度…. 0111-30度 低位在后
sendGree(0×20, 8);
sendGree(0×50, 8);
sendGree(0×02, 3);
mark(560);
space(10000);
space(10000);
sendGree(0×00, 8);
sendGree(0×21, 8);
sendGree(0×00, 8);
sendGree(0xF0, 8);
mark(560);
space(0);
digitalWrite(5, HIGH);
}
void open2()
{
TIMER_DISABLE_INTR; //Timer2 Overflow Interrupt
pinMode(3, OUTPUT);//PWM端口
digitalWrite(3, LOW); //PWM端口
digitalWrite(5, LOW);
TIMER_CONFIG_KHZ(38);//PWM端口频率KHz

sendpresumable();
//sendGree(0×31, 8);//000自动 100制冷 010除湿 110送风 001制热; 1开;00自动 10小风 01中风 11大风;0扫风;0睡眠//关
sendGree(0×39, 8);//000自动 100制冷 010除湿 110送风 001制热; 1开;00自动 10小风 01中风 11大风;0扫风;0睡眠//开
sendGree(0x0A, 8);//温度0000-16度 1000-17度 1100-18度…. 0111-30度 低位在后
sendGree(0×20, 8);
sendGree(0×50, 8);
sendGree(0×02, 3);
mark(560);
space(10000);
space(10000);
sendGree(0×00, 8);
sendGree(0×21, 8);
sendGree(0×00, 8);
sendGree(0xF0, 8);
mark(560);
space(0);
digitalWrite(4, HIGH);
}
void close2()
{
TIMER_DISABLE_INTR; //Timer2 Overflow Interrupt
pinMode(3, OUTPUT);//PWM端口
digitalWrite(3, LOW); //PWM端口
digitalWrite(5, LOW);
TIMER_CONFIG_KHZ(38);//PWM端口频率KHz

sendpresumable();
sendGree(0×31, 8);//000自动 100制冷 010除湿 110送风 001制热; 1开;00自动 10小风 01中风 11大风;0扫风;0睡眠//关
//sendGree(0×39, 8);//000自动 100制冷 010除湿 110送风 001制热; 1开;00自动 10小风 01中风 11大风;0扫风;0睡眠//开
sendGree(0x0A, 8);//温度0000-16度 1000-17度 1100-18度…. 0111-30度 低位在后
sendGree(0×20, 8);
sendGree(0×50, 8);
sendGree(0×02, 3);
mark(560);
space(10000);
space(10000);
sendGree(0×00, 8);
sendGree(0×21, 8);
sendGree(0×00, 8);
sendGree(0xF0, 8);
mark(560);
space(0);
digitalWrite(5, HIGH);
}

void setup()
{
pinMode(4,OUTPUT);
pinMode(5,OUTPUT);
digitalWrite(4, HIGH);
digitalWrite(5, HIGH);
}

void loop()
{
open1();
delay(500);
close1();
delay(500);
open2();
delay(500);
close2();
delay(500);
}