電子工作 22 - 赤外線リモートコントロール事始3 – 幅の違うパルスの組合せをデータ信号の判別に使う方法

概要

今回は、PICBasic Pro の独自コマンドの一つであるパルス信号の幅を測定する ”Pulsin” を赤外線通信に使う方法を試して見る。これもMelabs PICBASIC Forums に載っていたもので(peterdeco1氏)、原理が興味深いので、実際に動作するのかどうかテストした。元のままでは動かなかったので、修正を加えて動くようにした。

.

送・受信動作原理は以下のようである。

送信側

1)38KHzに変調された3msのスタートパルスを最初に送る。

2)2msの変調なしゼロセパレートスペースを送る。

3)その後、”H”なら、変調された2msのパルスを、”L”なら、変調された1msのパルスを送る。

4)今回の例では(入力スイッチSWは3個)、1つのSWから全部で5ビットの”H”と”L”との組合を1つのデータ信号して送る。各ビット間には、2msのゼロセパレートスペースを入れる。

例えばSW2を押すと、下図のようなパルスが連続的に発信される。各パルスなどの幅は公称値で、実際に測ってみると、スタートパルス (Startbit)の3msは2.3ms、ゼロセパレートスペース(Separatebit)の2msは、ほぼ公称値と等しく、“H”の2msは1.56ms前後、“L”の1msは0.75ms前後であった。また、変調パルス38KHzは、実際には43KHzであった。それでも、下のもう1つの図より明らかなように、赤外線モジュールからは綺麗な反転パルスが出力されていた。つまり、38KHzから相当外れても機能することが分かった。


 


受信側

1)3msのスタートパルスを待ち、到着したら、データ信号5ビットの各ビットのパルス幅サイズの判別にかかる(”H”か”L”(”1”か”0”)、つまり、2msか1ms)。到着しなければ、待ち続ける。

2)5ビットのうち、送信側で最初に送ったビットが受信側の最下位ビットに読込まれ、順次上位方向に読込まれる。

3)まず、データ信号5ビットの最初のビットの判別にが行われ、2msの”H”パルスなら、合成されるコードの0ビット目が Code.bit0=1 とされる。反対に”L”なら、Code.bit0=0となる。

4)残りの4ビットも次々と読込まれ、最終的に合成されるコードはCode=%01111=15などとなる。

5)合成されたコードが受信側であらかじめ設定してあるコードと一致した場合に、正しい信号が送られて来たとして、決められた仕事をする(今回はLEDの1つを点灯させる)。

  上の送信側で起こったとまったく同様に、パルスなどの幅は、実際にはゼロセパレートスペース(Separatebit)の値を除いて、すべて小さ目の値であった。


 


回路

最初、送信距離が2−3メートルしか出なので、調べたところ赤外線LEDを直接PICのGP4につないでも4.6mA程しか流れていないことが分かった。そこで、トランジスタを入れて17mAほど流れるようにした。これで、10メートル以上に送信距離が伸びた。これら回路では、送信側のSW1,SW2,SW3の各SWを押すと、対応する受信側のLED1、LED2、LED3が各1秒間点灯する。LED3に付けてあるブザーは、音でも確認するためのものである。今回は、下の写真に示すようなプレッドボードを使って実験を行った。左の写真で左手に黒く見えるLEDが赤外線LEDである。右の写真の左手の三本足の四角いのが赤外線受信モジュールである。両ブレッドボード上でPICに供給するDC電圧は自由に変えられる。


 



プログラム

  

送信プログラム

サブルーチンを使ってプログラムを簡潔化した。

 

'PulsinT.bas 2007.7.1     2007.6.30   Pulsin proj.

 

'************** Pin connection **********************

'12F629, 4MHz Internal Clock used

'Pin 1: Vdd (5.0V)

'Pin 8: Vss (GND)

'Pin 7: GPIO.0: input - connected to SW1

'Pin 6: GPIO.1: input - connected to SW2

'Pin 5: GPIO.2: input - connected to SW3

'Pin 3: GPIO.4: output - connected to IR LED via 100 ohm resistor

 

'*********** Main program ******************

CMCON=7 'Comparator not used

TRISIO=%000111  'GPIO.0, GPIO.1 and GPIO.2 = Input, others = Output

OPTION_REG.7=0  'Use of weak pull-up

WPU=%000111     'Pull-up for GPIO.0, GPIO.1 and GPIO.2

DEFINE OSCCAL_1K 1 'Set OSCCAL for 1K device

 

X var byte

SW1 var GPIO.0

SW2 var GPIO.1

SW3 var GPIO.2

GPIO.4=0

 

