(更新完成2016-07-24)Arduino Infrared Remote Control (AIRC)

本帖最後由 C_Law 於 2016-7-24 18:49 編輯

更新:
2016-07-24
15#
ExcelAIRC 內新增 Sheet:Wav2Pulses。

2016-03-06
6#
新增 ExcelAIRC,用 Excel 控制 AIRC。




Arduino Infrared Remote Control (AIRC)

今個新年假的搞作,用 Arduino 接收和發射紅外線遙控器訊號。玩開 Arduino 的朋友就算不打算玩紅外線遙控玩意,都值得玩下 AIRC,用來讀取平時屋企用開的遙控器,記低資料當買個保險,萬一日後壞遙控器(啋 …新年流流講呢尐,真係大吉利是,要 Lur 口水講過! ),都可以用 AIRC 發射訊號讓有學習功能的萬用遙控器去學。

按這裡」下載 AIRC.rar。

AIRC.rar 內有以下四個檔案:
1. ReadMe.txt      使用說明
2. AIRC.ino        AIRC 程式
3. Changes to Library.txt 修改 Library 說明
4. ir_Sharp.cpp.new    包含 Sharp 解碼程序的 cpp 檔




安裝及修改 Library:
AIRC 是建基於以下 Library 的 Arduino 紅外線遙控收發器:
A Multi-Protocol Infrared Remote Library for the Arduino
Written by Ken Shirriff
Version 2.0.1 June, 2015
http://www.righto.com/2009/08/mu ... remote-library.html
下載 Library:
https://github.com/z3t0/Arduino-IRremote

根據 GitHub 的 Library 安裝說明,這 Library 同 Arduino IDE 本身的 RobotIRremote Library 有衝突,所以先要將 RobotIRremote 的 Folder 從  Arduino IDE 的 Library folder 移走。再將這 Library 解壓入去 Library folder。

AIRC 需要對 Library 內的五個檔案作少許修改,有關修改詳情已在 Changes to Library.txt 列出。
1. IRremote.h
如不需要解碼 Sharp 的遙控器訊號,可以不改。

2. IRremoteInt.h
建議增加 RAWBUF 數目到 255。

3. irRecv.cpp
建議將紅外線接收器 Data 腳的 pinMode 改為 INPUT_PULLUP。
如需要解碼 Sharp 遙控訊號,加入有關的程式碼在 #if DECODE_SONY 之上。

4. ir_Sony.cpp
如需要解碼 15/20 bit 的 Sony 遙控訊號,建議將 SONY_DOUBLE_SPACE_USECS 數值由 500 改為 200。否則 Press and Hold 遙控鍵時只可以解碼到第一下訊號。

5. ir_Sharp.cpp
Sharp 的訊號分兩段:Normal(N)、Inverted(i),即使短按遙控器按鈕一下,也會先後發出 N 和 i 訊號,而 Sharp 的電器需要先後收到兩段訊號才會有反應。當 Press and hold Sharp 遙控器按鈕時,兩段訊號會梅花間竹的輪流發送(即是:NiNiNiNi.....)。原本的 Library 會發送 3 段訊號(NiN),其實足以正常遙控到 Sharp 電器,不過,如果想模擬 Press and hold 的話,重複去執行 Sharp 的發射程序的時候會發送出(NiNNiNNiN....),跟真正遙控器不一樣。因此,如果需要發射 Sharp 訊號,建議將發射次數改為雙數的 2(或者 4),令 AIRC 可以好似真正按遙控器一樣發射出 (NiNiNiNi....)。
另外,這個 Library 本身只提供 Sharp 的發射程序,並無 Sharp 的解碼器,我自己加上了解碼程序。
ir_Sharp.cpp.new 是修改後的新檔,改將發射次數改為 2,並加入解碼程序。如需發射接收 Sharp 遙控訊號號,可用這新檔複蓋原本 Library 的 ir_Sharp.cpp。




硬件:
Arduino UNO
紅外線接收器
IR LED 和限流電阻。

airc_00.jpg
2016-2-11 23:16


為了方便,我將 UNO 的 Digital pin 4, 5, 6 分別用作 IR LED 的 Gnd、接收器的 Vcc 和 Gnd。我用 110Ω 的限流電阻只因為剛好手頭上有,發射距離只有 2~3m,不過亦夠光足以讓有學習功能的萬用遙控器去學習。根據 ATMEGA 328P 的 Datasheet,每條 Pin 的最大電流是 40mA,應該還可以用再略低阻值的限流電阻以增加發射距離,又或者 IR LED 從 Vcc 取電,由 Pin 3 經 Transistor 去推粒 IR LED。

airc_01.jpg
2016-2-11 23:16


airc_02.gif
2016-2-11 23:16


使用說明:
將 AIRC.ino 上載到 Arduino 後,打開 Arduino IDE 的 Serial Monitor 便可使用,記得要將 Buad rate 設定做 115200,以及 Newline。

SerialMon_01.gif
2016-2-12 17:04





接收及發射:
AIRC 預設會自動解碼接收到的遙控訊號,AIRC 能解碼 Ken Shirriff 的 Library 提供的所有遙控器 Protcol,不過我無所有相關的電器作測試,所以這裡只集中講我有測試過的 4 個 Protocol:NEC、Sharp、Panasonic、Sony。

NEC
NEC 是我最常用的 Protocol,MagicTV/8仔高清電視機頂盒、有線電視解碼器,以及好多大陸山寨 DVD 機/Media player 的遙控器都是用 NEC Protocol。以下網頁有 NEC Protocol 的詳細說明:
http://www.sbprojects.com/knowledge/ir/nec.php
註:SB-Project 網頁內的說明是以 LSB 行先,不過 Ken Shirriff 的 Library 是以 MSB 行先,其它 Protocol 都一樣。

NEC.gif
2016-2-12 17:04


AIRC 收到 NEC 訊號後會顯示出它的編碼,例如有線電視遙控器的 ↑ 按鈕:
Rx:
NEC h2FF58A7 32

