卒業論文 競技用ロボットにおける制御回路とプログラムの開発 · 3.2...

37
競技用ロボットにおける制御回路とプログラムの開発 031214 2008 2 28 Copyright c 2008 by Takaaki Kumagai

Transcript of 卒業論文 競技用ロボットにおける制御回路とプログラムの開発 · 3.2...

卒 業 論 文

競技用ロボットにおける制御回路とプログラムの開発

石川工業高等専門学校 電気工学科

学籍番号 031214

熊谷貴明

主任指導教員 河合康典 助教授

2008年 2月 28日

Copyright c⃝ 2008 by Takaaki Kumagai

c⃝2008

Takaaki Kumagai

All rights reserved

要 旨

本研究では, 競技用ロボットの開発における負荷を軽減するための開発手法を提案する.

はじめに, 競技用ロボットの制御を行う回路について考察し, 再利用と保守を重視, 柔軟

性を損なわない設計の提案を行う. 制御回路は, ロボットの制御を行う制御基盤に各機能を

有する回路基板を接続することで構成し, 構成における模範となる形を提案する.また, 各基

盤の接続方法について規約を設け, 再利用と保守を容易にする.

次に, 競技用ロボットの動作を司る制御プログラムについて考察する. プログラムの設計

について, 再利用と保守を考慮し, 多数の機能を有することを前提とした設計を提案する. マ

イクロコンピュータの性能について考察を行い, マルチタスクシステムの導入を検討する.

また, 再利用と保守を考慮したプログラムの部品化について, 設計の方針を考察する.

最後に, プログラム開発において記述を行うプログラミング言語について考察し, 提案し

た設計に従いプログラムを製作する. アセンブラ言語とC言語の違いを考察し, C言語が優

位であることを示し, 実際に利用可能かを検討する. 検討する際に, C言語による開発環境

の選定も同時に行い, 開発環境の構築についても考察を行う.

i

目 次

第 1章 序論 1

1.1 研究の背景と動機 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

1.2 論文構成 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

第 2章 制御回路構成 2

2.1 はじめに . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

2.2 制御回路の機能分離 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

2.3 モジュール間の接続 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

2.4 電源回路と消費電流 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

2.5 保護回路 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

2.6 回路構成価格と回路規模 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

2.7 検討課題 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

2.8 おわりに . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

第 3章 制御プログラム構成 6

3.1 はじめに . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

3.2 マルチタスクシステムの導入 . . . . . . . . . . . . . . . . . . . . . . . . . . 6

3.3 タスクの時間精度要求 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

3.4 タスクシステムの実現 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

3.5 入出力プログラム . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

3.6 検討課題 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

3.7 おわりに . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

第 4章 開発環境の構築 10

4.1 はじめに . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

4.2 開発言語の違い . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

4.3 開発環境の選定と構築 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

ii 目 次

4.4 おわりに . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

第 5章 提案手法の評価 12

5.1 はじめに . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

5.2 製作の評価 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

5.3 実行性能 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

5.4 開発上の問題点 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

5.5 おわりに . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

第 6章 結論 14

6.1 本研究での成果 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

6.2 今後の課題 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

付 録A 本研究で製作したプログラム 15

A.1 C言語で製作プログラムソース . . . . . . . . . . . . . . . . . . . . . . . . . 15

謝辞 28

参考文献 29

iii

図 目 次

2.1 回路構成例 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

2.2 Zコネクタ形式の雄形状と雌形状 . . . . . . . . . . . . . . . . . . . . . . . . 3

3.1 タスク構成図 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

iv 表 目 次

表 目 次

2.1 Zコネクタの短絡による故障の発生 . . . . . . . . . . . . . . . . . . . . . . . 4

3.1 各タスクの時間精度要求 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

4.1 アセンブラ言語とC言語の違い . . . . . . . . . . . . . . . . . . . . . . . . . 10

4.2 構築した開発環境 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

1

第 1章

序論

1.1 研究の背景と動機

近年, ROBO-ONEをはじめとするロボットの動作を競うコンテストが多く実施されてい

る. しかし, ロボットのコンテストに参加するロボットの大半が「完成済みのロボット製品」

という現状であり, その原因としてロボットの製作に機械, 電気,情報といった複数の分野の

知識を必要とする上に, 時間とお金を多く消費する活動であるという問題が考えられる.

本研究では, 競技用ロボットに適した開発手法の提案を行い, ロボット開発における負担

を軽減し, ロボット開発活動の発展を促すことを目的とする.

1.2 論文構成

本稿では, 競技用ロボットの開発における模範となる開発手法を提案し, その評価を行う.

始めに, 競技用ロボットにおける制御回路と制御プログラムの設計について考察を行い, 模

範となる設計指針を提示して, その具体例を示す. 次に, 競技用ロボットの制御プログラム

開発における開発環境の構築を行う. その後, 構築した開発環境により設計したプログラム

の製作を行い, その評価を行う. 最後に, 提案手法の評価と検討を行い, 今後の課題を導出

する.

2 第 2 章 制御回路構成

第 2章

制御回路構成

2.1 はじめに

本章ではロボットの制御回路の構成について考察を行う. 制御回路は, 競技用ロボットに

要求される条件に対し柔軟に対応すべきであり, 開発負荷の軽減のために再利用と保守を考

慮する必要がある.

今回提案する制御回路構成は, 既製品である近藤科学社のモーションプロセッサを参考と

し, 各部品の既製品置き換えを考慮した.

2.2 制御回路の機能分離

一般的にロボット制御回路は, 中央の制御基盤と周辺の各回路は基板が分離されている

(文献 [1], [2]). 今回提案する回路の構成もこれに倣い, 回路機能の分離を行い, 回路基板を

