歡迎來到 黑吧安全網 聚焦網絡安全前沿資訊,精華內容,交流技術心得!

用家里舊的紅外遙控器控制樹莓派小車

來源:本站整理 作者:佚名 時間:2019-05-09 TAG: 我要投稿

0×01 前言
紅外遙控是一種無線、非接觸控制技術,在工業控制、航空航天、家電等領域都得到了廣泛應用。大部分的電視的遙控器,空調遙控器就都是紅外遙控。在baidu上檢索了樹莓派小車的各種控制方案,沒有找到紅外遙控的控制方案。所以本文嘗試使用紅外控制方案對樹莓派小車進行控制。
0×02 所需材料
1. 樹莓派小車。(樹莓派小車的安裝不是本文重點,如果讀者不熟悉小車的安裝,請自行搜索。)
2. 紅外接收頭
型號:VS1838B(價格很便宜,幾毛錢一個。)

3. 家里廢舊的紅外遙控器

0×03 紅外通訊協議學習
遙控器的基帶通信協議很多,大概有幾十種,用的最多的就是 NEC 協議了,下面開始了解下NEC協議。

圖 1 NEC 協議數據格式
NEC 協議的數據格式包括了引導碼、用戶碼、用戶碼(或者用戶碼反碼)、按鍵鍵碼和鍵碼反碼,最后一個停止位。停止位主要起隔離作用,一般不進行判斷,編程時我們也不予理會。其中數據編碼總共是 4 個字節 32 位。第一個字節是用戶碼,第二個字節可能也是用戶碼,或者是用戶碼的反碼,具體由生產商決定,第三個字節就是當前按鍵的鍵數據碼,而第四個字節是鍵數據碼的反碼,可用于對數據的糾錯。
注意: NEC 協議中的每一位數據本身也需要進行編碼,編碼后再進行載波調制。
引導碼:9ms 的載波+4.5ms 的空閑。
比特值“0”:560us 的載波+560us 的空閑。
比特值“1”:560us 的載波+1.68ms 的空閑。
紅外接收頭,當收到有載波的信號的時候,會輸出一個低電平,空閑的時候會輸出高電平,我們用邏輯分析儀抓出來一個紅外按鍵通過解碼后的圖形來了解一下,如圖 2 所示。

  圖 2  紅外遙控器按鍵編碼
從圖上可以看出,先是 9ms 載波加 4.5ms 空閑的起始碼,數據碼是低位在前,高位在后,數據碼第一個字節是 8 組 560us 的載波加 560us 的空閑,也就是 0×00,第二個字節是 8 組 560us的載波加 1.68ms 的空閑,可以看出來是 0xFF,這兩個字節就是用戶碼和用戶碼的反碼。按鍵的鍵碼二進制是 0x0C,反碼就是 0xF3,最后跟了一個 560us 載波停止位。對于我們的遙控器來說,不同的按鍵,就是鍵碼和鍵碼反碼的區分,用戶碼是一樣的。這樣我們就可以通過單片機的程序,把當前的按鍵的鍵碼給解析出來。
額外提一句:空調的遙控器比較特殊,用戶碼和鍵盤均存儲數據。
0×04 監聽紅外遙控
VS1838B的3個管腳分別為OUT、GND、VCC。當收到有載波的信號的時候,OUT管腳會輸出一個低電平,空閑的時候會輸出高電平。
本次將樹莓派的18引腳作為紅外接收引腳。
監聽紅外的機能代碼如下:
#define IR_INPUT_PIN  (18)
#define ERROR  (0xFE)
// 請事先破獲遙控器的各個鍵的按鍵碼,然后與小車的前、后、左、右、停的行為相對應。
// 以下5個值需要與遙控器的按鍵碼匹配。
#define IR_CONTROL_KEY_UP       (0x01)
#define IR_CONTROL_KEY_DOWN     (0x02)
#define IR_CONTROL_KEY_LEFT     (0x03)
#define IR_CONTROL_KEY_RIGHT    (0x04)
#define IR_CONTROL_KEY_STOP     (0x05)
// 信號量
sem_t g_edge_falling, g_edge_rising;
void setup();
void edgeFalling();
void edgeRising();
void GPIO_wait_for_edge(int event);
bool IRStart();
unsigned char getByte();
unsigned char getKey();
void setup()
{
    if(-1==wiringPiSetup())
    {
        std::cerr"wiringPi setup error"std::endl;
        exit(-1);
    }
   
    pinMode(IR_INPUT_PIN,INPUT);            //配置引腳為輸入
    pullUpDnControl(IR_INPUT_PIN,PUD_UP);   //引腳上拉到3.3v
    //注冊中斷處理函數
    if(0>wiringPiISR(IR_INPUT_PIN,INT_EDGE_FALLING,edgeFalling))
    {
        std::cerr"interrupt function[INT_EDGE_FALLING] register failure"std::endl;
        exit(-1);
    }
    if(0>wiringPiISR(IR_INPUT_PIN,INT_EDGE_RISING,edgeRising))
    {
        std::cerr"interrupt function[INT_EDGE_RISING] register failure"std::endl;
        exit(-1);
    }
}
void edgeFalling() {
    sem_post(&g_edge_falling);
}
void edgeRising() {
    sem_post(&g_edge_rising);

[1] [2] [3] [4]  下一頁

【聲明】:黑吧安全網(http://www.fhetww.live)登載此文出于傳遞更多信息之目的,并不代表本站贊同其觀點和對其真實性負責,僅適于網絡安全技術愛好者學習研究使用,學習中請遵循國家相關法律法規。如有問題請聯系我們,聯系郵箱[email protected],我們會在最短的時間內進行處理。
  • 最新更新
    • 相關閱讀
      • 本類熱門
        • 最近下載
        江西十一选五走势图爱彩乐