SWINR:  'SW search routine   キー入力ルーチン

IF SW1=0 THEN SW1R

IF SW2=0 THEN SW2R

IF SW3=0 THEN SW3R

GOTO SWINR

 

SW1R: 'Code HHHHH    “HHHHH”を送信するルーチン     

X=0

GOSUB Startbit  '3 ms

GOSUB Sepbit   'Separate bit=2 ms

GOSUB Hbit  '"H" '2 ms, actually 1.56ms

GOSUB Sepbit

GOSUB Hbit  '"H"

GOSUB Sepbit

GOSUB Hbit  '"H"

GOSUB Sepbit

GOSUB Hbit  '"H"

GOSUB Sepbit

GOSUB Hbit  '"H"

GOSUB Sepbit

Goto SWINR

 

SW2R: 'Code HHHHL   “HHHHL”を送信するルーチン 

X=0

GOSUB Startbit  '3 ms

GOSUB Sepbit   'Separate bit=2 ms

GOSUB Hbit  '"H" '2 ms

GOSUB Sepbit

GOSUB Hbit  '"H"

GOSUB Sepbit

GOSUB Hbit  '"H"

GOSUB Sepbit

GOSUB Hbit  '"H"

GOSUB Sepbit

GOSUB Lbit  '"L"  '1 ms, actually 0.75ms

GOSUB Sepbit

Goto SWINR

 

SW3R: 'Code HHHLL     “HHHLL”を送信するルーチン

X=0

GOSUB Startbit  '3 ms

GOSUB Sepbit   'Separate bit=2 ms

GOSUB Hbit  '"H" '2 ms

GOSUB Sepbit

GOSUB Hbit  '"H"

GOSUB Sepbit

GOSUB Hbit  '"H"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"  '1 ms

GOSUB Sepbit

Goto SWINR

 

Startbit:

High GPIO.4 'GETTING 38KHZ WITH THIS SUBROUTINE, actually 43KHz

High GPIO.4

Low GPIO.4

Low GPIO.4

X = X + 1

IF X < 99 Then STARTBIT '99 GIVES 3MS START PULSE

Return

 

Sepbit:

Pause 2  '2 ms

X=0

Return

 

Hbit:

High GPIO.4

High GPIO.4

Low GPIO.4

Low GPIO.4

X= X + 1

IF X < 66 Then Hbit '2MS CODEBIT

Return

 

Lbit:

High GPIO.4

High GPIO.4

Low GPIO.4

Low GPIO.4

LET X= X + 1

IF X < 33 Then Lbit '1MS CODEBIT

Return

 

'********** End of program ***************

'Note:

   'AKI Programmer's configurations:

   'FOSC  INTOSC (GP4:I/O); WDTE - Enable; PWRTE - Enable

   'MCLR - Internal ; BODEN - Enable; CD - Disable; CDP - Disable

 

受信プログラム

プログラムの中で “Pulsin GPIO.4 ,0 ,Codelength” が要の部分である。その意味するところは、“GPIO.4から入力された信号の幅を10ms単位で計測し、測定値をメモリCodelengthに格納せよ”というものである。ここで、真中の“0”はLレベルの信号(反転信号)を計測せよ、という意味である。“1”の場合は、Hレベルの信号の計測せよ、という意味である。パルス幅2ms=2000msは、10ms単位で計測すると200になり、それがメモリCodelengthに格納される。“H”と”L”に相当する2msと1msは、実際は1.56ms、0.75msだったので、元もとのIF Codelength > 150 Then Code.xxxxxxの部分は、IF Codelength > 100 Then Code. xxxxxx に変えた。そうしないと範囲を正しくカバーしないのでプログラムが動かない。

 

'PulsinR.bas 2007.7.2  Worked at last. Pulsin proj.

Frequency of Moduleted pulses - Designed 38KHz/Measured 43KHz

'Length of pulses:

'Startbit - Desined 3ms/Measured 2.3ms

'Separatelength - Desined 2ms/Measured 1.95ms

'Codes - "H" Desined 2ms/Measured 1.57ms; "L" Desined 1ms/Measured 0.83ms

 

'************** Pin connection **********************

'12F629, 4MHz Internal Clock used

'Pin 1: Vdd (5.0V)

'Pin 8: Vss (GND)

'Pin 7: GPIO.0: output - connected to LED1

'Pin 6: GPIO.1: output - connected to LED2

'Pin 5: GPIO.2: output - connected to LED3

'Pin 3: GPIO.4: input - connected to IR Receiver module

'Pin 4: GPIO.3: input - connected to MCLR via 100K resistor

 

'*************** Main program ***********************

CMCON=7  'Comparator off

