Raspberry PiにROS Kineticを入れてみた

その昔、学生時代に授業でROSを触っていました。当時は今ほど情報量がなくてドキュメントを見ても何をやっているのかよく分からなくて挫折してました。

ただ、最近Twitterを眺めているとROSの知見が増えてきて、今なら挫折をせずにやれるのではと思い、再入門をすることにしました。

ひとまずROSのチュートリアルを見ながら昔の感覚を思い出しつつUbuntu上でTurtlesimを動かすところまではやりきれるようになりました。(↓こんなの)

f:id:KMiura:20210907005037p:plain

でさらにROSを一からちゃんと勉強しようと思いROSの本を探してみたら、数こそ少ないですが昔よりはある程度の選択肢がありました。

その中でも使用言語がPythonで情報量が多そうな以下の本を購入しました。

で読み進めていくうちに自分でもRaspberry Piを使ってロボットを作ってみたいと思うようになりました。

昔作ってからまともに動かせていないロボットカーがあったので、そいつをROS対応にするのを目標にしようと思いました。

最近はaliexpressとかに「ROS対応」を謳ったロボットキットを見かけるようになりましたが、Raspberry Piを使っていると多分自分でROSのセットアップをさせると思います(もしかしてイメージが配布されている?)。

しかもそういうロボットにはそこそこのセンサーが入ってたり、筐体もしっかりしているので、値段がそこそこします。

それなら自分で作るのが安上がりです。

というわけでRaspberry PiにROS Kineticをセットアップしていきます。

今回はUbuntuではなく、Raspbian Busterで試してみます。

Raspbianでやったほうが後々ハードウェアの依存関係に悩まされずに済みそうという安易な考えですw。

結論としては、以下のROSのドキュメントにやり方が紹介されているのでそのとおりにやるだけです。

http://wiki.ros.org/ROSberryPi/Installing%20ROS%20Kinetic%20on%20the%20Raspberry%20Pi

基本的にはROSのソースファイルを落としてそこから依存パッケージをインストールするだけですが、このドキュメントはOSのバージョンによって手順が分けてあり、それがわかりやすくみえてちょいちょいややこしいところがあると感じました。

特に一番詰まったのはワークスペースのビルドに失敗するところです。

何時間も悩みましたが作業ディレクトリの違いという超初歩的ミスでしたw。

Linuxになれている今でもこんなミスをするわけで昔はもっと苦戦したでしょうね。そりゃ挫折するわけだ。

というわけでこんな初歩的ミスをなくすためにインストール用のシェルスクリプトを用意しました。

スクリプトを実行するとRaspbian BusterでROS Kineticをセットアップしてワークスペースも作成されるようになります。

PCのUbuntuでやるときよりもかなりビルドに時間が取られました。なので途中で失敗したときの手戻りは辛かったです…

念の為、Raspberry Piを再起動させて以下のコマンドを実行します。

このコマンドは簡単にいうとROSの基本的なプログラムを起動するもので、ROSのシステムを動かすときは必ず実行します。

roscore

実行後、以下のようにROSのバージョンやIPアドレスが表示されればROSは正常に起動しています。

started roslaunch server http://raspberrypi:44065/
ros_comm version 1.12.17


SUMMARY
========

PARAMETERS
 * /rosdistro: kinetic
 * /rosversion: 1.12.17

NODES

auto-starting new master
process[master]: started with pid [30552]
ROS_MASTER_URI=http://raspberrypi:11311/

setting /run_id to 35a98658-0f36-11ec-81c5-dca63297671e
process[rosout-1]: started with pid [30565]
started core service [/rosout]

これでロボット作りの第一歩が踏み出せたので、今度はセンサーの値を読み取ったりモーターをぶん回していこうと思います。

ジャンクのマザボ(ASUS P6T)を動かした話

初めて組んだ自作PCは特に不具合なく安定して動作しています。

これ以来ジャンクPC沼にハマってしまい、安くてお買い得なPCを求め続けるようになりました。

最近仕事終わりにおなじみパソコンショップパウに寄り道して1000円のCPUガチャに挑戦しました。

するとi7 930とXeon W3680を手に入れました!

帰り道にやってよかった(本当はフラッシュメモリガチャをやりたかったけど終わってた…)

なんと運がいいことにこの2つはLGA1366ソケットに対応しているので2つまとめて動作確認できるわけです。

ただ、LGA1366のマザボなんて持ってないので休日にまた例の如く大須や名古屋のハードオフを回ってたら奇跡的にハードオフ徳重店にジャンクのLGA1366のマザボをゲットしました。ちなみにこの店にはこれ以外のマザボはなかったので本当に運が良かったw。

それがASUS P6Tです。お値段は1650円、中途半端に高いけど

f:id:KMiura:20210823235026p:plain

開封の儀

サイズはATXなので、PCI-Eスロットがいくつもあるのでマイニングに使えそう(する予定ないけど)。

で更にいいなと思ったのが、DDR3のメモリスロットが6つもあります。

これで8GB×6枚を揃えればかなり強いPCできそうです。

そして、まな板PCで動作確認をするときに便利なスイッチがついているのは普通に嬉しいですね。

f:id:KMiura:20210823235720p:plain

そしてこいつがジャンクである理由がCPUソケットにグリスがこびりついているのとホコリがこびりついている上にピン折れが結構目立つことです。どうしてこうなった!

f:id:KMiura:20210824000237p:plain

とりあえずホコリでショートとかするとやばいので頑張ってピンセットで取り除いていき、ホコリは取り除くことができました。

そして、ピン折れもピンセットやジャンパーワイヤーを駆使してある程度は補正できました。

とりあえず動かした

というわけでCPU、メモリ、グラボという最小構成で動作確認をしてみました。

CPUはマザボを物色したときにパウのCPUガチャを再度挑戦したときに出たXeon E5640で試しました。今まで手に入れたLGA1366のCPUの中で一番低スペックなので壊れても大丈夫なやつを選びましたw

グラボは以前パウのジャンクセールで手に入れたGTS250です。普通はグラボはなくてもいいのですが、今回使ったマザボは映像出力の規格がかなり古いので、グラボはあったほうがいいです。

CPUファンに関してはLGA1366に対応したものがないので、手持ちのやつを申し訳程度に置いておきました。

動いたらいいなと思いつつ電源を入れたら、ファンは回ってますが画面は出力されませんでした…

