ホーム » スタッフ

スタッフ」カテゴリーアーカイブ

2024年9月
1234567
891011121314
15161718192021
22232425262728
2930  

検索・リンク

IchogoJamのロボット制作のメモ

2024年9月15日(日) 09:30~11:30

プログラム自動起動

IchigoJam で自走ロボットを作ると、モニターやキーボードをつけて動かすのは困難。このため、IchogoJam を起動したらすぐにプログラムを起動したい。

この場合は、プログラムを “SAVE 0” で保存しておき、IchogoJam を起動させるときに BTN() 機能で使う基板上のボタンを押しながら起動する。これにより起動時に “LOAD 0” を実行してくれる。

プログラムの切り替え

かにロボコンでは、スタート地点からボールの回収フィールドまでライントレースで移動し、回収の動作をして、再びライントレースでスタート場所に戻る必要がある。この際、ライントレース動作と回収動作は異なる動きとなる。

また、右コースか左コースかの違いによってプログラムを変化させたいかもしれない。こういう場合は、“LRUN” 機能を使う。

例えば、ライントレースの処理を “SAVE 0” で保存しておき、回収フィールドの処理を “SAVE 1″ で保存してあるのであれば、ライントレースの処理の中で「回収フィールドに到達した」と判断した時に、”LRUN 1” を実行すれば “LOAD 1″を実行してプログラムを起動できる。

IchigoJamと MableSylup への電源

IchigoJam を MapleSylup に接続してロボットとして動かす場合には、ジャンパーピン”J1″に注意が必要。

通常 IchigoJam と MapleSylup でロボットを使う場合、ジャンパーピン”J1″をショートさせて、MapleSylup に接続した乾電池などの電源を IchigoJam に供給して動かす。しかし、電流をたくさん使うようなモータ制御をする場合、乾電池だけでロボットを動かすと電流を モータに使われ、IchigoJam が誤動作する場合がある。

こういう場合には、IchigoJam には USB のモバイルバッテリーなどを搭載させ、IchigoJam はモバイルバッテリー、MapleSylup とモーターは乾電池で動かす。この場合には、ジャンパーピン”J1″ は抜いて動かす方がよい。

中間発表会の資料作成

パンチカード発掘

部屋の古い本を片付けたら、こんなの挟んであった。
{CAPTION}

情報制御基礎2024年講義録

6足歩行ロボットの組み立て

2024年9月14日(土) 13:00~15:30

6足歩行ロボット

音センサー歩行ロボット製作セット(楽しい工作シリーズNo.166)の「Cタイプ-6足歩行ロボット」を参考に6足歩行ロボットを作成する。

ギアボックスが、左右2chでシャフトが長いので2cmほど切り詰める作業が必要となった。

パーツも、今回の車体のベースとしているリモコンロボット製作セット(楽しい工作シリーズ No.162)の部品では、シャフトとか足りないので、実験室にあった以前購入しておいた別のキャタピラ型リモコンロボット製作セットの部品を流用。

車体の速度をあげるには

歩行速度を上げるには、どうすればいいか?

  • モータの電圧を上げる
  • モータを高速なタイプに交換
  • ギアボックスのギア比を変える
  • 脚を伸ばす
  • 中央のクランクアームの半径を伸ばす

オブジェクト指向プログラミング-2024年度講義録

IchigoJamと光センサー

7/31(水) 18:30~20:00 風邪のため

8/17(土) 09:30〜12:00

光センサーの機能

光センサーを GND=MapleSylupのGND, VCC=MapleSylupのVCC=5V, D0=IN2 に接続。

IN1 は BTN につながっているので、入力に接続するときは IN2, IN3, IN4 などを使うこと。

まずは電圧を測ってみよう。

MapleSylup  V+ = 5.03V
白テーブルの時 D0 = 0.19V 
黒線   の時 D0 = 4.96V

このような状態にならないのであれば、光センサー中央の青い調節ボリュームを動かして、黒線の上でだけ 4V を超えるように調整をする。

IchigoJam で光センサーを読み取る

IN() 関数は、指定した入力ポートが High=1 か Low=0 かを読み取る。