Rx:
NEC hFFFFFFFF 0

以上的 NEC h2FF58A7 32 代表接收到的訊號屬於 NEC protocol,數值是 16 進制的 h2FF58A7,訊號長度是 32 bit。

NEC 的主訊號(即是以上的 h2FF58A7,其實應該是 h02FF58A7,只不過開頭個 0 被省去)只會發射一次,當 Press and hold 遙控按鈕時,發射一次主訊號後,之後會重複發射一組 Repeat stream,AIRC 會用 hFFFFFFFF 顯示 Repeat stream。

NEC 的發射指令是:
NEC Data Nbits Repeat
  Data  是訊號數值
  Nbits 是訊號長度 bit 數,預設值是 32,可省去
  Repeat 重複發射次數,預設是 0,可省去

所有發射指令的數值參數以空格或 Tab 分隔,每個數值參數都可以用 2、10 或 16 進制,預設是 10 進制;如果用 2 進制就要在數值前加上 b,例如 b1001;如果要用 16 進制就要在數值前加上 h,例如 h2FF58A7。為了清楚輸入數值,可以加入 - 或 , 做分隔,例如 b0010-1111-1111-0101-1000-1010-0111、h02FF-58A7、50,288,807。

例如要發射一次上面提到的有線電視↑按鈕訊號,只需複製 Rx: 之後的一整行字串 NEC h2FF58A7 32,又或者省去 Nbits 只複製 NEC h2FF58A7,貼入 Arduino IDE 的 Serial Monitor 再按 Send。

如果需要重複發射,可在字串最尾再加上重複次數(不能省去 Nbits),例如:
NEC h2FF58A7 32 5
按 Send 後就會發射 1 次主訊號 h2FF58A7 另加 5 次重複訊號。

NEC_02.gif
2016-2-13 18:22


NEC 以及其它發射指令的最大重複次數是 999,如果打入 1000 或以上,AIRC 將會不斷重複發射。重複發射中途只要按一下 Send 就可以停止發射。也可以直接打入下一個指令(Pulses 除外)再按 Send 去發射新訊號。

Sharp
以下是 Sharp protocol 的詳細說明:
http://www.sbprojects.com/knowledge/ir/sharp.php

Sharp_01.gif
2016-2-12 17:04


Sharp_02.gif
2016-2-12 17:04


之前提過,Sharp 的遙控訊號分 Normal 和 Inverted 兩段。AIRC 會用以下方式顯示:
Rx:
Sharp h18 h99, Normal,   SharpRaw h6266 15

Rx:
Sharp h18 h99, Inverted, SharpRaw h6199 15

前面 Sharp 的 h18 和 h99 分別是 Sharp 的 Address 和 Command code;之後是 Normal 或 Inverted,Sharp 的遙控器發射時是先後 Normal + Inverted,所以即使是短按遙控按扭,都會分別收到一行 Normal 和一行 Inverted;再後面 SharpRaw 的 h6266/h6199 就是將前面的 Address、Command 以及  Expansion 和 Check bit 串連成一組 15 bit 數值。

Sharp 的發射指令是 Sharp 或 SharpRaw:
Sharp Address Command Repeat
 Address  Address code,通常同一件電器每個按鈕的 Address 都一樣
 Command 個別按鈕的 Command code
 Repeat   重複發射次數,預設是 0,可省去

SharpRaw Data Nbits Repeat
 Data   將 Address、Command 以及  Expansion 和 Check bit 串連成一組的數值
 Nbits  訊號長度 bit 數,預設值是 15,可省去
 Repeat  重複發射次數,預設是 0,可省去

例如要發射一次上面提到的訊號,可以用:
Sharp h18 h99
或者
SharpRaw h6199 15
或者省去 Nbits 的
SharpRaw h6199
如果想故意先發射 Inverted 訊號,可用 Inverted 的 Data:SharpRaw h6199 15 或者 SharpRaw h6199。

如要重複發射,例如想重複發射多 5 次,可在後面加上重複次數,例如:
Sharp h18 h99 5
SharpRaw h6199 15 5  (不能省去 Nbits)
以上指令會發射 1 次之後再重複發射多 5 次,即是總共 6 次。Sharp 的訊號必定是一段 Normal 加一段 Inverted,所以用以上指令是一共發射 12 段訊號。

Sharp_03.gif
2016-2-13 18:22


Panasonic
SB Project 並無 Panasonic protocol 相關的說明。它的訊號在 Header 之後有 48 bit 長, Ken Shirriff 的 Library 將這 48 bit 分割成 16 bit address + 32 bit data(command),例如 Panasonic VHS 錄影機的 Stop 按鈕訊號用以下方式顯示:
Rx:
Panasonic h4004 h9000009

前面的 h4004 是 16 bit address,後面的 h9000009 是 32 bit data(其實應該是 h09000009,只不過開頭個 0 被省去)。

不過,我有個 Panasonic VHS 錄影機的遙控器,它有個掣可以切換控制 Panasonic 的錄影機/電視機,我發覺當設定做錄影機遙控時,48 bit 的頭 32 bit 都完全相同(h40040900),而設定做電視機遙控時,所有按鈕的頭 32 bit 都是相同(h40040100),所以我覺得將 48 bit 分割成頭 32 bit address + 尾 16 bit command 會比較合理。但既然個 Library 用開 16+32,我暫時都照跟個 Library。

Panasonic 的發射指令是:
Panasonic Address Data Repeat
 Address  Address code
 Data    Data code
 Repeat   重複發射次數,預設是 0,可省去

例如上面提到的:
Panasonic h4004 h9000009   (省去 Repeat,只發射一次)
Panasonic h4004 h9000009 5   (包括 5 次重複,即是總共 6 次)

Sony
以下是 Sony protocol 的詳細說明:
http://www.sbprojects.com/knowledge/ir/sirc.php
AIRC 會用以下方式顯示接收到 Sony 訊號:
Rx:
Sony h13A4 20