原因は?

一応電源が入るということは少なくともCPUは正常に動作しているはずです。ピン折れが治ってなくて動作しなかったらCPUはショートして煙を出しそうな気がしますし。

でメモリスロットがやられている可能性があったので他のスロットでも試しましたが画面は表示されません…

やはりちゃんと冷却したほうがいいのかと思いましたが、冷却はなくてすぐ電源が落ちるだけで画面は表示されるはずです。

完全に外れか…と諦めかけてましたが、一晩寝てマザボを眺めていると明らかにボタン電池が古いことに気づきました。

これはもしかしたらボタン電池を新しく交換したら動くのではと思い、家に余ってたボタン電池に交換して無事に動きました。

ボタン電池が完全に死んでたせいでBIOSが開けなかったということですね。

というわけでちゃんとBIOSまで確認できてよかったです!

ただちゃんと冷却できてないせいですぐ電源が落ちるので、次はLGA1366に合うCPUクーラーを探そうと思います。

週末の佐古前装備のセールで探そうかな…

訳あってQuadro P400も手に入れた

先日ハードオフQuadro K2000を買って動作確認しました。

supernove.hatenadiary.jp

で問題なく動きましたが、ディープラーニングの環境構築をしたくてTensorflowを入れて以下の記事を参考にGPUが認識されているか確認しましたが、リストの中にGPUの情報が表示されませんでした。

sciencompass.com

原因はQuadro K2000のCuda Capabilityが3.0だからみたいです。

各モデルのCapabilityについてはこちらを参考にしました。

developer.nvidia.com

最新のTensorflowを動かすには最低3.5必要なのでそのままでは使えないです。

じゃあPytorchはどうかなと思ったのですが、Pytorchもインポートエラーにはなりませんが、Capabilityが3.5必要なのでやはり使えません。

それで以下の記事を参考にしてソースからインストールしようとしたのですが、ビルドにクソ時間がかかるし途中でビルドエラーになって対処がめんどくさいので断念しました。

notekunst.hatenablog.com

個人的にはPytorchだけは使えるようにしたかったのでなんとかしようと思いました。

というわけでCapabilityが3.5以上のグラボを物色するためにまた名古屋の中古PCショップを回りました。

正直ディープラーニング用のGPUなら新品買えよって思うかもしれませんが、そもそも使うPCはそれぞれの部品に1万円も使ってないのに、グラボだけバカ高いのは世代のバランス悪すぎるし何より気持ち悪いので、地道に中古品を探すことにしました。

ひたすら名古屋市内を行ったり来たり

まず、おなじみ大須のパウに行ってきましたがタイミング悪く低スペックのグラボしか置いてませんでした。

前に行ったときは確かQuadroも何度か見かけてました。(その時はQuadro知らなくて眼中になかった…)

手始めに名古屋栄伏見店

でその後Quadroを買った伏見のハードオフGeForceを売ってたのを思い出しました。

値段しか見てなくて番号まで覚えてなかったので仕方なくバスで伏見のハードオフに向かいました。

で、GeForceを置いてあった棚を確認したところ、なんとGTX 550 Tiでしたw。

Quadro K2000よりも古いモデルなのに倍の価格で販売しているのはどうかと思います。やっぱり価格設定おかしすぎる。

当たり前ですが、Capabilityは2.1で圧倒的に低かったので論外です。

他のGPUは以前買ったQuadro K2000が2個在庫であったぐらいです。

お次は覚王山

転んでもただでは起きない僕は地下鉄で覚王山ハードオフを目指しました。他のリサイクルショップだとグラボどころかPCパーツが置いてある確率が低いのでそこも探しているとキリがないのでハードオフ縛りでなるべく効率よく回ることにしました。

覚王山ハードオフを確認したところ、グラボは一つも置いてませんでした。

代わりにジャンクコーナーに大量のマザボがありました。割ときれいなものもあったので、この店舗はマザボ単体=ジャンクという発想なんですかね。

でもここでわかったのは店舗によってはネット販売してなくても掘り出し物がある可能性もあるということです。

悪あがきの千代田店

真っ昼間で外はめっちゃあついですが、守山区まで踏み出すことにしました。流石に地下鉄はないので市バスに乗って千代田店へ。バス停のすぐ近くなので帰りも安心です。

肝心の店内ですが、楽器や音響周りが充実してましたが、PC関連はイマイチでした。

でグラボもそれらしきもの見つけましたが、よくわからないメーカーだしNVIDIAGPUですらなさそうでした。

それにしても守山区ぐらいになると車の無料貸出があるんですね。さすが守山区ハードオフ。(ディスってないよ)

血迷って大須

ハードオフを3店舗回りましたが、もうこの時点でハードオフには期待しておらずしかも長距離移動で結構時間がかかったので、回れてもあと1店舗行くか大須の他の店舗を回るかで悩みました。

ざっと調べてみると知らないだけで中古パーツ売ってる大須のPCショップが何店舗も見つかったので再び大須に戻りました。

まずは赤門通のグッドウィル。グラボは中古で売ってましたが、やはりゲーミングPCをメインで扱うだけあってGeForceが多めでした。しかも割とスペック高めで安くても1万超えでした。

続いて同じく赤門通のPCコンフル。今までちらっと店先を眺めたことはありましたが店舗が狭く、品数そんなにない印象でした。

ただ中古を専門に扱っているっぽいし、一度見てみる価値はあるだろうと思い物色してみました。

これが当たりでしたよ!!

ガラスケースにある僅かなPCパーツの中に1万円切ってるグラボが2つありました。一つはQuadro K2200、もう一つはQuadro P400。

はい、まさかのQuadroが2種類在庫にありました。狭い店舗だと思ってましたが、穴場でしたね。

でこの2つの肝心なCapabilityですが、K2200は5.0、P400は6.1でした。

K2200はK2000の上位互換とも言えるぐらい見た目は全く同じでした。

P400はK2000よりもコンパクトな見た目だけど値段が高い(K2200が7700円でP400が8800円)のでどっちにするか迷いました。

迷った結果Capabilityも高くて発売時期が新しいP400を買うことにしました。

長い目で見たときにCapability高いほうが長くつかえるかなと思ったのと、何より見た目が結構きれいだったんですよね。

ただ、K2200はK2000と同様に4GBに対してP400はメモリーが2GBなので重めの学習でのメモリーエラーが心配でした(個人の遊び程度なのでそんなに学習させることあるかわかりませんがw)