ANA() 関数は、指定した入力ポートの電圧を 0〜1023 の値で読み取る。0Vで0, 3.3Vで1023となる。黒線の上だと電圧が4.9V なので 1023 となる。

((( 黒線 )))
PRINT IN(2)
1
PRINT ANA(2)
1023
((( 白線 )))
PRINT IN(2)
0
PRINT ANA(2)
61

IN命令は、ポート番号を指定しない IN() で呼び出すと、IN1,IN2,IN3,IN4 の値を IN1=1,IN2=2,IN3=4,IN4=8 の和で返す。(2進数の考え方)
2進数の各けたが次のような意味になっている。

 8   4   2   1
IN4,IN3,IN2,IN1

ロボットを動かす最初の実験

最初のロボット制御の実験として、車体を進ませて、黒線の所まで走ったら停止させてみよう。

  • 車体を前進させるためのポート (OUT1,OUT2) 左モーター, (OUT5,OUT6) 右モーター をつなぐ。
    • 「 OUT ‘010001 」 で車体が前に動くか確認する。
      • OUT1=1,OUT2=0 , OUT5=1,OUT6=0
    • 回転方向が揃っていないと車体が回転するので、方向が違っていたらモータの+端子,-端子を入れ替える。配線を直さないのなら、OUT1,OUT2などの1,0を入れ替える。
  • IN2 左光センサー、IN3 右光センサーにつなぐ。

<<の部分には何を書けばいい?>>
10 OUT <<前進>>
20 IF IN(2) = <<白>> THEN GOTO 10
30 OUT <<停止>>

車体をゆっくり動かす

ここまで説明した方法だと、車体が速く動きすぎるかもしれない。ゆっくり動かすにはどうしたらいいだろうか?

直流モータをゆっくり動かすには、モータに加える電圧を下げればいい。ただし、モーターの中身の電磁石はただの電線。電気がたくさん流れるのであまり良い方法ではない。

ゆっくりうごかすには、ちょっと動かして、ちょっと止める…を繰り返せばいい。

10 OUT <<前進>> : WAIT 1
20 OUT <<停止>> : WAIT 1
30 GOTO 10

車体を曲がらせる

車体の進行方向を曲げたかったら、片方を止めて、もう一方を動かせばいい。

  • 停止OUT1=0,OUT2=0 , 前進OUT5=1,OUT6=0

でも、これだと左タイヤを中心に回転してしまう。少しづつ左にまがるようにするにはどうすればいいだろうか?

2つの光センサーの扱い

ポートを指定しないIN()命令をつかうと、IN1,IN2,IN3,IN4 の値をまとめて読むことができる。今回の実験では、IN2,IN3に光センサーを接続する。この場合 IN() で読み込むと、以下のような値が読み込める。

IN()
IN4,IN3,IN2,IN1 = 0110 6
IN4,IN3,IN2,IN1 = 0010 2
IN4,IN3,IN2,IN1 = 0100 4
IN4,IN3,IN2,IN1 = 0000 0

しかし IN()では IN1,IN4 の値も読み込んでしまい、IN1,IN4には何もつながない状態であっても、他の電圧などの影響でIN1=1,IN4=1といった値になる場合もあるため、IN1,IN4の値が1であっても強制的に0に変化させたい。

2進数での論理積 &

論理積演算命令 x & y は、2進数の各桁が 両方とも1 の所だけ 1 になる計算命令。

x     = `0101  IN()=`1110
y     = `0011       `0110
x & y = `0001       `0110