TRISIO=%0010000  'all except GP4 are outputs.

DEFINE OSCCAL_1K 1

Codelength var Byte

Code var Byte  'for less than 8 code bits

X var Byte

Clear  'Content of all variables -> 0

Pause 500  'Settle down PIC & IR receiver module

 

Startpulse:

GPIO.0=0     ‘Found these three are necessary.

GPIO.1=0

GPIO.2=0

 

Pulsin GPIO.4,0,Codelength 'Read low pulse (IR LED On time)

IF Codelength < 200 Then Startpulse  'Searching 3 ms pulse (actually 2.3ms)

IF Codelength > 400 Then Startpulse

 

'Codepulses

'Checking Bit0

Pulsin GPIO.4,0,Codelength   ‘Lowest bit  ここから送られて来たビットを1個ずつ拾って1つのCodeを合成する

IF Codelength > 100 Then Code.bit0=1 '2 ms pulse is 1  original 150 was changed to 100 (as 2ms was found to be 1.56ms)

IF Codelength < 100 Then Code.bit0=0 '1 ms pulse is 0  original 150 was changed to 100 (as 1ms was found to be 0.75ms)

 

'Checking Bit1

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit1=1 '2 ms pulse is 1

IF Codelength < 100 Then Code.bit1=0 '1 ms pulse is 0

 

'Checking Bit2

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit2=1 '2 ms pulse is 1

IF Codelength < 100 Then Code.bit2=0 '1 ms pulse is 0

 

'Checking Bit3

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit3=1 '2 ms pulse is 1

IF Codelength < 100 Then Code.bit3=0 '1 ms pulse is 0

 

'Checking Bit4

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit4=1 '2 ms pulse is 1

IF Codelength < 100 Then Code.bit4=0 '1 ms pulse is 0

 

Pause 20   ‘An above synthesized Code is compared with the following three values 合成されたCode の設定値との比較

IF Code=31 Then LEDON1  '=%11111

IF Code=15 Then LEDON2  '=%01111

IF Code=7  Then LEDON3  '=%00111

 

CLEAR

Goto Startpulse  ‘If not matched, return to the Startpulse-waiting routine

 

LEDON1

High GPIO.0  'LED1 ON for 1sec 明かり1を灯せ

Pause 1000

Low GPIO.0

Goto Startpulse

 

LEDON2

High GPIO.1  'LED2 ON

Pause 1000

Low GPIO.1

Goto Startpulse

 

LEDON3

High GPIO.2  'LED3 ON

Pause 1000

Low GPIO.2

Goto Startpulse

 

'********** End of program ***************

'Note:

   'AKI Programmer's configurations:

   'FOSC  INTOSC (GP4:I/O); WDTE - Enable; PWRTE - Enable

'MCLR - Enable ; BODEN - Enable; CD - Disable; CDP – Disable

 

分かった事など

     データ信号として、違ったパルス幅のパルスを組み合わせて送り、それをPICBasic ProのコマンドPulsinで読込み、元のデータ信号を再生できた。つまり、データの送信が可能であった。

     全くアッセンブラのコマンドのお世話にならずにすんだ。

     基準の変調波38KHzから大きくずれた43KHzでも、送受信に支障はないようだ。

     入力キー(or SW)の数を増やすには、また、他のリモコンなどからの干渉を防ぐには、データ信号のビット数(今回5ビット)を増やせばよい(最大16ビット?)。

 

余談

こんな動作原理もあるんだなあ、ということが理解出来たのが最大の収穫であった。ロジックを考えた原作者に感謝したい。

PICBasic Proで組んだ赤外線送受信プログラムも外に発表されているが、アッセンブラのコマンドを含んでいて、しかも複雑。オジンには理解出来なかった。

梅雨の季節、長屋の気温は32度、湿気80%。そのためか、オシロが以前のようでない。ノイズ、接触不良のような症状が頻繁に出た。

 

<追加プログラムーSW1を押す毎に受信側出力がON/OFFを繰返す(Toggleの使用)>2007.7.5

 上記のプログラムでは、送信側の各SWを押すと、対応する受信側のLEDがONになり、離すとOFFになる(途中でONの状態が瞬時切れるのでセミモーメンタリ動作)。 これを送信側の各SWを押す毎に、対応する受信側のLEDがONからOFF、OFFからONへの変化を繰返す(ラッチ動作)ようにするには、以下のように上記の受信側プログラムの一部(2個所)を変える。今回は、SW1のみこの動作をするようにした(PulsinRt.bas)。 Pause 500を入れてあるので、SW1を押して0.5秒間以内に、指を離すと変化したONまたはOFFの状態が保たれる。0.5秒間以上押し続けると別の状態に変化する。この動作は、電源スイッチをON/OFFするような場合に役立つ。

 