何がともあれ補助電源を使わずにディープラーニングに使えそうなグラボを今度こそ手に入れることができてよかったです。

そして何気にPCコンフルも大須の店舗なので、大須の店舗で売ってたパーツだけでPCを組むことができました!

動作確認

というわけで早速持ち帰って搭載しました。K2000も大概ですが、もっとスッキリしましたね。

f:id:KMiura:20210725234641p:plain

ちなみに前回上げ忘れましたが、K2000のときはこんな感じです。アングル違うのは勘弁してほしいですが、ファンの部分が明らかに小さく収まってますね。

f:id:KMiura:20210725234910p:plain

ドライバーについてはもうすでにあたっていたので、前回同様glmark-es2でベンチマークを取ってみました(相変わらずglmark2の方はエラーが出ました)

結果はこちら。

 =======================================================
    glmark2 2021.02
=======================================================
    OpenGL Information
    GL_VENDOR:     NVIDIA Corporation
    GL_RENDERER:   Quadro P400/PCIe/SSE2
    GL_VERSION:    OpenGL ES 3.2 NVIDIA 470.57.02
=======================================================
[build] use-vbo=false: FPS: 4409 FrameTime: 0.227 ms
[build] use-vbo=true: FPS: 5599 FrameTime: 0.179 ms
[texture] texture-filter=nearest: FPS: 4631 FrameTime: 0.216 ms
[texture] texture-filter=linear: FPS: 4527 FrameTime: 0.221 ms
[texture] texture-filter=mipmap: FPS: 4870 FrameTime: 0.205 ms
[shading] shading=gouraud: FPS: 4376 FrameTime: 0.229 ms
[shading] shading=blinn-phong-inf: FPS: 4302 FrameTime: 0.232 ms
[shading] shading=phong: FPS: 4183 FrameTime: 0.239 ms
[shading] shading=cel: FPS: 4430 FrameTime: 0.226 ms
[bump] bump-render=high-poly: FPS: 3206 FrameTime: 0.312 ms
[bump] bump-render=normals: FPS: 5674 FrameTime: 0.176 ms
[bump] bump-render=height: FPS: 5541 FrameTime: 0.180 ms
[effect2d] kernel=0,1,0;1,-4,1;0,1,0;: FPS: 3285 FrameTime: 0.304 ms
[effect2d] kernel=1,1,1,1,1;1,1,1,1,1;1,1,1,1,1;: FPS: 1807 FrameTime: 0.553 ms
[pulsar] light=false:quads=5:texture=false: FPS: 5238 FrameTime: 0.191 ms
[desktop] blur-radius=5:effect=blur:passes=1:separable=true:windows=4: FPS: 1596 FrameTime: 0.627 ms
[desktop] effect=shadow:windows=4: FPS: 2720 FrameTime: 0.368 ms
[buffer] columns=200:interleave=false:update-dispersion=0.9:update-fraction=0.5:update-method=map: FPS: 929 FrameTime: 1.076 ms
[buffer] columns=200:interleave=false:update-dispersion=0.9:update-fraction=0.5:update-method=subdata: FPS: 1072 FrameTime: 0.933 ms
[buffer] columns=200:interleave=true:update-dispersion=0.9:update-fraction=0.5:update-method=map: FPS: 1156 FrameTime: 0.865 ms
[ideas] speed=duration: FPS: 4560 FrameTime: 0.219 ms
[jellyfish] <default>: FPS: 2821 FrameTime: 0.354 ms
[terrain] <default>: FPS: 299 FrameTime: 3.344 ms
[shadow] <default>: FPS: 3464 FrameTime: 0.289 ms
[refract] <default>: FPS: 706 FrameTime: 1.416 ms
[conditionals] fragment-steps=0:vertex-steps=0: FPS: 5144 FrameTime: 0.194 ms
[conditionals] fragment-steps=5:vertex-steps=0: FPS: 4573 FrameTime: 0.219 ms
[conditionals] fragment-steps=0:vertex-steps=5: FPS: 4955 FrameTime: 0.202 ms
[function] fragment-complexity=low:fragment-steps=5: FPS: 4663 FrameTime: 0.214 ms
[function] fragment-complexity=medium:fragment-steps=5: FPS: 4262 FrameTime: 0.235 ms
[loop] fragment-loop=false:fragment-steps=5:vertex-steps=5: FPS: 4756 FrameTime: 0.210 ms
[loop] fragment-steps=5:fragment-uniform=false:vertex-steps=5: FPS: 4788 FrameTime: 0.209 ms
[loop] fragment-steps=5:fragment-uniform=true:vertex-steps=5: FPS: 4388 FrameTime: 0.228 ms
=======================================================
                                  glmark2 Score: 3725 
=======================================================

小さいから性能出ないのではと侮っていましたが、結構上がってますね。

そういえばK2000のときよりもなんとなく画質が良くなってる気がしますね。

ディープラーニングのライブラリをインストール

そして、最後にTensorflowとPyTorchがpipでインストールしてGPU認識するか確認しました。

結果はどちらも問題なく認識しました!

これでエラーになってたらCudaのセットアップからし直すことになってましたが、その心配はいらなかったです。

ひとまずこれで自作PCの構成は落ち着いたので学生時代にやってた実験を改めてやってみようと思います。

NVIDIA Quadro K2000を手に入れた

自作PCに何かグラボを入れたいと思い、GTS250を装着しました。

supernove.hatenadiary.jp

それで色々調べてみるとこのグラボ、CUDA Toolkitは使えても6.5までのバージョンしか対応してないっぽいです。

おまけにこのグラボ2009年に製造されたようで起動時に一瞬以下の画面が表示されました。

f:id:KMiura:20210722232911p:plain

ディープラーニングをするには最低7.5以上は必要ですのでこれだと難しいなと断念することに…

でなにかいいグラボないかと仕事終わりに伏見のハードオフで物色をしていたらNVIDIA Quadro K2000を見つけました。

www.elsa-jp.co.jp

Quadroはゲーム向けではなく業務用のCAD向けでOpen GLに強いモデルらしいです。

Quadro K2000は2013年頃に発売されているのでそこそこ古いですが、ディープラーニングに最適なグラボとしても紹介されるのでお試しで買ってみました。価格は中古で4400円(税込)でした。今の中古相場だと7000円近くなのでまあまあといったところでしょう。