モジュール化する. 実際にモジュール化を行った回路構成の例を図 2.1に示す. ロボットの

遠隔制御を可能にする無線または有線による制御信号の送信, ロボットの搭載する各センサ

類, 制御対象のモータを駆動するドライバ回路の三種類を制御基板に接続可能にしている.

2.3 モジュール間の接続

モジュール間の接続には, 既製品でも広く採用されている Zコネクタ形式 (図 2.2)を採用

し, 既製品の利用や置き換えが円滑に行えるようにしている. ただし, 回路部品の節約の関

係上, 信号出力のドライブ回路はマイコンの出力回路である CMOSとなっている. この場

合, 長い伝送距離で信号が伝達出来ないため, 回路製作時には注意が必要である (伝送距離

2.4. 電源回路と消費電流 3

市販

コントローラ

無線

受信機

電波

無線

自作

コントローラ

自作

赤外線

受信機

赤外線

無線

制御

基盤

DCモータ

ドライバ

DCサーボ

モータ

ドライバ

距離

センサ

図 2.1: 回路構成例

図 2.2: Zコネクタ形式の雄形状と雌形状

の限界は経験的に 300mmと考えているが, 素子の個体差等もあるので正確な数字は求めて

いない).

2.4 電源回路と消費電流

回路全体を通して電源電圧は 5Vで統一している. これは既製品の幾つかが電源電圧 5V

を前提に設計されているためである. 5Vの電源供給は, 制御基盤が行う. 負荷の変動に対

しても安定な電圧を得るために, 電源回路は 7.2V二次電池と低損失三端子レギュレータに

よる安定化電源を配置している.

回路構成が付替えによって変更可能な回路の抱える問題として, 消費電流が大きくなるこ

とがある. 既製品の場合, 制御基盤からの外部への供給が 100mA程度に制限されている. 

今回製作した回路では, 1Aまで出力可能な電源回路を構成しているので,十分に余裕がある.

4 第 2 章 制御回路構成

表 2.1: Zコネクタの短絡による故障の発生

短絡箇所 故障する素子 素子の価格 内蔵保護回路の有無

電源, GND間 三端子レギュレータ 50円 有

電源, 信号間 マイコンの出力ピン 400円 無

GND, 信号間 マイコンの出力ピン 400円 無

2.5 保護回路

Zコネクタ形式は設置が容易であるが, 端子が剥き出しになっているため, 隣接する端子

が不意に短絡する場合がある. 端子間が短絡した場合の故障について, 表 2.1で示す. 短絡

による故障で, 保護する必要がある回路素子はマイコンである. 三端子レギュレータの場合,

内部に保護回路を有しており, 安全性が高い. また, 故障した場合でも素子の価格が安く交

換が容易い. しかし, マイコンの場合, 内蔵の保護回路が存在せず破損が起き易い. その上,

素子の価格も高く, 破損による損失が大きい. 破損の対策として, マイコンの出力ピンから

Zコネクタの信号線端子までの間に, 電流制限を行う抵抗 (330Ω程度)の挿入が有効である.

ただし, 前述した伝送距離の限界もあるのであまり大きな抵抗は使用できない.

2.6 回路構成価格と回路規模

今回製作した回路構成の場合, その構築に掛かる費用は 1000円程度であった (ただし基盤

の価格は計算が不能なため除いている). 参考製品である近藤科学社モーションプロセッサ

の値段が 3万円であることに比べると, 随分と安く抑えることが出来た.

製作した制御回路は, 6チャンネル程度とロボットの制御回路としては少ない制御性能で

ある. チャンネル数を増やす場合, 今回より高性能なマイコンの導入が必要になるなど, 検

討課題が増加するため, 今回は試験製作のため小規模な制御回路とした.

2.7 検討課題

今回製作した回路では「PCとの接続」「電源電圧の監視による過放電の防止」といった

幾つかの機能の実装を見送っている. 見送った要因として, 実装に時間が掛かる, 回路規模

が大きくなるがあり, 今回製作した小規模な制御基盤には除外した機能である. 今後, 制御

基盤の製作を行う場合はこれらの事も考慮すべきである.

2.8. おわりに 5

2.8 おわりに

本章では, 競技用ロボットの制御回路において, 既製品を参考に設計・製作を行った. 結

果, 既製品に大きく劣るものの, ある程度実用可能な制御回路の製作を, 安価に実現した. 今

後の発展として, 制御数の向上と機能の追加が考えられる.

6 第 3 章 制御プログラム構成

第 3章

制御プログラム構成

3.1 はじめに

本章では, ロボットの制御プログラムの構成について考察を行う. 制御プログラムは, 制

御回路構成に合わせて再構築が必要であり, 開発負荷の多くを占める. 今回提案する制御プ

ログラムの構成は, マルチタスクシステムの導入し, 低性能であるマイコン上で動作するこ

と考慮した設計を行い, 再利用と保守を重視するものである.

3.2 マルチタスクシステムの導入

競技用ロボットにおける制御プログラムは, 処理すべき事柄が多い. 各センサ値の入力, 制

御信号の入力, 制御対象への出力, 自立行動決定などを制御プログラムは実現する必要があ

る. 今回提案する手法では, プログラムの大まかな設計にマルチタスクシステムの導入を行

う. マルチタスクシステムは, 特定の仕事を処理する手続きを単位とし (タスクと呼ぶ), タ

スクマネージャが特定の条件に沿ってタスクの実行を行っていく方式である.

マルチタスクシステムには幾つかの実装の種類があるが, 今回使用する種類は, 原則とし

て並列動作を伴わないものである. 並列動作形式のものはプログラムの記述において, 再利

用性に優れているが, 幾つかの注意点とプログラム上の無駄が生じるため, マイコン上での

