私のIntel galileoフィジカルコンピューティング開発記録。
Galileoを使って猫の自動給餌装置を構築するぞ
更新履歴
140220 初版 v0.1
140221 概念実証まで執筆完了 v0.2POC(Proof of concept)
140222 概念実証に関する考察 v0.3
140223 回路図追加誤字修正 v0.31
140226 Linux追加 v0.41
140228 エラー発生につき停滞中 版変更なし
140302 利点と欠点追加 v0.5
140303 中間報告 v0.6
140304 中間報告2 v0.7
140306 互換性について現在の状況 v0.8
140307 文章追加、誤字の修正と校正 v0.9
140308 時刻検知スケッチUP v1.0
140309 時刻検知スケッチデバッグ v1.1
140313 誤字修正+筆者風邪 版変更なし
140315 代替案の作成(Galileo側) v1.2
140316 試作機が一応完成 v1.3
140320 試作機本格運用 v1.5
140329 記事のダイエット+試作機のレビュー v1.6
140329 おことわり+目次を追加。 v1.7
140330 本文追加 v1.8
140330 試作機バージョンアップ v2.0
140406 駆動系の小改良 v2.1
140418 最終期限に伴う、今までのまとめと最終報告 v2.2
※おことわり※
- 記事の正確さは勿論のこと、ハードウェア、ソフトウェアには十分注意を払って設計しましたが、全てのGalileoボード、ならびに周辺機器での正常動作を保証するものではありません。丸ごと真似しても動かない、または将来のリビジョン変更によって挙動が変化することも十分にあり得ます。(簡単なスケッチなのでそういった可能性はまずないとは思いますが、念のため)
- また、2014/03/29日現在、試作機完成と記述していますが、最終期限の4/18までに予告なくハード、ソフト面の仕様変更、ならびに更なる改良を行う可能性も十分にあり得ます。(仕様変更や改良を行った場合は改めてこの記事内で変更箇所を追記します)その点を留意して読んでいただければ幸いです。
- 2014/03/30 可変タイマーを実装。
- 2014/04/06 駆動系の小改良。
- 2014/04/18 最終報告と振り返り反省会。
- コメントや突っ込み、ダメ出し、改善案などはお気軽に頁最下部のコメント欄に書き込みいただけると幸いです。
目次
レビュー対象の製品と、それを使用したオリジナル試作機の開発過程をレポートしていく、というこの記事の都合上、本文はとてつもなく長大なものになっています。
以下に簡単な目次を付加しましたので、お読みいただく際に参考にしていただければ幸いです。
- 概要
- 目標
- 開発環境
- ハードウェアオーバービュー
- 互換性比較
- 開発ことはじめ ~環境構築~
- 開発ことはじめ ~Lチカからの概念実証実験~
- 開発ことはじめ ~Linuxで不揮発スケッチ~
- 開発ことはじめ ~トラブル発生~
- 開発ことはじめ ~dmesgから読み解くGalileo解剖~
- 中間報告~今までのまとめ~
- 利点と欠点
- 第一次報告 ~現在の状況~
- 中間報告1 ~モーター動作~
- 中間報告2 ~気が付いたこと~
- 中間報告3 ~メカニカル部~
- 中間報告4 ~スケッチ本体~
- 中間報告5 ~デバッグと路線変更~
- 中間報告6 ~試作機完成までの道のり~
- 工夫した点
- Arduino側のスケッチ
- 起動の様子
- 中間報告7 ~正常運用を目指して~
- 試作機完成 ~試作機の紹介~
- あきえりあ(おまけ) ~賢いタイマーの実装~
- あきえりあ ~センサーモジュール(プロトタイプ)を基板に起こす~
- あきえりあ ~偏る糸巻き機構を改善せよ~
- 編集後記
- 最終報告
- 反省点
- 余談(あとがき)
概要
おはよう諸君、お待たせした←待ってない(^^;)
今回は噂のArduino互換ボード、Intel galileoを使っての開発記録を謎なハイテンションでお届けしたい。
今回の試作機の目標
最終目標はIntel galileoを使って猫の自動給餌装置を作ることだ。
もうちょっと詳しく書くと、06:00と18:00になったら適量の餌を給餌するものだ。
開発環境の紹介
今回、開発の母艦となるPCにはこれを使用した。
デスクトップPCでもよかったのだが、ノートの方がなにかと使い勝手が良いのでこのような構成になったのだ。
開発に使用したソフトはPuTTYとIntel謹製のIntel Galileo Arduino SW 1.5.3 on Windowsを使用した。
14/03/29追記
Arduino IDEとGalileo IDEを同じPCにインストールすると色々とトラブルが発生したため、Arduino側の開発は上記に記したノートPCを、Galileo側の開発についてはデスクトップPCを使用するように環境を変更したことを付記しておく。
ハードウェアオーバービュー
---Overview of Intel® Galileo Evaluation board---
これがGalileo本体である。
Galileoボード本体の大きさについて、わかりやすく言うと、↑に示す写真でいうところの横幅長辺はほぼクレジットカード2倍分の長さ、また縦幅は7.2cm、タブレット菓子のケースの長さとほぼ同じ長さである。
グラサン姿のおっさん(失礼)(訂正:サングラス姿のガリレオでした。)が
"What will you make?キミはこれで何を作る"
と不敵な笑みをサングラスの下に隠している。
否が応でも好奇心をくすぐられるデザインで、早速開発に取り掛かりたくなること請け合いだ。何
箱表面の写真。左のFDはサイズ比較用だ。
ちなみに箱の裏面はこんな感じだ。
さて、箱と基板の紹介が終わったところで、ザックリとこのボードについて今現在把握している分の、簡単なハードウェア構成の説明をさせていただきたい。
まず、スペックを詳細に説明するために、今一度Galileoボードの写真を貼らせていただきたい。
画像をクリックすると大きい画像が表示されるぞ。
画像は500kb近くあるから、回線速度の遅い方は注意されたし。
ボード全景。
基板上に一番目立つ位置に燦然と輝く緑のBGAな石が、Intel謹製のPentium互換SoC、Quark X1000である。
Soc横のサイコロ状の部品はSoCに供給する電源を安定化させるためのコイルである。
スペック的には2.2μHである。
ちなみにこの写真には載っていないが、裏面にも同じサイコロ型のコイルが搭載されている。
つまりPCでいうところのVRMモジュールみたいなものだ。
要するにこのボードはArduinoの皮をかぶった2フェーズ構成のミニPCとも言えなくもないのだ。
相当低消費電力に自信があるのか、はたまた出たとこ勝負的な商品なのかどうか定かではないので筆者にはわかりかねるが、なんとこのSoC、ヒートスプレッダを装着していない。
ダイ剥き出しである。
Quark X1000 SoCは1.4mm×1.4mmの正方形BGAパッケージで基板に実装されている身の回りのもので例示すると、大体PCキーボードのキートップ1文字分の大きさに相当する。
虎の子のダイ自体は5mm×5mmの小さなものである。
これがSoCそのものである。稼働中は手で触れると火傷しそうになるほど熱を発する。
いろいろ調べてみたのだが、このボードの箱にはIntelの電子オルゴールは封入されていなかった。ちょっと残念だが、まあ当初の目標である「猫の自動餌やり機」を作るにあたっては、電子オルゴールなど無くても不都合を感じないため、このまま続行する。
箱の底部には各国の電源事情に合わせたコンセントプラグが封入されている。
電源アダプタ自体も100-250V、50-60Hzの電圧と周波数に対応するグローバル設計だ。
日本のコンセントプラグ実はこのコンセントプラグの規格はアメリカの規格なのだがを装着すると上のようになる。
さて、気になるボード本体の重量は54gだ。
風袋で何gか増えていると思うが、そこは許してほしい。
裸ボードの重量を明記したかったのだが、静電破壊でボードが壊れたら元も子もないのでこのまま撮影した。
I/Oピンのレイアウトは本家Arduinoの1.0に準拠したレイアウトになっている。
より具体的にいうと、Arduino Uno R3と同じシールド設計である。
本家Arduino Unoは名刺より小さいサイズだ。
重ねてみると以下のようになる。
確かにピンの並びが一緒だ。
SoC右横にはRAMが実装されている。なんとMicronのDDR3品である。
しかも128MBx2という豪華な構成だ。
電源コネクタ下部には、SDカードスロットとCypress社製の48Pin SSOPパッケージのEEPROMが実装されている。
互換性とおススメ用途別の比較
さて、Intel galileoと比較用に開発資材として入手したArduino Uno R3
の写真も出そろったので、ここで改めてArduino工作にあたって最も重要と思われる「互換性」について論じていきたい。
以下に簡単な互換性比較表をまとめてみたので、見てほしい。
Arduinoは構造が簡素なゆえ、多少乱暴に扱っても動くという性格のボードだ。
一方、Intel galileoについては、いかにもDOS/V PC/AT互換機然とした基板構成で、これをArduinoとして使うには少々複雑すぎる。
はっきり言ってArduinoのエミュレータを積んだ586パソコンである。少なくとも「初めてのArduino」の選択肢にはあまりお勧めできない。
また、初期搭載されている部品の関係上からか、5V電源入力でしか動かない、チップの交換ができない、シールドの互換性が100%確実でない、などといった弱点がある。
少々乱暴に言うと、前者はオモチャを作るのに適していて、後者は画面のないPCベースの装置制御基板みたいなものを作るのに至適だと感じた。
---本家Arduinoとの比較---
本家Arduinoが
- 8bitのATMEL AVRマイクロコントローラ
- 簡素な受動部品抵抗など
- 能動部品キャパシタ、インダクタ、発振回路
- 最低限のPCとの通信I/F ICモデルによって異なるがUART若しくはUSB
から構成されているのに対し、このIntel galileoボードは
- 32bitCPUと周辺ペリフェラルを内包するSoC
を軸に、
- SDIOストレージ
- 大容量RAM
- EEPROM
- デバッグ用のJTAGピンヘッダ
- RTC維持用の電池ピンヘッダ
- LAN
- USBクライアント
- USBホスト
- UART(RS-232C/USB)
- mini PCI Express slot
を搭載している。赤字で強調した部分は本家にはなく、実現するためには追加のシールドそもそも対応したシールドがない場合もあるがが必要な装置である。
要約すると、Intel galileoボードはArduino Unoの互換性を一応保ちつつ、最初からシールドが6個も付いているのだ。最初からクライマックスである。
つまるところ、こいつはPCDuinoや86Duinoと似たようなもので、半ば組み込み用のPCもどきとして設計されている印象を受けるのだ。
実にIntelらしい製品である。
但し致命的なことに、Galileoは画面出力を実装していない。
# S3のEmbedded用製品でmini PCIeグラフィックカードがあるようなので、入手できる方は試してみる価値はあるかもしれない。
---Getting started---
さて、前置きはこのくらいにして、早速Galileoを「自動餌やり機」として機能させるための準備に入っていくことにする。
何処からともなく
「自動餌やり機ごときにGalileoはオーバースペックなのでは?Arduinoで十分じゃん!」
との声が聞こえてきそうな気がするが、この際その手の手合いは黙殺する。
なぜこんな試作機を開発するのにArduinoではなくGalileoを使うかというと、実はこのGalileo、前述したように、RTC(リアルタイムクロック)が内蔵されているのだ。
それゆえ、タイマー動作をさせるにはもってこいなのだ。
閑話休題、いよいよ作成に取り掛かることにする。
まず最初に、動作させるために母艦PCにGalileo IDEをインストールしておく。
こうすることによって、PCにGalileoを繋いだときに即開発ができるようになるのだ。
この時、Galileo IDEのインストール先には注意が必要だ。
原則として2バイト文字や空白を含むフォルダはインストール先に使えない。
やってみるとわかるのだが、展開先のパスが長すぎて途中でセットアップがコケてIDEがインストールできないのだ。
この点は取説に書かれていないので注意が必要だ。
筆者はC:\ドライブ直下にGalileo IDEをインストールした。
文章で書くと長ったらしくなるが、スクリーンショットで説明するとこのようになる。
次に、電源ユニットをボード本体に取り付ける。
付属のStarting guideには、「一番最初に電源を取り付けねばボードが損傷するぞ(要約)」、と何ともおっかない警告文が載っていた。
実際基板上には過電圧or過電流に備えてヒューズがついているのだが、どうやらこのヒューズ、本家Arduinoと違い、リセッタブルではない。
外見的には普通のセメント抵抗のようなパッケージになっている。ここが壊れるとボードごとおじゃんになるので、細心の注意が必要だ。
DCプラグ上部のヒューズはリセッタブルじゃないんだぜ…
次に、GalileoボードのUSB client側に、PCとスマホでデータ転送をするUSB-microUSBケーブルを用いてPCに認識させる。
この時、デバイスマネージャー上では"Gadget serial 2.4"と表示されているはずだ。
Gadgetとは小道具、ちょっとした道具、という意味だ。開発時のコードネームだろうか。(注:SoCのコードネームはClantonですが、ボード本体のコードネームは筆者の調べた限り、判明しなかった。)
この段階ではまだArduinoとしての機能を果たしていない。
よって、Arduinoとして機能させるためにドライバのインストールを行う。
このままではまだ何もできないので、ドライバをインストールする必要がある。
デバイスマネージャー上からGadget serial 2.4を選択し、「ドライバの更新」から手動でドライバを更新する。
無事ドライバのインストールが完了すると、デバイスマネージャー上の表記がGadget serial 2.4からGalileo(COMx)(xは環境により異なる)となっているはずだ。
この時どのCOMポートにGalileoが接続されているか確認することをお忘れなく。
疑似COMポートとして認識され、これで準備は整った。
参考までに、筆者の環境ではCOM3にGalileoボードが接続されていることになっている。
おっと、大事なことを書き忘れていた。ドライバの場所は、
ドライブレター:\IDEをインストールした場所\hardware\arduino\x86\tools だ。
IDEをインストールした場所直下に「driver」というディレクトリとセットアッププログラムがあるが、これはまやかしで、実行しても正常にインストールできないので、この点注意が必要だ。
これも例によって説明書には一切書かれていないので筆者も最初はつまづいた。要注意だ。
---まずはLチカ---
さて、粗方の準備が整ったので、挨拶代わりにLEDをチカチカさせるスケッチを組んでみた。
なぜLチカなのかと疑問に思った読者も多いだろう。
ではここでLEDをモーターに置き換えて考えてほしい。そしてこのGalileoボードはArduinoと違い、RTCがあるのだ。
するとどうだろう、RTCで所定の時刻になるとモーターを作動させることが出来るのではなかろうか。
そういうわけで、どういうわけだ今回のLチカ実験は猫の自動餌やり機装置を完成させることが出来るかどうかを予め確認するための概念実証実験である。
Arduinoの世界ではプログラムのことをスケッチと呼ぶので、本稿もスケッチと呼称する。
組む、と言っても何も肩肘を張る必要なはい。今回はIDEから「ファイル」→「スケッチの例」→「Basics」→「Blink」を選択するだけでLEDをチカチカさせるスケッチを組むことができる。
この間わずか4ステップ、簡単である。
さて、スケッチが出来上がったらIDEのメニューバー下部、左から2個目のアイコン、「マイコンボードに書き込む」をクリックしてスケッチをコンパイルし、Galileoボードに転送する。
スケッチのコンパイル中。緊張の一瞬だ。
コンパイルされたスケッチの実行ファイル形式はELFバイナリだ。
このことから、GalileoボードはLinuxを動かしてArduinoをエミュレートしていると思われるが、まだdmesgが拝めていないので確認できない。
書き込み成功である。
では、記念すべき最初のスケッチの動作の動画をアップロードしたので、見ていただきたい。
今回はユニバーサル基板を使う必要性もない程度の回路なので、ブレッドボード上に突貫工事で作ってみた。
ご覧のとおり、元気に1秒間隔で点滅をしているのが分かるだろうか
さて、1個のLEDを点滅させることが出来たのだから、欲が出るというものが人情ということで、何LEDの数を増やしてみた。
以下に回路図と写真を示す。
プロの回路師さんに言わせると怒られそうなテキトー回路だが、参考にしていただければ幸いだ。
ここで注意しておきたいのだが、LEDは並列に繋いではならない。並列に繋ぐと一番弱い素子にストレスがかかるのだ。
壊れたFMトランスミッタから取り出した赤色LED性能諸元不明を使用したのだが、2番目、3番目になるにつれ輝度が落ちている。これではそのままモーターを制御するにはちょっと心許ない。
と言ってもこのボードが根性なしなのではなく、ただ単に1個目のLEDと2,3個目のLEDのスペックが違うために起きた現象と思われるので、特に問題はないと思われる。
と言いつつこのままでは筆者としても、読者の皆様としても「なんか足んない」との指摘を受けそうなので、1番目のLEDと同じもので作り直してみた。
LEDの点灯に於いては、一応ブリーダー抵抗をつけなければならないのだが、即席の突貫工事なのでそのまま繋いである。←ぉぃ
少しはマシになっているが、やはり2個目、3個目に行くにしたがって輝度が落ちている。
やはり少し力不足なのは否めない。
給装置機械を開発するには間に何か噛ませて制御する必要がありそうだ。
Galileo with linux.
さて、Lチカによる概念実証が終わったところで、今度はGalileoボードにLinux
をインストールして挙動を探っていきたいと思う。
準備
- 中身が消えてもいいmicroSDカード1枚(筆者はPanasonicの2GBを使用した)
その1
まず、Intel galileo自体のファームウェアをアップデートする。
方法は、GalileoボードをPCに繋いだ状態で
Arduino IDEを起動し、「ヘルプ」→「Firmware update」の順にメニューを選択すると、このような画面が現れる。
Linux導入にあたっては、ボードのファームウェアの更新が必要になることもある。
↑「電源に繋いでいて、USBケーブルを適切にPCと接続しているか」とのメッセージが出るので、問題なければYesを選択しよう。
ファームウェアのアップデートが始まった。この時、上記の画像からもわかるように、絶対にプラグを抜いたり、USB接続を外してはいけない。
アップデート自体には5分程度かかるので、この間はただひたすら待つしかない。
ちなみにアップデート中はCypress社製のEEPROMが結構発熱する。
成功するとこのような画面になる。
これでGalileoにLinuxを入れる準備が整った。
その2
ここ (https://communities.intel.com/docs/DOC-22226) からLINUX IMAGE FOR SD for Intel Galileo (to enable Wi-Fi)」
をダウンロードし、展開して出来たファイル群を全て先述のSDカードのルート直下に書き込む。
Raspberry pi
と違い、OSを書き込むにあたって、ddやWin32DiskImagerなどのdd系ツールは必要ない。エクスプローラ上で単に展開されたファイルをコピーするだけである、簡単である。
この際、フォーマットするSDカードはFAT32を推奨する。
書き込みが終了したら、USB、周辺機器、電源プラグの順に外して電源を切る。
その3
次に、OSファイル群を書き込んだSDカードをGalileoボード上のSDスロットに挿入し、電源プラグを挿入、電源を投入する。
ボードが壊れる恐れがあるため、他のコネクタは電源投入後に接続すべきだ。
それでは、準備が整ったので、sshによるリモートログインを試みる。
トラブル発生
Ethernetポートにケーブルを挿したのだが、ssh接続ができない。
これは困った。
pingすら通らない。
と困っているのも束の間、Intel galileoの海外フォーラムにて、「sshを使う場合は電源コネクタ挿す前にEthernetケーブルを挿しておくと上手くいく」との報告」
があったので、そのようにしたら難なく認識して、うまくいった。
若干説明書と矛盾しているのだが…これも例によって説明書には全く書かれていない。注意が必要だ。
紆余曲折を経て、漸くIntel galileoボードのLinuxにアクセスできるようになった。
初期状態ではログインユーザ名がroot、パスワードが無い状態だ。早めに変更すべきだ。
以下にsshのログを貼付する。
ログ中、筆者が分かる範囲内で注釈をつけてある。参考にしていただければ幸いだ。
login as: root
root@clanton:~# man head
-sh: man: command not found
- manコマンドは存在しないようだ。
root@clanton:~# dmesg
[ 0.000000] Initializing cgroup subsys cpuset
[ 0.000000] Initializing cgroup subsys cpu
[ 0.000000] Linux version 3.8.7-yocto-standard (clntonsw@irsswdev001) (gcc version 4.7.2 (GCC) ) #1 Tue Oct 1 00:09:01 IST 2013
[ 0.000000] e820: BIOS-provided physical RAM map:
(中略)
[ 0.000000] bootconsole [uart0] enabled
[ 0.000000] NX (Execute Disable) protection: active
- Intel Quark X1000 SoCはISA命令セットがPentium互換ではあるものの、なぜかNX bit機能が有効になっている。
[ 0.000000] efi: EFI v2.31 by EKI
- そしてBIOSではなくEFIを積んでいる。今のところIntelから提供されたLinuxイメージしか起動できないようだ。
[ 0.000000] efi: SMBIOS=0xfeee000 ACPI=0xf11e000 ACPI 2.0=0xf11e014
[ 0.000000] efi: mem00: type=7, attr=0xf, range=[0x0000000000000000-0x0000000000095000) (0MB)
[ 0.000000] efi: mem01: type=2, attr=0xf, range=[0x0000000000095000-0x0000000000097000) (0MB)
[ 0.000000] efi: mem02: type=0, attr=0xf, range=[0x0000000000097000-0x0000000000098000) (0MB)
(20行ほど同じ羅列が続くので中略)
[ 0.000000] mapped APIC to ffffb000 ( fee00000)
[ 0.000000] 0MB HIGHMEM available.
[ 0.000000] 254MB LOWMEM available.
[ 0.000000] mapped low ram: 0 - 0fef0000
[ 0.000000] low ram: 0 - 0fef0000
[ 0.000000] Zone ranges:
[ 0.000000] Normal [mem 0x00010000-0x0feeffff]
[ 0.000000] HighMem empty
[ 0.000000] Movable zone start for each node
[ 0.000000] Early memory node ranges
[ 0.000000] node 0: [mem 0x00010000-0x00096fff]
[ 0.000000] node 0: [mem 0x00098000-0x0009ffff]
[ 0.000000] node 0: [mem 0x00100000-0x0f0defff]
[ 0.000000] node 0: [mem 0x0feef000-0x0feeffff]
[ 0.000000] On node 0 totalpages: 61551
[ 0.000000] free_area_init_node: node 0, pgdat c1484720, node_mem_map cdd40200
[ 0.000000] Normal zone: 510 pages used for memmap
[ 0.000000] Normal zone: 0 pages reserved
[ 0.000000] Normal zone: 61041 pages, LIFO batch:15
[ 0.000000] Using APIC driver default
- 立派にAPICなんかも内蔵してある。将来デュアルコアGalileoでも出すつもりなのだろうか。
[ 0.000000] ACPI: PM-Timer IO Port: 0x1008
[ 0.000000] ACPI: Local APIC address 0xfee00000
[ 0.000000] mapped APIC to ffffb000 ( fee00000)
[ 0.000000] ACPI: LAPIC (acpi_id[0x01] lapic_id[0x00] enabled)
(ACPIと各種BUSの初期化の羅列が何十行か続くため、ここも中略)
[ 0.000000] e820: [mem 0x0fef0000-0xdfffffff] available for PCI devices
[ 0.000000] pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768
[ 0.000000] pcpu-alloc: [0] 0
[ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 61041
[ 0.000000] Kernel command line: root=/dev/ram0 console=ttyS1,115200n8 earlycon=uart8250,mmio32,0x8010f000,115200n8
reboot=efi,warm apic=debug rw LABEL=boot debugshell=5 efi_main=0x000000014650b550 jmp_code32=0x00000001812bdc0f
[ 0.000000] PID hash table entries: 1024 (order: 0, 4096 bytes)
[ 0.000000] Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
[ 0.000000] Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
[ 0.000000] __ex_table already sorted, skipping sort
[ 0.000000] Initializing CPU#0
- CPUは1つだけだ。
[ 0.000000] Initializing HighMem for node 0 (00000000:00000000)
[ 0.000000] Memory: 213068k/261056k available (3098k kernel code, 33136k reserved, 1547k data, 272k init, 0k highmem)
[ 0.000000] virtual kernel memory layout:
[ 0.000000] fixmap : 0xfffa2000 - 0xfffff000 ( 372 kB)
[ 0.000000] pkmap : 0xffc00000 - 0xffe00000 (2048 kB)
[ 0.000000] vmalloc : 0xd06f0000 - 0xffbfe000 ( 757 MB)
[ 0.000000] lowmem : 0xc0000000 - 0xcfef0000 ( 254 MB)
[ 0.000000] .init : 0xc148a000 - 0xc14ce000 ( 272 kB)
[ 0.000000] .data : 0xc1306812 - 0xc1489480 (1547 kB)
[ 0.000000] .text : 0xc1000000 - 0xc1306812 (3098 kB)
[ 0.000000] Checking if this processor honours the WP bit even in supervisor mode...Ok.
[ 0.000000] SLUB: Genslabs=15, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[ 0.000000] NR_IRQS:2304 nr_irqs:256 16
[ 0.000000] CPU 0 irqstacks, hard=c0090000 soft=c0092000
[ 0.000000] Console: colour dummy device 80x25
[ 0.000000] Lock dependency validator: Copyright (c) 2006 Red Hat, Inc., Ingo Molnar
[ 0.000000] ... MAX_LOCKDEP_SUBCLASSES: 8
[ 0.000000] ... MAX_LOCK_DEPTH: 48
[ 0.000000] ... MAX_LOCKDEP_KEYS: 8191
[ 0.000000] ... CLASSHASH_SIZE: 4096
[ 0.000000] ... MAX_LOCKDEP_ENTRIES: 16384
[ 0.000000] ... MAX_LOCKDEP_CHAINS: 32768
[ 0.000000] ... CHAINHASH_SIZE: 16384
[ 0.000000] memory used by lock dependency info: 3567 kB
[ 0.000000] per task-struct memory footprint: 1152 bytes
[ 0.000000] hpet clockevent registered
[ 0.000000] tsc: Fast TSC calibration using PIT
[ 0.000000] spurious 8259A interrupt: IRQ7.
[ 0.000000] tsc: Detected 399.076 MHz processor
- SoC内のCPUコアは400MHzで駆動されている。
[ 0.010015] Calibrating delay loop (skipped), value calculated using timer frequency.. 798.15 BogoMIPS (lpj=3990760)
[ 0.010137] pid_max: default: 32768 minimum: 301
[ 0.408253] Security Framework initialized
[ 0.408525] Mount-cache hash table entries: 512
[ 0.417681] Initializing cgroup subsys cpuacct
[ 0.417852] Initializing cgroup subsys freezer
[ 0.418653] Intel Pentium with F0 0F bug - workaround enabled.
- FDIVバグはないが、f0 0fバグのあるPentium として認識されているようだ。なぜ修正しなかったのか不思議ではある。
[ 0.418911] Last level iTLB entries: 4KB 0, 2MB 0, 4MB 0
[ 0.418911] Last level dTLB entries: 4KB 0, 2MB 0, 4MB 0
[ 0.418911] tlb_flushall_shift: 6
[ 0.419055] CPU: Intel 05/09 (fam: 05, model: 09, stepping: 00)
[ 0.419289] ACPI: Core revision 20121018
[ 0.510715] Performance Events: no PMU driver, software events only.
[ 0.515638] Enabling APIC mode: Flat. Using 1 I/O APICs
[ 0.515717] Getting VERSION: 30010
[ 0.515772] Getting VERSION: 30010
[ 0.515825] Getting ID: 0
[ 0.515873] Getting ID: f000000
[ 0.515925] Getting LVT0: 700
[ 0.515975] Getting LVT1: 400
[ 0.516043] enabled ExtINT on CPU#0
[ 0.516411] ENABLING IO-APIC IRQs
[ 0.516466] Synchronizing Arb IDs.
[ 0.516516] init IO_APIC IRQs
[ 0.516548] apic 1 pin 0 not connected
[ 0.516852] IOAPIC[0]: Set routing entry (1-1 -> 0x31 -> IRQ 1 Mode:0 Active:0 Dest:1)
[ 0.516973] IOAPIC[0]: Set routing entry (1-2 -> 0x30 -> IRQ 0 Mode:0 Active:0 Dest:1)
[ 1.581659] Trying to unpack rootfs image as initramfs...
[ 2.230402] Freeing initrd memory: 1408k freed
[ 2.248780] microcode: Intel CPU family 0x5 not supported
[ 2.255252] resource map sanity check conflict: 0xfff00000 0x1002fffff 0xff800000 0xffffffff reserved
[ 2.255363] ------------[ cut here ]------------
[ 2.255479] WARNING: at /build/clntonsw/slave_magnum/meta-clanton/build/compile/yocto_build/tmp/work/clanton-poky-
(IOAPIC, PCI, Ethernet関連の初期化メッセージの羅列が続くためここも中略)
linux-uclibc/linux-yocto-clanton/3.8-r0/linux/arch/x86/mm/ioremap.c:171 __ioremap_caller+0x27a/0x440()
[ 2.255641] Info: mapping multiple BARs. Your kernel is fine.
[ 2.255703] Modules linked in:
[ 2.255791] Pid: 1, comm: swapper Not tainted 3.8.7-yocto-standard #1
[ 2.255862] Call Trace:
[ 2.255959] [<c102f59f>] warn_slowpath_common+0x5f/0x80
[ 2.256074] [<c1023a7a>] ? __ioremap_caller+0x27a/0x440
[ 2.256184] [<c1023a7a>] ? __ioremap_caller+0x27a/0x440
[ 2.256298] [<c102f63e>] warn_slowpath_fmt+0x2e/0x30
[ 2.256408] [<c1023a7a>] __ioremap_caller+0x27a/0x440
[ 2.256525] [<c149ab13>] ? intel_cln_board_data_init+0x1a/0x19d
[ 2.256634] [<c149aaf9>] ? efi_capsule_update_init+0x8d/0x8d
[ 2.256744] [<c1023caa>] ioremap_nocache+0x1a/0x20
[ 2.256852] [<c149ab13>] ? intel_cln_board_data_init+0x1a/0x19d
[ 2.256962] [<c149ab13>] intel_cln_board_data_init+0x1a/0x19d
[ 2.257062] [<c110e613>] ? sysfs_add_file+0x13/0x20
[ 2.257152] [<c110e6bc>] ? sysfs_create_file+0x1c/0x20
[ 2.257253] [<c149aaf9>] ? efi_capsule_update_init+0x8d/0x8d
[ 2.257352] [<c100121a>] do_one_initcall+0x10a/0x150
[ 2.257447] [<c148aa6b>] kernel_init_freeable+0x106/0x1a0
[ 2.257541] [<c148a457>] ? do_early_param+0x7a/0x7a
[ 2.257648] [<c12fbc1b>] kernel_init+0xb/0xd0
[ 2.257747] [<c13055fb>] ret_from_kernel_thread+0x1b/0x30
[ 2.257853] [<c12fbc10>] ? rest_init+0xb0/0xb0
[ 2.258005] ---[ end trace 1e7a29e738eea211 ]---
[ 2.258100] MFH: mfh @ 0xe1008000: id 0x5f4d4648 ver 0x00000001 entries 0x0000000a
[ 2.260872] MFH: Warning platform data MFH missing - using hardcoded offsets
[ 2.266250] resource map sanity check conflict: 0xfff10000 0x100000075 0xff800000 0xffffffff reserved
[ 2.266515] CLN-PLT: Clanton Platform ID = 6
[ 2.289913] Intel Clanton side-band driver registered
[ 2.294885] IMR setup complete
[ 2.297202] eSRAM CTRL 0x047f3f91 block 0x00000000
[ 2.297276] eSRAM pages 128
- SoC内に512KB4KB * 128pagesの内蔵SRAMを混載しているのが分かる。
[ 2.318724] intel_cln_esram_test_probe/Oct 1 2013/00:07:49 complete OK !!
[ 2.337804] HugeTLB registered 2 MB page size, pre-allocated 0 pages
[ 2.481626] msgmni has been set to 456
[ 2.494542] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 252)
[ 2.494930] io scheduler noop registered
[ 2.495014] io scheduler deadline registered
[ 2.495230] io scheduler cfq registered (default)
[ 2.530957] input: Sleep Button as /devices/LNXSYSTM:00/LNXSYBUS:00/PNP0C0E:00/input/input0
[ 2.531844] ACPI: Sleep Button [SLPB]
ACPI, APIC, Ethernet, USB, Bluetooth関連のメッセージが数十行続くため、ここも略させてもらった。
[ 13.266044] Intel(R) Wireless WiFi driver for Linux, in-tree:
[ 13.271978] Copyright(c) 2003-2012 Intel Corporation
[ 13.555391] Bluetooth: Core ver 2.16
[ 13.561007] NET: Registered protocol family 31
[ 13.565505] Bluetooth: HCI device and connection manager initialized
[ 13.572707] Bluetooth: HCI socket layer initialized
[ 13.577719] Bluetooth: L2CAP socket layer initialized
[ 13.583206] Bluetooth: SCO socket layer initialized
- SPI, Wi-Fi, Bluetoothドライバが読み込まれた。
[ 13.606125] usbcore: registered new interface driver btusb
[ 14.296760] usbcore: registered new interface driver usbhid
[ 14.302517] usbhid: USB HID core driver
[ 17.935475] eth0: device MAC address <削除しました>
[ 19.940491] libphy: stmmac-1:01 - Link is Up - 100/Full
[ 23.982014] NET: Registered protocol family 10
- ethernet関連の初期化完了。
このことから、Intel galileoを運用する場合、通信が行われ、準備が整うまでに30秒~1分程度かかることが読み取れる。
GalileoのLinuxについて
GalileoのLinux(以後Clantonと呼称)は組み込みLinuxゆえ、cpやrmやらの基本コマンドはBusyboxに内包されている。
(3/16追記)ClantonはSoCのコードネームでした、訂正してお詫びします。
root@clanton:~# ls -l /bin
lrwxrwxrwx 1 root root 12 Sep 30 2013 ash -> /bin/busybox
-rwxr-xr-x 1 root root 904208 Sep 30 2013 bash
-rwxr-xr-x 1 root root 596948 Sep 30 2013 busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 cat -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 chgrp -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 chmod -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 chown -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 cp -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 cpio -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 cttyhack -> /bin/busybo
x
lrwxrwxrwx 1 root root 12 Sep 30 2013 date -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 dd -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 df -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 dmesg -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 dnsdomainname -> /bin/b
usybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 dumpkmap -> /bin/busybo
x
lrwxrwxrwx 1 root root 12 Sep 30 2013 echo -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 egrep -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 false -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 fgrep -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 fsync -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 grep -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 gunzip -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 gzip -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 hostname -> /bin/busybo
x
lrwxrwxrwx 1 root root 12 Sep 30 2013 ionice -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 iostat -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 ip -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 kill -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 ln -> /bin/busybox
lrwxrwxrwx 1 root root 17 Sep 30 2013 login -> /bin/login.sha
dow
-rwxr-xr-x 1 root root 51884 Sep 30 2013 login.shadow
lrwxrwxrwx 1 root root 12 Sep 30 2013 ls -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 mkdir -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 mknod -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 mktemp -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 more -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 mount -> /bin/busybox
lrwxrwxrwx 1 root root 24 Sep 30 2013 mountpoint -> /bin/moun
tpoint.sysvinit
-rwxr-xr-x 1 root root 4836 Sep 30 2013 mountpoint.sysvinit
lrwxrwxrwx 1 root root 12 Sep 30 2013 mv -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 netstat -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 nice -> /bin/busybox
lrwxrwxrwx 1 root root 19 Sep 30 2013 pidof -> /bin/pidof.sys
vinit
lrwxrwxrwx 1 root root 14 Sep 30 2013 pidof.sysvinit -> /sbin
/killall5
lrwxrwxrwx 1 root root 12 Sep 30 2013 ping -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 ping6 -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 ps -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 pwd -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 rm -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 rmdir -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 sed -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 setserial -> /bin/busyb
ox
lrwxrwxrwx 1 root root 9 Sep 30 2013 sh -> /bin/bash
lrwxrwxrwx 1 root root 12 Sep 30 2013 sleep -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 stty -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 sync -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 tar -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 touch -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 true -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 umount -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 uname -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 usleep -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 vi -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 zcat -> /bin/busybox
root@clanton:~# ls -l /bin
lrwxrwxrwx 1 root root 12 Sep 30 2013 ash -> /bin/busybox
-rwxr-xr-x 1 root root 904208 Sep 30 2013 bash
-rwxr-xr-x 1 root root 596948 Sep 30 2013 busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 cat -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 chgrp -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 chmod -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 chown -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 cp -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 cpio -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 cttyhack -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 date -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 dd -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 df -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 dmesg -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 dnsdomainname -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 dumpkmap -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 echo -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 egrep -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 false -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 fgrep -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 fsync -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 grep -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 gunzip -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 gzip -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 hostname -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 ionice -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 iostat -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 ip -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 kill -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 ln -> /bin/busybox
lrwxrwxrwx 1 root root 17 Sep 30 2013 login -> /bin/login.shadow
-rwxr-xr-x 1 root root 51884 Sep 30 2013 login.shadow
lrwxrwxrwx 1 root root 12 Sep 30 2013 ls -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 mkdir -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 mknod -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 mktemp -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 more -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 mount -> /bin/busybox
lrwxrwxrwx 1 root root 24 Sep 30 2013 mountpoint -> /bin/mountpoint.sysvinit
-rwxr-xr-x 1 root root 4836 Sep 30 2013 mountpoint.sysvinit
lrwxrwxrwx 1 root root 12 Sep 30 2013 mv -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 netstat -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 nice -> /bin/busybox
lrwxrwxrwx 1 root root 19 Sep 30 2013 pidof -> /bin/pidof.sysvinit
lrwxrwxrwx 1 root root 14 Sep 30 2013 pidof.sysvinit -> /sbin/killall5
lrwxrwxrwx 1 root root 12 Sep 30 2013 ping -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 ping6 -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 ps -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 pwd -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 rm -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 rmdir -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 sed -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 setserial -> /bin/busybox
lrwxrwxrwx 1 root root 9 Sep 30 2013 sh -> /bin/bash
lrwxrwxrwx 1 root root 12 Sep 30 2013 sleep -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 stty -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 sync -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 tar -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 touch -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 true -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 umount -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 uname -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 usleep -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 vi -> /bin/busybox
lrwxrwxrwx 1 root root 12 Sep 30 2013 zcat -> /bin/busybox
root@clanton:~#
このようによく使うであろうコマンドは全てBusyboxを呼び出すようになっている。
GalileoボードにClantonを入れる利点として、「スケッチが消えない」という利点がある。
後日談本家Arduinoでもスケッチは消えないことを確認した、訂正してお詫びしたい。
以下、先述した「消えないスケッチ」を動画でご確認いただきたい。
スケッチ自体はClantonをインストールしたSDカード内の
/sketch/sketch.elfに格納されている。
x86でArduinoを模倣して動かすとだけあって、スケッチのサイズは異常に大きい。
# ls -la
drwxr-xr-x 2 root root 1024 Jan 1 2001 .
drwxr-xr-x 18 root root 1024 Jan 1 2001 ..
-rwxr--r-- 1 root root 49184 Feb 26 2014 sketch.elf コンパイル済みスケッチ本体
↑これを見てくれ、実行ファイルだけでも約50KBもある。
Arduinoとx86のニコイチボードの宿命か、どうしてもファイルサイズはデカくなるようだ。
初期状態ではrootにパスワードが設定されていないため、passwdコマンドで適当なパスワードを設定した。
スケッチを実行中は↓のように、上記のsketch.elfファイルが実行されていることが見て取れる。
今までのまとめ
とりあえず、粗方触ってみての筆者のGalileoボードに関する印象(3/6まで)は以下の通りである。
利点
- CPUが強力8bit 16MHzのAVRの比ではない、32bit, 400MHz
- にもかかわらずファンレス運用が可能
- Arduinoシールドと互換性が一応ある※後述
- 最初からLANを積んでいるOUIからIntel製コントローラと判明した
- USBホスト端子を積んでいるため、各種USB機器の使用も可能
- ArduinoモードとSDから任意のx86用OS現時点ではIntelから提供されているClantonLinuxをブートできるデュアルブート仕様
- メモリ領域が大きいSRAM 512KB, RAM 256MBため、スケッチの大きさを気にしなくてよい
欠点
- SoCからすべてのバスが出ているわけではなく、Arduinoに使われているATMEL AVRをエミュレートしているため、CPU周りが若干ブラックボックス化している。マイコンを直叩きで制御したい方にはこの点に関してはArduinoの方が優っている
- SoCの機能がイマイチ中途半端。上の画像はGalileoにssh接続してシェルから/proc/cpuinfoを覗いてみたところだ。ISA命令セットこそP5/586Pentium互換であるものの、P5時代では無いはずのNX bitやらPAEが無駄に搭載されている、少なくとも趣味の電子工作でシールドを乗っけて開発するためには些かオーバースペックな感が否めない。ここからは完全に筆者の邪推と想像であるが、Atom系列のラインを減価償却したのでついでにAtomコアからTDPを引き下げるように各種命令を削除してP5互換コアのSoC作ってArduinoエミュレータをEEPROMに乗っけてArduino互換機を作ってみました、という良くも悪くもIntelらしい印象を受ける。なんだか昔のi740を彷彿とさせる。
- 最初からシールドを6つ以上SD, LAN, USB, SRAMSoC内, RAMDDR3, RTC, UART, mini PCIe, Bluetoothドライバも積んでいるため、Arduino用の各種シールドを運用しようとするとトラブルが発生する傾向が強い少なくとも筆者はDFRobot製のArduino LCD Shieldで表示が極端に遅くなるといった不具合を確認した、ボードのリビジョン変更で改善されることを強く望む。エミュレーションにリソースが取られるのかどうかは知らないが、Arduino部分のI/Oピンの切り替えがかなり遅い。これにより非互換が生じるボードもあることを念頭に置いた方がよい。
- 仕様書(リンク先pdfの4ページ目)を見る限り、I2C接続とマルチプレクサで全てのArduino互換ピンを駆動させている実装の都合上か、シールドによっては遅くて使い物にならないといった(例: )非互換が生じる。
- まだ出始めの製品であるため、参考文献が殆ど英語のものが多く、初めてのArduinoでアート作品を作るのには敷居が高い。
- ボード本体とIDEの出来が若干悪く(中間報告その2で後述する)、環境によってはGalileoを認識できず、思いついたときに即開発が出来ないことがある。スケッチの転送でIDEのログに"/dev/tty* Permission denied."などと表示されるのは大体これのせいである。大抵は開発機PCの再起動や接続先の変更で改善するが、再起動や接続先の変更中に自分の考えている脳内スケッチ要はアイデアが消えてしまうことも多々あるため、この点に関しても改善を求む。
というわけで、完全に良くも悪くもIntel「らしい」ボードだ、もちろんこれは褒め言葉である。
14/03/06 中間報告
現在の状況
さて、今現在のIntel galileoを使っての猫の自動餌やり機開発の状況であるが、散々期待させておきながら、残念ながらまだあまり上手くいってないのが現状である。(14/03/03)
(14/03/16追記:試作機が一応完成しました。ページ最下部、中間報告その6をご覧ください)
課題としては
- どのようにして一定量の餌を出す機構を作るか
- そのトリガーイベントとしてGalileoのRTCを利用するが、RTCをどのように読み取るか
主にこの2点でかなり悩んでいるのが実情である。
簡単に図で説明すると、このようになる。
下手な絵で申し訳ない。
- 筒状のサイロに餌を入れておき、中間地点で蝶番式の蓋を取り付けておく。
- RTC時間検出で0→1で蓋が下方へ下がり、餌を排出する。
- 排出すると、1→2の順序で蓋を元に戻す。
- 2の状態になったら餌をサイロに再充填して0の状態に戻る。
と、まあこのような感じである。
状態遷移図に書き起こすと、こんな感じだ。
多少間違いがあるだろうがお許しいただきたい。
さて、自動餌やり機であるが、おそらく大手のペットショップやホームセンターに行けば数千円で買えるのではなかろうか。残念ながら筆者の近傍にはそのような店がないので確証が取れないが(^^;)
では、なぜ安価で済ませられるものにこんなにも血道をあげて開発に勤しんでいるかそれはただ単に筆者が工作好きだからである。好きだから続けられる、好きだから多少困難でも挑戦できる。この点もただ単に出来合いの既製品を買うことでは到底味わえない、開発の「醍醐味」である。
時にエラーが発生することが多々ある。というか今現在も発生中である。しかし、これを解決したときの感慨もひとしおであるのも事実。こういったことも楽しみの一つである。
エラーや困難な課題を克服できなければ楽しくないという方(世間ではそれをドMと呼ぶ)にはお誂え向きの逸品だ。
また、組み込みLinuxをdmesgで解析して「あれができる」「これはできない」という事実から現在の案を練り直していく過程もまた面白い。
まさしく、ガリレオだけに
「実に面白い」
のである。
中間報告その1
現在(14/03/04)、Arduinoモーターシールドを使ってモーターを正転、逆転させることに成功した。
ただしモーターシールドがGalileo上で動かず苦戦している。
またもやIDE上で"/dev/tty* No such device."などとエラーが出てスケッチが転送できていない状態が続いている。
中間報告その2 ~気が付いたこと~
今までスケッチの転送ができず、再起動を強いられる状態が長く続いていたが、このボードを長く触っているうちに海外フォーラムから以下のようなトピックが見つかったので、報告したい。
曰く、
「ボードのRESETボタンを何回か押すと治る」
とのこと。
他にも、原因はボード自体の設計とIDEの両方が考えられる、とのことだ。
/dev/tty* Permission denied. などと出るのはGalileo IDE上のshスクリプトをCygwinで動かしているときにスクリプト実行が何らかの原因で完走できなかったときに表示されるようだ。
その時宛先のCOMポートxがsh上では/dev/ttyS(x-1)となるため、この点でどうやら不整合が起こっていると推測する。
それにしても、RESET連打で治るとは…Windows9x時代のCtrl+Alt+Delを思い出してしまった。
やはり、色々な意味でIntelらしいボードである。Arduinoの標榜する「プロトタイピングボード」ではなく、どちらかというと「組み込み制御機器用マザーボードβ版」という印象だ。
今後のリビジョンアップに期待したい。
中間報告その3
2014/03/06
やっと自動餌やり機のサイロ部分が完成した。
サイロ部分には、どこのご家庭にもあるラップフィルムの芯を利用した。
蓋はまだつけていないし、サイロの固定もまだ仮止めの段階だ。
駆動機構もまだ思案中なので結構先が思いやられる。
ホントにこんなので、大丈夫なんだろうか…
そこはアイデアと努力で何とかするしかない。というかしてみせる。
中間報告その3-2 ~メカニカル部分を考え直す~
2014/03/07
タイトル通り、今回は給飼装置の要となる部分のメカニカル部分特に餌の貯蔵庫となるサイロ部分を考え直すのだ。
ラップの芯だとどうしても入れられる餌の量が限られるため、波型ボール紙を使用し、サイロ部分を大幅に見直した。
名付けて「サイロ2号(仮)」である。
餌の収容容量が格段に増えた。
まだ仮なので赤テープで留めてある。
とはいうものの、愛猫に作り置きを食べさせるわけにもいかないので、このサイロに供給するのは2食分と決めてある。
早速手作業で給飼実験をやってみた。
見事に大失敗である。
以前よりサイロの高さが増したため、餌がものすごい勢いでボロボロと散乱し、供給した餌はほとんど猫用の茶碗(この写真には写ってないけど)に入らない。
サイロ出口、末端部に重力による餌の高速落下を緩衝するため、区切り棒を十字型に入れた。
若干改善されたが、まだまだ問題は山積している。
どうにかそれっぽくなったが、自動給飼が問題である。
中間報告その4 ~時刻を検知するスケッチ~
(2014/03/08追記)
さて、ハード面はまた後ほど考えるとして、せっかく設定したRTCから時刻が読み取れなければどうしようもない。
というわけで、時刻取得スケッチを作ってみた。
// declaration of valiables.
char buf[6]; // buffer length.長さは後で調整すべきか。
long timeval;
// setup procedure.
void setup(){
// long timeval; //ここに宣言するのかコンストラクタで宣言するのか
Serial.begin(9600); // initialize serial port.デバッグプリントがシリアルモニタから見えるように。
}
// loop procedure.
void loop(){
/*
timelogを読み込む
atoiでString→intに変換
*/
system ("date '+%H%M%S' > /home/root/timelog.txt"); // コンソールでコマンドを打つのと同義。
FILE *fp;
fp = fopen("/home/root/timelog.txt","r"); // Linux側の操作。
fgets(buf, 6, fp);
fclose (fp);
long timeval = atoi(buf); // bufに格納された時刻の文字列をatoiで数字に変換する。longは必要か否か
Serial.println(timeval); // for debugging use.
//timelogの判定
if ((timeval == 060000) || (timeval ==180000)){
/*
トリガー発動
// insert the "feeding procedure" code here.
*/
delay(1000); // 確実にtimeval != 060000 もしくはtimeval != 180000にするための待ち時間。
Serial.println("ON"); // for debugging use.
}
//timelog判定終了
} // loop end.
loop()メソッド内の一部の処理はもはやArduinoスケッチではなく、ほとんどLinuxの命令叩き処理とC言語になってしまった。しかもloop()メソッド内で何回もファイルアクセスを延々と繰り返している。まだまだ改良の余地大有りである。
クロック数の低いArduino単体でやるならばより正確な時計メソッドを実装する必要があると思われる。(例:delay()以外の命令実行にかかるクロック数の算出とか)
コンパイルは通ったが、また例のごとくスケッチの転送でコケる状態が続いている。よってまだ確認できていないのが現状である。
せっかく書いたコードが動くことを期待して楽しみにしながら転送ボタンを押したものの、肝心のスケッチがGalileoに転送されないのだ。実にもどかしい。
中間報告その5 ~デバッグ~
2014/03/09
報告その4で記載したコードが正常に動かなかったので、丸1日デバッグに明け暮れた。
修正後のコードはこんな感じだ。
//コンストラクタ
//ethernet shieldと衝突するエラー **B0100000063f694
//#include <signal.h> //avoid error
char buf[7]; // buffer length.長さは後で調整してください。
//long timeVal;
//long timeDelta;
//long CurTime;
int led = 13; // initialization indicator.
int trig = 12; // turn on when encountered trigger event.
// target time definition in long int.
// synopsis: HHMMSS
const long firstTime = 060000;
const long secondTime = 180000;
int i;
int counter=0; // for debug use.
int feed = 2; // feed counter.
int tooktime; // took time in ms for linux-shell manipulations.
int total; // grand-total time in ms.(total += tooktime)
unsigned long lpcounter=1; // loop count.
int aTime; // avelage time for shell manipulation.
int oTime; // not to exceed 1000ms in one loop.
int curTime; // current time.
void setup(){
// signal(SIGPIP,SIG_IGN); // avoid error
pinMode (led, OUTPUT);
pinMode (trig, OUTPUT);
// long timeval; //ここに宣言するのかコンストラクタで宣言するのか
Serial.begin(9600); // initialize serial port in order to enable printing debug info.
for (i=0;i<10;i++){
digitalWrite(led,HIGH);
digitalWrite(trig,HIGH);
delay(300);
digitalWrite(led, LOW);
digitalWrite(trig, LOW);
delay(200);
} // Serial and LEDs initialization end.
}
void loop(){
digitalWrite(led,LOW);
/*
timelogを読み込む
atoiでString→intに変換
*/
tooktime = millis();
curTime = millis();
system ("date '+%H%M%S' > /var/volatile/timelog.txt"); // コンソールでコマンドを打つのと同義。
FILE *fp;
fp = fopen("/var/volatile/timelog.txt","r"); // Linux側の操作。
fgets(buf, 7, fp);
fclose (fp);
//for debugging code from this line to...
Serial.print("buf:");
Serial.print(buf); // print raw data in buf(buffer).
Serial.print(" ");
//until this line.
long timeVal = atoi(buf); // bufに格納された時刻の文字列をatoiで数字に変換する。longは必要か否か
Serial.print("timeVal:");
//------------------------------------------------
// timeDelta routine.
// system ("date '+%H%M%S' > /var/volatile/timelog.txt"); // コンソールでコマンドを打つのと同義。
// fgets(buf,7,fp);
// fclose(fp);
// long curTime = atoi(buf);
//
//
// timeDelta = curTime-timeVal;
// Serial.println(timeDelta);
Serial.println(timeVal); // for debugging use.
// /* old time calc routine(BUG)(begin) */
// oTime=timeVal--;
// if (timeVal-oTime == 0){
// Serial.print("in 1000ms.");
// }
// // oTime=timeVal--;
// Serial.println(oTime);
///* old time calc routine(BUG)(end) */
//timeDelta routine end.
/*[!!] FATAL BUG
this routine returns an error with "**B0100000063f694" errorcode.
so do not use it.
*/
//remove file.
system("rm -f /var/volatile/timelog.txt");
//timelogの判定
if ((timeVal == firstTime) || (timeVal == secondTime)){
/*
トリガー発動
*/
// insert the "feeding procedure" code here.
digitalWrite(trig,HIGH);
Serial.println("ON"); // for debugging use.
feed--;
if (feed == 0){
/* notify food empty */
feed = 2;
} // end food_empty detection.
Serial.println(timeVal);
delay(1000); // 確実にtimeval != 060000 もしくはtimeval != 180000にするための待ち時間。
/*
Blink LED for trigger when "Feeding Event" has come.
*/
//from this line to...
digitalWrite(trig, HIGH); // turn the LED on (HIGH is the voltage level)
delay(10000); // wait for a second
digitalWrite(trig, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
digitalWrite(led, LOW);
//until this line.
}
Serial.print(" OFF feed:");
Serial.print(feed);
Serial.print(", took:");
tooktime = millis()-tooktime;
Serial.print(tooktime);
Serial.print(" ms. Ave.");
total +=tooktime;
// lpcounter++;
aTime = total / lpcounter; //Avelage time of shell execution.
Serial.print(aTime);
Serial.println("ms.");
lpcounter++;
// Avelage time is 86 ms. in this sketch.
// min:83ms
// Max:93ms.
delay(900);
//timelog判定終了
} // loop end.
走らせるとまず最初にInit, Trig両方のLEDを10回点滅させ、デバッグ用にシリアルポートを開く。
所定の時刻になると10秒間Trigと書かれた方のLEDが光る。
一つ問題として、なぜかエラーコードを吐いてクラッシュすることがあるのが問題だ。
思考実験段階では上々だ。あとはLEDをモータードライバに置き換えてメカニカル部を作成すれば完成するはずだ…
中間報告その5 ~路線変更~
2014/03/15
RTCを読むスケッチが一定時間経つと正常にRTCの値を返さなくなった。そこで折角RTCモジュールを作った意味が殆どなくなってしまうが、次のように機械を組み合わせて実装することにした。
- Galileo上で12時間ごとに発動する疑似ソフトウェアタイマーを実装する。
- ↓
- イベントが発動する時刻になると別のArduinoに信号を送る。
- ↓
- 別のArduinoがその信号をキャッチ。
- ↓
- モーターシールドを作動させる。
という回りくどい折衷案を考えた。
Galileo側のスケッチは以下のとおりである。
/*
140315
Pseudo clock sketch for Intel Galileo.
Galileo側のソフトウェアクロックプログラム。(暫定的突貫工事)
12時間ごとにloopメソッド内からfeed()を呼び出す。
*/
int h,m,s; // hours, minutes, seconds.
int led = 13; // # of output pin.
void setup() {
pinMode (led, OUTPUT);
Serial.begin(9600); // for debugging use.
}
// Pseudo clock. impremented by software using nesting delay.
void loop(){
feed();
// for (h=0;h<12;h++){ //実際に使うときはここを使う。
for (h=0;h<1;h++){ // 試験的に1時間タイマーにしている。
for (m=0;m<60;m++){
for (s=0;s<60;s++){
delay(1000);
}
s=0; // 秒の繰上りを元に戻す。
}
m=0; // 分の繰上りを元に戻す。
}
h=0; // 時の繰上りを元に戻す。
} // end of loop().
void feed(){
digitalWrite(led,HIGH); // ここの出力を別のArduinoに検出させる。
delay(30000);
Serial.println("done."); // デバッグプリント。
digitalWrite(led,LOW);
} // end of feed().
中間報告その6 ~代替案→試作機完成~
2014/03/16
RTCの読み込みがうまくいかない不具合があったので、前回の報告通り、タイマー部分をソフトウェアで実装し、GalileoとArduinoを1台ずつ使って実装するという回りくどい構成になった。
Galileo側のソース
こちらは自力でスケッチを起こした。
/*
140316
Pseudo clock sketch for Intel Galileo.
Galileo側のソフトウェアクロックプログラム。
12時間ごとにloopメソッド内からfeed()を呼び出す。
*/
int h,m,s; // hours, minutes, seconds.
int led = 13; // # of output pin.
void setup() {
pinMode (led, OUTPUT);
Serial.begin(9600); // for debugging use.
}
// Pseudo clock. impremented by software using nesting delay.
void loop(){
feed();
for (h=0;h<12;h++){ //実際に使うときはここを使う。
// for (h=0;h<1;h++){ // 試験用。
for (m=0;m<60;m++){
for (s=0;s<60;s++){
delay(1000);
}
s=0; // 秒の繰上りを元に戻す。
}
m=0; // 分の繰上りを元に戻す。
}
h=0; // 時の繰上りを元に戻す。
} // end of loop().
void feed(){
digitalWrite(led,HIGH); // ここの出力を別のArduinoに検出させる。
delay(30000);
Serial.println("done."); // デバッグプリント。
digitalWrite(led,LOW);
} // end of feed().
工夫した点
- 起動させて約12時間後になるとGalileoのDigital13番ピンからArduino側にHIGH信号を送る。
- Galileoから送られた信号を検出し、サイロを開放するモーターの駆動を行う部分にはArduino とモーターシールド を使用した。
- Arduino側の電源はGalileo側のUSBホスト端子を使用した。(後日談:上手く動かなくなったのでACアダプタ経由に変更した。)
送信部
ピン13とGND(写真上部)で構成した。
受信部
先ほどの信号線2本はArduino側のAnalog in0とGNDに繋がる。(写真左側参照)
Galileo側出力がLOWの時はArduino側のアナログ入力信号レベルは10前後をうろつく。
一方、Galileo側出力がHIGHになるとArduino側の入力信号レベルは200前後に跳ね上がる。
これを利用した。
サイロ部分
1のカードの上に1食分の餌が載っている。
サイロ内
同様に2のカードの上にも餌が載る寸法だ。
メカ駆動部
- モーターシールドからモーターを駆動し、ギアボックスで巻き上げ時に必要なトルクを稼いだ。
- プーリーの代わりにマッチ棒で簡単な輪軸(この場合正方形になるのだが)機構を組み立てた。
Arduino側のソース
こちらはArduino IDEサンプルスケッチの"motor demo"に変更を加えて使うことにした。
motor demoスケッチの作者に感謝である。
/*************************************************************
* Motor Shield 1-Channel DC Motor Demo
* by Randy Sarafan
*
* For more information see:
* http://www.instructables.com/id/Arduino-Motor-Shield-Tutorial/
*
*************************************************************/
int sensVal=0; // アナログピン0の状態保存用変数。
const int aPin = 0; // どのanalogReadピンを使うかの定義。
void setup() {
Serial.begin(9600);
//Setup Channel A
pinMode(12, OUTPUT); //Initiates Motor Channel A pin
pinMode(9, OUTPUT); //Initiates Brake Channel A pin
// include the library code:
}
void loop(){
//forward @ full speed
sensVal = analogRead(aPin);
Serial.println(sensVal); // for debugging use.
if (sensVal > 200){
digitalWrite(12, HIGH); //Establishes forward direction of Channel A
digitalWrite(9, LOW); //Disengage the Brake for Channel A
digitalWrite(3, 255); //Spins the motor on Channel A at full speed
delay(3000);
digitalWrite(9, HIGH); //Engage the Brake for Channel A
delay(1000);
digitalWrite(9, LOW); // Disable the brake for Channel A
}
digitalWrite(9,HIGH); // brake A
} // end loop.
午後6時20分前後、無事試作機が起動した。
午前6時にGalileo側のスケッチを走らせたのだが、やはり時計をループの入れ子で実装しているため、誤差が出てしまった。
起動の様子
途中で餌が詰まったため、少ししか出ていない。
サイロ部分を揺らすと餌が全量供給された。
これでひとまずIntel Galileoを使ってのオリジナル試作機の開発状況は「一応」完成した。開発の苦労が報われる瞬間はとても嬉しいものだ、素直にそう思う。
だがまだ粗削りな部分があるので、改良していきたい次第である。
試作機の完成度が上がり次第、また報告したい。
中間報告その7 ~正常運用を目指して~
サイロ部分を工夫して、緩衝材を少し減らしてみた。
その後、タイマー動作から餌やりまでの過程を動画に収めたので、ぜひ見てほしい。
給飼後の写真はこうなった。
十字部分の緩衝材の内、1本を抜いた。
我が家の猫も大喜びである。(猫バカ)
試作機完成 ~試作機の紹介~
さて、記念すべき3月16日に試作機が完成し、その後ソフトウェア面、ハードウェア面両方の微調整を行った結果、試作機の完成度が「自動餌やり機」と呼べる域にまで達した(特に課題となっていた給餌時刻の誤差をある程度収束できた)ので、手前味噌ながら、筆者の試作機についての説明をしたいと思う。
特徴
- 12時間ごと(スケッチの改変により外部モジュールからの入力により時間間隔は変更可)の全自動タイマーによる給餌
- シンプルな構成による保守の簡易化
- 5V単一電源2つで駆動する経済性
制御系
まず、サイロ内の餌が落下しないように留めておくサイロストッパー(後述)に繋がっているストッパー制御糸(上部写真の1と書かれた部分)から、滑車がわりのロープ(上部写真の2と書かれた部分)に張力が伝達し、上部写真3のガイドチューブストッパーで固定されたガイドチューブ(上部写真4)の中を通り、ギヤボックスで巻き上げられる寸法になっている。
サイロ系
こちらが給餌の主軸となるサイロ部分である。完成の域に達したので赤テープを外そうと考えたが、このままでも問題ないので(少々見てくれは悪いが)そのままにしてある。
紙面の都合上、読みやすくするため上部写真のサイロストッパーは1段になっている(上部写真7-2参照)が、上部写真7-2のサイロストッパー先端(糸のついていない方)と上部写真7-1に挟むサイロストッパー末端とを糸で繋げることによって2段給餌を可能にしている。
上部写真6の給紙用サイロに7-1、7-2と同様の切り込みを等間隔で入れ、サイロストッパーを増やすことによって3段化、4段化への改造も可能だ。
サイロにためておく餌は上部写真に5と番号が振られている「給餌口」から充填する。
上部写真に8と記載されているサイロ固定機構はインシュロックで固定するよりも、写真のようにビニールテープで留めておく方がしなやかにサイロを固定できるため、敢えて変更しなかった。
以下、9-1、9-2と記載されている「サイロ傾き制御機構」で猫のエサ用の食器への排出口の傾きを手動で調整できる。
この部分は電動制御も考えたのだが、毎日猫の機嫌によって固定元のケージの物理的位置が変わってしまうので、止むを得ず手動制御になった。
あきえりあ(おまけコーナー)
おまけ企画(03/30)
インテリジェントなタイマーが欲しい!!
さて、自動餌やり機のタイマーであるが、誤差が数分あるものの12時間ごとに発動してくれている。おかげで筆者も早朝に叩き起こされることも少なくなった。
しかしながら、人間の欲望というのは底知れぬもので、しばらく試作機と付き合っているうちにある重大な不満点を発見してしまった。
うっかりして別のスケッチをGalileoにアップロードしてしまった時、それは起こった。
Galileo上の自動餌やりスケッチを消してしまった場合、また一からアップロードし直す羽目になる。勘のいい方ならもうこの時点でお気づきになると思うが、上記のスケッチでは電源投入時に初回の給餌が行われる仕組みになっているため、
- 必ず「06:00か18:00」までに保存していたスケッチをPCにロードし
- 時刻きっちりにスケッチをGalileoに転送
させなければならない。これでは本末転倒である。できることならこの際スケッチを再アップロードする時にタイマー時間の間隔も可変にしておきたいところだ。
で、作った。(相変わらず前置きが長い)
何を隠そう、(何も隠してないが)また別のArduino互換機であるDFRduino Uno R3にDFRobot LCD shieldを亀の子状に据えつけ、プログラムを書き込んだ
タイマーコントロールモジュールと
タイマーの時間をGalileo側に伝える
センサーモジュールである。
ちなみに、タイマーコントロールモジュールの電源はGalileoから拝借している。
センサーモジュール部、写真の黒い筒のようなものは熱収縮チューブである。
バラシてみるとこのように
LEDとCdSセルが対面状態になっている。
これで光学的にカップリングしているのだ。MIDI信号と同じ原理である。
何故このような謎構成になったかというと、実はGalileo(Arduinoも同じ、Dueは除く)、(本物の)アナログ信号の送信ができないのだ。ADCはあるけど、DACが無いのだ。
それゆえ、信号を直接タイマーコントロールモジュールからGalileoのアナログピンに結線してもサンプルを取る時間によって信号レベルは大きく変化し、使い物にならないのだ。
割り込みで信号線を監視するにしてもスケッチは煩雑になるし、ポーリング時間によってタイマーの構成も変えなければならない。
そこで筆者は考えた。ちらつくPWM出力を平滑化できないものか、と。
で、たどり着いたのがこの方式ってわけだ。
CdSは安価だし、そんなに高速な部品でもない(と思う)のでピッタリなのだ。
これで Galileo側のスケッチの追加は最小限で済んだ。
int h,m,s; // hours, minutes, seconds.
int led= 13; // # of output pin.
int interval = 12;
int i;
int refVal = 0; // CdS光量
void setup() {
pinMode (led, OUTPUT);
Serial.begin(9600); // for debugging use.
delay(3000); // 3秒間待ってやる!
} // バルス!
// Pseudo clock. impremented by software using nesting delay.
void loop(){
for (i=0;i<10;i++){
refVal += analogRead(A0); // refValの総計を取る。
}
refVal = refVal / 10; // refValの平均値を算出
// refVal判定ブロック
// 平均値の値によってinterval(時間単位)を決める。
// もっとスマートに出来ないものか。
if (refVal >= 46){
interval = 12;
}
if (refVal >= 48){
interval = 11;
}
if (refVal >= 50){
interval = 10;
}
if (refVal >= 53){
interval = 9;
}
if (refVal >= 56){
interval = 8;
}
if (refVal >= 60){
interval = 7;
}
if (refVal >= 65){
interval = 6;
}
if (refVal >= 71){
interval = 5;
}
if (refVal >= 79){
interval = 4;
}
if (refVal >= 89){
interval = 3;
}
if (refVal >= 105){
interval = 2;
}
if (refVal >= 135){
interval = 1;
}
// interval--; // 誤差修正 (for debugging use.)
if (interval <= 0) // ニューメリックチェック
{
interval = 1; // エラー時は1時間間隔にする。
}
これが追加したコードである。refVal(CdSが受け取った光量の閾値)は環境ごとに、また回路の構成や光学カップリングのやり方、LEDの色によってセンサーだけに千差万別になってしまうので、数値は参考程度に捉えていただければ幸いだ。
タイマーコントロールモジュールのスケッチは単にメッセージを表示し、キー入力を監視して、それに見合ったPWM出力信号をLEDに送信するスケッチだから貼るまでもないと思う。考えてみれば結構簡単に実装できるぞ!
そういうわけで、この試作機には1~12時間の1時間間隔で設定できるタイマーが加わった。凄く賢くなったのだ。
こんなの何処も売ってないよ!(自画自賛)
あきえりあ2 ~プロトタイピングから基板起こし~
さて、いつまでも
このようにブレッドボード上に配置していては格好が悪いし、何より次の機械を開発するためのブレッドボードが占有されていて、開発がやりにくい。
そこで、基板を起こすことにした。
これがそのセンサー基板である。
試作機なので試作機らしく紙エポ基板で作った。
基板右部分のピンソケットにタイマーコントロールモジュールからの信号を結線する。
また、万が一のカップリングモジュールの破損対策として、ENIACと同じようにピンソケット右から3列目にカップリングユニットをモジュラー形式にして、交換できるようにした。
ちょっともったいないが、右から4列目~10列目は結線していない。
タイマーコントロールモジュールとセンサーモジュールが正常に動いている場合は、左下のLED(パイロットランプ)が高輝度で点灯するように作っている。
電源が入っていないなど、タイマーコントロールモジュールに不具合があればパイロットランプは暗く点灯するように設計している。
筆者としては、部品面にジャンパーを2本も飛ばしてしまったのが少し悔しい。
まあ、試作機なので割り切ればいいだけの話だが。
あきえりあその3 ~正確に糸巻きする~
試作機レビューでちらっと説明したガイドチューブだが、宙吊りのままでは思うように糸巻きが出来ず、巻き上げるにしたがって、マッチ棒プーリーの内周から外周へと糸を巻いてしまう不具合が課題となっていた。
この問題を解決すべく、ガイドチューブ自体を巻き上げ機構近傍に設置することにした。
以下が、改修後の装置である。
ガイドチューブの出口をモーター機構のすぐ隣に配置することによって、この問題は解決された。
編集後記
~開発の楽しさ、醍醐味、興味深い点~
レビュー対象の製品と、それを使用したオリジナル試作機の開発過程をレポートしていく、というこの記事の都合上、本文はとてつもなく長大なものになった。
14/03/30
また、本文中盤で述べたとおり、最初のうちはエラーが頻発して1日潰れる、なんてこともあった。
しかしながら、電子工作やプログラミングを本業ではなく趣味の一つとしてやっている自分でさえ、エラーを潰して自分の思ったとおりに動く試作機を一応完成させることが出来た、ということに大きな喜びを感じている。
プログラミングを一つのアスリートの競技に例えるならば、今回の試作機開発(コーディングから始まり、プロトタイピングとフィジカルコンピューティング)企画はトライアスロンに似た印象を受けた。
どれもこれも中途半端な筆者だが、スケッチで行き詰ったら工作をして、工作で行き詰ったら電装系を考えて、電装系で迷ったら、…というように、根を詰めずに一つずつの作業をきちんとローテーションを組んで取り組んでいったらその成果が螺旋的に蓄積され、その結果として、成果物としての「試作機の完成」に(どうにか)漕ぎ付けることが出来た。
あるときは頭を使い、またある時は童心に還って図工めいたことをし、デザインが気に食わなかったら美術めいたことをできるこのレビュー企画、ならびに試作機開発の過程などは全て一人でやったので、苦しいこともあったが、最終的には「やってよかったな」、「挑戦してみてよかった」、「自分でもこんなものが作れるんだ」、と、喜びを感じている。まさに苦は楽の種である。
また、コミュニティ内では、筆者以上にスキルのある方々と気軽に意見を交わすことが出来、大変ありがたく、貴重な経験が出来たことを嬉しく思っている。
最後に、末筆ながら、読者の皆様方も、最後まで筆者の拙いウナギの寝床式の記事にお付き合いいただき、誠にありがとうございます。
・・・と、ここで締めくくるような文体になったが、まだまだ最終期限まで時間がある。締め切りまで使える時間を有効に利用し、一つ上の見出し「あきえりあ」の項目に何か新しく、そして筆者のみならず、読者の皆様方にも「実に面白い」と感じていただけるようなことを書けるよう努力したい。
14/04/18 最終報告
さて、ここまで駆け足で開発と試作機のレビューを行わせてもらったが、今日で筆者の提出したプロジェクトは報告期限を迎える。試作機も無事完成したことであるし、この項を以て一旦レビューに区切りを打ちたい。
これまでの開発記録やその結果完成した成果物、またそれに関わるプロセスを時系列、発生した問題ごとにつらつらと書き綴らせてもらったが、いかがだっただろうか。楽しんでもらえたら幸いである。
ちなみに、この自動餌やり機にかかった費用を概算すると、次のようになる。
- Galileoボード 7000円
- Arduino uno 3またはその互換機 x2 ~7000円
- LCDシールド 3000円
- モーターシールド 4000円
- 段ボールのライナー部分だけ巻いたボール紙 600円
- ストッパーカード 100円(100円均一の情報カード(名刺サイズ)を利用)
- モーターとギアボックス 1000円
- 糸、セロテープ 200円
25000円もあればお釣りがくる算段だ。
これを安いとみるか高いとみるかは各人の判断に任せたい。(たぶん高いと思われる方が大半だ。)
反省点(失敗エピソード)
実は、モーターシールド部分を汎用のモータードライバIC(Toshiba TA7291P)で簡略化&低コスト化したかったのだが、時間的な事情により、プロトタイプはブレッドボード上に作成できたものの、ついに期日までには実装することができなかった。
プロトタイプ。
緑の信号線で回転、逆回転を決める。
ロジック電圧とモーター電圧の都合上、本家のモータードライバシールドより速度は落ちる。
無事実装できていれば、前述のモーターシールド部分の価格は1/6以下(150円@IC と200円@基板)(配線材は含まず)というお手ごろ価格で実現できたはずだ。コストダウンにチャレンジできず、また、自作モータードライバ基板を披露できなく、申し訳なく思うとともに、筆者としても心残りである。
余談
なんと、Intel Galileoであるが、つい先日生産中止がアナウンスされ、次世代モデルとしてIntel Galileo2が発表になった。
初代で欠点となっていたI2Cの低速さによるシールド互換性や、電源の接続順序の煩雑さ等がどう改善されているか、筆者としても今後の動きに目が離せそうにない。
Manyaさん
2014/03/07
ラップの芯を見ていて思いつきました。
ラップ内にスクリューを仕込んで、
モーターでスクリューを回しても一定量供給を達成できそうですね。
駆動系も一つで済みそう。
ただ、丁度良いスクリューがあるかどうかが問題ですね。。。
しばさん
2014/03/07
有益なアイデアコメントありがとうございます!!
船のプラモデルに使うようなスクリューを取り付けたら上手くいきそうな気がしてきました!
ラップの芯だとサイロにするには何本もいるし、芯が固くて加工が難しいので、段ボールのライナーだけのやつでサイロ2号(仮)を作ってみました。
んー、まだまだ道のりは遠いです・・・><;
ちばとどさん
2014/03/07
ねこえさが1回分ずつ入ったサイロが数本あって、その下に1つ分だけ穴の空いた円盤を付けて、その円盤を1回毎に必要な角度だけ回まわすという考えです。円盤にベルトを付けて回すか、軸に直接モータを直接付けるかです。
図で伝わりますか?このままでは作れないと思いますけど、アイデアだけです。
Manyaさん
2014/03/07
いろんなアイデアが出てきて面白いです^^
しばさん
2014/03/08
そ、その発想はなかったです…!!
アイデアは絶賛受付中です(*^-^*)
タコシーさん
2014/03/17
お疲れ様でした
しばさん
2014/03/18
ちばとどさん
2014/03/19
ねこ「あ、時間だ! にゃんにゃん」
カラコロン。(カリカリが1個落ちる)
ねこ「あれー?1個? にゃー」
はたして、ねこはご飯をたべらるのか! 本格運用、楽しみにしてます。
しばさん
2014/03/19
昨日運転したときは、サイロ末端の緩衝部分を除去したので、めでたくカリカリが全部落ちましたよ~。(*^-^*)
蒼-aoi-さん
2014/03/30
感動・感心してレビューを拝見しておりました。
大変だけど楽しい感じがすごく伝わってきます!
私も昔、自動餌やり機にチャレンジしたことがあります。
結局、完成はできなかったのですが...(汗
案1:
CDRのスピンドルケースの一部に扇形に穴をあけ、中に着けた十字の間仕切りをモーターで回すことで、4回分くらいの餌が出る感じ。
→ドライフードが挟まった時に、バゴンといい音がして、猫ビックリ!
案2:
調味料入れに餌をいれ、モータでふたをパカッと開ける感じ。
→猫が勝手に開けて、モータで開けた時には、すでに空。
案3:
筒の中にスクリュー(ワカサギ釣りの穴あけのような)を入れて回して、グリグリと出てくる感じ。
→餌が詰まりやすくで、すぐに回らなくなる。
案4:
ペットボトルに餌を入れ、その下に振動板をあてがい、モーターでブルブルさせると、えさがポロポロと落ちる感じ。
→振動が強すぎて、餌が粉化して、猫むせる。
そもそも、うちの猫はモーター音が怖くて、どのパターンであっても、餌やり機に近づけなかったんですけどね(笑)。
しばさん
2014/03/31
コメントありがとうございます、そしてアイデアまで!感謝です!!
>>All
コメントでいただいたアイデアは色々考えて実装できるものはやっていきたいと思います。