このことから、IN()&6 (6=`0110)を使えば、IN2,IN3 の値だけを取り出すことができる。

ライントレース処理

光センサー1個で、白黒の境界を走る。

光センサー2個で、黒線の上を走る。

10 A=IN()&6
20 IF A=6 THEN OUT <<<前進>>>
30 IF A=2 THEN OUT <<左前進>>
40 IF A=4 THEN OUT <<右前進>>
50 IF A=0 THEN OUT <<止まる>>
60 GOTO 10

急カーブ対策

ライントレースでは急なカーブがあるとコースから外れることもでてくる。こういう時は車体の大きく曲がらせるようにモータを制御すればいい。しかし大きく曲がるようにすると、車体が左右に頻繁に首を振る動きとなり、移動が遅くなってしまう。

こういう時は、どうすればいいだろうか?

「前回のセンサーの値」と「今回のセンサーの値」が、とかの場合。

「前回のセンサーの値」と「今回のセンサーの値」が、とかの場合。

2024年度 情報メディア工学(前期)全講義録

プログラムのバージョン管理とオープンソース

プログラムを複数人で開発する場合のバージョン管理と、オープンソースプログラムを使う場合の注意を説明する。

バージョン管理システム

プログラムを学校や自宅のパソコンで開発する場合、そのソースコードはどのように持ち運び管理修正すべきだろうか?

最も原始的な方法は、常に全部を持ち歩く方法かもしれない。しかし、プログラムが巨大になってくるとコピーに時間がかかる。またコピーを取る時に、どれが最新なのか正しく把握する必要がある。

  • 同期方式 – 2つのディレクトリのファイルの古い日付のファイルを、新しい日付のファイルで上書きするようなディレクトリ同期ソフトを使って管理
  • 圧縮保管 – ファイル全体だと容量も多いため、複数のファイルを1つのファイルにまとめて圧縮を行う tar コマンドを使うことも多い。(tar ball管理)

diffとpatch

プログラムの修正を記録し、必要最小限で修正箇所の情報を共有する方式に patch がある。これには、2つのファイルの差異を表示する diff コマンドの出力結果(通称patch)を用る。diff コマンドでは、変更のある場所の前後数行の差異を !(入替) +(追加) -(削除) の目印をつけて出力する。patch コマンドに diff の出力を与えると、!,+,- の情報を元に修正を加えることができる。(通称「patchをあてる」)

((( helloworld-old.c )))
  #include <stdio.h>

  void main() {
        printf( "Hello World\n" ) ;
  }
 
((( helloworld.c )))
  #include <stdio.h>

  int main( void ) {
        printf( "Hello World\n" ) ;
        return 0 ;
  }
 
((( diff の実行 )))
$ diff -c helloworld-old.c helloworld.c
 
((( 生成された patch 情報 )))
*** helloworld-old.c    2022-07-25 10:09:10.694442400 +0900
--- helloworld.c        2022-07-25 10:09:26.136433100 +0900
***************
*** 1,5 ****
  #include <stdio.h>

! void main() {
        printf( "Hello World\n" ) ;
  }
--- 1,6 ----
  #include <stdio.h>

! int main( void ) {
        printf( "Hello World\n" ) ;
+       return 0 ;
  }

インターネットの初期の頃には、他の人のプログラムに対して間違いを見つけると、作者に対してこのpatch(diff出力)をメールなどで送付し、プログラムの修正が行われた。

広く世界で使われている Web サーバ apache は、オープンソースで開発されてきた。当初はプログラム公開後に間違いや機能追加の情報(patch)が世界中のボランティア開発者から送られてきながら改良が加えられていった。このため、”a too many patches”「つぎはぎだらけ」という自虐的皮肉を込めて apache と名付けられたと言われている。

初期のバージョン管理システム

バージョン管理システムは、複数人で少しづつテキストファイルに修正を加えながら改良を行うような際に、誰がどのような修正を行ったかという修正履歴を管理するためのツール。unix などのプログラム管理では rcs (revision control system) が使われていたが、その改良版として cvs (concurrent version system) が使われるようになっていった。(現在は後に紹介する Git などが主流)

  • ci コマンド(check in) – ファイルをバージョン管理の対象として登録する。
  • co コマンド(check out) – ファイルを編集対象とする(必要に応じて書き込みロックなども可能)。co されたファイルは、編集した人が ci して戻すまで ci することができない。
  • 修正結果を ci する際には、新しい編集のバージョン番号などをつけて保存される。
  • co コマンドでは、バージョン番号を指定してファイルを取り出すことも可能。
                 [Bさんの修正]
                /check out \check in
ファイルver1.0-----→ver1.1------→ver1.2
     \check out  /check in
      [Aさんの修正]

集中管理型バージョン管理システム

rcs,cvs では、ファイルのバージョンは各ファイルを対象としているため、ファイルやディレクトリの移動や削除は管理が困難であった。これらの問題を解決するために、集中管理を行うサーバを基点として、対象ファイルのディレクトリ全体(ソースツリー)に対してバージョン番号を振って管理を行う。subversion はサーバに ssh などのネットワークコマンドを介して、保存・改変を行うことができる。

しかし、複数の人の修正のマージ作業の処理効率が悪く、処理速度が遅いため使われなくなっていった。同様のバージョン管理システムが企業により有償開発されていた(BitKeeperなど)が製品のライセンス問題が発生し、業を煮やした Linux 開発の Linus が Git のベースを開発・公開している。

分散型バージョン管理システム

Gitは、プログラムのソースコードなどの変更履歴を記録・追跡するための分散型バージョン管理システムである。Linus によって開発され、ほかの多くのプロジェクトで採用されている。(以下wikipedia記事を抜粋加筆)

Gitは分散型のソースコード管理システムであるため、リモートサーバ等にある中心リポジトリの完全なコピーを手元(ローカル環境)に作成して、そのローカルリポジトリを使って作業を行う。

一般的な開発スタイルでは、大雑把に言えば、以下のようなステップの繰り返しで作業が行なわれる:

  1. git clone – リモートサーバ等にある中心リポジトリをローカルに複製する。
  2. git commit – ローカルでコンテンツの修正・追加・削除を行い、ローカルリポジトリに変更履歴を記録する。
    • 必要に応じて過去の状態の閲覧や復元などを行う。場合によってはこのステップを何度か繰り返す。
  3. git push – ローカルの変更内容を中心リポジトリに反映させる。
  4. git merge – git push の段階で、作業者ごとの変更内容が衝突することもある。Gitが自動で解決できる場合もあれば、手動での解決する。
  5. git pull – 更新された中心リポジトリ(他者の作業内容も統合されている)をローカルの複製にも反映する。これによりローカル環境のコードも最新の内容になるので、改めてステップ2の作業を行う。
  ローカルリポジトリ(Aさん)
           ver1.0a1      ver1.0a2          ver1.1a1
       修正--(git commit)--修正--(git commit)      修正--(git commit)
      /git clone              \git pushgit pull Bさんの修正
中心リポジトリver1.0-----------------ver1.1       も含まれる
      \git clone              /git push
       修正--(git commit)--修正--(git commit)   編集の衝突が発生すると 
           ver1.0b1      ver1.0b2     git merge が必要かも
  ローカルリポジトリ(Bさん)

GitHub

Git での中心リポジトリを保存・管理(ホスティング)するためのソフトウェア開発のプラットフォーム。コードの管理には Git を利用し GitHub 社によって保守されている。2018年よりマイクロソフトの傘下企業となっている。

GitHub では単なるホスティングだけでなく、プルリクエストやWiki機能(ドキュメントの編集・閲覧機能)といった、開発をスムーズに行うための機能も豊富である。(個人的な例:github.com/tohrusaitoh/)

GitHub で管理されているリポジトリには、公開リポジトリ非公開リポジトリがあり、非公開リポジトリはその管理者からの招待をうけないとリポジトリ改変に参加できない。

企業でのプログラム開発で GitHub を内々で使っている事例なども多いが、間違って公開リポジトリと設定されていて企業の開発中のプログラムが漏洩してしまった…との事例もあるので、企業での利用では注意が必要。

オープンソースとライセンス

オープンソースプログラムは、プログラムのソースコードをインターネットで公開されたものである。しかし、元となったプログラムの開発者がその利用に対していくつかの制約を決めていることが多い。これらのオープンソースプログラムでのソフトウェア開発手法の概念として「伽藍とバザール」を紹介する。

伽藍とバザール

伽藍(がらん)とは、優美で壮大な寺院のことであり、その設計・開発は、優れた設計・優れた技術者により作られた完璧な実装を意味している。バザールは有象無象の人の集まりの中で作られていくものを意味している。

たとえば、伽藍方式の代表格である Microsoft の製品は、優秀なプロダクトだが、中身の設計情報などを普通の人は見ることはできない。このため潜在的なバグが見つかりにくいと言われている。

これに対しバザール方式では明確な方針が決められないまま、インターネットで公開されているプログラムをボランティアを中心とした開発者を中心に開発していく手法である。

代表格の Linux は、インターネット上にソースコードが公開され、誰もがソースコードに触れプログラムを改良してもいい(オープンソース)。その中で、新しい便利な機能を追加しインターネットに公開されれば、良いコードは生き残り、悪いコードは自然淘汰されていく。このオープンソースを支えているツールとしては、前に述べた git が有名。

オープンソース・ライセンス

ソースコードを公開している開発者の多くは、ソフトウェア開発が公開することで発展することを期待する一方で、乱用をふせぐために何らかの制約をつけていることが多い。最初の頃は、開発者に敬意を示す意味で、プログラムのソースコードに開発者の名前を残すこと、プログラムを起動した時に開発者の名前が参照できること…といった条件の場合もあったが、最近ではソフトウェアが広く普及・発展することを願って条件をつけることも多い。

こういったオープンライセンスの元となったのは、Emacs(エディタ),gcc(コンパイラ)の開発者のストールマンであり、「ユーザーが自由にソフトウェアを実行し、(コピーや配布により)共有し、研究し、そして修正するための権利に基づいたソフトウェアを開発し提供することにより、ユーザーにそのような自由な権利を与えた上でコンピュータやコンピューティングデバイスの制御をユーザーに与えること」を目標に掲げた GNU プロジェクトがある。linux を触る際のコマンドで、g で始まるプログラムの多くは GNU プロジェクトのソフトウェア。

GNU プロジェクトが掲げる GNU ライセンス(GPL)では、GPLが適用されていれば、改良したソフトウェアはインターネットに公開する義務を引き継ぐ。オープンソースライセンスとして公開の義務の範囲の違いにより、BSD ライセンスApacheライセンスなどがある。

コピーレフト型 GNU ライセンス(GPL) 改変したソースコードは公開義務,
組み合わせて利用では対応箇所の開示が必要。
準コピーレフト型 LGPL, Mozilla Public License 改変したソースコードは公開義務。
非コピーレフト型 BSDライセンス
Apacheライセンス
ソースコードを改変しても公開しなくてもいい。

GPLライセンス違反

GPLライセンスのソフトウェアを組み込んで製品を開発した場合に、ソースコード開示を行わないとGPL違反となる。大企業でこういったGPL違反が発生すると、大きな風評被害による損害をもたらす場合がある。

最近のライセンスが関連する話題を1つ紹介:GitHub を使った AI プログラミング機能「Copilot」というサービスが提供されている。Copilot のプラグインをインストールした vscode(エディタ) では、編集している関数名や変数名などの情報と GitHub で公開されているプログラムの 学習結果を使って、関数名を数文字タイプするだけで関数名・引数・処理内容などの候補を表示してくれる。しかし、Copilot を使うと非オープンライセンスで開発していたプログラムに、オープンソースのプログラムが紛れ込む可能性があり、非オープンソースプロジェクトが GPL で訴えられる可能性を心配し「Copilot は使うべきでない」という意見の開発者も出ている。Copilot だけでなく、生成系 AI によるプログラムでも、同様の問題が指摘されている。

理解度確認

IchigoJamとMapleSylup

7/25(木) 18:30~20:00

ボタンとLED点灯

IchigoJam には、LED 命令と BTN() 関数がある。BTN() 関数は、SW2 のボタンが押されていれば1,押されていなければ0を返す。
このため、ボタンを押している間 LED を点灯する関数は以下のように書ける。

10 LED BTN()
20 GOTO 10
RUN

これを踏まえ、ボタンが押された回数を数えるプログラムを作ってみよう。以下のプログラムは、BTN() が 1 の時、Aの値を増やし、Aの値を表示する。

10 A=0
20 IF BTN()=1 THEN A=A+1 : PRINT A
30 GOTO 20
RUN

しかし、このプログラムは1回ボタンを押すだけで、Aの値はいくつも増えるはずである。

これは、IchigoJam の処理が速いため、人間がボタンを1度押してボタンを離すまでの間に何度も繰り返すためである。

練習問題:ボタンを1回押したら1つづつ増えるようにプログラムを書いてみよう。(練習問題)

このプログラムであれば、ボタンが押されない間待ち、押されたらボタンが離れるまで待ち、1回とカウントする。(練習問題)

10 A = 0
20 IF BTN()=0 THEN GOTO 20
30 IF BTN()=1 THEN GOTO 30
40 A = A+1
50 PRINT A
60 GOTO 20

“でもこのプログラムでも「チャタリング」の影響で上手くカウントできない。どう直せばいいのだろうか?”と書いてチャタリングによる誤動作を見せるつもりだったけど、実際にやってみると、IchigoJam の処理速度の影響で、WAITなしでもチャタリングによる誤動作は発生しなかった。

チャタリングは数100μsec~数msecほど継続する可能性がある。このため「25 WAIT 1」と「35 WAIT 1」を追加すれば、問題ない。

複数のLEDの点灯

IchigoJam の定番の最初のプログラムでは、LED1,LED0 命令で LED を点灯させる実験をするが、OUT1~OUT4ポートを使って複数の LED を点灯させてみよう。

              LED 1 2 3 4
    OUT 1, 1      ✕✕✕ 一つづつポートを1に変化
    OUT 2, 1      〇✕✕
    OUT 3, 1      〇〇✕
    OUT 4, 1      〇〇〇
    OUT 2, 0      〇〇〇

    OUT 0         ✕✕✕✕ まとめて消す命令
    OUT `1100      4ポートまとめて点灯/消灯
    OUT `1010     

(練習問題)

10 OUT `1100 : WAIT 20
20 OUT `0110 : WAIT 20
30 OUT `0011 : WAIT 20
40 OUT `0110 : WAIT 20
50 GOTO 10

10進数と2進数

OUT 命令で、複数ポートをまとめて変更する際には、「`1010」といったIchigoJam BASICでの2進数の取扱いの理解が必要なので、ちょっとだけ10進数,8進数,2進数の説明。

IchigoJam BASIC で2進数を扱う場合は、バッククオート` を使う。シングルクオート’ と間違いに注意。

10進数とは 123)10 = 1✕102 + 2✕10 + 3 のように、数字を10をひとまとめとして、10が10個で100を表すというように各桁を対応させたもの。

人間が8本指で進化したら、数字は8をひとまとめで扱い、123)8 = 1✕82 + 2✕8 + 3 = 83)10 として表現する8進数になったかもしれない。

コンピュータの中では、電気のある/なし の2通りで表現することで動いているため、各桁を0と1で表す 2進数 が便利。1010)2 = 1✕23 + 0✕22 + 1✕21 + 0 = 10)10

IchigoJam によるモータ制御の実験

IchigoJam で モータを動かす場合、MapleSylup というモータドライバボードを使うと簡単にモータが制御できる。

IchigoJam には、主要な出力ポートが OUT1~OUT6まである。このうち、OUT2~OUT5までは サーボモータの制御に使える。

(重要) IchigoJam の OUT ポートに直接「直流モーター」を接続してはいけない。モータを回すために大量の電流が使われるため IchigoJam は誤動作などを起こす可能性が高い。場合によってはモータから出るノイズで IchigoJam が壊れる可能性がある。必ず MapleSylup などのモータを動かす専用の回路を経由させること。

直流モータとサーボモータ

直流モータは、直流の電圧を加えることで回転するモータで、電圧を加える方向で右回転・左回転を簡単に制御できる。

サーボモータは、模型飛行機などの羽の角度などを変化させることに特化したモータで、中に直流モータと信号に応じて回転角度を変えるための電子回路が組み込まれているため、パルス幅信号PWM により簡単に角度を変化させることができる。

ただし、モーターは電流がたくさん流れるため、IchigoJam の電源からモータを回すと、IchigoJam を動かすための電力が不足して誤動作してしまう。このため、MapleSylup のモータドライバによって乾電池からの電力でモータを回す必要がある。

ポートの配線

IchigoJam の上に MapleSylup を接続して、MapleSylup のジャンパを配線する。

  • OUT2ポートを、サーボモータではなく直流モータの配線につながるように、J2 を 2=3 接続となるようにジャンパをつなぐ。
  • 同様に、J3 を 2=3 接続となるようにジャンパをつなぐ。

直流モータを動かす(OUT1,OUT2 , OUT5,OUT6)

MapleSylup では、今回 OUT1,OUT2 と OUT5,OUT6 の出力ポートにそれぞれ直流モータを接続する。OUT1,1 とOUT2,0 の時、OUT1側が V+, OUT2側が GND=0V になることでモータが回転する。OUT1,0 と OUT2,1 とすれば、OUT1側がGND=0V, OUT2側が V+ となることで、先ほどとは逆方向に回転する。

((( モータを片方だけ動かす )))
OUT 0      OUTポート全部を 0 にする。
OUT 1,1    左モータが回転する。(OUT2 がまだ0のため)
OUT 1,0    左モータが止まる。
OUT 2,1    左モータが逆転で動く。
OUT 2,0    左モータが止まる。
OUT 5,1    右モータが回転する。
OUT 5,0
OUT 6,1    右モータが逆転で動く。
OUT 6,0
((( モータを複数動かす )))
OUT 1,1
OUT 5,1    両方のモータが動く
OUT 1,0
OUT 5,0

((( モータを複数同時に設定 )))
OUT '000001  OUT1=1,OUT2=0,OUT5=0,OUT6=0 左モータが動く
OUT '010000  OUT1=0,OUT2=0,OUT5=0,OUT6=0 右モータが動く

サーボモータを動かす(PWM2)

MapleSylup では、OUT2,OUT3,OUT4,OUT5 をサーボモータに接続できるが、OUT2 は、直流モータを動かすために使うので、今回は OUT3,OUT4 を使う。

サーボモータを動かすためには、専用の PWM 命令を使う

PWM 3, 100
PWM 3, 200

PWM2, 50  PWM2,100

サーボモータを左右に動かすプログラムは以下のようになる。(練習問題)

10 PWM 3,100 : WAIT 30
20 PWM 3,200 : WAIT 30
30 GOTO 10

差分とフィードバック制御

情報制御基礎の授業を通して、入力値を制御するため、コンピュータを使う場合の数値処理の基礎的な話として、信号の平滑化を説明してきたので、最後に差分について説明をする。また、実際には、入力値を制御に利用する一般的な構成のフィードバック制御について説明する。

変化の検出

例えば、以下のような若干のノイズが混ざった入力信号が与えられたとする。この波形で「大きな山が何ヶ所ありますか?」と聞かれたら、いくつと答えるべきであろうか?山の判断方法は色々あるが、4カ所という答えは、1つの見方であろう。では、この4カ所という判断はどうすればいいだろうか?

こういった山の数を数えるのであれば、一定値より高いか低いか…という判断方法もあるだろう。この絵であれば、15ステップ目、32ステップ目付近は、100を越えていることで、2つの山と判断できるだろう。

こういった予め決めておいた値より「上か?/下か?」で判断するときの基準値は、しきい値(閾値:threshold)と呼ぶ。

しかし、この閾値では、40ステップ目から50ステップ目も100を越えており、以下のようなプログラムを書いたら、40ステップ目~50ステップ目すべてをカウントしてしまう。

#define THRESHOLD 100
int x[ 100 ] = {
   // 波形のデータが入っているとする。
} ;

int count = 0 ;
for( int i = 0 ; i < 100 ; i++ ) {
   if ( x[i] >= THRESHOLD )
      count++ ;
}

また、65ステップ目の小さな山も1個とカウントしてしまう。

この問題を避けるために、閾値を130にすると、今度は最初の2つの山をカウントできない。どうすれば、山の数をうまくカウントできるのだろうか?

差分を求める

前述のような問題で山の数を数える方法を考えていたが、数学で山を見つける時には、何をするだろうか?

数学なら、山や谷の頂点を求めるのならば、微分して変化量が0となる場所を求めることで、極大値・極小値を求めるだろう。そこで、山を見つけるために入力値の変化量を求めてみよう。

表計算ソフトで差分を計算するのであれば、セルに図のような式を入力すればいいであろう。このようなデータ点で前の値との差差分と呼ぶ。数学であれば、微分に相当する。

このグラフを見ると、波形が大きく増加する部分で、差分が大きな正の値となる。さらに波形が大きく減少する部分で差分が負の大きな値となる。特にこのデータの場合、山と判断したい部分は差分が20以上の値の部分と定義することも考えられる。

#define TH_DIFF 20
int x[ 100 ] = {
   // 波形のデータが入っているとする。
} ;

int count = 0 ;
for( int i = 0 ; i < 100 ; i++ ) {
   if ( x[i] - x[i-1] >= TH_DIFF
        && x[i+1] - x[i] <= -TH_DIFF )
      count++ ;
}

しかし、このプログラムでは、山の数をうまくカウントしてくれない。うまく、山の数を数えるためには、差分の値を山と判断するための閾値(この場合は20)を調整することになるだろう。

移動平均との差

前回の講義で示したデータの例で、移動平均を取ると分かる事例ということで、船につけられた加速度センサーで、長い周期の波による船の揺れと、短い周期のエンジンによる振動があったとき、エンジンの振動を移動平均で取り除くことができるという事例を示した。

これを逆手にとれば、元の信号と移動平均の差を取れば、エンジンの振動だけを取り出すことも可能となる。以下は、前の事例で、前後5stepの移動平均(水色線)と元信号(青線)の差をとったものが緑線となっている。このような方法をとれば、元信号の短い周期の変動を抽出することができる。

制御工学の概要

以下に、制御工学ではどのようなことを行うのか、概要を述べる。
ここで紹介する制御理論は、古典制御理論と呼ばれる。

制御工学では、入力値と、何らかの処理を施し出力値が得られるシステムで、どのように制御するかを考える。

例えば、電気ポットの温度制御をする場合、設定温度の値を入力値とし、何らかの処理を行い、出力となるヒーターの電流を制御し、最終的には温度が測定される。ヒーターは、設定温度と温度計の値の差に応じて電流量を変化させる。このように一般的な制御では、最終的な温度が入力に戻っている。このように目標値に近づけるために、目標値との差に応じて制御することをフィードバック制御という。


制御の仕方には様々な方法があるが、 がとある時間で0からYに変化した場合を考える。入力と出力で制御された波形の例を示す。

この波形では、黒のように入力値が変化した場合、それに追いつこうと出力が変化する。(1)理想的には、速やかに追いつく赤のように変化したい。しかし、(2)慎重に制御をする人なら、変化への制動が大きい過制動(青点線)となり、目標値に追いつくまでに時間がかかる。(3)一方、すこしでもずれたら直そうとする人なら、時間的には速い反応ができるかもしれないが、目標値を追い越したり、増えすぎ分を減らしすぎたりして脈動する過制御(赤点線)となるかもしれない。

PID制御

目標値、出力、ずれ(偏差)、制御量とした時、基本的なフィードバック制御として偏差の使い方によってP動作,I動作,D動作がある。参考 Wikipedia PID制御

比例制御(P制御)

偏差に比例した制御を行う方式(を比例ゲインと呼ぶ)

今年のコロナ騒動を例にとるならば、比例制御は、今日の感染者数y(t)と目標としたい感染者数x(t)の差に応じて、対策の強さu(t)を決めるようなもの。

積分制御(I制御)

偏差のある状態が長い時間続く場合、入力値の変化を大きくすることで目標値に近づけるための制御。(は積分ゲイン)

積分制御は、目標の感染者数x(t)を感染者数y(t)が超えた累積患者数に応じて、対策を決めるようなもの。
移動平均は、一定範囲の値の和(を範囲のデータ数で割ったもの)であり、積分制御は移動平均の値に応じて制御するとみなすこともできる。

微分制御(D制御)

急激な出力値の変化が起こった場合、その変化の大きさに応じて妨げようとする制御。(は微分ゲイン)

微分制御は、目標数と感染者数の差が、前日よりどのぐらい増えたか(患者の増減の量:変化量)に応じて、対策を決めるようなもの。

PID制御

上記のI制御やD制御だけでは、安定させることが難しいので、これらを組み合わせたPID制御を行う。

この中で、の値は、制御が最も安定するように調整を行うものであり、数値シミュレーションや、ステップ応答を与えた時の時間的変化を測定して調整を行う。

システム

最新の投稿(電子情報)

アーカイブ

カテゴリー