開発を考慮し採用しない. ただし, 割り込みを含む優先度の高い処理タスクについては, こ

の限りではないとする.

3.3. タスクの時間精度要求 7

3.3 タスクの時間精度要求

タスクの設計を行う際に, タスクが要求する時間の精度を考える. 制御プログラムにおい

て, 考慮すべき時間の概念は次のものが考えられる.

• 物理的な条件の成立からタスク起動までの時間 (タスク起動遅延時間)

• 時間周期で実行されるタスクの周期の誤差とその累積 (呼び出し周期誤差)

• 時間のカウント精度 (経過時間計測精度)

• 時間のカウント長 (経過時間計測長)

これらの事を留意するため, タスクの設計を行う際には, どの程度の遅延や精度に許容でき

るかを設定及び算出する必要がある. まず, タスク起動における遅延時間だが, 遅延時間を

小さくするにはハードウェア割り込みを利用したタスクの優先度付けが有効である. この方

式では, 他のタスクが実行中であっても条件が成立すれば優先度が高いタスクが実行される

ため, 遅延時間はほぼ最小となる. 次に, 時間周期の誤差だが, 周期的に実行されるタスク

が正確な周期に対し, どの程度の誤差に耐えれるかを考える. 最後に, 時間計測の精度と長

さについてだが, これらはトレードオフの関係にあり, 精度を重視すると長さが疎かになり,

逆も然りである. 今回提案する手法では, 以下の複数種の時間計測カウンタを実現し, 精度

と長さの要求を満たしている.

• 16bitのハードウェアカウンタ (タスク側からの再設定は不能)

– ソフトウェアカウントのカウントアップ, イベントの発生期間の算出に用いる

• 8bitのソフトウェアカウンタ

– 周期実行タスクの条件

• 精度をタスク側が設定可能な 16bitのハードウェアカウンタ

– 信号の入出力における PWM波形幅の計測に用いる (ビジーループウェイト)

時間計測におけるカウンタの精度や長さは, 用途に合わせて幾つかのパターンを用意してい

る. 複数種の時間計測カウンタを設けることで, 再利用が円滑に行えるようにしている.

8 第 3 章 制御プログラム構成

表 3.1: 各タスクの時間精度要求

許容起動遅延 呼び出し周期誤差 カウンタ精度 カウンタ長

信号入力タスク 100 µsec none 1 msec , 20 µsec 30msec , 2500 µsec

連続信号入力タスク < 1msec ±100msec / 500msec none none

信号出力タスク < 1msec ±20msec / 100msec 2µsec 2500µsec

3.4 タスクシステムの実現

上記条件に従いタスクシステムを実現する. 今回製作するプログラムは制御信号の入力と

制御対象への出力のみを行うものとする. 製作したタスクの構成図を図 3.1に示す. 配置す

るタスクは, 下記の 3つとし, 各タスクに以下の仕事を配置する.

•  信号入力タスク

– 制御信号の入力と内部表現型への変換

• 連続信号入力判定タスク

– 一定時間制御信号の取得に失敗すると, 入力が正常でないと判断する

• 信号出力タスク

– ロボットの動作制御におけるアシスト補整を行う

– 制御対象へ制御信号を出力する

また, 表 3.1に配置するタスクの時間精度における要求を示す. noneと書かれている項目は,

その時間要求について考慮が必要ないという意味である. 各タスクにおいて, 優先度付けに

よるタスクの割り込み実行が必要なほど, 時間要求が厳しくなかったので, 今回は優先付け

を行わなかった. この時間精度と実際の遅延時間等については, 第 5章で詳しく述べる.

3.5 入出力プログラム

制御信号の入出力を行うプログラムは, 使用する回路モジュールに合わせて用意する必

要がある. 前章で, 接続におけるハードウェアの規約を設けたが通信のデータに関する規約

を設けていない. これも既製品等の利用を考慮したもので, 必要に合わせて製作する必要が

ある. 今回製作したプログラムでは, 三和電子機器株式会社の無線コントローラ製品である

3.6. 検討課題 9

タスクマネージャ

制御信号

入力

タスク

出力遮断

タスク

ドライバ

出力

タスク

I/O

port

Tim

er Interrupt

reset

clear

outputcommand

input

input

interrupt

図 3.1: タスク構成図

SANWA ProBoの受信機RX-101の信号を取得するプログラムと, PWMの波形幅を用いて

信号を出力するプログラムを製作した. これらのプログラムを回路構成に合わせて切り貼り

する必要がある.

3.6 検討課題

今回製作したプログラムは小規模だったが, 今回提案した設計指針に従うなら, 現在使用

している低価格マイコンでも大規模なプログラムによる制御が可能だと思われる. 今後の課

題として, 時間計測やより複雑なタスクシステムをサポートするOSの構築が必要だと思わ

れるが, 現状の低価格マイコンでは構築が困難だと思われる.

3.7 おわりに

本章では, ロボット開発における大きな負担であるプログラムの開発について, 指針とな

る設計思想の提案と, その実現例を示した. 今後の発展として, OS等の再利用を促進する

ためのプログラムの開発が考えられるが, 現状の低価格マイコンでは困難である. この先の

ハードウェア性能の進歩に期待し, 更なる開発負荷軽減のための課題としておく.

10 第 4 章 開発環境の構築

第 4章

開発環境の構築

4.1 はじめに

本章では, 前章で設計した制御プログラムについて, それを記述するプログラミング言語

と開発環境について考察を行う. 一般にマイコンのプログラム開発に用いられている言語

は, アセンブラ言語とC言語であるが, その両者の違いを示し, 使用する言語を決定する (文

献 [3]). 次に, 構築の容易さや経済性を考慮し, 開発環境の構築を行う.