ちなみに店舗にはGTXも箱入りでありましたが8800円もしたので迷いましたが、年代的に近かったので安かったQuadroを選びました。久々にハードオフ行きましたけど、相変わらず価格設定ガバガバですよね。

取り付け

早速自作PCに取り付けました。

GTS250よりも薄いのと補助電源がいらないので、だいぶ見た目がスッキリしました。

接続はDVIからやってみましたが、問題なく動作して画面も出力しました。ご覧の通りデバイスも認識してます

01:00.0 VGA compatible controller: NVIDIA Corporation GK107GL [Quadro K2000] (rev a1)
01:00.1 Audio device: NVIDIA Corporation GK107 HDMI Audio Controller (rev a1)

ドライバーのインストール

バイスは認識しましたが、Ubuntuを使っているのでグラボのドライバーは手動で当てる必要があります。

というわけでドライバーをインストールします。

普通はコマンドラインをつかいますが、UbuntuであればGUIでインストールできます。

ソフトウェアとアップデート→追加のドライバを開くとドライバーのインストール画面が開きます。

するとグラボのドライバーが自動検索で出力されます。

f:id:KMiura:20210723092540p:plain

そこから検証済みと表示されているドライバーをインストールしておきます。このドライバーがどうやら最新版みたいです。

ドライバーを選択したら変更の適用をクリックします。するとインストールをしてくれて、終わるとボタンがグレー表示になります。

f:id:KMiura:20210723091407p:plain

一度再起動をして、設定→このシステムについてをクリックして以下のようにグラボのモデル名が表示されたらドライバーは正常にあたっています。

f:id:KMiura:20210723094040p:plain

ベンチマーク

グラボ取り付けたのでベンチマークをやってみます。

Linuxベンチマークはあまりよく知らない(というかベンチマーク自体やったことないw)のであれこれ調べてみましたが、フリーで手軽に試せるソフトとしてGLmark2を見つけました。

インストールは以下のコマンドでできます。

sudo apt install glmark2

実行はglamark2をコマンドで実行するだけです。

実はドライバーがあたってないときに先に動かしてみましたが、その時のスコアは500程度でした(実行結果は取り忘れました)。おそらくintelの内蔵グラフィックを使っているからだと思います。

調べてみると、GLmark2のスコア一覧が出てきましたが、ビンゴでした。GLmark2のバージョンが違うのでなんとも言えませんがそんな大幅に変わることはないと思うので目安としてはちょうどいいでしょう。

openbenchmarking.org

で改めてGPUのドライバーを当ててサイド実行してみました。

ところがこんなエラーが出ました。

Error: Failed to add fragment shader from file None:
Error:   0(15) : error C0000: syntax error, unexpected identifier, expecting "::" at token "highp"
Error: 0(36) : warning C1503: undefined variable "TextureCoord"
Error: 0(37) : warning C1503: undefined variable "TextureCoord"
Error: 0(38) : warning C1503: undefined variable "TextureCoord"

ググってみましたが、同じような問題を抱えている人もいましたが解決はできませんでした。

あれこれ模索していたらglmark2-es2というOpen GL ES2のパフォーマンスを測定するソフトがあるようなので、ダメ元でインストールしてみました。

sudo apt install glmark2-es2

実行は同様にglmark2-es2と実行するだけです。

するとエラーはなく、以下の実行結果がでました。

=======================================================
    glmark2 2021.02
=======================================================
    OpenGL Information
    GL_VENDOR:     NVIDIA Corporation
    GL_RENDERER:   Quadro K2000/PCIe/SSE2
    GL_VERSION:    OpenGL ES 3.2 NVIDIA 470.57.02
=======================================================
[build] use-vbo=false: FPS: 3491 FrameTime: 0.286 ms
[build] use-vbo=true: FPS: 4435 FrameTime: 0.225 ms
[texture] texture-filter=nearest: FPS: 4044 FrameTime: 0.247 ms
[texture] texture-filter=linear: FPS: 3999 FrameTime: 0.250 ms
[texture] texture-filter=mipmap: FPS: 4088 FrameTime: 0.245 ms
[shading] shading=gouraud: FPS: 3760 FrameTime: 0.266 ms
[shading] shading=blinn-phong-inf: FPS: 3782 FrameTime: 0.264 ms
[shading] shading=phong: FPS: 3609 FrameTime: 0.277 ms
[shading] shading=cel: FPS: 3618 FrameTime: 0.276 ms
[bump] bump-render=high-poly: FPS: 2599 FrameTime: 0.385 ms
[bump] bump-render=normals: FPS: 4396 FrameTime: 0.227 ms
[bump] bump-render=height: FPS: 4293 FrameTime: 0.233 ms
[effect2d] kernel=0,1,0;1,-4,1;0,1,0;: FPS: 3099 FrameTime: 0.323 ms
[effect2d] kernel=1,1,1,1,1;1,1,1,1,1;1,1,1,1,1;: FPS: 1996 FrameTime: 0.501 ms
[pulsar] light=false:quads=5:texture=false: FPS: 3842 FrameTime: 0.260 ms
[desktop] blur-radius=5:effect=blur:passes=1:separable=true:windows=4: FPS: 1483 FrameTime: 0.674 ms
[desktop] effect=shadow:windows=4: FPS: 2316 FrameTime: 0.432 ms
[buffer] columns=200:interleave=false:update-dispersion=0.9:update-fraction=0.5:update-method=map: FPS: 1098 FrameTime: 0.911 ms
[buffer] columns=200:interleave=false:update-dispersion=0.9:update-fraction=0.5:update-method=subdata: FPS: 1318 FrameTime: 0.759 ms
[buffer] columns=200:interleave=true:update-dispersion=0.9:update-fraction=0.5:update-method=map: FPS: 1265 FrameTime: 0.791 ms
[ideas] speed=duration: FPS: 3391 FrameTime: 0.295 ms
[jellyfish] <default>: FPS: 2290 FrameTime: 0.437 ms
[terrain] <default>: FPS: 335 FrameTime: 2.985 ms
[shadow] <default>: FPS: 3094 FrameTime: 0.323 ms
[refract] <default>: FPS: 837 FrameTime: 1.195 ms
[conditionals] fragment-steps=0:vertex-steps=0: FPS: 3982 FrameTime: 0.251 ms
[conditionals] fragment-steps=5:vertex-steps=0: FPS: 3503 FrameTime: 0.285 ms
[conditionals] fragment-steps=0:vertex-steps=5: FPS: 3979 FrameTime: 0.251 ms
[function] fragment-complexity=low:fragment-steps=5: FPS: 3976 FrameTime: 0.252 ms
[function] fragment-complexity=medium:fragment-steps=5: FPS: 3500 FrameTime: 0.286 ms
[loop] fragment-loop=false:fragment-steps=5:vertex-steps=5: FPS: 3894 FrameTime: 0.257 ms
[loop] fragment-steps=5:fragment-uniform=false:vertex-steps=5: FPS: 3947 FrameTime: 0.253 ms
[loop] fragment-steps=5:fragment-uniform=true:vertex-steps=5: FPS: 3756 FrameTime: 0.266 ms
=======================================================
                                  glmark2 Score: 3121 