1)

Startpulse:

GPIO.0=0    ‘Found these three are necessary

GPIO.1=0

GPIO.2=0

の部分からGPIO.0=0を削除して、以下のように変える。

 

Startpulse:

GPIO.1=0

GPIO.2=0

 

2)

LEDON1

High GPIO.0  'LED1 ON for 1sec 明かり1を灯せ

Pause 1000

Low GPIO.0

Goto Startpulse

の部分を以下のように変える。

 

LEDON1

Toggle GPIO.0

Pause 500     ‘0.5 sec

Goto Startpulse

 

<後で分かった事など> 2007.7.11

前の電子工作21<追加 - 上記の調光器にAC100Vライン用ON/OFFスイッチを追加し、電子工作22のプログラムでコントロールする>でふれたように、5ピットの“H”と”L”の組合せでは、電球型蛍光灯からのノイズに弱く、誤動作を頻繁に起こすことが分かった。8ビットに増やしても、時折ノイズを拾って誤動作を起こした。そこで、更に12ビットに増やしたところ、ほぼ誤動作は駆逐された。 ビット数を増やすと、操作性やレスポンスが若干落ちるが、間違いなく誤動作する確率は下がる。

 

 

<追加プログラム – 誤動作防止のためデータ信号を5ビットから16ビットに増やしてみた>2007.7.12

上記のデータ信号5ビットを使ったプログラムでは、電球型蛍光灯からのノイズで誤動作を頻繁に起こすことが分かった。そこで、データ信号を一気に16ビットに増やし、送信側の各SWに以下のように僅かに違うビット並びを振分け、それらを正確に受信側で認識するかどうかテストしてみた。 その結果は上々で、3つの送信データ信号を正確に受信側で区別して認識できた。送信距離も10メートル以上と以前と変わらず、応答速度も5ビットの場合とあまり変わらない感じであった。これで耐ノイズ性が大きく改善され、実用目的に十分使えると思われる。

もう一つ実験途中に分かったことは、送信側と受信側の間の空間が電球型蛍光灯で照明されていると、送信距離が低下することである。チューブ型やサークル型の蛍光灯にはあまり影響を受けないようだ。理由は不明である。

 

送信データ

SW1: 0000 0000 0000 0001  (=1)

SW2: 0000 0000 0000 0011  (=3)

SW3: 0000 0000 0000 0111  (=7)

 

送信プログラム: 'PulsinTx.bas

'PulsinTx.bas (paired with PulsinRx.bas) 2007.7.12 16-bit code differentiation

'test  Works well!

'************** Pin connection **********************

'12F629, 4MHz Internal Clock used

'Pin 1: Vdd (5.0V)

'Pin 8: Vss (GND)

'Pin 7: GPIO.0: input - connected to SW1

'Pin 6: GPIO.1: input - connected to SW2

'Pin 5: GPIO.2: input - connected to SW3

'Pin 3: GPIO.4: output - connected to IR LED via 100 ohm resistor

 

'*********** Main program ******************

CMCON=7 'Comparator not used

TRISIO=%000111  'GPIO.0, GPIO.1 and GPIO.2 = Input, others = Output

OPTION_REG.7=0  'Use of weak pull-up

WPU=%000111     'Pull-up for GPIO.0, GPIO.1 and GPIO.2

DEFINE OSCCAL_1K 1 'Set OSCCAL for 1K device

 

X var byte

SW1 var GPIO.0

SW2 var GPIO.1

SW3 var GPIO.2

GPIO.4=0

 

SWINR:  'SW search routine

IF SW1=0 THEN SW1R

IF SW2=0 THEN SW2R

IF SW3=0 THEN SW3R

GOTO SWINR

 

SW1R: 'Code LLLL LLLL LLLL LLLH  16ビットデータ信号送信ルーチン

X=0

GOSUB Startbit  '3 ms

GOSUB Sepbit   'Separate bit=2 ms

GOSUB Hbit  '"H" '2 ms         最下位ビット  最初に受信側に読込まれる

GOSUB Sepbit

GOSUB Lbit  '"L" '1 ms

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"      最上位ビット

GOSUB Sepbit

Goto SWINR

 

SW2R: 'Code LLLL LLLL LLLL LLHH

X=0

GOSUB Startbit  '3 ms

GOSUB Sepbit   'Separate bit=2 ms

GOSUB Hbit  '"H"

GOSUB Sepbit

GOSUB Hbit  '"H"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

Goto SWINR

 

SW3R: 'Code LLLL LLLL LLLL LHHH