4.2 開発言語の違い

マイコンのプログラム開発で主に使用される言語は, アセンブラ言語とC言語だが, 両者

の特徴を表 4.1に示す. C言語はプログラミングを学習する上で, 標準的な位置づけの言語

であり, 多くの人が新たに勉強する必要がない. また, 記述方法はC言語がより簡単であり,

開発量の削減が見込まれる.

 

表 4.1: アセンブラ言語とC言語の違い

アセンブラ C言語

利用者数 少ない 多い

記述形式 コマンド形式 数式形式

コード量 多い 少ない

実行速度 速い 遅い

再利用性 低い 高い

4.3. 開発環境の選定と構築 11

表 4.2: 構築した開発環境

分類名 製品名 値段

マイコン PIC18F1320 400円

ライター PICkit2 Microcontroller Programmer $ 34.99

コンパイラ PIC C18 Compiler $ 495(無償版有)

統合開発環境 MPLAB 無料

4.3 開発環境の選定と構築

今回使用した開発環境は, 日本国内での開発を想定し選定を行った. 実際に構築した開

発環境を表 4.2に示す. 構築費用は$ 15(送料)を含め$ 1=108.02円と考え, 約 6万円であ

る. しかし, 残念ながら 6万円という値段はロボット開発において安くはない価格である.

PIC18F1320は, 秋月電子通商で購入可能であり, 入手が容易である.

その他, 使用するマイコンにPICを選んだ理由として, 日本語の資料が多く勉強が容易で

あることがある. 他の低価格マイコンとしてAVRマイコンがあるが, 現状ではAVRに関す

る日本語資料は少なく, 勉強する際は英語が必須となる.

4.4 おわりに

競技用ロボットの開発に適した開発手法の考案として, 開発における言語の選定とマイコ

ン, 開発環境の選定と構築を行った. 残念ながら, 今回の構築した開発環境は, 構築に必要な

費用が多く, 経済的とは言い難い. 今後改善が必要である.

12 第 5 章 提案手法の評価

第 5章

提案手法の評価

5.1 はじめに

前章までに提案した設計によるプログラムについて, C言語でプログラムの製作を行い,

その開発過程を評価する. 提案手法により開発負荷が軽減されるか検証を行う.

5.2 製作の評価

提案した設計によるプログラムの製作を行った. 結果, C言語によるプログラムの製作は

4日で終了した. ソース行数は 500行程度であった. 小規模な制御プログラムであるとはい

え, 後々における機能の追加やプログラムの再利用を考慮したプログラムを短い期間で開発

することが出来た.

5.3 実行性能

C言語によるプログラムの製作は, アセンブラによる製作に比べ, 生成されるバイナリの

実行精度が劣る傾向にある. 生成されたバイナリを逆アセンブルした結果, ハードウェア割

り込みの遅延時間が 24 [cycles]以上あった. 同様のプログラムをアセンブラ言語で製作した

場合, 遅延は 4 [cycles]のみである. PICにおける命令実行時間の計算は次式に従う.

Tcycle[sec] =4

Frequency[Hz](5.1)

ここで, FrequencyはPICの動作周波数, Tcycleは 1命令 (1 [cycle])当りの実行時間である. 今

回使用したPICは,動作周波数を 40MHzと設定したため, 1 [cycle]当りの時間経過は 1 [µsec]

である. これらから, C言語によるプログラム製作の場合, ハードウェア割り込みの遅延時

5.4. 開発上の問題点 13

間は, 2.4 [µsec]となる. 第 3章で記述した通り, 本設計の回路では, タスクの起動における許

容遅延時間は 100 [µsec]と, 製作したプログラムの遅延時間に比べ非常に大きく十分に余裕

であることが分かる. これより, 今回プログラミング言語として採用した C言語は, 開発に

おいて実用可能であることが分かる.

5.4 開発上の問題点

今回使用したC言語のコンパイラでは, 使用できるC言語の規格が古く, 効率的なプログ

ラミングを行う際の障害となった. C言語における古い規格の問題点として, ソースコード

上の手続きと, バイナリ上のサブルーチンが同義になっている問題がある. マイコンのよう

な資源が限定された環境では, サブルーチン化によるオーバーヘッドが生じてしまい, 実行

効率の良いプログラムの製作が行えない. これらを解決するためには, 新しい規格のC言語

をサポートするコンパイラの採用が必要である.

5.5 おわりに

本章では, 提案手法による開発を行い, 実用可能なプログラムを短い期間で製作できるこ

とを示した. 今後の課題として, 新しい規格の C言語の導入や, 他の言語の利用が挙げら

れる.

14 第 6 章 結論

第 6章

結論

6.1 本研究での成果

本研究では, 開発負荷の多い競技用ロボットの開発において, それを効率的に行うための

模範となる手法を示し, 提案手法が十分に実用可能であることを示した.

6.2 今後の課題

本研究において, C言語のによるプログラム開発の効率化を行ったが, 以下の問題点が

残った.

• 環境構築に掛かる費用が安価ではない

• コンパイラに採用されているC言語の規格が古く,設計と実装に幾つかのズレが生じた

今後は, 本提案で使用したものとは異なるコンパイラの採用などにより, これらの問題点の

解決が必要である. また, 本提案では利用を見送ったが, PICマイコンに比べAVRマイコン

は, 価格に対して性能が良く, 資料の少なさ以外に不採用とした理由がない. 今後の検討課

題として, AVRマイコンによる同様の提案も必要であると思われる.

15

付 録A

本研究で製作したプログラム

A.1 C言語で製作プログラムソース

本稿で示した設計と開発環境により製作したソースファイルを添付する.