=======================================================

うん、明らかにスコアが上がりました。ちゃんとGPU使えていますね。

先程のスコア一覧で見ると大体中間ぐらいのスペックですね。

openbenchmarking.org

同じNVIDIA製品だとNVIDIA Quadro P2000のスコアと近いです。

多分これなら安定して3Dのシュミレータも動かせると思います。

というわけで次回からはROSを久々に触ってみようと思います。

自作PCにUbuntuを入れてみた

前回は無事に自作PCをOS入れる1歩手前の状態まで完成させました。

supernove.hatenadiary.jp

supernove.hatenadiary.jp

なので、今回はこのPCにOSを入れていきたいと思います。

で入れるOSですが、WindowsMacはそれぞれ現役のマシンを持っているので、このPCにはLinuxを入れようと思います。

Windowsだとライセンス料がどうとかうるさそうですが、Linuxならタダですw。

Linuxと言っても色んな種類がありますが、今回は学生時代に使ってたUbuntuを久々にデスクトップで使おうと思います。

で、GPU入れたことだしROS突っ込んでGazebo動かしたり、Deeplearningぶん回したいわけです(1度に2つやるのは贅沢かな…)。

というわけでセットアップやってみます。

イメージディスクを作成

まずはUbuntuのインストールディスクを作成します。

昔はCDにイメージを焼いていましたが、USBフラッシュメモリを使っても作成できます。

パウのTwitterキャンペーンでツイートするとUSBフラッシュメモリがもらえるのですが、なんとそれが32GBもあります!(大学のノベルティはたった4GBしかないちゃっちいやつだったのでなお感動w)

丁度いいのでこのUSBフラッシュメモリにイメージを焼いていきます。

ちなみにUSBであれば最低4GBあれば大丈夫そうです(つまり大学のちゃっちいUSBでも大丈夫w)

以下のサイトから【Ubuntu 20.04.2.0 LTS】のイメージをダウンロードします。

jp.ubuntu.com

ダウンロードしたイメージをUSBに書き込みます。

書き込みの方法はいろいろありますが、僕はEtcherを使いました。

www.balena.io

USBから起動

USBイメージをインストールするPCのUSB端子に指してから起動します。

f:id:KMiura:20210720005901p:plain

僕のやつは自動でUSBから起動してくれましたが、デュアルブートとかでUSBから起動しないときは起動直後にBIOSを立ち上げて、USBから起動するように設定をいじるといいです。(昔それでデュアルブートした気がします )

USBから起動すると以下のメニューが出ます。OSが正常に起動するか確認するためにUbuntuを試したいときはTry Ubuntuを選びますし、とにかくインストールしたければInstall Ubuntuを選択します。

インストール

それではHDDにUbuntuをインストールします。

言語は日本語設定にしてあとは画面の指示にしたがってインストールするだけです。

必要な設定を終えるとインストール画面になります。

いやー、この画面だけでも懐かしいw。「ファイルのコピーは間もなく完了します。」って言いながら結構時間かかるんですよねw。

インストールが完了すると、HDDからUbuntuを起動するようになります。

そのときにインストールに使ったUSBが刺さっていると、抜くように言われるのでそのまま引っこ抜きます。

そして以下の画面が表示されれば無事にUbuntuはインストール完了です。

昔は結構時間かかっていましたが、今やってみたら意外と簡単ですね。

f:id:KMiura:20210720011249p:plain

おまけ:日本語入力の切り替え

日本語入力の切り替えは半角/全角キーを使えばいいですが、僕はUSキーを使っているので、半角/全角キーはないわけです。

そこで代わりのキー入力をCtrl + Spaceに変更します。

設定を開いて、地域と言語から入力ソースで日本語入力(Mozc)の歯車マークを選択します。

f:id:KMiura:20210720013109p:plain

このとき、日本語入力それ以外の入力ソースが登録されている場合は削除します。

キー設定の選択から編集をクリックします。

f:id:KMiura:20210720013808p:plain

編集画面でCtrl + Spaceになっている箇所を割り当てられていないキーに変更するか、必要がなければその入力を削除してもいいです。

その後、hankaku/zenkakuになっている箇所をすべてCtrl + Spaceに変更します。

f:id:KMiura:20210720014308p:plain

設定を適用したらログアウトするか再起動すると設定が反映されます。

これでUSキーでも快適に日本語入力ができるようになります。

ジャンクや中古パーツで自作PCを作ってみた-その2-

今回は以前取り組んだ初の自作PCづくりの続きです。

supernove.hatenadiary.jp

前回は最小構成でBIOSを起動できることを確認しました。

なので今回はPCケースを買って前回接続しなかったパーツも含めてOSを入れれば動かせる状態にパソコンを完成させます。

PCケースの物色

例のごとく大須のパウで良さげなPCケースがないか探しました。

探すといい感じのPCケースが見つかりました。写真では分からないですが、実はフロントのカバーが1箇所空いていたので、ついでにジャンクで売ってたDVDドライブも買いました。

せっかくデスクトップ組み立てるならDVDドライブはあって困ることはないですね。むしろあると便利ですね。

ちなみに買ったケースはCooler MasterのElite 430です。

ゲーミングPC向けなのかサイドパネルが透けていて更に光るファンが付いているので、動かすとなんかかっこいいPCになりそうなのでその期待を込めて買ってみました。

まぁジャンクなので傷だらけでボロボロですが、値段は300円なので文句はありません。

www.coolermaster.com