X=0

GOSUB Startbit  '3 ms

GOSUB Sepbit   'Separate bit=2 ms

GOSUB Hbit  '"H" '2 ms

GOSUB Sepbit

GOSUB Hbit  '"H"

GOSUB Sepbit

GOSUB Hbit  '"H"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

GOSUB Lbit  '"L"

GOSUB Sepbit

Goto SWINR

 

Startbit:

High GPIO.4 'GETTING 38KHZ WITH THIS SUBROUTINE

High GPIO.4

Low GPIO.4

Low GPIO.4

X = X + 1

IF X < 99 Then STARTBIT '99 GIVES 3MS START PULSE

Return

 

Sepbit:

Pause 2  '2 ms

X=0

Return

 

Hbit:

High GPIO.4

High GPIO.4

Low GPIO.4

Low GPIO.4

X= X + 1

IF X < 66 Then Hbit '2MS CODEBIT

Return

 

Lbit:

High GPIO.4

High GPIO.4

Low GPIO.4

Low GPIO.4

LET X= X + 1

IF X < 33 Then Lbit '1MS CODEBIT

Return

 

'********** End of program ***************

'Note:

   'AKI Programmer's configurations:

   'FOSC  INTOSC (GP4:I/O); WDTE - Enable; PWRTE - Enable

'MCLR - Internal ; BODEN - Enable; CD - Disable; CDP – Disable

 

受信プログラム: PulsinRx.bas

'PulsinRx.bas (paired with PulsinTx.bas) 2007.7.12 16-bit code differentiation

'test  Works well!

 

'************** Pin connection **********************

'12F629, 4MHz Internal Clock used

'Pin 1: Vdd (5.0V)

'Pin 8: Vss (GND)

'Pin 7: GPIO.0: output - connected to LED1

'Pin 6: GPIO.1: output - connected to LED2

'Pin 5: GPIO.2: output - connected to LED3

'Pin 3: GPIO.4: input - connected to IR Receiver module

 

'*************** Main program ***********************

CMCON=7  'Comparator off

TRISIO=%0010000  'all except GP4 are outputs.

DEFINE OSCCAL_1K 1

Codelength var Byte

Code var word  'for 16-bit code formation 16ビットなのでByteからWordに変えた

X var Byte

Clear  'Content of all variables -> 0

Pause 500  'Settle down PIC & IR receiver module

 

Startpulse:

GPIO.0=0

GPIO.1=0

GPIO.2=0

 

Pulsin GPIO.4,0,Codelength 'Measure low pulse (IR LED On time)

IF Codelength < 200 Then Startpulse  'Searching 3 ms pulse

IF Codelength > 300 Then Startpulse

 

'Codepulses     16ビットCode合成ルーチン “H” or ”L”

'Checking Bit0

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit0=1 '2 ms pulse is 1  initial 150->100 changed

IF Codelength < 100 Then Code.bit0=0 '1 ms pulse is 0

 

'Checking Bit1

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit1=1 '2 ms pulse is 1

IF Codelength < 100 Then Code.bit1=0 '1 ms pulse is 0

 

'Checking Bit2

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit2=1 '2 ms pulse is 1

IF Codelength < 100 Then Code.bit2=0 '1 ms pulse is 0

 

'Checking Bit3

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit3=1 '2 ms pulse is 1

IF Codelength < 100 Then Code.bit3=0 '1 ms pulse is 0

 

'Checking Bit4

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit4=1 '2 ms pulse is 1

IF Codelength < 100 Then Code.bit4=0 '1 ms pulse is 0

 

'Checking Bit5

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit5=1 '2 ms pulse is 1

IF Codelength < 100 Then Code.bit5=0 '1 ms pulse is 0

 

'Checking Bit6

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit6=1 '2 ms pulse is 1

IF Codelength < 100 Then Code.bit6=0 '1 ms pulse is 0

 

'Checking Bit7

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit7=1 '2 ms pulse is 1

IF Codelength < 100 Then Code.bit7=0 '1 ms pulse is 0

 

'Checking Bit8

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit8=1 '2 ms pulse is 1

IF Codelength < 100 Then Code.bit8=0 '1 ms pulse is 0

 

'Checking Bit9

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit9=1 '2 ms pulse is 1

IF Codelength < 100 Then Code.bit9=0 '1 ms pulse is 0

 

'Checking Bit10

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit10=1 '2 ms pulse is 1

IF Codelength < 100 Then Code.bit10=0 '1 ms pulse is 0

 

'Checking Bit11

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit11=1 '2 ms pulse is 1

IF Codelength < 100 Then Code.bit11=0 '1 ms pulse is 0

 