• stdafx.h

– コンパイラによる整数のビット幅や文法の違いを吸収する

• main.c

– 製作プログラムの本体

• probo.h , probo.c

– 三和電子機器株式会社製品の SANWA Proboの受信機RX-101からのデータ取得

を行う

ソースコード A.1: stdafx.h

#ifndef __STDAFX_HEAD_

#define __STDAFX_HEAD_

#if __18CXX == 1

// Microchip社PIC C18 C o m p i l e r用の定義

typedef unsigned char byte;

typedef unsigned char uint8;

typedef char int8;

typedef unsigned short uint16;

typedef short int16;

typedef unsigned long uint32;

typedef long int32;

typedef unsigned char bool;

#define true 1

16 付 録 A 本研究で製作したプログラム

#define false 0

#define BitSet(X,Y) X|=(1<<Y)

#define BitClear(X,Y) Y&=~(1<<Y)

#define BitTest(X,Y) ((X&(1<<Y))==1)

#define Bin(X) 0b ## X

#else

#define overlay

#endif

#endif

ソースコード A.2: main.c

#include <p18f1320.h>

//外部オシレータ10 MHz PLLx4 外 部 ク ロ ッ ク 異 常 時 の フ ェ イ ル セ ー フ 監 視 OFF ,内 部/ 外 部 ス イ ッ チ オ ー バ ー OFF ,パ ワ ー ア ッ プ タ イ マ ON

#pragma config OSC = HSPLL , FSCM = OFF , IESO = OFF , PWRT = ON

//ブラウトアウトOFF ,ブ ラ ウ ン ア ウ ト 電圧4.7 V,ウ ォ ッ チ ド ッ グ OFF ,ウ ォ ッ チ ド ッ グ ポ ス ト ス ケ ーラ(:32768)

#pragma config BOR = OFF , BORV = 45, WDT = OFF , WDTPS = 32768

//マスタークリアOFF

#pragma config MCLRE = OFF // PBAD = DIG ,CCP2MX = C1

// Stack Full&Overflow Reset=OFF ,低 電 圧 書 込 OFF , BackgroundデバッガOFF

#pragma config STVR = OFF , LVP = OFF , DEBUG = OFF

// CP2 = OFF ,CP3 = OFF ,

#pragma config CP0 = OFF , CP1 = OFF , CPB = OFF

// WRT2 = OFF , WRT3 = OFF

#pragma config CPD = OFF , WRT0 = OFF , WRT1 = OFF

#pragma config WRTB = OFF , WRTC = OFF , WRTD = OFF , EBTR0 = OFF

// EBTR2 = OFF ,EBTR2 = OFF ,EBTR3 = OFF

#pragma config EBTR1 = OFF , EBTRB = OFF

#include"stdafx.h"

#include"SANWA_ProBo.h"

uint8 PrevReceiveStartTime;

bool ReceiveSuccess;

prbChannelsDirection CommandBuffer;

//ビット変数の定義と構造体へのフィールド割り当て

struct _BitFields

unsigned bitLimitTimerEnable : 1;

unsigned bitLedLightingEnable : 1;

unsigned bitFailedRecieveLimit : 1;

BitFields;

#define LimitTimerEnable BitFields.bitLimitTimerEnable

#define LedLightingEnable BitFields.bitLedLightingEnable

#define FailedRecieveLimit BitFields.bitFailedRecieveLimit

uint8 DriveA;

uint8 DriveB;

uint8 DriveC;

uint8 DriveD;

uint8 DriveE;

A.1. C言語で製作プログラムソース 17

uint8 DriveF;

uint8 OutputDriveA;

uint8 OutputDriveB;

uint8 OutputDriveC;

uint8 OutputDriveD;

uint8 OutputDriveE;

uint8 OutputDriveF;

uint8 OutputDriverCount;

uint8 LedLightingInterval;

uint8 LedLightingCount;

uint8 LimitTimerCount;

//関数のプロトタイプ宣言

// P r o B oからのデータ受信

void receiveProBo(void);

// P r o B oの受信データをドライバ制御データに変換

void encodeProBoCommand(void);

//制御のアシストプログラム

void assistControll(void);

// O u t p u t D r i v e rタスクの初期化

void initOutputDriver(void);

// L i m i t T i m e rタスクの初期化

void initLimitTimer(void);

// O u t p u t D r i v e rタスクのプログラム

void upcountOutputDriver(void);

// L i m i t T i m e rタスクのプログラム

void upcountLimitTimer(void);

// L e d L i g h t i n gタスクのプログラム

void upcountLedLighting(void);

// L e dの点滅

void setLed_OnAndOff(uint8 x);

// L e dの点灯

void setLed_On(void);

// L e dの消灯

void setLed_Off(void);

// L i m i t T i m e rタスクのプログラムを再セットする

void resetLimitTimer(void);

// P u l s e W i d eを送信可能な状態にする

void setupPulseWide(uint8 duty ,uint8 direction );

// P u l s e W i d eを送信する

void outputPulseWide(void);

//ドライバへのデータ送信プログラム

void outputDriver(void);

// t i m e r 1の割り込みハンドラ

void timer1_isr(void);

#pragma code vector =0x08

void interrupt(void)

_asm GOTO timer1_isr _endasm

#pragma code

#pragma interrupt timer1_isr

18 付 録 A 本研究で製作したプログラム

void timer1_isr(void)

//フラグのクリア

PIR1bits.TMR1IF = 0;

upcountLimitTimer (); //無制御リミットタイマのカウントアップ

upcountOutputDriver (); //出力タイマのカウントアップ

upcountLedLighting (); // L E D点滅タイマのカウンタアップ

void main()

//割り込み設定

//優先度割り込みを使用しない