配送は800円で今回買ったケースよりも高くなるので流石に気が引けました…

なので店員さんが、持ち帰り用の紐と持ち手を用意してくれたので縛り付けてなんとか手で持っていきました。

途中で紐がゆるくなってずり落ちないか心配でしたが、落ちることはなく無事に家までたどりつきました。

組み立て

前回のセッティングから電源を取り外してマザボをケースに取り付けます。

そしてバックパネルがついていたので先にとりつけています。

f:id:KMiura:20210718170351p:plain

六角スペーサーもついていたのでスムーズに行くと思いましたが取り付けに必要なネジがなくて困りました。

しかもそれ以外のパーツの取付けに必要なネジもなさそうなので用意します。

というわけでAmazonでネジが一式入ったセットを見つけたので購入しました。

このキットにはブラシとドライバーもセットになっていたのでPCの組み立てに困らないでしょう。

このキットのネジとフェルトのワッシャーを使って固定したのですが、スペーサーのネジ穴とマザボのネジ穴が少しずれていたのでなんとか力技で押さえつけました。

これで正しいのかはよくわからないけど壊れなかったので多分大丈夫なはず…

f:id:KMiura:20210718182604j:plain

続いてケースと一緒に買ったDVDドライブを取り付けました。

f:id:KMiura:20210718184442p:plain

見ての通り接続はSATAなのでここはパーツに困ることはありません。

何しろSATAケーブルはジャンクセールで大量に仕入れましたからねw。

あとはケースのフロントパネルの配線をしました。

f:id:KMiura:20210718185951p:plain

これはマザボのドキュメントを参考にしました。

www.manualslib.com

あとは、電源ケーブルを前回同様各種に配線したところで一旦動作確認、と思ったら動作確認で使ってた電源だと明らかにケーブルの長さが足りません…

12ピンはギリ取り付けましたが、4ピンが全く届きません…

これは詰んだと思いましたが、以前のジャンクセールでもう一個電源買ってたので交換してみました。

すると長さが十分で無事に必要な配線ができました!いやぁ良かった…

f:id:KMiura:20210718190802p:plain

ここで一旦動作確認。無事にBIOS開けました。

そしてフロントパネルのUSBにキーボードを接続するとちゃんと認識しましたし、画像のように取り付けたDVDドライブも認識できているので大丈夫そうです。

f:id:KMiura:20210718191334p:plain

グラボとHDDの取り付け

さて、これでHDDをつければパソコンとして動かせますが今回は運良くグラボが手に入ったのでそれも取り付けます。

使うグラボは、NvidiaのGTS250の1GBです。結構古いですが、今でも普通に使えそうなスペックですしCudaにも対応してそうです。

取り付ける前に裏の金属カバーをぶち抜きました。上2つが今回ぶち抜いたやつで下の2つは買ったときにすでにぶち抜かれていました。

ぶち抜いて取り付けようとしたら、グラボが取り付けられなくて悩みました。

このようにネジで固定しようにもできません…

f:id:KMiura:20210718193424j:plain

理由はグラボ側のパネルの金具が少し反ってたせいでケース側の口に引っかかっていただけでした。

なので、多少強引ですが引っかからないように金具を少し曲げてみたら無事に奥まで刺さりました。

そしてネジの固定も余裕でした。

f:id:KMiura:20210718193243p:plain

ここでGTS250には6ピンの補助電源が必要です。が、今回使っている電源には6ピン端子がありません。代わりにSATA電源の端子はまだ余っています。

というわけでSATAから6ピン電源への変換ケーブルをまたまたAmazonで追加発注しました。

接続は問題なくできたので、多分動くはずです。

最後にHDDも取り付けて完成です!

少々配線汚いですが、これでもきれいに束ねたほうです…

f:id:KMiura:20210718193815p:plain

最後の動作確認

マザボではHDMI接続ができませんでしたが、グラボのおかげでHDMI接続ができるようになりました。

そして画面もしっかり映りました。(解像度がおかしい気もしますが、多分ドライバーを当てれば解決するかもしれません)

f:id:KMiura:20210718194136p:plain

HDD、DVDドライブもご覧の通り認識できているので安心しました。(ST31000528ASがHDDの型番になります)

f:id:KMiura:20210718195346p:plain

まとめ

というわけで今回はジャンク・中古のパーツで自作PCを作りました。

途中動かなくて焦りましたが、大体は配線ミスや接触不良だったので良かったです。

特にジャンクパーツは動くかどうかの確認が明記されていないのでギャンブルチックでしたが、今の所は動作に問題なさそうで良かったです。

初めてにしてはうまく行った方ではないでしょうか。

ただ、現状はPCのパーツを組みこんだだけで、まだOSをインストールしてません。

なので、次回はOSをインストールしてPCが起動できるかどうかを検証します。

AWSでRaspberry Piの自動更新システムを構築してみた

その昔学生時代にRaspberry Piを使ったプロトタイピングをクラウドソーシングで引き受けていました。

あまり細かく言えませんがざっくりいうとクラウド連携をする車載システムの開発です。

とりあえずひとしきり必要なプログラムを開発し終わったときに「じゃあそのプログラムになにか修正が入ったらクラウドにアップロードして稼働中のRaspberry Piのプログラムを更新できるようにしてほしい」

というんです。そんなのやったことないよ…

「そもそも当時はRaspberry Piのプログラムを自動実行したことないのでそこから調べないといけないし無理だよな…」って考えていたらいつの間にか契約が切れました。

まぁ依頼主の態度も気に入らなかったので結果オーライといったところでしょうw。

あれから数年経った今ならある程度知識が身についたしそれぐらい簡単にできるよなとふと思い立ちました。

というわけで今回はAWSを使ってRaspberry Piで動かしてるプログラムを自動更新するシステムを構築してみたのでその記録です。

なお、今回はどんな感じで作ったのか流れをざっくりまとめるだけなので細かい手順は自分でググってもらえると🙏(AWSは日々UIが変わるので細かい手順書くのやめた)

用意するもの

システム構成

大まかなシステム構成はこんな感じです。

まず、手元でプログラムを修正したら修正したソースコードをS3にアップロードします。ユーザーが行う作業はこれだけです。

あとはコードがアップロードされたことをトリガーにLambdaを立ち上げてAWS IoT経由で通知を行います。

その後Rapsberry PiでS3からコードをダウンロードしてプログラムの更新を行うという流れです。