'Checking Bit12

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit12=1 '2 ms pulse is 1

IF Codelength < 100 Then Code.bit12=0 '1 ms pulse is 0

 

'Checking Bit13

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit13=1 '2 ms pulse is 1

IF Codelength < 100 Then Code.bit13=0 '1 ms pulse is 0

 

'Checking Bit14

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit14=1 '2 ms pulse is 1

IF Codelength < 100 Then Code.bit14=0 '1 ms pulse is 0

 

'Checking Bit15

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit15=1 '2 ms pulse is 1

IF Codelength < 100 Then Code.bit15=0 '1 ms pulse is 0

 

Pause 20

IF Code=1 Then LEDON1  '=%0000 0000 0000 0001 (=1)

IF Code=3 Then LEDON2  '=%0000 0000 0000 0011 (=3)

IF Code=7 Then LEDON3  '=%0000 0000 0000 0111 (=7)

 

CLEAR

Goto Startpulse

 

LEDON1

High GPIO.0  'LED1 ON

Pause 1000

Low GPIO.0

Goto Startpulse

 

LEDON2

High GPIO.1  'LED2 ON

Pause 1000

Low GPIO.1

Goto Startpulse

 

LEDON3

High GPIO.2  'LED3 ON

Pause 1000

Low GPIO.2

Goto Startpulse

 

'********** End of program ***************

'Note:

   'AKI Programmer's configurations:

   'FOSC  INTOSC (GP4:I/O); WDTE - Enable; PWRTE - Enable

'MCLR - Enable ; BODEN - Enable; CD - Disable; CDP – Disable

 

例えば、送信側のSW3 (0000 0000 0000 0111)を押すと、受信側の赤外線受信モジュールが以下のようなパルス列を出力し、12F629がそれを読込んで、各パルスの幅を測定し、16ビットの“H”と“L”の列を再構築する。その並びを十進で読み、予め設定してある数値と一致したら、対応する仕事をする。出力がシャープで綺麗なのには感心する。

 


 


気づいた事など

  今回用いたデータ信号の送受信では、“H”と”L”を2種類のパルス幅にそれぞれ託して送信し、受信側でそれらの幅を計って送信データ信号の配列を再合成している。したがって、商用のリモコンで使われているデータ信号の送受信原理と多少違う。商用のものを参考にすると、今回の送受信システムが他からの干渉を受けるのを避けるには、以下のようなことが大切なようだ。

1)     パルスの数を多くする。商用のものでは、10本位から、30−40本も使っているものがある。

2)     パルスの幅を狭くする。例えば、商用のものでは 0.35ms、0.64ms など使われている。 

3)     Separate bit を2−3種類に増やす。商用のものでは、“L”の区間に相当。

4)     パルス配列の中の“H”と”L”の組合せを複雑にする。

5)     商用のパルス配列を参考にする。

尚、オシロで受信パルスを測定する時は、IR Receiver Module のOUTPUTピンとGNDをプローブに接続する。

  

<追加プログラム – 受信精度を上げる為の改良>2007.7.16

上記の追加プログラムPulsinRx.bas 2007.7.12) の受信側で、原因が分からない受信エラー(SW1に対応するGPIO.0で)が発生しブザーが鳴った。そこで、送信データ信号の再合成を2回繰返すように改良した。つまり、1回目の合成送信データ信号と、2回目のそれとを比較して同じであれば、各対応するLEDONを実行する、というものである。 SW入力に対する応答(LEDの点灯)もスムーズであり、また、合計で32ビットもチェックしているので、もう誤動作は起こさないと期待される。

 

受信プログラム(改良版): PulsinRy.bas

'PulsinRy.bas 2007.7.16  Repeat the code making routine twice to avoid reading

'error.

 

'PulsinRx.bas (paired with PulsinTx.bas) 2007.7.12 16-bit code differentiation

'test  Works well!

'PulsinR.bas 2007.7.2  Worked at last. Pulsin proj.

'Frequency of Moduleted pulses - Designed 38KHz/Measured 43KHz

'Length of pulses:

'Startbit - Desined 3ms/Measured 2.3ms

'Separatelength - Desined 2ms/Measured 1.95ms

'Codes - "H" Desined 2ms/Measured 1.57ms; "L" Desined 1ms/Measured 0.83ms 

'************** Pin connection **********************

'12F629, 4MHz Internal Clock used

'Pin 1: Vdd (5.0V)

'Pin 8: Vss (GND)

'Pin 7: GPIO.0: output - connected to LED1

'Pin 6: GPIO.1: output - connected to LED2

'Pin 5: GPIO.2: output - connected to LED3