// T i m e r 1を割り込み設定

//プログラムの初期化

TRISA = Bin (00000000);

// R B 0を信号入力として使用する

TRISB = Bin (00000001);

// T i m e r 0の設定 T0CON

// OpenTimer0 ()で も 設 定 可 能 だ が 、 こ こ で は 使 わ な い

// bit7 0 - T i m e r 0を停止させる

// bit6 0 - 16 b i tタイマとして使用する

// bit5 0 - 内 部 ク ロ ッ ク を カ ウ ン ト す る

// bit4 1 - T 0 S Eのデフォルト値

// bit3 0 - プ リ ス ケ ー ラ を 使 用 す る

//bit2 -0 000 - 1:2の プ リ ス ケ ー ラ

T0CON = Bin (00010000);

// T i m e r 1の設定

// OpenTimer1 ()で も 設 定 可 能 だ が 、 こ こ で は 使 わ な い

// bit7 0 - 正 直 よ く わ か ら ん の で default設定

// bit6 0 - シ ス テ ム ク ロ ッ ク に 利 用 し な い

//bit5 -4 11 - プ リ ス ケ ー ラは1:8

// bit3 0 - 発 信 器 と し て 使 用 し な い

// bit2 0 - bit is ignored

// bit1 0 - 内 部 ク ロ ッ ク で カ ウ ン ト す る

// bit0 1 - T i m r t 1を動作させる

T1CON = Bin (00110001);

//割り込みの設定

// RCON

// IPEN 0 -多 重 優 先 度 割 り 込 み を 使 用 し な い

RCONbits.IPEN = 0;

//割り込みの設定

// PIE1

// bit6 0 - A/ D変換割り込みを使用しない

// bit5 0 - E U S A R Tの受信割り込みを使用しない

// bit4 0 - E U S A R Tの送信割り込みを使用しない

// bit2 0 - C C P 1の割り込みを使用しない

// bit1 0 - T i m e r 2の割り込みを使用しない

// bit0 0 - T i m e r 1の割り込みを使用する

PIE1 = Bin (00000001);

A.1. C言語で製作プログラムソース 19

//割り込みの設定

// INTCON

// bit7 1 - 割 り 込 み を 許 可 を す る

// bit6 1 - 特 殊 割 り 込 み を 許 可 す る

// bit5 0 - T i m e r 0の割り込みを許可しない

// bit4 0 - I n t 0の割り込みを許可しない

// bit3 0 - RB Port C h a n g eの割り込みを許可しない

//bit2 -0 000 - Timer0 ,Int0 , R Bの割り込みフラグをクリアする

INTCON = Bin (11000000);

//処理ループ

while(true)

INTCONbits.GIE = 0; //受信チェックのため、割り込みを禁止する

//プロボからのデータを受信する

receiveProBo ();

INTCONbits.GIE = 1; //割り込みを許可する

//ここで溜まっている割り込みが全て処理される( Idel処理 )

/*

* 受 信 タ ス ク

* -receiveProBo () -コ マ ン ド 受 信 タ ス ク

* + encodeProBoCommand () -コ マ ン ド 解 釈 プ ロ グ ラ ム

* + t i m e r 0を使用する

*/

void receiveProBo ()

uint8 def;

bool successed = 0;

if(prbCheckStart () == false)

return;

//前回データ受信との時間差を計算し、現時刻を保存する

def = TMR1H - PrevReceiveStartTime;

PrevReceiveStartTime = TMR1H;

//受信のデータの正当性をチェックし、成功のフラグを保存する

if(108 < def && def < 125 && BitTest(ReceiveSuccess ,0))

BitSet(successed ,0);

if(BitTest(successed ,0))

//受信データが正当である場合

//非受信状態を検出するタイマーをリセットする

resetLimitTimer ();

// L e dの発光モードを常時点灯に変更する

setLed_On ();

//バッファ中のデータを、成功バッファに書き込み

CommandBuffer = prbReceive;

//データの受信と行い、成功の合否を保存する

ReceiveSuccess = prbGetDirections ();

//正当性が保証されたデータを、内部表現に変換し、出力タスクのバッファに書きこむ

if(BitTest(successed ,0))

20 付 録 A 本研究で製作したプログラム

encodeProBoCommand ();

void encodeProBoCommand ()

uint8 allow;

DriveA = 0;

DriveB = 0;

DriveC = 0;

DriveD = 0;

DriveE = 0;

DriveF = 0;

allow = CommandBuffer.Directions & 0x0f;

//前進(↑)

if(allow == 0b0001)

BitSet(DriveA , 0);

BitSet(DriveB , 0);

//後進(↓)

if(allow == 0b0010)

BitSet(DriveA , 1);

BitSet(DriveB , 1);

//逆時計回転(←)

if(allow == 0b0100)

BitSet(DriveA , 0);

BitSet(DriveB , 1);

//時計回転(→)

if(allow == 0b1000)

BitSet(DriveA , 1);

BitSet(DriveB , 0);

/*

* 出 力 タ ス ク プ ロ グ ラ ム

* -initOutputDriver () -タ ス ク の 初 期 化 を 行 う

* -upcountOutputDriver () -ド ラ イ バ 出 力 タ ス ク

* -outputDriver ()

* + assistControll () -制 御 ア シ ス ト プ ロ グ ラ ム

* + setupPulseWide () -デ ー タ の P W M送信を行うための事前処理プログラム

* + outputPulseWide () -デ ー タ の P W M送信を行う

*   + union PulseWide  -パ ル ス 幅 を 計 算 す る た め の 共 有 体

*/

void initOutputDriver ()

OutputDriverCount = 256 - 2;

void upcountOutputDriver ()

A.1. C言語で製作プログラムソース 21