f:id:KMiura:20210712231541p:plain

AWS IoTでの作業

モノ(AWS IoT上でのインスタンスみたいなやつ)を作成し、ポリシーも作成します。

モノの名前はraspi_update_callとします。

ポリシーは以下の設定でOKです。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iot:*",
      "Resource": "*"
    }
  ]
}

ポリシーと紐付けた証明書を作成し、証明書をダウンロードします。

Raspberry Piと通信をするために必要なファイルはAmazonRootCA1.pem【証明書ID】-certificate.pem.crt【証明書ID】-private.pem.keyの3つです。

またAWS IoTのトップ画面の設定からデバイスデータエンドポイントをメモしておきます。

細かい作業はこの記事がわかりやすいです。

dev.classmethod.jp

S3の用意

S3バケットを用意します。バケット名はraspi-codesとします。

IAMの作成

ついでにIAMも用意します。以下の設定をしたポリシーを用意します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListAllMyBuckets"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::raspi-codes",
                "arn:aws:s3:::raspi-codes/*"
            ]
        }
    ]
}

SDKの認証で使うため、IAMユーザーを作成するときはプログラムによるアクセスを選択します。

後の設定はデフォルトのままでOKです。IAMユーザーを作成したらアクセスキーIDとシークレットアクセスキーをメモしておきます。

Lambdaの作成

S3を連携するためのLambda関数を作成します。

設計図タブをクリックしてs3-get-object-pythonを選択します。

f:id:KMiura:20210712235631p:plain

ポリシーのアタッチ

Lambda関数の設定→アクセス権限から実行ロールで表示されているロールの編集ボタンをクリックします。

そこから以下の内容のポリシーを新たに追加してLambdaの実行ロールにアタッチします。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "iot:Publish",
            "Resource": "*"
        }
    ]
}

コードの作成

Lambdaは以下のソースコードに書き換えます。

import json
import urllib.parse
import boto3

print('Loading function')

s3 = boto3.client('s3')
iot = boto3.client('iot-data', region_name="ap-northeast-1")


def lambda_handler(event, context):
    # print("Received event: " + json.dumps(event, indent=2))

    # Get the object from the event and show its content type
    bucket = event['Records'][0]['s3']['bucket']['name']
    key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
    try:
        print(key)
        iot.publish(
            topic="raspberry_pi/msg",
            qos=0,
            payload=key
        )
        return 'Success'
    except Exception as e:
        print(e)
        print('publish Failed')
        raise e

Raspberry Piでの作業

ここからRaspberry Piでの作業です。

SDKCLIをインストール

SDKのインストール

S3の接続に使うboto3とAWS IoTのSDKをインストールします。

sudo pip3 install boto3 AWSIoTPythonSDK

CLIのインストール

AWSCLIツールをインストールします。

sudo pip3 install awscli

Cofigureを設定

aws configure

access key IDとsecret access key、リージョンを設定します。

リージョンは使用するS3のリージョンを設定します。

プログラムを更新するためのコード

以下のレポジトリのsample/basicPubSub/basicPubSub.pyを参考にS3から受け取った通知に合わせてプログラムを更新するコードを作成します。

github.com

以下のソースコードと同じディレクトリ上にcertディレクトリを用意して、certディレクトリにAWS IoTの作業のときにダウンロードした3つの認証ファイルを保存します。

hostの値は先程メモしたデバイスデータエンドポイントに書き換えます。

ファイル名は、subscriber.pyとします。

'''
/*
 * Copyright 2010-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */
 '''

from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient
import boto3
import subprocess
import logging
import time


s3 = boto3.resource('s3')
bucket = s3.Bucket('raspi-codes')

# Custom MQTT message callback
def customCallback(client, userdata, message):
    msg = message.payload.decode()
    print("Received a new message: ")
    print(msg)
    print("from topic: ")
    print(message.topic)
    print("--------------\n\n")
    
    if msg == 'disp_7seg.py':
        updateCode()

def updateCode():
    file_name = '/home/pi/disp_7seg.py'
    try:
        subprocess.call(['rm', file_name])
        bucket.download_file('disp_7seg.py', file_name)
        subprocess.call(['sudo', 'chmod', '755', file_name])
        subprocess.call(['sudo', 'systemctl', 'restart', 'disp_7seg.service'])
        print('Success')
    except Exception as e:
        print('Failed')
        print(e)


host = 'yourhost.iot.ap-northeast-1.amazonaws.com'
rootCAPath = 'cert/AmazonRootCA1.pem'
certificatePath = 'cert/certificate.pem.crt'
privateKeyPath = 'cert/private.pem.key'


clientId = 'raspi_update_call'
topic = 'raspberry_pi/msg'
port = 8883

# Configure logging
logger = logging.getLogger("AWSIoTPythonSDK.core")
logger.setLevel(logging.DEBUG)
streamHandler = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
streamHandler.setFormatter(formatter)
logger.addHandler(streamHandler)

# Init AWSIoTMQTTClient
myAWSIoTMQTTClient = AWSIoTMQTTClient(clientId)
myAWSIoTMQTTClient.configureEndpoint(host, port)
myAWSIoTMQTTClient.configureCredentials(rootCAPath, privateKeyPath, certificatePath)

# AWSIoTMQTTClient connection configuration
myAWSIoTMQTTClient.configureAutoReconnectBackoffTime(1, 32, 20)
myAWSIoTMQTTClient.configureOfflinePublishQueueing(-1)  # Infinite offline Publish queueing
myAWSIoTMQTTClient.configureDrainingFrequency(2)  # Draining: 2 Hz
myAWSIoTMQTTClient.configureConnectDisconnectTimeout(10)  # 10 sec
myAWSIoTMQTTClient.configureMQTTOperationTimeout(5)  # 5 sec

# Connect and subscribe to AWS IoT
myAWSIoTMQTTClient.connect()
myAWSIoTMQTTClient.subscribe(topic, 1, customCallback)
time.sleep(2)

# Publish to the same topic in a loop forever
while True:
    time.sleep(1)

7セグLEDを表示するプログラム

Pythonコード

以下の記事を参考にコードを作成します。

denkisekkeijin.com

使用する7セグLEDはアノードコモンなのでそれを考慮して以下のコードを保存します。

ファイル名はdisp_7seg.pyです。保存先は/home/piです。