'Pin 3: GPIO.4: input - connected to IR Receiver module

 

'*************** Main program ***********************

CMCON=7  'Comparator off

TRISIO=%0010000  'all except GP4 are outputs.

DEFINE OSCCAL_1K 1

Codelength var Byte

Code var word  'for 16-bit code formation

Code1 var word  '7.16

Code2 var word  '7.16

X var Byte

Clear  'Content of all variables -> 0

Pause 500  'Settle down PIC & IR receiver module

 

Startpulse:

GPIO.0=0

GPIO.1=0

GPIO.2=0

 

'1st  1回目の送信データの再合成

Pulsin GPIO.4,0,Codelength 'Measure low pulse (IR LED On time)

IF Codelength < 200 Then Startpulse  'Searching 3 ms pulse

IF Codelength > 300 Then Startpulse

 

'Codepulses

'Checking Bit0

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit0=1 '2 ms pulse is 1

IF Codelength < 100 Then Code.bit0=0 '1 ms pulse is 0

 

'Checking Bit1

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit1=1

IF Codelength < 100 Then Code.bit1=0

 

'Checking Bit2

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit2=1

IF Codelength < 100 Then Code.bit2=0

 

'Checking Bit3

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit3=1

IF Codelength < 100 Then Code.bit3=0

 

'Checking Bit4

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit4=1

IF Codelength < 100 Then Code.bit4=0

 

'Checking Bit5

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit5=1

IF Codelength < 100 Then Code.bit5=0

 

'Checking Bit6

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit6=1

IF Codelength < 100 Then Code.bit6=0

 

'Checking Bit7

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit7=1

IF Codelength < 100 Then Code.bit7=0

 

'Checking Bit8

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit8=1

IF Codelength < 100 Then Code.bit8=0

 

'Checking Bit9

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit9=1

IF Codelength < 100 Then Code.bit9=0

 

'Checking Bit10

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit10=1

IF Codelength < 100 Then Code.bit10=0

 

'Checking Bit11

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit11=1

IF Codelength < 100 Then Code.bit11=0

 

'Checking Bit12

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit12=1

IF Codelength < 100 Then Code.bit12=0

 

'Checking Bit13

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit13=1

IF Codelength < 100 Then Code.bit13=0

 

'Checking Bit14

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit14=1

IF Codelength < 100 Then Code.bit14=0

 

'Checking Bit15

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit15=1

IF Codelength < 100 Then Code.bit15=0

 

Code1=Code  '7.16  Code1 - 1st Code 

            'don't insert pause here ここに Pauseなどを入れるとSW入力にスムースに応答しない。

 

'2nd  2回目の送信データの再合成

Pulsin GPIO.4,0,Codelength

IF Codelength < 200 Then Startpulse

IF Codelength > 300 Then Startpulse

 

'Codepulses

'Checking Bit0

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit0=1

IF Codelength < 100 Then Code.bit0=0

 

'Checking Bit1

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit1=1

IF Codelength < 100 Then Code.bit1=0

 

'Checking Bit2

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit2=1

IF Codelength < 100 Then Code.bit2=0

 

'Checking Bit3

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit3=1

IF Codelength < 100 Then Code.bit3=0

 

'Checking Bit4

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit4=1

IF Codelength < 100 Then Code.bit4=0

 

'Checking Bit5

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit5=1

IF Codelength < 100 Then Code.bit5=0

 

'Checking Bit6

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit6=1

IF Codelength < 100 Then Code.bit6=0

 

'Checking Bit7

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit7=1

IF Codelength < 100 Then Code.bit7=0

 

'Checking Bit8

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit8=1

IF Codelength < 100 Then Code.bit8=0

 

'Checking Bit9

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit9=1

IF Codelength < 100 Then Code.bit9=0

 

'Checking Bit10

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit10=1

IF Codelength < 100 Then Code.bit10=0

 

'Checking Bit11

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit11=1

IF Codelength < 100 Then Code.bit11=0

 

'Checking Bit12

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit12=1

IF Codelength < 100 Then Code.bit12=0

 

'Checking Bit13

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit13=1

IF Codelength < 100 Then Code.bit13=0

 

'Checking Bit14

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit14=1

IF Codelength < 100 Then Code.bit14=0

 

'Checking Bit15

Pulsin GPIO.4,0,Codelength

IF Codelength > 100 Then Code.bit15=1

IF Codelength < 100 Then Code.bit15=0

 

Code2=Code  'Code2 - 2nd Code

 

'JUMPtoLED

Pause 20

IF Code1=1 AND Code2=1 Then LEDON1  '=%0000 0000 0000 0001  1回目と2回目の再合成された送信データの比較