if(++ OutputDriverCount == 0)

//ドライバー回路に信号を送る

outputDriver ();

//タイマーを更新する

OutputDriverCount = 256 - 2;

void outputDriver ()

if(FailedRecieveLimit == true)

OutputDriveA = 0;

OutputDriveB = 0;

OutputDriveC = 0;

OutputDriveD = 0;

OutputDriveE = 0;

OutputDriveF = 0;

else

OutputDriveA = DriveA;

OutputDriveB = DriveB;

OutputDriveC = DriveC;

OutputDriveD = DriveD;

OutputDriveE = DriveE;

OutputDriveF = DriveF;

//センサ値などを利用した制御コード

assistControll ();

//ドライバへの出力を行う

// DriveA - B 0の出力 ( PulseWide出力 )

setupPulseWide (117, OutputDriveA );

LATBbits.LATB0 = 1;

outputPulseWide ();

LATBbits.LATB0 = 0;

// DriveB - B 1の出力 ( PulseWide出力 )

setupPulseWide (117, OutputDriveB );

LATBbits.LATB1 = 1;

outputPulseWide ();

LATBbits.LATB1 = 0;

// DriveC - B 2の出力 ( PulseWide出力 )

setupPulseWide (117, OutputDriveC );

LATBbits.LATB2 = 1;

outputPulseWide ();

LATBbits.LATB2 = 0;

// DriveD - B 3の出力 ( PulseWide出力 )

setupPulseWide (117, OutputDriveD );

LATBbits.LATB3 = 1;

outputPulseWide ();

LATBbits.LATB3 = 0;

22 付 録 A 本研究で製作したプログラム

void assistControll ()

// P u l s e W i d eを送信可能な状態にする

typedef union

uint16 value;

struct

uint8 High;

uint8 Low;

;

PulseWide;

void setupPulseWide(uint8 duty ,uint8 direction)

const uint16 PulseWideBias = 234;

PulseWide wide;

wide.value = 0 - PulseWideBias;

if(direction == 0b01)

wide.value += duty;

if(direction == 0b10)

wide.value -= duty;

// T M R 0のセットアップを行う

// T i m e r 0の設定 T0CON

// OpenTimer0 ()で も 設 定 可 能 だ が 、 こ こ で は 使 わ な い

// bit7 0 - T i m e r 0を停止させる

// bit6 0 - 16 b i tタイマとして使用する

// bit5 0 - 内 部 ク ロ ッ ク を カ ウ ン ト す る

// bit4 1 - T 0 S Eのデフォルト値

// bit3 0 - プ リ ス ケ ー ラ を 使 用 す る

//bit2 -0 101 - 1:64の プ リ ス ケ ー ラ

T0CON = Bin (00010101);

TMR0L = wide.Low;

TMR0H = wide.High;

INTCONbits.TMR0IF = false;

void outputPulseWide ()

T0CONbits.TMR0ON = 1;

while(INTCONbits.TMR0IF == false);

/*

* 正 常 受 信 検 出 タ イ マ タ ス ク

* -initLimitTimer () -タ ス ク の 初 期 化

* -resetLimitTimer () -タ イ マ の ク リ ア と 再 設 定

 * -upcountLimitTimer () -タ ス ク フ ァ ン ク シ ョ ン

*/

void initLimitTimer ()

A.1. C言語で製作プログラムソース 23

LimitTimerEnable = false;

void resetLimitTimer ()

LimitTimerCount = 256 - 6;

LimitTimerEnable = true;

void upcountLimitTimer ()

if(LimitTimerEnable == true)

//タイマのカウントが有効ならば、カウントアップを行う

if(++ LimitTimerCount == 0)

//カウントアップの結果が0な ら ば 、 受 信 が 出 来 て い な い と 判 断

//受信が出来ていない状態を示すフラグを立てる

FailedRecieveLimit = true;

//リミットが入ったので、タイマーのカウントを止める

LimitTimerEnable = false;

//受信に失敗しているので、 L E Dを点滅状態にする

setLed_OnAndOff (256 - 10);

/* 状 態 表 示 用 の L E D制御プログラム

* -upcountLedLighting () -点 滅 処 理 を 行 う タ ス ク

* -setLed_OnAndOff (uint8) -点 滅 状 態 に 移 行

* -setLed_On () -点 灯 状 態 に 移 行

* -setLed_Off () -消 灯 状 態 に 移 行

*/

uint8 LedLightingInterval;

void upcountLedLighting ()

if(LedLightingEnable == true)

if(++ LedLightingCount == 0)

//出力を反転させる

LATAbits.LATA2 ^= 1;

//タイマーを再セットする

LedLightingCount = LedLightingInterval;

//第一引数で与えた周期で点滅する

void setLed_OnAndOff(uint8 x)

LedLightingInterval = x;

LedLightingCount = x;

LedLightingEnable = true;

//点灯する

void setLed_On ()

LedLightingEnable = false;

24 付 録 A 本研究で製作したプログラム

LATAbits.LATA2 = 1;

//消灯する

void setLed_Off ()

LedLightingEnable = false;

LATAbits.LATA2 = 0;

ソースコード A.3: probo.h

#ifndef _SANWA_PROBO_HEAD_

#define _SANWA_PROBO_HEAD_

/*

* P r o B oの受信信号を検査するプログラムです

* -&pin 入 力 を 受 け 付 け る ポ ー ト の ピ ン

* -&timer 一 定 時 間 毎 に カ ウ ン ト さ れ る カ ウ ン タ( 関 数 内 で ク リ ア さ れ る)

*/

#include <p18f1320.h>

#include "stdafx.h"

typedef union

uint16 Directions;

struct

unsigned FwCh1 : 1;

