IMG_20181209_170405.jpg (163.42 KB, 下載次數: 73)
下載附件
2018-12-9 17:27 上傳
硬件:
Arduino UNO
紅外遙控接受接受模塊
LCD12864 液晶顯示屏
紅外發射器
代碼:
#include "InfraredRemote.h"
#include "LCD12864RSPI.h" //3,8,9 引腳
#define AR_SIZE( a ) sizeof( a ) / sizeof( a[0] )
unsigned char show0[]={0xBA, 0xEC,0xCD, 0xE2,0xD2, 0xA3,0xBF, 0xD8,0xB6, 0xE6,0xBB, 0xFA}; //紅外遙控舵機
unsigned char show1[]={0xD2, 0xA3,0xBF, 0xD8,0xD6, 0xB8,0xC1, 0xEE,0x3A, 0x00}; //遙控指令:
unsigned char show2[]={0xD0, 0xFD,0xD7, 0xAA,0xBD, 0xC7,0xB6, 0xC8,0x3A, 0x00}; //旋轉角度:
unsigned char show3[]={0x28, 0x00,0xB0, 0xB4,0x30, 0x00,0xB8, 0xB4,0xD4, 0xAD,0x29, 0x00}; //(按0復原)
#define PWM_pin 2 //舵機引腳
int pulsewidth = 0; //高電平時間
char d[3]; //定義年值存儲數組,3位
void setup()
{
Serial.begin(9600);
pinMode(PWM_pin,OUTPUT);
pinMode(IR_IN,INPUT_PULLUP);//設置紅外接收引腳為輸入
Serial.flush(); //清除串口緩沖器內容函數。
timer1_init();//定時器初始化
startRun(0);
LCDA.Initialise();
delay(100);
LCDA.DisplayString(0,1,show0,AR_SIZE(show0));
LCDA.DisplayString(1,0,show1,AR_SIZE(show1));
LCDA.DisplayString(1,5," ",AR_SIZE(" "));
LCDA.DisplayString(2,0,show2,AR_SIZE(show1));
LCDA.DisplayString(2,5,"0",AR_SIZE("0"));
LCDA.DisplayString(3,1,show3,AR_SIZE(show3));
}
void loop()
{
remote_decode(); //譯碼
if( adrL_code == 0x45 ) {
LCDA.DisplayString(1,5," 1 ",AR_SIZE(" 1 "));
//Serial.println("1");
startRun(10);
} else if( adrL_code == 0x46) {
LCDA.DisplayString(1,5," 2 ",AR_SIZE(" 2 "));
//Serial.println("2");
startRun(20);
}else if( adrL_code == 0x47 ) {
LCDA.DisplayString(1,5," 3 ",AR_SIZE(" 3 "));
//Serial.println("3");
startRun(30);
} else if( adrL_code == 0x44 ) {
LCDA.DisplayString(1,5," 4 ",AR_SIZE(" 4 "));
//Serial.println("4");
startRun(40);
} else if( adrL_code == 0x40 ) {
LCDA.DisplayString(1,5," 5 ",AR_SIZE(" 5 "));
//Serial.println("5");
startRun(50);
} else if( adrL_code == 0x43 ) {
LCDA.DisplayString(1,5," 6 ",AR_SIZE(" 6 "));
//Serial.println("6");
startRun(60);
} else if( adrL_code == 0x07 ) {
LCDA.DisplayString(1,5," 7 ",AR_SIZE(" 7 "));
//Serial.println("7");
startRun(70);
} else if( adrL_code == 0x15) {
LCDA.DisplayString(1,5," 8 ",AR_SIZE(" 8 "));
//Serial.println("8");
startRun(80);
} else if( adrL_code == 0x09 ){
LCDA.DisplayString(1,5," 9 ",AR_SIZE(" 9 "));
//Serial.println("9");
startRun(90);
} else if( adrL_code == 0x19) {
LCDA.DisplayString(1,5," 0 ",AR_SIZE(" 0 "));
//Serial.println("0");
startRun(0);
} else if( adrL_code == 0x16) {
LCDA.DisplayString(1,5," * ",AR_SIZE(" * "));
//Serial.println("*");
startRun(100);
} else if( adrL_code == 0x0d) {
LCDA.DisplayString(1,5," # ",AR_SIZE(" # "));
//Serial.println("#");
startRun(110);
} else if( adrL_code == 0x18) {
LCDA.DisplayString(1,5," Up",AR_SIZE(" Up"));
//Serial.println("Up");
startRun(120);
} else if( adrL_code == 0x08 ){
LCDA.DisplayString(1,5," L ",AR_SIZE(" L "));
//Serial.println("left");
startRun(130);
} else if( adrL_code == 0x1C ){
LCDA.DisplayString(1,5," OK",AR_SIZE(" OK"));
//Serial.println(" OK ");
startRun(140);
} else if(adrL_code == 0x5A) {
LCDA.DisplayString(1,5," R ",AR_SIZE(" R "));
//Serial.println("Right");
startRun(150);
} else if( adrL_code == 0x52 ) {
LCDA.DisplayString(1,5," D ",AR_SIZE(" D "));
//Serial.println("Down");
startRun(160);
}
adrL_code = 0x00;
adrH_code = 0x00;
ir_code = 0x00;
}
void servopulse(int servopin, int myangle) /*定義一個脈沖函數,用來模擬方式產生PWM值*/
{
pulsewidth = (myangle * 11) + 500; //將角度轉化為500-2480 的脈寬值
digitalWrite(servopin, HIGH); //將舵機接口電平置高
delayMicroseconds(pulsewidth);//延時脈寬值的微秒數
digitalWrite(servopin, LOW); //將舵機接口電平置低
delay(20 - pulsewidth / 1000); //延時周期內剩余時間
}
void startRun(int degree) {
if (degree >= 0 && degree <= 180) //判斷收到數據值是否符合范圍
{
//直接獲取旋轉角度
dtostrf(degree,3,0,d);
LCDA.DisplayString(2,5,(unsigned char *)d,AR_SIZE(d));
//Serial.print("moving servo to ");
//Serial.print(degree, DEC);
//Serial.println();
for (int i = 0; i <= 50; i++) //產生PWM個數,等效延時以保證能轉到響應角度
{
servopulse(PWM_pin, degree); //模擬產生PWM
}
}
}
InfraredRemote.h
#ifndef __InfraredRemote__H__
#define __InfraredRemote__H__
#include <Arduino.h>
#define IR_IN 11 //紅外接收
extern void timer1_init(void); //定時器初始化函數
extern char logic_value();//判斷邏輯值“0”和“1”子函數
extern void pulse_deal();//接收地址碼和命令碼脈沖函數
extern void remote_decode(void);
extern void remote_deal(void);//執行譯碼結果函數
extern unsigned int ir_code;// 用戶編碼值
extern unsigned int adrL_code;//命令碼
extern unsigned int adrH_code;//命令碼反碼
#endif
InfraredRemote.cpp
#include "InfraredRemote.h"
int Pulse_Width = 0;//存儲脈寬
unsigned int ir_code = 0x00;// 用戶編碼值
unsigned int adrL_code = 0x00;//命令碼
unsigned int adrH_code = 0x00;//命令碼反碼
void timer1_init(void)//定時器初始化函數
{
TCCR1A = 0X00;
TCCR1B = 0X05;//給定時器時鐘源 //64us進行一次計數器累加
TCCR1C = 0X00;
TCNT1 = 0X00;
TIMSK1 = 0X00; //禁止定時器溢出中斷
}
void remote_deal(void)//執行譯碼結果函數
{ //數據顯示
Serial.print("\nir_code:");
Serial.println(ir_code,HEX);//16進制顯示
Serial.print("adrL_code:");
Serial.println(adrL_code,HEX);//16進制顯示
Serial.print("adrH_code:");
Serial.println(adrH_code,HEX);//16進制顯示
}
char logic_value()//判斷邏輯值“0”和“1”子函數
{
TCNT1 = 0X00;
while(!(digitalRead(IR_IN))); //低等待
Pulse_Width=TCNT1;
TCNT1=0;
if(Pulse_Width>=7&&Pulse_Width<=10)//低電平560us
{
while(digitalRead(IR_IN));//是高就等待
Pulse_Width=TCNT1;
TCNT1=0;
if(Pulse_Width>=7&&Pulse_Width<=10)//接著高電平560us
return 0;
else if(Pulse_Width>=25&&Pulse_Width<=27) //接著高電平1.7ms
return 1;
}
return -1;
}
void pulse_deal()//接收地址碼和命令碼脈沖函數
{
int i;
int j;
ir_code=0x00;// 清零
adrL_code=0x00;// 清零
adrH_code=0x00;// 清零
//解析遙控器編碼中的用戶編碼值
for(i = 0 ; i < 16; i++)
{
if(logic_value() == 1) //是1
ir_code |= (1<<i);//保存鍵值
}
//解析遙控器編碼中的命令碼
for(i = 0 ; i < 8; i++)
{
if(logic_value() == 1) //是1
adrL_code |= (1<<i);//保存鍵值
}
//解析遙控器編碼中的命令碼反碼
for(j = 0 ; j < 8; j++)
{
if(logic_value() == 1) //是1
adrH_code |= (1<<j);//保存鍵值
}
remote_deal();
}
void remote_decode(void)//譯碼函數
{
TCNT1=0X00;
while(digitalRead(IR_IN))//是高就等待
{
//if(TCNT1>=1563) //當高電平持續時間超過100ms,表明此時沒有按鍵按下
//{
// ir_code=0x00ff;// 用戶編碼值
// adrL_code=0x00;//鍵碼前一個字節值
// adrH_code=0x00;//鍵碼后一個字節值
// return;
//}
}
//如果高電平持續時間不超過100ms
TCNT1=0X00;
while(!(digitalRead(IR_IN))); //低等待
Pulse_Width=TCNT1;
TCNT1=0;
if(Pulse_Width>=140&&Pulse_Width<=141)//9ms
{
while(digitalRead(IR_IN));//是高就等待
Pulse_Width=TCNT1;
TCNT1=0;
if(Pulse_Width>=68&&Pulse_Width<=72)//4.5ms
{
pulse_deal();
return;
}
else if(Pulse_Width>=34&&Pulse_Width<=36)//2.25ms
{
while(!(digitalRead(IR_IN)));//低等待
Pulse_Width=TCNT1;
TCNT1=0;
if(Pulse_Width>=7&&Pulse_Width<=10)//560us
{
return;
}
}
}
}
|