前面的 h13A4 是數值(其實應該是 h013A4,只是前面的 0 被省去),後面的 20 是 bit 數。我以前是用舊版 Library 和朋友家的 Sony 電視機做測試,試過 12 bit 和 20 bit 都正常(朋友個遙控器無 15 bit 的訊號)。趁新年放假得閒,想話執執個 AIRC.ino 放上來,才發現個 Library 早已推出新版,於是因應新 Library 再改改我的 AIRC.ino,雖然無大改動,但朋友家已經換電視,我無得再試。

Sony 的發射指令是:
Sony Data Nbits Repeat
  Data  是訊號數值
  Nbits 是訊號長度 bit 數,根據 SB Project 的說明,可以是 12、15 或 20
  Repeat 重複發射次數,預設是 0,可省去

例如上面提到的:
Sony h13A4 20    (省去 Repeat,只發射一次)
Sony h13A4 20 5   (包括 5 次重複,即是總共 6 次)

無法解碼的訊號
AIRC 預設會列出無法解碼訊號的 Pulse length,例如:
Rx:
Unknown encoding: C4FDF993 (32 bits)
36 Pulses:   s82000     m550     s100     m350     s100     m350    ...(部份省去)...     m350     s300     m300

Pulses length 的單位是 μs,解像度為 50μs。s 字頭代表 Space,m 代表 Mark。第一個 Space 數值代表這個訊號串和之前一個訊號串之間的間格時間。不過由於解碼以及 Serial.print 一大堆文字都需要一段時間,Serial.print 完之後可能已經過了之後的訊號串,所以第一個 Space 的數值未必真正是兩個訊號串之間的間隔。

AIRC 可以用 PLxxx 指令控制是否顯示 Pulse length:
PLHide    完全隱藏 Pulse length,即使未能解碼的訊號也不會顯示
PLGap    只顯示兩個訊號串之間的間隔時間
PLUnknown  只顯示未能解碼訊號的 Pulses length(預設)
PLShow   不論能否解碼都顯示 Pulses length
 
在 Serial Monitor 輸入 PLGap(無需理會大小階)後按 Send,再按遙控按鈕,就會顯示出兩個訊號串之間的間隔時間,以 NEC protocol 為例:
Rx:
NEC h2FF58A7 32
       Gap: s2923000

Rx:
NEC hFFFFFFFF 0
       Gap:   s38400   ←主訊號後的間隔

Rx:
NEC hFFFFFFFF 0
       Gap:   s96450   ←之後每個重複訊號的間隔

Rx:
NEC hFFFFFFFF 0
       Gap:   s96450   ←之後每個重複訊號的間隔

PLGap 對於 NEC protocol 尤為重要,因為主訊號只發射一次,而主訊號後面的間隔和再之後每個重複訊號串的間隔並不一樣,如果 Serial.print 出整個訊號的 Pulse length,已經超過第一個間隔,再 Serial.print 可能係再之後的重複訊號串,無法顯示出第一個間隔,例如:
Rx:
NEC h2FF58A7 32
68 Pulses: s2027950    m9050    s4300     m750   ...(省去部份)...    s1550     m700

Rx:
NEC hFFFFFFFF 0
  4 Pulses:   s96500    m9100    s2100     m750   ←上面 Serial.print 完之後已錯過第一個重複訊號串
                         這裡顯示的 Gap 其實是再之後的重複訊號串間隔
Rx:
NEC hFFFFFFFF 0
  4 Pulses:   s96450    m9100    s2100     m700

ReadPulses
雖然用 PLUnknown  可顯示無法解碼的訊號 Pulse length,用 PLShow 更可以強制顯示,不過,每收一段訊號,AIRC 會先嘗試解碼,又要 Serial.print 出 Pulse length,當中都花幾多時間,過程中可能已錯過下一組甚至多組訊號。所以我另外寫多個 ReadPulses 指令,它會一直讀取 Pulse length 直至用完 Buffer(之前修改 Library 提到將 RAWBUF 改到 255 就是為了這用途),又或者一秒內再無接收到新 Pulse,然後才 Serial.print 出 Pulse length 及嘗試解碼。用法是:
ReadPulses Gap
 Gap 間隔時間 μs,當讀到一個 Sapce 的長度超過 Gap 就會分割開,之後的 Pulses 會當作是下一個訊號。如果省去的話,預設是 5000μs。

輸入指令後按 Send,在 5 秒內按遙控器按鈕,以有線電視 ↑ 按鈕為例,會得到以下 Pulses length 資料:
ReadPulses 5000. Press a key within 5s....
123 puluses were read. An extra space of 1s is added to the end.
RxPulses:
Pulses kHz  68 Repeat    m9196    s4344     m728    ...(部份省去)...     m736    s1536     m708   s38752
RxCode:
NEC h2FF58A7 32

RxPulses:
Pulses kHz   4 Repeat    m9200    s2092     m708   s96260
RxCode:
NEC hFFFFFFFF 0

RxPulses:
Pulses kHz   4 Repeat    m9196    s2092     m716   s96260
RxCode:
NEC hFFFFFFFF 0

(部份省去)

RxPulses:
Pulses kHz   4 Repeat    m9164    s2120     m708 s1000000
RxCode:
NEC hFFFFFFFF 0

每行 RxPulses: 之後是一段訊號的數據,以第一段 RxPulses 為例(先不理 kHz 和 Repeat,稍後在 Pulses 會講)。在 kHz 和 Repeat 之間的 68 代表這一組訊號總共有 68 個 Mark + Space,這數目是由第一個 Mark m9196 起計,到最尾的 Space s38752,所以一定是雙數,以 NEC protocol 來講,開頭的 Header 有一個 Mark 加 一個 Space,之後 32 bit 數值又每 bit 有一個 Mark 加 一個 Space,加上最後的 End mark 和 Gap space,所以總共是 1 + 1 + 32*2 +1 + 1 = 68。