unsigned ReCh1 : 1;

unsigned FwCh2 : 1;

unsigned ReCh2 : 1;

unsigned FwCh3 : 1;

unsigned ReCh3 : 1;

unsigned FwCh4 : 1;

unsigned ReCh4 : 1;

unsigned FwCh5 : 1;

unsigned ReCh5 : 1;

unsigned FwCh6 : 1;

unsigned ReCh6 : 1;

unsigned FwCh7 : 1;

unsigned ReCh7 : 1;

unsigned FwCh8 : 1;

unsigned ReCh8 : 1;

;

prbChannelsDirection;

#define prbINPUT_PIN PORTBbits.RB0

#define prbTIMER TMR0L

extern prbChannelsDirection prbReceive;

bool prbCheckStart(void);

bool prbGetDirections(void);

void prbWaitRising(void);

void prbWaitFalling(void);

A.1. C言語で製作プログラムソース 25

#endif

ソースコード A.4: probo.c

const unsigned int Channel_Forward = 1900;

const unsigned int Channel_Reverse = 1100;

const unsigned int Channel_Stop = 1500;

/*

* P r o B oの受信信号を検査するプログラムです

* -&pin 入 力 を 受 け 付 け る ポ ー ト の ピ ン

* -&timer 一 定 時 間 毎 に カ ウ ン ト さ れ る カ ウ ン タ( 関 数 内 で ク リ ア さ れ る)

*/

#include "stdafx.h"

#include "SANWA_ProBo.h"

uint8 prbInterval;

prbChannelsDirection prbReceive;

void prbWaitRising ()

while(prbINPUT_PIN == 0)

prbInterval = prbTIMER;

if(prbInterval > 200)

return;

prbTIMER = 0;

return;

void prbWaitFalling ()

while(prbINPUT_PIN ==1);

bool prbCheckStart ()

if(prbINPUT_PIN == 0)

return false;

prbTIMER = 0;

prbWaitFalling ();

return true;

bool prbGetDirections ()

prbReceive.Directions = 0;

// T i m e r 0の設定 T0CON

// OpenTimer0 ()で も 設 定 可 能 だ が 、 こ こ で は 使 わ な い

// bit7 1 - T i m e r 0を動作させる

// bit6 0 - 16 b i tタイマとして使用する

// bit5 0 - 内 部 ク ロ ッ ク を カ ウ ン ト す る

// bit4 1 - T 0 S Eのデフォルト値

// bit3 0 - プ リ ス ケ ー ラ を 使 用 す る

26 付 録 A 本研究で製作したプログラム

//bit2 -0 110 - 1:128の プ リ ス ケ ー ラ

T0CON = Bin (10010110);

// Ch1

prbWaitRising ();

if(prbInterval < 78) return false;

if(prbInterval > 156) return false;

if(prbInterval > 140) prbReceive.FwCh1 = 1;

if(prbInterval < 94) prbReceive.ReCh1 = 1;

prbWaitFalling ();

// Ch2

prbWaitRising ();

if(prbInterval < 78) return false;

if(prbInterval < 156) return false;

if(prbInterval < 140) prbReceive.FwCh2 = 1;

if(prbInterval < 94) prbReceive.ReCh2 = 1;

prbWaitFalling ();

// Ch3

prbWaitRising ();

if(prbInterval < 78) return false;

if(prbInterval < 156) return false;

if(prbInterval < 140) prbReceive.FwCh3 = 1;

if(prbInterval < 94) prbReceive.ReCh3 = 1;

prbWaitFalling ();

// Ch4

prbWaitRising ();

if(prbInterval < 78) return false;

if(prbInterval < 156) return false;

if(prbInterval < 140) prbReceive.FwCh4 = 1;

if(prbInterval < 94) prbReceive.ReCh4 = 1;

prbWaitFalling ();

// Ch5

prbWaitRising ();

if(prbInterval < 78) return false;

if(prbInterval < 156) return false;

if(prbInterval < 140) prbReceive.FwCh5 = 1;

if(prbInterval < 94) prbReceive.ReCh5 = 1;

prbWaitFalling ();

// Ch6

prbWaitRising ();

if(prbInterval < 78) return false;

if(prbInterval < 156) return false;

if(prbInterval < 140) prbReceive.FwCh6 = 1;

if(prbInterval < 94) prbReceive.ReCh6 = 1;

prbWaitFalling ();

// Ch7

prbWaitRising ();

if(prbInterval < 78) return false;

if(prbInterval < 156) return false;

if(prbInterval < 140) prbReceive.FwCh7 = 1;

if(prbInterval < 94) prbReceive.ReCh7 = 1;

prbWaitFalling ();

// Ch8

prbWaitRising ();

if(prbInterval < 78) return false;

if(prbInterval < 156) return false;

if(prbInterval < 140) prbReceive.FwCh8 = 1;

A.1. C言語で製作プログラムソース 27

if(prbInterval < 94) prbReceive.ReCh8 = 1;

prbWaitFalling ();

return true;

28 謝辞

謝辞

本研究を進めるあたり, 様々な御指導をして下さった河合康典 助教授に心より深く感謝

いたします.

ならびに, 日頃から様々な御協力をいただいた寺西由佳 氏, 杉本憲之 氏をはじめとする

河合研究室のメンバーに感謝します.

最後に, 本研究生活を支えてくださった両親および兄弟に心から御礼申し上げます.

29

参考文献

 

[1] 谷腰欣次, DCモータの制御回路設計 (第 3版), CQ出版社, 1986.

[2] 西村輝一 ほか, 二足歩行ロボットのモデルベース開発, オーム社, 2005.

[3] 後閑哲也, C言語による PICプログラミング入門, 技術評論社, 2002.