IF Code1=3 AND Code2=3 Then LEDON2  '=%0000 0000 0000 0011

IF Code1=7 AND Code2=7 Then LEDON3  '=%0000 0000 0000 0111

 

CLEAR

Goto Startpulse

 

LEDON1

High GPIO.0  'LED1 ON

Pause 1000

Low GPIO.0

Goto Startpulse

 

LEDON2

High GPIO.1  'LED2 ON

Pause 1000

Low GPIO.1

Goto Startpulse

 

LEDON3

High GPIO.2  'LED3 ON

Pause 1000

Low GPIO.2

Goto Startpulse

 

'********** End of program ***************

'Note:

   'AKI Programmer's configurations:

   'FOSC  INTOSC (GP4:I/O); WDTE - Enable; PWRTE - Enable

   'MCLR - Enable ; BODEN - Enable; CD - Disable; CDP – Disable

 

<追加プログラム – SW1を押している間受信側LED出力がON、放すとOFFになる動作(モーメンタリ動作)をさせる>2007.7.20

上記の受信プログラム(改良版) PulsinRy.bas で送信側のSW1を押し続けた場合、受信側の対応するLED出力は点灯し続けるが、プログラムがキースキャン(入力キーを探し続ける)をしているので、途中で点灯が一時的に中断する瞬間が一定の間隔で入ってくる。この間隔(今回は150 ms程度)を除かないと、完全なモーメンタリ出力にはならない。つまり、SW1を押している間、LED出力は一瞬たりとも消えずに点灯し続けなければならない。さて、どうやって、このキースキャンのために中断する部分(12F629(2)のGP.0の出力がLowになる)を除いてやるか(Highにする)。いろいろと考えた末、もう一個の12F629を使い、プログラムで修正をすることを思いついた。下図のように、一段目の12F629(1)のGP0の出力が追加した12F629(2)のGP0に入り、そして、GP1より出てLED1につながっている。この回路で、送信側でSW1を押し続けると、12F629(1)のGP0出力はHigh/Low を繰返す信号になるが、12F629(2)のGP1出力はHighの状態が連続する信号にすることが出来た。


 


 


プログラム

送信プログラム: 'PulsinTx.bas (上記)

 12F629(1)のプログラム: PulsinRy.bas (上記)

12F629(2)のプログラム: 'PulsinRu.bas−以下のように新しく作成した。

 送信側のSW1を押し続けた時に、12F629 (2)のGP0に入ってくる信号はHの部分が500ms、次にLの部分が約150ms間繰返す矩形波である(上図の波形参照)。このL部分の150msをHに変えるには、入力してくるHの部分の立ち上りを検知したら、その部分の500msに、L部分の150msを加えた650msをGP1よりHとして出力してやればよいと考えた。実際には、650msでは、依然としてL部分が存在し続け、LED1は非連続点灯する。800msにすると、L部分は完全に消えてLED1は完全な連続点灯する。ロジック考え、たったこれだけのプログラム作成するのに3日間もかかった。難しい。

   

'PulsinRu.bas 2007.7.18  Momentary output using a 2nd 12F629.. Succeeded at last

'taking 3 days to make this simple program.

 

'************** Pin connection **********************

'12F629, 4MHz Internal Clock used

'Pin 1: Vdd (5.0V)

'Pin 8: Vss (GND)

'Pin 7: GPIO.0: input from the GPIO.0 of 1st 12F629

'Pin 6: GPIO.1: output - connected to 2nd 12F629's LED

'*************** Main program ***********************

CMCON=7  'Comparator off

TRISIO=%000001

 

GPIO.1=0  'without this, LED sometimes turns ON when power is turned ON (added on 2007.7.23)

 

WaitpulseH:

IF GPIO.0=0 then WaitpulseH  'Wait H-pulse period 1段目の12F629 (1)からの“H”出力待ち

High GPIO.1  'Turn on LED connected to GPIO.1   “H”が来たら 800ms GP1出力を”H”にする

Pause 800 'Space between 2 H-pulse periods; this was experimentally decided.

          'If it is <750ms, a small space (turned-off period of LED) is

          'formed b/t 2 H-pulse periods. But 800 completely eliminates this space,

          'realizing a real momentary switching action.

Low GPIO.1

goto WaitpulseH

 

'********** End of program ***************

'Note:

   'AKI Programmer's configurations:

   'FOSC  INTOSC (GP4:I/O); WDTE - Enable; PWRTE - Enable

   'MCLR - Diable ; BODEN - Enable; CD - Disable; CDP - Disable

  

   

Menu Pageへ戻る    

Topへ戻る