以前、机上検討していた455kHzマルチチャンネル対応送信機と受信機を実際に製作してみました。
送信機側は下の写真のブレッドボード上に組み立てたPIC12F683を使った送信機をやめにして、代わりに以前製作していた赤外線送信機のハードをそのまま流用してプログラムを455kHz化しました。(下の写真のLCD表示器とジョイスティックが付いたモノ)受信機側はブレッドボード上に組み立てた受信機に「455kHz用受光素子」(http://fwhp6462.cocolog-nifty.com/blog/2009/04/455khz-c685.html)で作った変換基板を使って実装しました。写真右側のPIC10F222だけ使用しています。左側のPIC12F683は以前赤外線で送受信しないで電線を直結して動作確認した時のものです。今回は使用していません。既存のPIC10F222などを使用している受信機の受光素子の交換とプログラムの書き換えで使用可能と思います。

受信機のプログラムは以前のマルチチャンネル化検証で作成した各チャンネル7ビットの3チャンネルから各チャンネル8ビットの2チャンネルに修正しました。また、以前は保留していたパリティチェックを追加し、さらに安全対策としてペアリング前はモータとラダーを駆動しない機能を追加しました。
<4月7日追記>
無信号状態が続いた場合にモータを停止する機能追加。およびペアリング後にスロットル最大→スロットル最小にしないと出力をONにしない機能を追加。ペアリング要求ビットが10回連続してセットされていないとペアリングしないように修正。
| ビット |
機能 |
| 1~9 |
スタートを表すための9ビット連続した”1” |
| 10 |
0固定(スタート以外に”1”が9ビット連続した箇所ができないようにする) |
| 11 |
1固定 |
| 12 |
2CHの場合は0、4CHの場合は1 |
| 13~15 |
チャンネル(3ビット、上位ビットから送る) |
| 16 |
0固定(スタート以外に”1”が9ビット連続した箇所ができないようにする) |
| 17~24 |
スロットル(8ビット、上位ビットから送る) |
| 25 |
0固定(スタート以外に”1”が9ビット連続した箇所ができないようにする) |
| 26~33 |
ラダー(8ビット、上位ビットから送る) |
| 34 |
0固定(スタート以外に”1”が9ビット連続した箇所ができないようにする) |
| 35 |
ペアリング要求1 |
| 36 |
ペアリング要求2リザーブ |
| 37 |
パリティ用(ビット11~36のうち1であったものが偶数個であれば1) |
<4月7日修正>
ビット35、36の機能割り当てを修正。およびチャンネル、スロットル、ラダーのデータ送出順を追記。パリティの詳細も追記。送信機側は1(ON)の場合に赤外線を出します。(受光素子の信号端子が0Vになります。)
4CHの場合はビット12を1にして、ビット17~34の「8ビットデータと1ビットの0」を2回繰り替えしている部分を「6ビットデータと1ビットの0」を4回繰り返すようにします。(送信機側には実装してあるのですが、受信機側が未作成)
明日以降はプログラムの細かい修正と(←4月7日済)プリント基板化の予定です。(基板はエッチングまで済んでいて部品をハンダ付けしていない状態なので1時間もあれば完成なのですが。)
<4月7日追記>受信機側プログラムです。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// IRRX455 (PIC10F222) 2CH PCM IR Remote Control Receiver
// for CC5X
//
// Ver 0.10 09.02.05 T.Kojima マルチチャンネル化検証用
// Ver 0.20 09.02.09 T.Kojima 赤外線受信動作とPWM制御動作を交互に実行するように修正
// Ver 0.30 09.04.05 T.Kojima 2ch/4chを分離、本ソースは2ch用
// Ver 0.31 09.04.06 T.Kojima ペアリング方法見直し(電源投入後に1回だけ有効とし,要求が10回連続した場合のみ有効とした)
// 無信号時にスロットル制御量を徐々に絞る制御を追加
// スロットルを上限まであげた後に下限まで下げないとモータ、アクチュエータをONにしない処理を追加
// SOT23 DIP
#define signal GPIO.3 // Pin6 Pin8
#define rud1 GPIO.0 // Pin1 Pin5
#define rud2 GPIO.1 // Pin3 Pin4
#define motor GPIO.2 // Pin4 Pin3
#define TMR0_48us 6
#define TMR0_24us 3
unsigned char stat; // 信号受信ステータス
unsigned char Bits_cnt; // ビットカウンタ
bit rud_pol_1; // ラダーを振る方向1 どっちが右なのかは回路次第
bit rud_pol_2; // ラダーを振る方向2
bit resv2; // 予備
bit parity_bit;
bit error_f;
bit ch_fix;
bit max_chk;
bit min_chk;
unsigned char chsel; // ペアリング要求
unsigned char next_seq;
unsigned char rud_wid;
unsigned char th_wid;
unsigned char TMR0ck; // 受信した信号をチェックするタイミング
unsigned char chnum;
unsigned char ch;
unsigned char ch0;
unsigned char ch1;
unsigned char TMR0_1;
unsigned char TMR0_2;
unsigned char i;
unsigned char parity;
unsigned char stop_tmr;
void main(void)
{
// Hard config
OPTION = 0xc3; // TMR0は16分周モードで使用する (TMR0が1回オーバーフローするごとに約2ms経過する)
TRISGPIO = 0x08; // GPIO3は入力, 他は出力
ADCON0 = 0x00; // 全ピンデジタル指定
OSCCAL = 0xc20; // 要調整
// IO Pin Initial
rud1 = 0;
rud2 = 0;
motor = 0;
// WORK Initial
stat = 0;
chnum = 0;
ch_fix = 0;
parity = 0;
chsel = 0;
max_chk = 0;
min_chk = 0;
while (1){
error_f = 0;
// STARTビットの先頭を探す
while(signal == 1){};
TMR0ck = TMR0 + TMR0_24us;
// STARTビットのチェック
// 半サイクル後から1サイクルごとにSTARTビットのチェックを9回繰り返す
Bits_cnt = 0;
while ((error_f == 0) && (Bits_cnt < 9)){
if (TMR0ck == TMR0){
// 信号はONか?
if (signal == 1){error_f = 1;};
Bits_cnt++;
TMR0ck = TMR0ck + TMR0_48us;
};
};
// "0"のチェック
next_seq = 0;
while ((error_f == 0) && (next_seq == 0)){
if (TMR0ck == TMR0){
// 信号はONか?
if (signal == 0){error_f = 1;};
next_seq = 1;
TMR0ck = TMR0ck + TMR0_48us;
parity = 0;
};
};
// "1"のチェック
next_seq = 0;
while ((error_f == 0) && (next_seq == 0)){
if (TMR0ck == TMR0){
// 信号はONか?
if (signal == 1){error_f = 1;};
next_seq = 1;
TMR0ck = TMR0ck + TMR0_48us;
parity = 0;
};
};
// "0"のチェック
next_seq = 0;
while ((error_f == 0) && (next_seq == 0)){
if (TMR0ck == TMR0){
// 信号はONか?
if (signal == 0){error_f = 1;};
next_seq = 1;
TMR0ck = TMR0ck + TMR0_48us;
parity = 0;
};
};
// chnum受信
if (error_f == 0){
Bits_cnt = 0;
while (Bits_cnt < 3){
if (TMR0ck == TMR0){
// 信号はONか?
Bits_cnt++;
chnum = chnum * 2;
if (signal == 0){
chnum++;
parity++;
};
TMR0ck = TMR0ck + TMR0_48us;
};
};
// "0"のチェック
next_seq = 0;
while ((error_f == 0) && (next_seq == 0)){
if (TMR0ck == TMR0){
// 信号はONか?
if (signal == 0){error_f = 1;};
next_seq = 1;
TMR0ck = TMR0ck + TMR0_48us;
};
};
};
// data1受信
if (error_f == 0){
Bits_cnt = 0;
ch0 = 0;
while (Bits_cnt < 8){
if (TMR0ck == TMR0){
// 信号はONか?
Bits_cnt++;
ch0 = ch0 * 2;
if (signal == 0){
ch0++;
parity++;
};
TMR0ck = TMR0ck + TMR0_48us;
};
};
// "0"のチェック
next_seq = 0;
while ((error_f == 0) && (next_seq == 0)){
if (TMR0ck == TMR0){
// 信号はONか?
if (signal == 0){error_f = 1;};
next_seq = 1;
TMR0ck = TMR0ck + TMR0_48us;
};
};
};
// data2受信
if (error_f == 0){
Bits_cnt = 0;
ch1 = 0;
while (Bits_cnt < 8){
if (TMR0ck == TMR0){
// 信号はONか?
Bits_cnt++;
ch1 = ch1 * 2;
if (signal == 0){
ch1++;
parity++;
};
TMR0ck = TMR0ck + TMR0_48us;
};
};
// "0"のチェック
next_seq = 0;
while ((error_f == 0) && (next_seq == 0)){
if (TMR0ck == TMR0){
// 信号はONか?
if (signal == 0){error_f = 1;};
next_seq = 1;
TMR0ck = TMR0ck + TMR0_48us;
};
};
};
// resv1受信
next_seq = 0;
if (error_f == 0){
while (next_seq == 0){
if (TMR0ck == TMR0){
// 信号はONか?
next_seq = 1;
if (signal == 0){
chsel++;
parity++;
}
else {
chsel = 0;
};
TMR0ck = TMR0ck + TMR0_48us;
};
};
// resv2受信
next_seq = 0;
while (next_seq == 0){
if (TMR0ck == TMR0){
// 信号はONか?
next_seq = 1;
if (signal == 0){
resv2 = 1;
parity++;
}
else {
resv2 = 0;
};
TMR0ck = TMR0ck + TMR0_48us;
};
};
// parity受信
next_seq = 0;
while (next_seq == 0){
if (TMR0ck == TMR0){
// 信号はONか?
next_seq = 1;
if (signal == 0){
parity_bit= 1;
}
else {
parity_bit = 0;
};
TMR0ck = TMR0ck + TMR0_48us;
};
};
};
// パリティチェック
if ((parity & 0x01) == 0) {if (parity_bit){;}else{error_f=1;};};
if ((parity & 0x01) != 0) {if (parity_bit){error_f=1;}else{;};};
// チャンネル設定要求?
if ((error_f == 0) && (ch_fix == 0) && (chsel > 10)){
ch = chnum;
ch_fix = 1;
};
if ((error_f == 0) && (ch_fix) && (chnum == ch)){
if (ch0 > 0xe0){max_chk = 1;};
if ((ch0 < 0x10) && max_chk){min_chk = 1;};
if ((max_chk == 1) && (min_chk == 1)){
// 制御量計算
th_wid = ch0;
rud_pol_1 = 0;
rud_pol_2 = 0;
rud_wid = 0;
if (ch1 > 0x80){
rud_pol_1 = 1;
rud_wid = ch1 - 0x80;
}
else if (ch1 < 0x80){
rud_pol_2 = 1;
rud_wid = 0x80 - ch1;
};
rud_wid = rud_wid * 2;
// RUD,TH ON/OFFタイミング設定
TMR0ck = TMR0;
TMR0_1 = TMR0ck + rud_wid;
TMR0_2 = TMR0ck + th_wid;
stop_tmr = 250; // 500ms信号を受信しなければ徐々に制御量を絞るための時間設定
// RUD,TH PWM制御
// 信号受信成功後0~18msの間は信号を受信しても無視してPWM制御を行う
for(i=0;i<9;i++){
// RUD,TH ON
while ((TMR0 != TMR0ck) && (TMR0 != (TMR0ck+1)));
if (rud_wid > 5){
if (rud_pol_1 == 1){
rud1 = 1;
}
else if(rud_pol_2 == 1){
rud2 = 1;
};
};
if (th_wid > 5){
motor = 1;
}
else {
motor = 0;
};
// RUD,TH OFF
while ((rud1 == 1) || (rud2 == 1) || (motor == 1)){
if ((TMR0 == TMR0_1) || (TMR0 == (TMR0_1+1))){
rud1 = 0;
rud2 = 0;
};
if ((TMR0 == TMR0_2) || (TMR0 == (TMR0_2+1))){
motor = 0;
};
};
};
// 信号受信成功後18ms以降は信号を受信するまでPWM制御する。信号受信したらPWM制御は終了する
while(signal != 0){
// RUD,TH ON
while ((TMR0 != TMR0ck) && (TMR0 != TMR0ck+1)){if (signal==0){break;};};
if (rud_wid > 5){
if (rud_pol_1 == 1){
rud1 = 1;
}
else if(rud_pol_2 == 1){
rud2 = 1;
};
};
if (th_wid > 5){
motor = 1;
}
else {
motor = 0;
};
// RUD,TH OFF
while ((rud1 == 1) || (rud2 == 1) || (motor == 1)){
if (signal==0){
rud1 = 0;
rud2 = 0;
motor = 0;
break;
};
if ((TMR0 == TMR0_1) || (TMR0 == (TMR0_1+1))){
rud1 = 0;
rud2 = 0;
};
if ((TMR0 == TMR0_2) || (TMR0 == (TMR0_2+1))){
motor = 0;
};
};
//無信号時は制御量を徐々に絞る処理
if (stop_tmr > 0){
stop_tmr--;
}
else {
if (th_wid > 0){th_wid--;};
TMR0_2 = TMR0ck + th_wid;
stop_tmr = 5;
};
};
};
};
};
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PIC10F222用のROMデータです。(IRRX_455-2ch.zip)
最近のコメント