每行 RxCode: 是根據 Pulses length 解碼出來的 Protocol 和數值。如果無法解碼會顯示 Unknown encoding。

留意最後一組 RxPulses 的最尾一個 Space 是 1 秒,因為我未等到 AIRC 讀滿 Buffer 已放開遙控器按鈕,所以它最後讀到的是最後一段 NEC repeat stream 的 End mark,由於 AIRC 做 ReadPulses 時一定讀雙數的 Pulses length,所以會自動在最後加多 1 秒的 Space,並不代表真正收到 1 秒的 Space。另外,如果我長按到裝會 Buffer,以 RAWBUF = 255 以及 NEC 訊號為例,主訊號總共有 68 個 M + S,之後每個重複訊號有 4 個,Buffer 裝到滿的時候,最後一個重複訊號只夠位裝一個 Mark 以及額外加上 1 秒的 Space,因此使用 ReadPulses 時不要信最尾一組訊號的數值。

我將 RAWBUF 改為 255,其實都不算多,以 48 bit 的 Panasonic 訊號為例,連同 Header、End Mark 及 Gap Space,一段訊號都已經用了 100,255 都只夠裝到約兩段半訊號。如果想讀取係冷氣機的遙控器訊號可能都只是勉強夠,以我房部陳年"凶宅"(日立 OEM 年代)的遙控器,按一個掣就要用 212(連最後加上的 1 秒 Space)。

Pulses
既然 AIRC 可以讀取訊號的 Pulse length,當然也可以用 Pulse length 資料去發射訊號,甚至乎可以發射天馬行空的自製訊號(有無電器讀得明又是另一回事 ),發射指令的格式是:
Pulses kHz InitialEnd Repeat m1 s2 m3 s4......sX

是否覺得以上格式有點似層相識?皆因之前 ReadPulses 時也是以這格式顯示讀取的 Pulse length,方便 ReadPulses 後直接複製出來用。以下是 Pulses 後面各參數的說明:

kHz
發射的 Carrier frequency。不同的 Protocol 會用不同的 Carrier frequency,一般家電遙控器都用 3x~4x kHz,而根據 Library 的說明,可用的 kHz 範圍是 36~40 kHz。雖然 AIRC 無法讀取 Carrier frequency 的數值,但我發覺不太重要,以 Sony protocol 為例,根據 SB Project 網頁的說明是用 40kHz,但我之前用朋友家的 Sony 電視機做測試,由 36~40 都試過,全部都正常遙控得到部電視機,而且也不會因為我不是用 40 而影響到接收距離(就算有都不明顯);我屋企用 NEC protocol 的電器,應該是 38kHz,但同樣由 36~40 都試過,也不覺得有分別。
如果輸入的 kHz 數值是 0,AIRC 只會嘗試解碼,而不會發射。

InitialEnd
主訊號的 Mark + Space 總數量。如果輸入 0,會自動改為後面 m1 s2 m3...sX 的總數量。

Repeat
額外重複發送次數。

m1 s2 m3 s4....sX
訊號中每個 Pulse 的時間長度,單位是 μs,最大是 1000000(即是 1 秒)。由 Mark 開始,最尾是 Gap space。如果輸入的最尾數值不是 Space,會自動加多 1 秒 Space。Mark + Space 的總數量是 RAWBUF - 1(如果 RAWBUF 是雙數就是 RAWBUF - 2)。

對於長按遙控按鈕時會將主訊號重複發送的 Protocol(例如 Sony、Panasonic),用 ReadPulses 讀得 Pulses 後,只要將 Pulses 行複製,再修改 kHz 和 Repeat 後就可以按 Send 發射出去。例如以下是 ReadPulses 讀取的 20 bit Sony 訊號:
RxPulses:
Pulses kHz  42 Repeat    m2532     s476    m1332     ...(部份省去)...     m736     s496     m732   s13756
RxCode:
Sony h813A4 20

如果要額外發射多 5 下 Repeat,應該改為:
Pulses 40  42 5    m2532     s476    m1332     ...(部份省去)...     m736     s496     m732   s13756

對於主訊號只發射一次的 Protocol(例如 NEC),ReadPulses 會讀得:
RxPulses:
Pulses kHz  68 Repeat    m9196    s4340     ...(部份省去)...     m732   s38724
RxCode:  (↑主訊號↑)
NEC h2FF58A7 32

RxPulses:
Pulses kHz   4 Repeat    m9176    s2120     m732   s96236
RxCode:  (↑重複訊號↑)
NEC hFFFFFFFF 0

RxPulses:
Pulses kHz   4 Repeat    m9204    s2092     m728   s96240
RxCode:  (↑重複訊號↑)
NEC hFFFFFFFF 0

在主訊號之後的每個重複訊號都是相同的 4 個 Mark + Space,可以先複製主訊號的 Pulses 行(紅色),修改 kHz(38) 和 Repeat(例如想在主訊號後再發射多 5 次重複訊號),InitialEnd(68)保持不變,然後再將一個重複訊號的 4 個 Mark +Space(綠色)加到最尾,整個 Pulses 指令即是:
Pulses 38  68 5    m9196    s4340     ...(部份省去)...     m732   s38724   m9204    s2092     m728   s96240

以上指令一共有 72 個 Mark+Space,開頭的 1~68(主訊號)只會發射一次,之後會根據 Repeat 數值(5)重複發射 69~72(重複訊號)。

至於一個訊號會分開兩組輪流發射的 Protocol(例如 Sharp),用 ReadPulse 會讀到:
RxPulses:
Pulses kHz  32 Repeat     m452    s1560    ...(部份省去)...     m432   s45576
RxCode:
Sharp h10 h80, Normal,   SharpRaw h4202 15

RxPulses:
Pulses kHz  32 Repeat     m456    s1556    ...(部份省去)...     m424   s39544
RxCode:
Sharp h10 h80, Inverted, SharpRaw h41FD 15