#!/usr/bin/env python3
import RPi.GPIO as GPIO
GPIO.cleanup()

GPIO.setmode(GPIO.BCM)
GPIO.setup(23, GPIO.OUT)
GPIO.setup(24, GPIO.OUT)
GPIO.setup(25, GPIO.OUT)
GPIO.setup(12, GPIO.OUT)
GPIO.setup(16, GPIO.OUT)
GPIO.setup(20, GPIO.OUT)
GPIO.setup(21, GPIO.OUT)

z_0 = [1, 1, 1, 0, 1, 1, 1]
z_1 = [1, 0, 0, 0, 1, 0, 0]
z_2 = [1, 1, 0, 1, 0, 1, 1]
z_3 = [1, 1, 0, 1, 1, 1, 0]
z_4 = [1, 0, 1, 1, 1, 0, 0]
z_5 = [0, 1, 1, 1, 1, 1, 0]
z_6 = [0, 1, 1, 1, 1, 1, 1]
z_7 = [1, 1, 0, 0, 1, 0, 0]
z_8 = [1, 1, 1, 1, 1, 1, 1]
z_9 = [1, 1, 1, 1, 1, 0, 0]

numbers = [z_0, z_1, z_2, z_3, z_4, z_5, z_6, z_7, z_8, z_9]


def set_segment(s_or, s_om, s_ol, s_mm, s_ur, s_um, s_ul):
    GPIO.output(23, GPIO.HIGH if s_or == 0 else GPIO.LOW)
    GPIO.output(24, GPIO.HIGH if s_om == 0 else GPIO.LOW)
    GPIO.output(25, GPIO.HIGH if s_ol == 0 else GPIO.LOW)
    GPIO.output(12, GPIO.HIGH if s_mm == 0 else GPIO.LOW)
    GPIO.output(16, GPIO.HIGH if s_ur == 0 else GPIO.LOW)
    GPIO.output(20, GPIO.HIGH if s_um == 0 else GPIO.LOW)
    GPIO.output(21, GPIO.HIGH if s_ul == 0 else GPIO.LOW)


while True:
    try:
        set_segment(*z_0)
    except KeyboardInterrupt:
        break

GPIO.cleanup()

配線

Raspberry Piと7セグLEDの配線は以下の図のとおりです。

f:id:KMiura:20210713034645p:plain

Serviceファイル

プログラムを実行するときにはsystemctlを使います。

そこで、以下のserviceファイルをdisp_7seg.serviceで保存します。

保存先は/etc/systemd/systemです。

[Unit]
Description=Display 7seg LED

[Service]
ExecStart=/home/pi/disp_7seg.py
Environment=PYTHONUNBUFFERED=1
Restart=on-failure

[Install]
WantedBy=default.target

動作確認

いよいよ動作確認です。

7セグLEDを表示するプログラムを起動

はじめに以下のコマンドでdisp_7seg.pyに対して実行権限を変更します。

sudo chmod 755 ~/disp_7seg.py

次に以下のコマンドでデーモンを再読み込みして7セグLEDを起動します。

sudo systemctl daemon-reload
sudo systemctl start disp_7seg.service

実行後に以下のように7セグLEDで0を表示したらプログラムは正常に動作しています。

f:id:KMiura:20210713031742p:plain

プログラムを更新するコードを起動

subscriber.pyの保存先ディレクトリ上で以下のコマンドでプログラムを実行します。

python3 subscriber.py

今回はプログラムが更新する様子をデモで見せるためにserviceファイルを用意しませんでしたが、disp_7seg.pyと同様にsystemctlを用意して自動起動してもいいと思います。

S3にソースコードをアップロードする

disp_7seg.pyになにか修正を加えてS3バケットにアップロードしてみます。今回は、以下の数字の1を表示するプログラムに書き換えます。

#!/usr/bin/env python3
import RPi.GPIO as GPIO
GPIO.cleanup()

GPIO.setmode(GPIO.BCM)
GPIO.setup(23, GPIO.OUT)
GPIO.setup(24, GPIO.OUT)
GPIO.setup(25, GPIO.OUT)
GPIO.setup(12, GPIO.OUT)
GPIO.setup(16, GPIO.OUT)
GPIO.setup(20, GPIO.OUT)
GPIO.setup(21, GPIO.OUT)

z_0 = [1, 1, 1, 0, 1, 1, 1]
z_1 = [1, 0, 0, 0, 1, 0, 0]
z_2 = [1, 1, 0, 1, 0, 1, 1]
z_3 = [1, 1, 0, 1, 1, 1, 0]
z_4 = [1, 0, 1, 1, 1, 0, 0]
z_5 = [0, 1, 1, 1, 1, 1, 0]
z_6 = [0, 1, 1, 1, 1, 1, 1]
z_7 = [1, 1, 0, 0, 1, 0, 0]
z_8 = [1, 1, 1, 1, 1, 1, 1]
z_9 = [1, 1, 1, 1, 1, 0, 0]

numbers = [z_0, z_1, z_2, z_3, z_4, z_5, z_6, z_7, z_8, z_9]


def set_segment(s_or, s_om, s_ol, s_mm, s_ur, s_um, s_ul):
    GPIO.output(23, GPIO.HIGH if s_or == 0 else GPIO.LOW)
    GPIO.output(24, GPIO.HIGH if s_om == 0 else GPIO.LOW)
    GPIO.output(25, GPIO.HIGH if s_ol == 0 else GPIO.LOW)
    GPIO.output(12, GPIO.HIGH if s_mm == 0 else GPIO.LOW)
    GPIO.output(16, GPIO.HIGH if s_ur == 0 else GPIO.LOW)
    GPIO.output(20, GPIO.HIGH if s_um == 0 else GPIO.LOW)
    GPIO.output(21, GPIO.HIGH if s_ul == 0 else GPIO.LOW)


while True:
    try:
        set_segment(*z_1)
    except KeyboardInterrupt:
        break

GPIO.cleanup()

起動すると以下の動画のように0と表示していた7セグLEDが1に変わることが確認できたら成功です。


www.youtube.com

まとめ

今回はRaspberry Pi上で動かしているプログラムを自動更新するシステムをAWSで作ってみました。

今までの知識を駆使すれば意外と簡単でした。ただ、AWS IoTのUIが変化していたので過去の記憶を頼りにカンで作業を進めたら思いの外時間がかかりました。

これをあの頃思いついていたら良かったなーw