Stage 17 : Aquaponics Maintenance Robot
仕様書
radio-rx はブロックされないXBusインプットで接続される。
motor はシンプルアウトプットで接続すること。
tool-clean と tool-feed はシンプルアウトプットで接続すること。
メンテナンスロボットは最初、Station 0 にいる。
motor の値が 50 から 100 を行き来する度に、ロボットは次の駅へ移動する。
motor の値が 50 から 0 を行き来する度に、ロボットはひとつ前の駅へ移動する。
radio-rx から送られてくるデータパケットは次のような配列となる。ただし、潅水作業は清掃作業が終わってから行うこと。
※補足
データパケットの1つ目に送られてくる値は移動する回数ではなく、
その位置まで移動しろという意味なので、
現在位置からその場所までの位置計算が必要です。
例:
現在位置が 2 の時、データパケットの1つ目の値が 5 だった場合、
motor に 100 50 100 50 100 50 の順番で 50~100のパルスを 3回 出力する必要がある。
その次のデータパケットにて(現在位置 5)、1つ目の値が 1 だった場合、
motor に 0 50 0 50 0 50 0 50 の順番で 50~0 のパルスを 4回 出力する必要がある。
ヒント
...
マイコンを複数使用して作業を分けることが必要です。
具体的には motor に出力しつつ現在位置を記憶しておくマイコンと、
motor の停止を待ち、停止後に tool-clean と tool-feed に出力を送るマイコンです。
処理に必要なデータパケットは全部で 3つ ありますが、
その中でも motor を動かす処理には現在位置から次に進めるのか前に戻すのか(50~100のパルスか50~0のパルス)、
と言う別々の処理が必要なため比較的コード数が長くなると予想できます。
その為、データパケットを分解して処理させる機構は tool-clean と tool-feed の
出力を制御するマイコンに持たせた方が無難でしょう。
利便上、tool-clean と tool-feed を出力するマイコンを M-Tool、
motor を動かすマイコンを M-Motor と呼称します。
M-Tool では radio-rx からデータパケットを受け取り、その 1つ目 の値を M-Motor に送信させます。
M-Motor に値を送信したと言う事はメンテナンスロボットの移動が終了するまで、 M-Tool には何もさせません。
M-Motor からメンテナンスロボットの移動が終了したと言うシグナルを受け取れるようにして停止させましょう。
この時点で M-Motor では、メンテナンスロボットを移動させたい位置の情報が読み込めます。
(motor の値は初期値で 50 を持つようになっているので、M-Motor は motor に 50 を出力した後、その状態でシグナルを待つ様にしましょう)
M-Motor では現在位置を accレジスタ に格納しておくことで、M-Tool から送信されてきた移動先の情報と比較した時、
その移動先の情報と accレジスタ の値によって 50~100 のパルスを出力すべきなのか、50~0 のパルスを出力すべきなのか判断できます。
その上で、出力ごとにメンテナンスロボットが移動するので、accレジスタ の値を加算または減算し、
M-Tool から送信されてきた値になるまで繰り返せば motor の出力は完成します。
この条件を満たしたら M-Motor の処理完了を待たせている M-Tool に対して何かしらのシグナルを送れば M-Motor の処理は終了です。
M-Motor からのシグナルを受け取った M-Tool は、残りの 2つ のデータパケットを gen命令 などを使って、
tool-clean や tool-feed に出力すればこの問題はクリアできます。
配線例
回答例
解説動画
Stage 18 : Remote Kill Switch
仕様書
radio-rx はブロックされないXBusインプットで接続される。
power-0、power-1、power-2 はシンプルアウトプットで接続され、
工業用機器によって制御された高出力スイッチである。
radio-rx から送られてくるデータパケットを読み込み、次の表の対応するコマンドを実行する。
-1 |
継続 |
何もしない |
0 |
スイッチを切る |
別の値を読み込み、その出力をオフにする |
1 |
スイッチを入れる |
別の値を読み込み、その出力をオンにする |
データパケットを受信せずに 5TU 経過した場合、全ての出力をオフにします。
※補足
データパケットは 0 か 1 のコマンドが送信されてきた時、
2つ目の値が存在し、それは 0~2 のスイッチの種類を指定している。
ヒント
...
処理系をマイコンで分けましょう。ひとつは radio-rx からのコマンドを読み込み、
power に対して出力する値を作るマイコンです。M-Switcher とします。
もうひとつは 5TU をカウントする為のマイコンです。こちらは M-Counter とします。
まずは情報を整理します。
この問題において radio-rx から送られてくる値は、
-1
が単独で送られてくるか、もしくは [0, 1] や [1, 2] のように複数送られてくる場合と2パターン存在します。
0 と 1 が最初に送られてきた場合、それはスイッチのオンオフを制御するコマンドであり、
どのスイッチに対してか、と言う「どのスイッチか」と言う情報が 0 ~ 2 の値で送られてきます。
データパケットを受け取るマイコン側ではこれを処理する必要があります。
そして power-0 ~ power-2 についてはシンプルアウトプットでの接続が必要なため、
DX300 を使用して各出力を制御させましょう。
データパケットから送られてきた値を最大で2つの値を使用しなければならない M-Switcher を、
radio-rx からのデータを読み込むマイコンとしましょう。(逆にするとXBusの同期が大変になる為)
M-Switcher では radio-rx から送信されてきた値によって、5TU の間、受信の有無をチェックする必要があります。
しかしこの 5TU と言う時間は M-Counter にチェックさせるので、
M-Switcher に -999 ではない何かしらのデータが送られてこれば M-Counter へ何かしらのデータ(シグナルは何でもよい)を送信します。
次にひとつ目のデータは -1 0 1 のいずれかです。その値はブロックされないXBusインプットなので、-999をチェックするために、
ひとつ目の値は既に副次レジスタに格納されているはずです。DX300 に出力すべき値はその副次レジスタの値と、
2回目に読み込みを行う値を使って作ります。
この時、既に何らかのスイッチがオンになっている場合、そのスイッチはそのままで次のスイッチの制御をしなければなりません。
DX300 に出力した値が 100 だった時、次に [1, 0] が送信されてきた場合、出力は 101 とする必要があります。
データパケットが送信されてくる度に、現在の出力状態を変更しなければなりません。(上書きではない)
その為、多目的レジスタに格納されている値に対して「桁数と変更する値」を指定して多目的レジスタの値を書き換える dst命令 が便利です。
多目的レジスタの現在値が 100 の時、[1, 0] が送信されてきたら、 dst 0 1 を実行すると多目的レジスタの値は 101 となってくれます。
このようにして値を作れば M-Switcher は想定通りの動きをします。
また、M-Counter から最後の受信から、5TU経過するまでのカウントされている値を読み込めるようにし、
そのカウントが 0 になったら多目的レジスタの値を初期化する処理を挟んでおきます。
次に M-Counter ですが、こちらは 1TU ごとに多目的レジスタの値を 1 ずつ減算処理させます。
この時、多目的レジスタの値を 1TU ごとに M-Switcher へ送信するようにしましょう。
そして、M-Switcher からのシグナルを受け取った時、多目的レジスタの値を 5 にします。
多目的レジスタの値が 0 になった時、M-Counter から DX300 に対して 0 を送信させるようにすれば
M-Counter も完成となります。
(マイコンを使用しなくても 5TU のカウンティングは可能なので、その方法も考えてみてください)
配線例
回答例
解説動画
Stage 19 : Smart Grid Control Router
仕様書
meter-in と meter-out は、ノードを次世代送電網に接続するXBusインプットとアウトプットである。
lower-in と lower-out は、低いID番号を持つノードを接続するXBusインプットとアウトプットである。
higher-in と higher-out は、高いID番号を持つノードを接続するXBusインプットとアウトプットである。
データパケットの最初の値は宛先のID番号で、パケットの処理方法を示している。
ID < meter ID |
データパケットを下位ノードに再送信する |
ID = meter ID |
データパケットをメーターに再送信する |
ID > meter ID |
データパケットを上位ノードに再送信する |
ノードのローカルID番号は、XBusインプットとして読み取り可能なセキュアIDチップに格納されている。
データパケットの2つ目の値は、残りのデータパケットの長さを示している。
※ざっくり要約
3箇所の XBus入力 から順不同で流れてくるデータパケットを読み込み、その最初の値とセキュアIDチップの値を比較して、
IDが大きいか、同じか、小さいか、によって送信先を切り替え、読み込んだものと同じデータパケットをアウトプット側に出力しなさい。
ヒント
...
方法は幾つかありますが、ここで紹介しているものは2つ目のデータである、データパケットの残りの長さを使用しないパターンです。
2つ目のデータであるデータパケットの残りの長さを多目的レジスタに代入して、その値が 0 になるまで出力を繰り返すのは無難な方法だと思いますが、
マイコンの数が恐らく増えます。1つのマイコンでは行数が足りなくて処理しきれないと思います。
そこで、邪道ですがデータパケットの最初の値に着目してみましょう。
この問題の仕様書には一切の記入がありませんが、入力されてくるデータパケットの値は必ず、
最初の値(ID番号情報)が 100以上 の数値になっていて、2つ目以降のデータは全て 99以下 の数値で構成されています。
その為、宛先を指定している最初の値と、それ以外のデータでしっかり区切る事が可能です。
行いたい処理としては、
- データがなくなるまで処理を続けさせる(slx命令を使って判定させましょう)
- 最初の値は繰り返し処理でセキュアIDチップの値と比較する為、参照し続けるので、レジスタに格納させる。
- 2つ目以降のデータは格納している最初の値と比較し、再送信する為、毎回レジスタに格納する
- 格納済みの最初の値とセキュアIDチップの値を比較し、それぞれの出力先に対する処理をさせる(tcp命令が便利です)
- 上記 2 ~ 4 の処理が終わり次第、次のデータがあるかどうかを判定する行へジャンプする
このような流れです。ただし、最初のデータなのかそれ以外なのかを判定する機構を作らないと、
(恐らく)1つ目の値を格納しているレジスタに上書きしてしまい、2つ目以降のデータが正常な場所に送信されない、
などと言う不具合が起こります。最初の値は 100 以上、それ以外の値は 99 以下の数値を取ることを忘れないでください。
配線例
回答例
解説動画
Stage 20 : Pocket I Ching Oracle
仕様書
button と oracle は、MEMSベースのオラクルエンジンに接続されたシンプルインプットである。
display は、易占いヘキサグラムを視覚化するように設計されたカスタムLCDスクリーンに対応するディスプレイ出力である。
ボタンが押されると、オラクルエンジンは易占いヘキサグラムの6行に対応する6つの値を生成します(下から上)。
最後の値が生成された時、生成された値の通りにディスプレイを更新する。
※ざっくり要約
button の入力があったその瞬間から、1TUごとに oralce の入力のオンオフを読み取り、
6TU経過した時点で、その間の6つの数字を使用してディスプレイに値を出力する。
ディスプレイへの出力は下から上に向かって、1TU目の状態、2TU目の状態、3TU目の状態、と言う順番でオンオフ(0か100)を出力すること。
余談
・I Ching Oracle って?
I Ching Oracle とは中国発祥の占いである「易占い」の事だと思われます。
易占いは6本の陰と陽を組み合わせたヘキサグラムと呼ばれる図形を元にした占いです。
・MEMS って?
MEMSは Micro Electro Mechanical Systems の略。
機械用部品のひとつで、微細加工技術によって集積化されたデバイスのことです。
Microと言う名の通り、ダニよりも小さなデバイスっぽいですが、詳しくは Wikipedia などをご覧ください。
ヒント
...
6つのオンオフデータを取り扱う必要があります。複数のマイコンで処理させることもできますが、
マイコンをひとつで行うことも可能です。レジスタには最大で3桁の値しか格納できないので、
100P-14などのランダムアクセスメモリを利用するとスムーズに解けるかもしれません。
今回は多目的レジスタと副次レジスタのみを使用して問題を解いていきます。
レジスタひとつに3桁の格納が可能なので、レジスタがふたつあれば6桁の値の格納は可能です。
また、ここまで問題を解いてきた方であればどのような値を作るべきか分かるかと思いますが、
110101 や 001011 などの 0 と 1 で構成された数値を作っていきます。
110101 ならば、多目的レジスタに 110 が格納され、副次レジスタに 101 が格納されているイメージです。
これらの値を DX300 を経由して下段3つと上段3つのディスプレイ出力口に接続させ、出力すればクリアな訳です。
重要なのは、値の作り方です。
これには button から 100 が入力されてきた瞬間から、6TUの間だけ毎回 oracle の値をチェックして、
その都度、現在の多目的レジスタの値を変更していきます。指定した桁を変更する算術命令である dst命令 を利用しましょう。
この時、毎回 oracle から流れてくる値が 100 か 0 かをチェックしていては行数の無駄になります。
oracle側からの入力も DX300 を挟むようにして、マイコンへの入力値を 0 か 1 に変更しましょう。
こうすることで dst命令 の第二オペランドは oracle側の DX300 に接続するXBusピンを指定すれば済むようになります。
大まかな流れとしては…
- button のオンオフをチェックする
- button がオンになってからTUごとに指定された桁の値を dst命令を使って oracle(DX300経由)の値に書き換える
- 6回(6TU)繰り返す(ただし繰り返し方法には注意/後述)
- 6TU目に完成したふたつの値をそれぞれディスプレイ(DX300経由)に出力させる
処理としては6回、oracle の値によって桁の置き換えを行いますが、6回繰り返すことはできません。(6回をカウントするレジスタが空いていない為)
その為、3回行う処理(1~3桁目を作る)を2回繰り返す、と言う流れにしましょう。
マイコンのみで作る場合は多目的レジスタと副次レジスタにそれぞれ3桁の数字を作るしかなく、
また、dst命令は算術命令なので暗黙的に多目的レジスタで処理されます。
つまり、最初は副次レジスタを使ってないないが、最初の3桁が完成したら次の3桁の処理の為、
多目的レジスタの値を副次レジスタに移動させてから、次の3桁を処理を行うことになります。
その為、1度の繰り返しならば副次レジスタにある数値の有無で判定ができると言う訳です。
副次レジスタに値がなければ多目的レジスタの値を副次レジスタに代入させてもう一度繰り返す。
副次レジスタに値があるなら多目的レジスタの値はふたつ目の3桁の値なので全体の値は完成している(6TU経過している)
このように作ると、マイコンひとつで処理をまとめることができるはずです。
配線例
回答例
解説動画