先複製屬於 Normal 的 Pulses 整行(紅色),再將屬於 Inverted 的 Mark + Space(綠色)加到最尾。由於 Normal 和 Inverted 都分別有 32 個 Mark+Space,而重複時是兩組輪流發射,所以 InitialEnd 要改為 32+32 = 64,再修改 kHz(38) 和 Repeat(5,例如要額外發送多 5 次),整行 Pulses 指令就是:
Pulses 38  64 5     m452    s1560    ...(部份省去)...     m432   s45576     m456    s1556    ...(部份省去)...     m424   s39544

之前有提過,當 AIRC 正在重複發射訊號時,打入新的指令行就可以終止現有的重複發射並且執行新指令行,新指令行可以是 NEC、Sony…之類的發射指令,也可以是其它非發射指令,唯獨是新指令不能是 Pulses 指令行。曾經試過在重複發射中途輸入新的 Pulses 指令行,雖然能終止目前的重複發射,但新的 Pulses 指令行卻沒有正常執行,唯有在程式中做手腳,如果舊發射指令不是自然結束,而新指令又是 Pulses,就會要求重新再輸入新指令。如果有需要在重複發射中途輸入新的 Pulses 指令,應該先按一下 Send 發出一行空白的指令行去終止目前的重複發射,然後才輸入新的 Pulses 指令。

我都不肯定當舊的重複發射中途輸入新的 Pulses 指令為何會不能正常執行。純綷靠估,可能是舊的重複發射被終止後還有小小手尾要跟,未有即時讀取新的指令行,由於 Pulses 的指令行字數太多,當 Serial in 的 Buffer 被填滿都未開始讀取的話,再後面的字就無法讀取,引至指令行不原整而無法正常執行,而其它指令行的字數相對地較小,就算無即時讀取都未必填滿 Buffer,所以後來仍然能正常讀取和執行。不過真係純綷靠估,請問有無玩開 Arduino 的師兄可以指點迷津!?




其它指令
RxEnable  啟用接收解碼(預設)
RxDisable 停用接收解碼

TxHide 隱藏發射指令(預設)
TxShow 當收到發射指令行後會 Serial.print 出來

Status Serial.print 出 Rx、Tx、PL 狀態,例如:
Status: RxEnable, TxHide, PLUnknown




所有指令
再列出一次所有指令:
發射:
NEC Data Nbits Repeat
Sharp Address Command Repeat
SharpRaw Data Nbits Repeat
Panasonic Address Data Repeat
Sony Data Nbits Repeat
Pulses kHz InitialEnd Repeat m1 s2 m3 s4......sX

接收:
ReadPulses Gap

其它:
Status
RxEnable
RxDisable
TxHide
TxShow
PLHide
PLGap
PLUnknown
PLShow




總算在放假的最後一日完成!

無真正學過寫 C,以前間中玩玩 Arduino,都只係上網抄多過自己寫。今次算係寫得最長的一次,邊抄邊學邊寫,所以寫得好核突 ,獻醜了!

本帖最後由 C_Law 於 2016-2-14 20:40 編輯

另外想講講兩點:
1. 發射其它 Protocol 訊號
2. 關於 Pulses 的 FixOne 和 FixTwo




發射其它 Protocol
目前 AIRC 只提供 4 個 Protocol 的發射指令(NEC、Sharp、Panasonic、Sony)。其實 Ken Shirriff 個 Library 還有提供多個 Protocol 的發射程序,只不過我無相關的電器去測試,所以無加入到 AIRC。

我已經在 AIRC.ino 內以 Remarks 方式寫上加入其它發射程序的方法,只要稍加修改就應該可以用得。

主要修改位置有三個:
i.
loop() 入面 Check serial in 部份,在 CMD=ReadCMD() 之後一堆 if...else if...的最尾。

ii.
TxCode() 內近開頭的一堆 if...else if....的最尾。

iii.
TxCode() 內讀取完 Numeric parameters 後的一堆 if...else if...的最尾。




關於 Pulses 的 FixOne 和 FixTwo
下圖四條訊號波形是用 Audacity 以 96kHz 取樣率經 WinLIRC audio receiver 錄取。

PFix_01.gif
2016-2-14 20:29


當中的第三條 CA-Up 是直接錄取自有線電視遙控器的↑按鈕,錄音同時以 ReadPulses 錄取 Pulse length,加上 Repeat 後,就得出以下的 Pulses 指令行:
Pulses 38  68 5    m9204    s4328     m744     s392     m716     s396     m748     s384     m744     s404     m716     s392     m744     s388     m736    s1512     m744     s392     m744    s1500     m744    s1528     m728    s1520     m744    s1508     m748    s1524     m716    s1532     m740    s1504     m744    s1536     m712     s388     m748    s1536     m716     s392     m744    s1528     m716    s1532     m740     s392     m720     s396     m740     s396     m736    s1504     m752     s392     m744    s1500     m744     s392     m744     s392     m716    s1528     m748    s1500     m744    s1536     m716   s38744   m9200    s2092     m720   s96260

第一條 P-0-0 (FixOne = 0, FixTwo=0)是用以上指令 Pulses 指令行發射訊號時錄得的波形。照計 P-0-0 和 CA-Up 應該是一樣一樣,但明顯睇得出 P-0-0 的波形比較長。

當中有兩個原因,首先,Library 的 IRremote.cpp 內的 MATCH_MARK 和 MATCH_SPACE 有提過,接收器收輸出的訊號,Mark 的長度會比真正發射長度長約 100μs,相反 Space 的長度就會短約 100μs。我在 TxPulses() 內以 FixTwo = 100 修正這誤差。上圖 P-0-100 就是加上 FixTwo 的波形。

另一方面,程式運行時也需要時間去處理,因此會用了比較長時間(ie. 波形睇起來比較長),我再用 FixOne 去修正這問題。我將著眼點放於較短的 Pulses,所以忽略開頭的 Header Mark+Space(1, 2),先將 P-0-100 和 CA-Up 兩個波形的 2 和 3 之間的 Rising edge 對齊,之後移動主訊號尾,量度兩條波形的 End mark rising edge(66~67 之間)的差距:358 samples@96kHz = 358/96000 =3729μs。

PFix_02.gif
2016-2-14 20:29


PFix_03.gif
2016-2-14 20:29


這是由 m3~s66 所多出的時間,平均每個 Mark 或 Space 多出時間就是 FixOne = 3729/(66-3+1) = 58μs。

第四條 P-58-100 就是加入 FixOne 和 FixTwo 修正後所發射出來的波形。中間搵一段有闊有窄的 Pulse 放大來看,P-58-100 和原裝的 CA-Up 已經好接近,可以收貨。

PFix_04.gif
2016-2-14 20:29

TOP

TOP

有無一個database,載滿了所有遙控的資料?

我自己用緊Logitec Harmony

TOP

好有心機做,謝謝分享

TOP

本帖最後由 C_Law 於 2016-3-6 18:41 編輯

ExcelAIRC

最初寫 AIRC 的心目中的主要用途是用來備份遙控器的訊號資料,但係用 Arduino IDE 的 Serial monitor 的話,讀到的資料要另外 Copy 出來儲存,想發射訊號出去又要次次人手打 Command,實在太煩,所以心諗想寫個程式可以一次過做齊備份和發射,而第一個諗到的方法就是用 Excel VBA 去控制 AIRC。

有關控制 Serial port 的 VBA code 是來自以下網頁:
Serial Port Communication in Excel (VBA)
http://dev.emcelettronica.com/serial-port-communication-in-excel-vba

暫時在 32bit WinXP + Office 2007 和 32bit Win7 + Office 2007 測試過 ExcelAIRC 可正常使用。但 XP+Office 2000 就用不到 Com port(雖然 Office 2000 不能開 *.xlsm,但其實我最初係用 *.xls 去寫 ExcelAIRC,後來發覺 Office 無法用到以上的 Serial port VBA code,既然舊版 Office 用不到,就索性另存新檔做新版的 *.xlsm,改用新版還可以更改格仔顏色,可以做到當 ExcelAIRC 收到遙控訊號時更改相關格仔顏色的效果)。




基本用法:
[按這裡]下載 ExcelAIRC.rar。

解壓後開啟 ExcelAIRC.xlsm 及啟用巨集。

xAIRC01.gif
2016-3-5 19:18


xAIRC02.gif
2016-3-5 19:18


輸入 Arduino 的 Com port no.(B2) 及 Buad rate(B3),然後按 Toggle button "Com port" 啟用 Com port。當 Com port 啟用後,除了 B4、B5 及 E1 格之外,所有儲存格都不能直接修改,如果想修改就要再按一次 "Com port" 掣先將 Com port 關閉。

Row 7~8 的 Textbox 就好似 Arduino IDE 個 Serial monitor 的 Send box,在這裡打入文字後按 Enter 或者 Click "Send" 掣就會發送到 Arduino。在這裡可輸入 AIRC 的指令,也可以輸入 ExcelAIRC 的指令(例如會自動加 Repeat 的 Tx code、Name code、Combo code...etc,有關指令會在稍後作詳細說明)。

Row 11~19 的 Textbox 就好似 Arduino IDE 個 Serial monitor 的 In box,從 AIRC 傳過來、又或者從 ExcelAIRC 產生的文字訊息,都會在這裡顯示出來。不過上下次序跟 Arduino IDE 相反,新收到的文字行會放在最頂,舊的文字行會被向下推。

由 E2 格開始,右邊及以下所有格仔都可以用作一個向 Arduino 傳送文字的按鈕。每個按鈕由兩部份組成:1.名稱、2.控制碼。每個按鈕的名稱放在 Worksheets("Button") 的一個 Cell,而相對的控制碼就放在 Worksheets("Code") 的相同 Cell 位置。ExcelAIRC 已設定好所有 AIRC 的非發射指令(E2:I4 的 Status、TxHide…etc)、以及有線電視遙控器的所有按鈕(粉紅色的 F6:I16)。

注意,如需要重複按相同的發射按鈕(例如想轉去有線 22 台,需要按兩次 2),不要按得太快,否則 Excel 會當係 Double click。

每按一個按鈕格仔,這格仔的相關控制碼除了會發送到 Arduino 之外,亦會複製到 E1 格,Double click E1 格的話就會再複製到 Send box,方便需要又試又改的時候,可以將上次用按鈕格仔發送的控制碼複製入 Send box,經修改後按 Enter 或 Send 再發送出去。

每個格仔的控制碼可以是一個獨立指令,也可以是多個指令集中在一個格仔,稍後會詳細講控制碼的格式。

按一個按鈕格仔後,除了控制碼會複製到 E1 格之外,如果是多個指令集中在一個格仔的話,每個指令會分割開,並顯示在 Inbox 內。例如按 DisCh(53) 格仔,它的控制碼是按次序發送有線電視遙控器的 5、3 和 OK 按鈕。整個格仔的控制碼是:
{NEC h2FFA05F 32}{NEC h2FFC03F 32}{NEC h2FF708F 32}

In box 會見到已分割開,實際發送到 Arduino 的每行指令。:
ExcelAIRC: NEC h2FF708F 32   相當於 CA-OK
ExcelAIRC: NEC h2FFC03F 32   相當於 CA-3
ExcelAIRC: NEC h2FFA05F 32   相當於 CA-5

(ps.ExcelAIRC 的 In box 上下次序是新行放在最頂)

如果控制碼內使用 Name code(例如 [CA-5]),ExcelAIRC 都會先搵出 [CA-5] 對應的指令,在 In box 顯示真正發送到 Arduino 的指令 NEC h2FF708F 32。




設定按鈕格仔名稱及控制碼:
如果想修改個別 Cell 的名稱和控制碼,例如想將 E9 格改為 Panasonic 錄影機遙控器的 Channel UP 掣:
1.先對著 AIRC 按遙控器的 Channel UP 掣
2.用 Mouse highlight 有關的 AIRC 指令(即是 Rx: 之後的一整行,亦即是之上的一行),按 Ctrl-C 複製
3.按 Edit Cell 後再跟指示按一下 E9 格
4. 輸入按鈕格名稱及控制碼後按 OK

xAIRC03.gif
2016-3-5 21:48


修改後的 Cell 可以立刻使用。不過,如果想改個 Cell 的底色、文字顏色…等等,要先關閉 Com port 才可以改。

按鈕名稱:
按鈕名稱不能用 % 符號、Square 及 Curly 括號 [ ] { },其它 Printable 的文字符號都應該可以用。

ExcelAIRC 可以一次過放入多個遙控器的資料,建議為不同遙控器的按鈕名稱加上 Prefix。因為使用 Name code 作為控制碼的時候,ExcelAIRC 會根據按鈕名稱搵出相對的 AIRC 指令,再發送去 AIRC,如果有線的 1 字鍵的按鈕名稱是 1,錄影機的 1 字鍵又是 1,ExcelAIRC 就有機會傳錯指令去 AIRC。因此我習慣會將有線電視遙控器的按鈕名前加上 CA-、Sharp 錄影機加上 SV-…等等,加上 Prefix 後就不會產生混淆。

按鈕控制碼:
按鈕控制碼有四種:Tx Code、Exact code、Name code 及 Combo code。

1. Tx Code
Tx Code 是帶有 % 開頭,但不包括 Repeat 的 AIRC 發射指令。亦即是 % 加上接收到訊號時 In box 內 Rx: 之後的一行文字。

當按落一個使用 Tx Code 的按鈕格仔時,ExcelAIRC 會跟據 Tx Repeat 核取方塊(Checkbox) 的狀態及 B4 格的數值,自動將 Repeat 數值加上指令再傳送到 AIRC。如果 Repeat 值是 1000 或以上,AIRC 會無限重複發射,如果要終止發射,可以按任何一個空白格仔。

另一方面,當 AIRC 接收到遙控訊號時,ExcelAIRC 也會嘗試在 Worksheets("Code") 內搜尋是否有相同 Tx Code 的格仔,如果有,就會令 Worksheets("Button") 內對應的格仔變顏色,直到放開遙控器按鈕才變回原來顏色。

xAIRC04.gif
2016-3-6 00:03


有兩種 Protocol 要注意,首先, Sharp protocol,它有兩種發射指令:Sharp 和 SharpRaw,Tx Code 只用 Sharp,例如 ExcelAIRC 收到 Sharp 錄影機遙控器的 Channel Up 按鈕時顯示的資料:
Sharp h18 h88, Inverted, SharpRaw h61DD 15
Rx:

Sharp h18 h88, Normal,   SharpRaw h6222 15
Rx:

Sharp h18 h88, Inverted, SharpRaw h61DD 15
Rx:

Sharp h18 h88, Normal,   SharpRaw h6222 15
Rx:

(ps. 以 ExcelAIRC 的 In box 上下排列次序,新行放在最頂)

Sharp 的 Tx code 只要紅字的一截,亦即是第一個 comma 之前的一截,Tx code 是:
%Sharp h18 h88

其次是 NEC 的訊號分開主訊號和重複訊號,當長按遙控器的一個按鈕時,主訊號只發送一次,之後會重複發射重複訊號,Tx Code 要使用主訊號。例如當 AIRC 接收到有線電視 ↑ 按鈕時顯示的資料是:
NEC hFFFFFFFF 0  ←這是 NEC 的重複訊號
Rx:

NEC hFFFFFFFF 0  ←這是 NEC 的重複訊號
Rx:

NEC h2FF58A7 32  ←這是 NEC 的主訊號
Rx:


這按鈕的 Tx code 就是 % 符號再加上面紅色的一行字:
%NEC h2FF58A7 32

至於 Sony 和 Panasonic 的遙控器,長按一個按鈕時是重複發射相同訊號,因此每行 Rx: 之後的一行都是相同,只需抽一行出來做 Tx code。

最後,Pulses 格式的發射指令也可用作 Tx code,但要將 kHz 改為適當數值,至於 Repeat 維持不變,例如:
%Pulses 38 68 Repeat m1 s2 m3 s4...etc
發射時,ExcelAIRC 會自動修改 Repeat 才將指令傳送到 AIRC。

不過,如果用 Pulses 格式作為 Tx code,當 AIRC 收到訊號時,ExcelAIRC 是不會自動改變相關按鈕格仔的顏色。

2. Exact Code
顧名思義就是真正傳送到 AIRC 的控制碼,亦即是用 Arduino IDE 的 Serial monitor 時打入 Send box 的字。ExcelAIRC 不會自動因應 Tx Repeat 狀態和 B4 格數值加上 Repeat,如果需要 Repeat 就要直接打入 Exact code 內。

本身沒有 Repeat 的指令亦應該用 Exact code,例如:Status、TxHide…etc。

3. Name Code
Name code 是以 Square bracket 包住的按鈕名稱,有關名稱的按鈕必需已在之前位置的按鈕格仔中定義了 Tx code 或 Exact code。Name code  主要是配合下面所講的 Combo code 一齊使用,當按下一個使用 Name code 的按鈕格仔時,ExcelAIRC 會從之前相同名稱的格仔找出對應 Tx code 或 Exact code,再傳送去 AIRC。

4. Combo Code
ExcelAIRC 可以設定用一個按鈕格仔傳送多個指令到 AIRC,每個指令按發送次序用 Curly bracket 包住,例如 F18:H18 就是三個使用 Combo code 的按鈕格,只要按一個格仔,就能將有線電視轉台到 22、52 或 53 台。

Combo code 的 Curly bracket 內可以是 Tx code、Exact code 或 Name code,例如:
{RxDisable}{Status}
先叫 AIRC 停止接收遙控訊號,再叫 AIRC 傳回 Rx、Tx、PL 狀態。

{NEC h2FFA05F 32}{[CA-2]}{[CA-OK]}
h2ffao5f 是有線電視遙控器 5 號數字按鈕的 NEC data 值,以上 Combo code 就是叫 AIRC 發射有線的 5、2 和 OK 按鈕訊號。當然,第一組的 {} 內也可以改為 {[CA-5]}。

{%NEC h2FFA05F 32}{%[CA-2]}{%[CA-OK]}
這行看似同上面一樣,但多了個 %,實際發射出去的訊號會因應 Tx Repeat 狀態和 B4 數值加上 Repeat。

之前嘗試用 Audio 方式發射遙控訊號時發現,如果要發射多個訊號到一件家電,訊號與訊號之間需要分開一定的時間,這間隔時間可在 B5 格更改,不過,它只是個大約數值,是 ExcelAIRC 傳送兩個指令之間的間隔時間,並非等到 AIRC 連同 Repeat 完整發射完才發送下一個指令,所以如果有太多 Repeat,而且又 Combo gap 又設定得太短,有可能根本係上一組未發射完就即刻發射下一組,變成兩組之間根本無間隔時間,所以用 Combo code 的話最好不要用 % 令 ExcelAIRC 自動加上 Repeat。

另外,如果想連組發射相同按鈕的遙控訊號去一件電器,例如要轉到有線電視 22 台(按 2、2、OK),兩個 2 之間要用比較長的間隔時間,有兩個方法,一係加大 Combo gap 時間,但之後的 2 和 OK 亦同樣會加長間隔時間;另一個方法是在兩個 2 之間加多一對甚至多對 Curly bracket {},即是由:
{[CA-2]}{[CA-2]}{[CA-OK]}
改為
{[CA-2]}{}{[CA-2]}{[CA-OK]}




關於 TV Vol+ 和  TV Vol- 命令按鈕(Command button)
最後想講講這兩個用來控制我屋企部 Sharp 電視機音量大細的令按鈕。兩個按鈕的寫法是一樣,只是個 Code 不同,因此只會講 TV Vol+。

Sharp 電視機增加音量的 AIRC 指令是:
Sharp h10 h28, Inverted, SharpRaw h435D 15
Rx:

Sharp h10 h28, Normal,   SharpRaw h40A2 15
Rx:


我只要 Sharp 的部份,即是 Sharp h10 h28。我在 TV Vol+ 個命令按鈕的 MouseDown event 去傳送無限重複發射的指令,即是在指令加上 Repeat 值 1000 變成 Sharp h10 h28 1000,另外就在 MouseUp event 中傳送一個空白行去終止發射,於是乎可以做到好似真正的遙控器一樣,用 Mouse click & Hold 住個命令按鈕時便不停地重複發射,一旦放開就停止。
  1. Private Sub cbTvVolUp_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal y As Single)
  2.   SendToComPort ("Sharp h10 h28 1000")
  3. End Sub

  4. Private Sub cbTvVolUp_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal x As Single, ByVal y As Single)
  5.   SendToComPort ("")
  6. End Sub
複製代碼
當初寫 AIRC 時加入無限重複發射功能,就是為了想做這個效果。本來我都希望做到用 Mouse 按落一個按鈕格仔時可以做到這個效果,但原來 Excel VBA 本身無儲存格的 MouseDown、MouseUp event,上網搵來搵去都搵不到,最近似的都只係 SelectionChange event,不過 SelectionChange event 並非 Click 落去的一刻觸發,而係在放開手時候觸發,所以 Click 落去 Cell 無法做到好似真正遙控器的 Press and Hold 就不停重複發射的功能。

有無熟 Excel VBA 的師兄到方法去做到 Cell 的 MouseDown、MouseUp event?

另外,由於用 SelectionChange event 去查出被 Click 落去的 Cell,顧名思義,一定要有 Change 才偵測得到,如果要連續按相同的 Cell 就要另外想辦法,我的方法是搵個無用的 D1 做 Home cell,每 Click 完一個格都自動跳回去 D1 格,因此就算要連續 Click 同一個格仔(例如 G11 的有線電視數字按鈕 2),每按一下 G11,實際是先跳去 G11 再跳去 D1,再按 G11 都會觸發到 SelectionChange event。雖然不會寫入 D1 格,但最好都不要使用 D1 格作其它用途。

TOP

回覆 6# C_Law


    office 2007 + win10, COM PORT, 完全不動作, DCB 估計要用 WIN32 INIT 才可以

TOP

office 2007 + win10, COM PORT, 完全不動作, DCB 估計要用 WIN32 INIT 才可以 ...
xiao 發表於 2016/6/13 18:01


你用 64bit windows?
我只係用過 32bit。

另外,你的 Com port no. 係幾多?
http://dev.emcelettronica.com/se ... cation-in-excel-vba
入面的 VBA code 有講到只可以用 Com1~Com4。

TOP

回覆 8# C_Law


    是的 大概看過他寫的 電dcb comm init 應該是用win16 api
win32 api 使用 createfile 打開 comm port handle
所以實驗一下 果然開不了com5有出現 不過開啟是沒有反應 也不報錯

TOP

本帖最後由 GbE 於 2016-6-14 12:26 編輯

C_Law 讚

如果想讀取係冷氣機的遙控器訊號可能都只是勉強夠,以我房部陳年"凶宅"(日立 OEM 年代)的遙控器,按一個掣就要用 212(連最後加上的 1 秒 Space)。

師兄想問日立的冷氣是否都係行 NEC protocol, 事緣我想智能地控制下佢,見淘有現成件好易控制,似乎容易做到想做嘅嘢,唸緊淘唔淘。

TOP