SSDに換装したWindows7 AHCI モードでクラッシュ

一世代前のノートブックパソコン、まだまだ使えるのだが、動作がやや緩慢、そこで最近ぐっと購入しやすい値段になってきたSSDに換装してみた。 使ったのは250GBのSamsung840EVo。
Windows用のマイグレーションソフトウエアが付属してくるのでUSBを通してSATAに接続できるケースさえ手元にあればディスクイメージのコピーは問題なくできる。 あとはパソコンの裏ケースをはずし、HDDを取り出して、SSDを組み付けるだけ。ただし、Dual Bootで入れておいたMint Linuxはきれいに無視されるので、バックアップとリストアをしっかりおこなっておいて、再導入する必要があった。またWindowsのリカバリーパティションも複製されないようなので、リカバリーディスクを作成しておく必要がありそうだ。
Windows7の起動とアプリケーションの起動が圧倒的に早くなった。 めでたしめでたし、と思ったが、付属のSamsung Magicianという管理ツールを使ってみると、AHCIモードが無効になっているので、最適状態ではない、というようなメッセージが出ている。
AHCIというのはディスクの管理モードのようで、BIOS画面を見るとHDDのアクセス方法の選択肢の一つになっていた。 このパソコンの規定値はIDEアクセスモードになっており、これをAHCIに変えてやればよいと思ったのだが、設定を切り替えて作動させてみるとWindowsが起動途中でクラッシュする。いわゆるBSOD(Blue Screen of Death=青いエラー画面)が出てその内容を読む暇もなくリセットがかかる。

しょうがないので、Bios設定を元にもどし、再起動。 Google検索で”BSOD Windows 7 AHCI SSD”のキーワードで検索したら、 以下の記事を発見。なんと4ねんん以上も前に書かれている。こういうEarly Adapterがいてくれるおかげで後からついていく我々はネット検索するだけで問題解決ができてしまう。

HKEY_LOCAL_MACHINE / SYSTEM / CurrentControlset / Services /msahci
このレジストリの値を0に変更(自分の場合は3になっていた)してWindowsを終了し起動の途中でF2キー(Deleteキーの場合もある)を押してBios画面を呼び出して AHCIに設定しWindows7を起動すると今度はクラッシュすることなく必要なドライバーを導入した後、再起動を促されるのでもう一度リブートして解決。

Python、comprehension を使った一括処理

Pythonには” … for … in”という構文を使った、一括でメンバー要素を処理する機能がある。Comprehensionと呼ばれ、リスト、セット、辞書に使える。
リストの使用例

>>> a_list =list(range(10))
>>> a_list
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a_list = [x**2 for x in a_list]  --List comprehension
>>> a_list
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

If を使い、要素のFilteringをしてから処理することもできる。下はリスト中、偶数だけを処理して新しいリストを作成した例。 

>>> a_list = list(range(10))
>>> a_list = [x**2 for x in a_list if (x%2 ==0)]
>>> a_list
[0, 4, 16, 36, 64]

Python Dictionary の キーと値をスワップして新しい辞書を作る。

>>> week_dict={'Mon':'月','Tue':'火','Wed':'水','Thu':'木','Fri':'金','Sat':'土','Sun':'日'}
>>> youbi_dict={value:key for key,value in week_dict.items()}
>>> youbi_dict
{'木': 'Thu', '土': 'Sat', '月': 'Mon', '火': 'Tue', '水': 'Wed', '日': 'Sun', '金': 'Fri'}
>>> week_dict
{'Mon': '月', 'Fri': '金', 'Tue': '火', 'Sat': '土', 'Sun': '日', 'Wed': '水', 'Thu': '木'}
>>> week_dict['Fri']
'金'
>>> youbi_dict['日']
'Sun'

辞書は順番はキープしないのだ。

Raspberry Pi でパソコン電源をInternet上から操作

家の外部からタブレットなりノートパソコンなりを使って自宅のパソコンにリモートアクセスするためのアプリというのは色々ある。Internet経由でアクセスする、というもので、Linuxでは当たり前のように実装されているし、 WindowsでもRemote Desktopというアプリケーションが同梱されているし、ファイアウオールでRemote Desktopが使えない環境でもWebベースのTeamViewer とかlogmeinというサードパーティの製品を使えばセキュアな接続がいとも簡単にできてしまう。 Chromeをブラウザとして使用しているのならChrome remote desktopというアプリが今の旬である。

 なぜそんなことが必要か、という疑問が湧くかもしれないが自分の場合、外部からお気に入りの開発環境にログインし、コード開発を一つのマシン上で行う、という使い方がメインになっている。 もちろん将来的にすべての作業がブラウザ上でできる、という環境が構築されればそんな必要はなくなるわけだが、

問題はパソコンにアクセスするには当然のことながら当該パソコンの電源が入っていなくてはならない、という事。
 エコの観点からみると年がら年中つけっぱなしになっているパソコン、というのはエネルギーの浪費に見える。 WEBサーバーを自宅のパソコンを使って構成していた時には電源をつけっぱなしにするしかなかったのだが、アイドル状態でも常に80Wくらいの消費電力が発生していた。
 現在はCubieboardという、手のひらに収まるサイズのArmcortexの開発ボードをサーバーとして使って賄っており、消費電力は3W以下だ。

で、パソコンの電源を使うときだけ遠隔操作でオンする方法がないか調べてみた。

 InstructableにElectric Impというモジュールを使って電源のオンオフをする方法が紹介されている
このモジュール、SDカードと同じform factorだが、内部にWifiモジュールとArm Coretex M3を内臓したれっきとした開発ボードであって、クラウドサービスに接続してパソコンやタブレット上から専用のコントロールパネルアプリを使って接続されたデバイスのリモートコントロールができるようになっている。

InstructableではこのElectric Impに簡単なトランジスタを追加して、PCのPower switch lineを瞬間的にショート状態にする。(つまりパソコンのスイッチを押したのと同じ状態にする)ことによってPCを起動する方法が述べられている。 Electric Impの値段は25ドル程度だが、サポート用の部品(Imp用のブレークアウトなど)を買い足すと40ドルくらいの出費になりそうだ。
自宅でcubieboardのWEBサーバーを随時動かしているのであえてアカウントを作ってクラウドを使ってコントロールする必要はないわけで、 そうすると似たようなことはArduinoでもできるはずと思うわけだが、これまたArduino本体にWifi、あるいはEthernetシールドを追加すると40ドルくらいの出費になる。 CubieBoardのGPIOをパソコンのスイッチに接続して操作することも可能だろうが、部屋が2階と地下室に分かれているし、メインサーバーになっているカードのGPIOで他のデバイスをハードウエアコントロールというのは安全性の面から心理的抵抗がある。

そこで遊び終わって引出しに眠っていたRaspberry Piを使うことにした。Desktop用のLinuxが走るほどのグラフィック性能を持つボードをただの電源スイッチとして使う、というといかにももったいない感じがするのではあるが Piの値段も含めて40ドルくらいで済んでしまうのでコストパーフォマンスの面から考えると他の方法に比べても高くはない、というか他の手間を考えるとこちらのほうが安上がりの感じ。

調べてみるとデバイス制御をPythonベースのhttp サーバーから実行できるWEBIOPIというPi用のライブラリーを発見した。 これをインストールするとGETとかPOSTのHTTP用のプロトコルを使ったRESTという手法でハードウエアのコントロールができるようになる。 つまりWEBサーバー上にページを作り、そのページ上にボタンを描画して、WEBIOPIで提供されているRESTコールを紐つけるという方法でPiのGPIOピンの遠隔操作ができるようになる。 このRESTという手法、非常に単純で、urlのパスに模してパラメーターをサーバーに送ってあげるというもの。GETはアドレスをブラウザで指定するだけで実行できるのでたとえば APIですべてのGPIOの状況を取得するAPIを使うには webiopiをバックグラウンドで走らせている状態で、

https://example.com/GPIO/*

とアドレスをブラウザに打ち込むだけで、Jason書式でGPIOの各ピンの状況が返ってくる。 ただし、これではページの表示自体がJasonのレスポンスになるので実用的ではなく、実際にはJavaScriptでコードを書くことになるが、webiopiにはうwebiopi.jsというヘルパーファイルが同梱されているので、使う難易度は低くなっている。

GPIOの使い方だが、
出力用に設定したGPIOピンをトランジスタを介してパソコンの電源スイッチとパラレルに接続し、パルス上の信号を出力してやるとパワースイッチを押したのと同様のことになり電源が立ち上がる。(電源が入っているときには逆に電源が落ちる)。電源スイッチへ接続されるピンはパソコンのマザーボード上のフロントパネルコネクター部分(パソコンケースのケーブル類を接続するコネクタ部分)に接続ピンがあるのでワイヤーをスプライスしてつなげてやればよい。。
また信号を出す前にパソコンの電源が入っているかどうかをわかっている必要があるのだが、フロントパネルコネクターには電源表示用のLEDへ接続されるピンも存在している。 そこでこのピンをGPIOでモニターすることによってパソコンに電源が入っているかどうかの判定をすることにした。

実際に組んだ回路。使ったGPIOピンは25をパワースイッチ用の出力に、24をLED電圧モニター用の入力にそれぞれ使用。 IntelのPC Interface 仕様(下に抜粋を載せます)を読む限り、パワースイッチ端子はトランジスタに直接接続(PWR+をコレクタ側に、PWR-をEmitter側に)しても大丈夫と思うが、5Vの小型リレーがたまたま手元にあったので使ってみた。NPNトランジスタのかわりに2N7000のようなFETを使えば、R1は必要ない。入力ピンのほうはLEDのVfでクランプされる電圧になるので規定の3.3V以下。万が一LEDがオープンとなっ場合5Vかかってしまうが、GPIOには保護用のクランプダイオードくらいはいっているのだろうと勝手に思い込んでいるので,保険は電流制限のR2のみ。

Table 5. Switch/LED Front Panel Electrical Connection

Pin Signal Description
2 FP PWR/SLP MSG LED pull-up (330 ohm) to +5 V
6 PWR_SW_P Power Switch high reference pull-up (10000 ohm) to +5 V
8 PWR_SW_N Power Switch Low reference pull-down (100 ohm) to GND

贅沢の極み?

贅沢の極み?


html pageの記述


<!DOCTYPE html>
<html lang="en">
<head>
<base href="https://example.com/" />
<title>PC power </title>
<!--[if IE]><script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
</head>

<body>
    <h2>Turn On Basement PC</h2>
    
パソコンの電源操作ボタンでやんす。!
<form class="buttonBar"></form>

<script type="text/javascript" src="//code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript" src="poweronbutton.js"></script>
</body>
</html>

参照されているJavascriptの記述

/**
 * Created on 5/4/14.
 * poweronbutton.js となっているが、実際にはGPIOのモニターも行う総括的なコード
 * powerbutton element id='pb'
 * html form tag class = buttonBar.
 * GPIO #25 connected to 1n2222 which drives spdp relay to momentariry close power switch.
 * PC power switch is momentary switch.  if PC is off, it will turn on PC.  if PC is on, it will turn off pc
 * relay connected to power connections of PC system panel terminals.
 * GPIO24 connected to Power LED terminal.
 * webiopi (python httms and coap server) installed on target raspberry pi
 *
 */
function setupGPIO(){   // set GPIO25 to out for pc power switch connection.
                        // and  GPIO24 to in  for monitoring PC power LED terminal status
    $.post( 'https://example.com/GPIO/24/function/in',
        function(data) {
            if (data==='IN')setTimeout(monitorPower(),1000);
                  });
    $.post( 'https://example.com/GPIO/25/function/out',
        function(data) {
            data =(data=='OUT')?'PC Power':'setup failed';
            $('#pb').attr("value",data);

        });
}

// }
function turnon(){ // RET command to output pulse
    $.post(
        'https://example.com/GPIO/25/sequence/1000,010',
        function(data) {
            data=(data==0)?'Power switch pushed':'NG';
            $('#pb').attr("value",data); }

    );
}
function monitorPower(){//monitor GPIO 24 status every one second
    $.get('https://example.com/GPIO/24/value',
        function(data){
            data= (data==='0')?'PC is OFF':'PC is ON';
            $('#powerstatus').html(data);
    setTimeout(monitorPower(),1000); //call myself every 1second

})

}
$(function(){
    $('<input type="button" class="power" id="pb" />')
        .appendTo('.buttonBar')
        .attr("value", "Initializing")
        .attr("title", "Turn on Somethin'")
        .click(function () {
            turnon();
        });
    $('<div></div>')
        .appendTo('.buttonBar')
        .attr('id','powerstatus');
      setupGPIO();
    }
);

ターゲットのRaspberry Piにwebiopiが導入され起動されていることが前提になる。 また、上の方法では同梱されてくるwebiopi.jsは使わずに自前のJavaScriptでREST APIを直接アクセスしている。

ページの仕組み:
ブラウザーがページを読み込み終わった時点で、上のjavascriptが以下の作業を実行する。
ボタンを描画し、ボタンのラベルを”Initializing” と表示する。
GPIO25を出力ピンに設定。 ボタンのラベルを”PC Power”と書き換え、ボタンのクリック動作にパルスを送信するRESTコマンドを紐つける。
GPIO24を入力ピンに設定。同時に入力ピンの1秒ごとのモニターをスタート。WEBIOPIからRESTで返された状況に応じてページ上に”Power is ON” または ”Power is OFF”を一秒ごとに更新表示

JavaScriptの部分はRefactoringやnamespacing をやっていないので改善の余地あり。またPower LEDのモニターだけではパソコンがオンしていることはわかっても、実際にWindowsが立ち上がっているかどうかはわからないので、何らかのインターネットサービスをPi側からモニターする手法を併用するほうがよさそうだし、CSSの記述も追加してページの見栄えもよくしたいと思うが、一応初期の目的はこれにて達成。

なお、WEBIOPI自体にログイン形式のセキュリティ機能が実装されており、ページの最初のロード時にログインネームとパスワードを聞いてくる仕組みになっている。ログインとパスワードの初期値がそれぞれ”webiopi” と”raspberry” となっているので、マニュアルの手順に従って変更しておく必要がある。

また、Raspberry Piへの電源だが、パソコンの電源に5V standbyが存在しているため、ここから引き込んでいる。24p/20pコネクタの紫の線だが、マザーボードの電源側への要求スペックが500mAで電源側の仕様が2Aなので余裕のようだ。Raspberry PiもPCの筐体に入れてしまったので見た目もすっきりである。

<後記> 電力消費計を入手したので、実際のところ、どれだけエコになっているのか測定してみた。 パソコンを普通に電源投入すると80Wくらの消費になっていた。 パソコンをオフにすると7Wだ。パソコン用の電源が動いていて5Vのスタンバイ電源からPiとその他に供給しているということだ。 その差73Wだが、電気代で考えるとまったくパソコンをオンしなかった場合、年間約50ドルちょっとの節約になる。パソコンの稼働率が10パーセントくらいと仮定すると45ドルの節約なので1年でもとが取れる計算になる。

困ったときはログファイル

Cubieboard2 (Arm7 Cortex Dual core 1GHz, 1GByte Ram, 4GByte Flash, OS=armhf debian 7) という、約60ドルで中国から購入したデベロッパーボードを使って運営しているホームサーバーの管理にISPConfig3という管理ソフトを導入して使用している。 Mailサーバー、Webサーバー、DNSそしてnginxプロキシなどをWEBブラウザから一括管理できるので重宝している。
このツール、HowtoForgeというサイトでサポートされていて、”Perfect Server” というシリーズで多様な組み合わせのサーバー設定のチュートリアルが掲載されている。 たとえばこの記事はOSはDebian,サーバープロキシにnginx, mailにはDoveCot、DNSにはBindを使ったサーバー構築の手順が述べられており、実は自分のサーバーはこれを参考にして立ち上げた。(DNSとNGINX、PHP、MySQLの部分はともかく、メールサーバーとメールフィルターの設定は自分ひとりの能力では手も足も出なかった。きちんと設定できたのは上の記事のおかげである)
 最近バージョンのアップデートをしようと思い立ち、コントロールパネルに指示されているiSPsonfig-update.shというコマンドを実行してみた。  アップデート自体はまったく問題なく行えたのだが、 コントロールパネルにログインしようとしてみたところいつもログイン画面が出るはずのurlが空っぽのページになっている。 
他のサービス(メール、Webサイト、DNS、SSHなど)は普通に動いているので、IPSConfigのダッシュボードへのログインが表示できないという限定された不具合だ。 幸いなことにISPConfigのUpdateツールがまず実行するのは旧バージョンのバックアップなので最悪の場合はリストアを行えばよいが、ページのヘッダー情報を見てみると、エラー番号が500、Internal Server Errorとなっているので、これはPHPの実行時、ページレンダリングの途中でおかしくなっている、とあたりをつけた。 NginxのErrorLogを眺めてみると大当たり、Fatal Errorが記録されていた。

11:54:25 [error] 3452#0: *528 FastCGI sent in stderr: "PHP message: PHP Warning:  require_once(/usr/local/ispconfig/interface/lib/config.inc.php): failed to open stream: Permission denied in /usr/local/ispconfig/interface/web/index.php on line 31
PHP message: PHP Fatal error:  require_once(): Failed opening required '../lib/config.inc.php' (include_path='.:/usr/share/php:/usr/share/pear') in /usr/local/ispconfig/interface/web/index.php on line 31" while reading response header from upstream,云々

上のエラーメッセージはindex.phpの31行目config.inc.phpを読み込もうとしたところ、拒否されました。と言っている。 ../libr/config.inc.phpのアクセスレベルがきつすぎるようだ、。
そこでこのファイルを調べてみるとOwner,GroupともISPCONFIGとなっているのは良いとして、Ownerのみに読み書き権限があたえられており、Groupレベルで読み書き禁止となっている。  それではと、Groupレベルでの読み出しも許可に書き換えてみたところ、あっさりと復活した。

#  chmod g+r config.inc.php

これが普通とは思わない。何らかの理由でサーバーのワーカープロセスとファイルのオーナー情報が背反しているためにファイルアクセスできなくなっていると考える。 少し思い当たることがあって、同じサーバー内部でModxを使ったサイトを運営しているのだが、アップデートするたびにSetupフォルダーをマニュアルで削除しなくてはならない、という作業が発生している。 Setupフォルダーの削除はインストール画面でチェックをいれてやれば自動的に行ってくれるはずなのだが、このサーバーではそれができてない。

というわけで、本日わかったこと。
1. Linuxのアクセスレベル管理がいまいち理解できてないなあ。
2. Linux 不具合解析はまずError Logを読む事。

Python でテクストファイルを読み書きする。

With と For iterater を使うとファイルを明示的にクローズしないでもよいそうだ。
例題でやっているのはTest.txtというファイルから一行ずつ読み込んでリストを作成し、それをリストオブジェクトのSortedメソドで並び替えをしたのち、test2.txtというファイルに書き戻す、という作業。 なんか簡単にできるし(簡単だけど)、コメントを入れなくても読み解きやすい感じ。このあたりがPythonの強みか。

a_list=[]
with open("test.txt", mode="r",encoding='utf-8') as a_file:
     for a_line in a_file:
         a_list.append(a_line.rstrip())

a_list = sorted(a_list)

with open("test2.txt", mode="w", encoding='utf-8') as a_file:
    for a_line in a_list:
        a_file.write(a_line+'\n')

PIC マイコンライターを入手したので….

30年ほど遅れたがPICマイコンのことを調べてみようと思った。

入門用に使ってみようと思うPICマイコン、資料を見ると16F84というのが盛んに議論されているが、Microchipのホームページをみてもこのマイコンはリストアップされていない。型番が古いためのようで、Gooligum Electronicsのサイトによれば、最近のPICマイコンのラインアップでさらに性能が向上し、かつ安価で入手性が良いのは以下のようなものになるらしい。

性能によって 4つのファミリーに分けられる。
BaseLine :12ビット命令系 割り込みがないなど制限があるが単純で使いやすいとのこと。 10F200(6端子)12F509(8端子)、16F506(14端子) など
Mid-Range: 14ビット命令系 BaseLineの拡張版で割り込み制御、メモリーの増設PWM、モーターコントロール、I2C,SPI I/F やLCDコントロールなどの周辺回路の追加、、 12F629(8端子) 16F690(20端子) 16F887(40端子)など. このシリーズが16F84の系統らしい。
Enhanced Mid-range:14ビット命令系 Mid-rangeの拡張版でさらなるメモリーの追加、命令群の増設、Cコンパイラ用に最適化したメモリーアクセス手順、改善された実行速度など 12F1501(8端子)、 16F8124(14端子)、16F1946(64端子)など
High End : 16ビット命令系 いわゆる18Fシリーズ 周辺回路にUSB,Ethernet、CANとの接続性が追加され、メモリーもプログラムは128Kまで、データも4Kまで対応 18F1220(18端子)、18F2455(28端子)、18F8520(80端子) など
ややこしいのは、これらのマイコン、インストラクションは12~16ビットの幅があるが扱うデータが8ビットなのですべて8ビットマイコンだということ。

Mouser.comで値段をみると 12F509-I/P $0.85、12F629-I/P $1.10 、12F1501-I/P $0.92 (すべて8端子)ということで、 BaselineとEnhanced Mid-rangeとでは値段に差がない。 それならよりパワフルらしい12F1501をベースに勉強してみようかと思ったのだが、 データシートの最初の数ページを読んで挫折した、というか 勉強するのをやめた。
何故か。
PICマイコンはプログラム領域とデータ領域が別に取ってある。 プログラム領域は連続しているのだが、データ領域は128本の8ビットデータレジスタ(ファイルレジスタ)を一つのバンクとして、最大32のバンクを切り替えて使うようになっているらしい。 ただし同じデータをどのバンクでもアクセスできるようにいくつかのレジスタは同一レジスタへのアクセスなのだ。(たとえばバンク切り替え指定のレジスタなど) AVRに比べると煩雑な感じである。 それなりの理由があってこうなっているのだろうが、 これはもういけません。 自分の頭脳がこの先を読むのを拒否しております。

というわけでPICマイコンの勉強はしばらくおあずけ。

Arduino でAVR マイコンのプログラム

前回、手持ちのArduino MicroでAVRマイコンのライターを作成したので、それを使ってAVRマイコンをプログラムしてみる。

用意したのはAtmega168Aという28ピンのチップ。 買った状態では内部発振の1Mhzで動くようになっている。内部発振では1Mhzと8Mhzを選択できる。ちなみにArduino Unoは同系列の328P

まずは手始めにArduinoのIDEを使ってArduinoのスケッチを書き、コンパイルさせてAVRチップにアップロードしてみる。手順さえ間違わなければ これでちゃんと動作してしまうんである。

168AVRのチップのピン配列(PortB,PortC,PortD etc.,) と Arduino式の(D0~D13,A0~A5) ピン配列の関係についてはここにマッピング情報がある。 LEDのBlinkスケッチを使う場合、LEDを接続するD13に該当する出力ピンはPB5である、ということがわかる。

蛇足ながら、PB6とPB7はArduinoボードではクリスタルに接続されているために入出力ピンとしては使えないが168を内部発振で使う場合には使用可能、ただしDigitalPinの定義がないので、Cに落とした記述が必要。

IDEのメニューからTarget Board を選ばなければならいないが、当然のことながらAtmega168などという選択肢はない。ので、Arduino Pro Mini(with 8Mhz Atmega168)というのを代わりに選ぶ。

ただし、AtMega168は工場出荷時の内部クロックは1Mhzに既定値設定されている(内部発振8Mhzを8分割) 上記のBoard 選択では8Mhz 用にコンパイラがタイミングループを調整するので1秒の点滅を指定すると8秒の点滅になる。 これが嫌ならAVRDUDEを使ってAtmegaのFuseを書き換え内部クロックを8Mhzに設定するか、または Arduino/hardware/arduino/boards.txt にならって1Mhz のAtmega168をバリエーションとして追加してあげる必要がある。
8Mhzに設定するにはAVRDUDEを使ってフューズ設定を書き換えることになる。

C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avrdude.exe-c arduino -p atmega168 -P com5 -U lfuse:w:0xe2:m

Boards.txtへのアイテムの追加はこの記事が参考になる。

Arduino IDEではShiftキーを押しながらアップロードボタンをクリックするとUSBに接続されているライターを使ってターゲットBoard(Arduinoまたはマイコンチップ)にコードをアップロードしてくれる仕組みになっているが、このためにはToolメニューの中からプログラマを指定する必要がある。Arduino Unoをライターとして使う場合は”Arduino as ISP” という項目を選べばよいのだが、自分が使っているArduino Micro はこれでは動作してくれない。(Leonardでも同様) この設定はArduino/hardware/arduino/programmers.txtというファイルにあるが、Unoに指定の

Arduinoisp.protocol=stk500v1

ではうまくリセットがかからないようだ。以下のようにこのprogrammers.txt にMicro/leonard 専用の選択肢を追加してIDEを再起動し解決

arduinoisp.name=Arduino Micro or Leo as ISP
arduinoisp.communication=serial
arduinoisp.protocol=arduino
arduinoisp.speed=19200

これで、Atmega168のPB5にLEDを接続し、BlinkスケッチをダウンロードするとLEDが点滅を始める。

Arduinoを使うと豊富なライブラリーが使えるという利点があり、ATtinyをArduino IDEでプログラムしようというプロジェクトもあって資料も豊富だ。

欠点としては

1.ターゲット用にBoards.txt項目を追加する必要がある。 ただし、一度の作業。

2.Arduino IDEの使い心地。 これは個人的な嗜好の問題だがAVR用にC/C++をコーディングするのならArduino IDEよりも強力な無料のIDE (Eclipse with AVR  plugin [Linux, Windows],   AtmelStudio [Windows])が存在する。

突然我が家にPICプログラマ(ライター)がやってきた。

近所で立ち寄れる電子部品を扱う店がRadioShack以外はほとんど壊滅状態になった今日この頃、米国で電子工作に使う部品とか工具を入手しようとすると通信販売に頼るのが普通だろう。 ざっとあげてみるだけでも、ICなどの電子部品はDigikey.comかMouser.com 。
この二社は工場で使うような大口注文からホビースト向けにICのばら売りまでこなしてくれるので重宝する。スイッチとかモーターなどはallelectronics.com。あとはAmazonをみれば大体なんでも入手できる感じ。 またHobbyist専用のキットやSMTのセンサー部品などを扱いやすいように小さな配線板にモジュール的に実装した製品などはadafruit.comやSparkfun.comなどが品揃えも豊富かつ対応が早い。 少し時間がかかるのを覚悟すれば中国からSeeedstudioなども使える。

で、やっとこさ本題に入るが、Sparkfun.comでは年に1度か2度の頻度で梱包があいているものとか、傷不良、旧製品などの半端ものの処分をする。 形式としては、縦横15cm、奥行き20cmくらいの箱に雑多な製品や売れ残り品を詰め込み、福袋のようにして(この場合は福箱か) Dumpster Dive と銘打って売り出す。 数量的には100個くらいのようで、インターネットで時間を決めてよーいドンで始めると2分くらいで完売する。

ところでDumpster Diveという言葉だが、 dumpsterというのは路地の裏側などに置いてある大きなゴミ箱のことである。 このゴミ箱を漁ろうとするとよじ登って入り込み、それこそ潜って物色するような感じになる。 乞食や浮浪者だけではなく、大きな食料品店やレストランのdumpsterは普通に食せるものが平気で捨てられている、ということで、Dumpster Diveの愛好者グループも存在する由である。

そんなところからSparkfunのサイトでも何が入っているかわからないよ、ということでDumpster Diveと銘打ったイベントになっている。

今回、クリックしてみたら運よく購入することができた。 $10プラス送料で一体何が送られてくるか楽しみにしていたのだが、 送ってきたものを開けてみれば想像以上の収穫だった。

  1. CanaKit USB PIC Programmer: Microchip純正 PICKIT2 と完全互換の PICマイコン用プログラマ。まともに購入すると販売価格60ドルくらいである。Firmware 更新用のボタンスイッチの上部がとれていたが、マイコンのプログラムには全く支障がないことを手持ちのPIC18F2550で確認。ボタンも手持ちの押しボタンスイッチに半田付け交換し、完全復帰。PICKIT2と違ってICPの他に40ピンのZIFソケットも付いているのでDIPマイコンを直接焼くことができる。
  2. PCduino: Allwinner A10を実装したArduinoとピンコンパチのArmCortex Development board. これまたMotorolaのLapdockに接続し、内臓2GBフラッシュからLubuntuが立ち上がることを確認。 wifi内臓+Arduinoシールド互換のPcduino2が出たので、Sparkfunはpcduinoの扱いをやめ、旧品在庫として処理したらしい。 これもまともに買えば50ドル以上はしそうだ。
  3. FTDI USB シリアル コンバーター: このブレークアウトほしかったんだよね。上のPcduinoにも実装されているDebug用のシリアルピンに接続するにぴったりではないか。 小売価格15ドル
  4. I2C対応室外用ソーナーモジュール X2 : 1個90ドルくらいするはずなのだが、車載用のバックアップウオーニングか自立歩行ロボットでも作りますか?
  5. 車両Diagnostic Kit: 車両のダイアグコネクタに接続して車両情報を読み取るためのモジュール。コネクタケーブル付き。やはり普通に買うと60ドルくらいする。
  6. 電解コンデンサーが山ほど。
  7. コンパレーターIC,A/DコンバーターIC、Opt Interrupter、ギャップセンサーICがそれぞれ一個づつ.
  8. Banana plug端子が半ダースほど
  9. USBのBlueToothドングル一個
  10. Stepper motor のドライバーボード、6枚続きのアレー状態が一枚。これをうまく切り離すことができれば使えそうだが、手持ちのロータリーツールで破損させずに切断できるかな。
  11. 3ピンロータリーエンコーダ

小売価格としては恐らく300ドル以上は行っている。たまたま当たりだったのか、いつもこんなものなのか、こういうセールがあればまたチャレンジしてみたいと思った次第。

一番嬉しかった(困った?)のはPICプログラマである。 前にも書いたがPICマイコン始めてみたいと思っていたのだが専用プログラマが高いので遠慮していた。それが入手できたのでもう言い訳ができなくなってしまったわけだけれど、今、AVRマイコンの学習も佳境に入っているところだ。 週末の日数が足りないよ..

Arduino でAVRプログラムライター

先回、ArduinoのIDEに同梱されているスケッチでAVRプログラマを作成できると知識だけで(無責任に)書いたのだが、本当にできるんだろうね、と検証してみたので結果を書いておく。

結果  できました。

前置き:
ATMELのサイトを眺めてみると、もっとも安価でかつポピュラーな純正プログラムライターはATMEL AVRISP MK2 なるものだが、価格は、とみると$34となっている。 本格的に開発に使おうとするならAVRDragonというのが良さげだが、これが$49.

MK2はArduino Unoの値段とほぼ同じ。 またAdaFruit.com でAVRプログラマシールドなるものを売っているが、シールドにZifソケットや328Pチップをつけてくれているとは言え、$17. これにArduinoを購入することになるので$50くらいの出費になる。これまたAVRDragonとほぼ同じ値段。

Arduino Proとか$10くらいの廉価品を買ってきてセットアップすれば本格的なライターより安くは組めるだろうが同じくらいの出費をするなら専用ライターを買ったほうが良いに決まっている。(Atmel Studioという統合型のIDEでデバッグなどにそのまま使える) Arduinoを使ってAVRプログラマを作成するというのはどこかに使っていないArduinoが転がっていて、かつAVRとC(++)をちょっと試してみようか、という状況ならともかく、普通はなるべく安いライターを探すことをまず考えるだろう。ま、arduinoを使えば、AVRに挫折したときに改めてArduinoとして再利用できる、という利点はある。実はAvrdudeを使えばプリンタ用のパラレルポートから直接ワイヤーを配線してAVRマイコンをプログラムすることが可能(つまりライターすらいらないの)だそうだが、最近のパソコンではパラレルポートなど実装していない。 (追記:amazon.comで$6のUSB ISPプログラマを売っているのを見つけた。現在のところこれが最安値)

本文
で、自分の場合、うっかり買ってしまったArduino Microという小さなArduino boardが手元に転がっていた。 そこで、このArduino Microに Arduino IDEのメニューのSampleの中から”Arduino ISP”というサンプルスケッチをアップロードし、このプログラムの中に書いてある通りにブレッドボードに配策し、試してみても動かない。

延べ4時間くらい、はまってしまったのだが、ネットを調べて最終的にはマイコンチップをプログラムできるようになった。 要点をかいつまんで書いておく。
1.Arduino MicroはArduino Leonardと同じく32u4というマイコンチップを使っている。 従前のArduinoが使っていたAtmega328Pというチップではない。このため、DigitalPinに対する入出力ポートの割り付けが従来とは異なっている。
2.このため、上記のスケッチで #define RESET SS となっている部分はUnoなどではPin10があてがわれるが、マイクロとLeonardではPin17に定義されている。 このPin17、RX_LEDへと接続されてしまっているので、上の表記は #define RESET 10 とPin 10に明示的に変更してやる必要がある。
3.同じようにSPI用のピン3本(MOSI,MISO,SCK) スケッチ上のコメントでは11,12,13の3つの出力に接続するような指示になっているが、Micro (Leonardも)の場合、SPIはこれらのピンにはマッピングされていない。幸いなことにMicroの場合、MOSI,MISO,SCKの3本がヘッダーピン配列に物理的に存在しているので、ここに接続してやることになる。(Leonardの場合はUnoと同じヘッダーピン配置というのが災い?してこれらのピンは存在しないので、ICP用の6本ピンヘッダーの当該PINにそれぞれ接続することになる。(ただし、ResetはPin10に接続)

回路図的にはこんな感じ。

Arduino Micro as AVRISP

Arduino Micro as AVRISP ダブルクリックで大きな図を見る

実際のブレッドボードへの配策はこんな感じ。

AVR ISP using Arduino Micro (at left)

AVR ISP using Arduino Micro (at left)左のArduinoMicroで右のATmega168をプログラムする図

手順だけ羅列すると
1.Arduino のSample sketchからArduino ISP をIDEに読み込み、#define reset SS を #define reset 10と書き換える。
2.”Arduino as ISP”スケッチをArduino Microにアップロード
3.上のようにワイヤを配策。LED3点については無くてもOK(だがあると恰好よい)
4.CファイルをAVR-GCCでコンパイルし、生成できたHEXファイルをAVRDUDEを使ってアップロード, あるいはArduino IDEでスケッチを作成、sift-Uploadでターゲットをプログラム。(この部分の説明は記事を改めていずれそのうち)

Arduino とは何か

今まで何度も取り上げていて、いまさら何かと切り出すのもなんだが、一度整理しておく。
はじめてArduinoのをみたのはおそらく2010年の年末だ、なんと近所のRadio Shackで入門本と一緒に売っていた。 (RadioShackが昔のように、電子工作の小物を置くようになったというのは非常にうれしいことである。最近はRaspberry PiとかBeaglebone Blackの入門キットも売っている。 閑話休題)
BasicStampに比べると値段が手ごろだったので購入したのだが、このときの解釈は Arduino = 開発ボード

しかし、入門本を読み、LEDの点灯を試み、サーボモーターやリレーの操作、さらには16×2ケタのLCDを表示するという一応のイニシエーションを行ったあと、改めて眺めてみれば、Arduino というのは開発ボード(だけ)ではなかった。

ボードを購入したあと、ユーザーはArduinoのサイトから開発環境をダウンロードしてプログラミングすることになる。 このときSketchという言語でプログラムを書くのだが、これはWiringという言語がもとになっている。 そしてWiringもSketchも基本的にはC言語を使ったFrameWorkだ。

IDEのGUIはJavaでできているものの、そのバックグランドで動いているものはAVRマイコン用に特化したGCC(AVR-GCC)であり、AVRDUDE(AVR Downloader/UploaDEr) という、マイコンプログラムの先人達によって鍛えられたAVRマイコン用のTool chainである。

ではArduino環境は従来のマイコン開発環境と比べると何が違うのか。
-ハードもソフトもできる限りのアブストラクト化がなされている。
という一点につきる。 AVR8はportB,C,D それぞれ8ビットが入出力になっており、本来のATMEL のC言語の操作ではこれらのポートレジスターにビット操作での書き込みをおこなっていた、つまりPortBの ビット0とか6とかを気にしてコーディングしていくのだが、 アブストラクション(抽象化)を行った結果、 ArduinoのユーザーはDigital pin 0~13, Analog input pin 0~5 という入出力ピンの操作だけを考えればよいようになっている。
スケッチもSetup()という初期化ルーチンとloop()という繰り返しルーチンを書けば、あとはTool chainがコンパイルし、プログラムをアップロードしてくれる。 このからくりはArduino のプログラムフォルダー(自分のWindows環境ではC:\Program Files (x86)\Arduino\hardware\arduino\cores\arduino)の中のmain.cppを眺めてみるとなんとなく見えてくる。

#include <Arduino.h>

int main(void)
{
	init();

#if defined(USBCON)
	USBDevice.attach();
#endif
	
	setup();
    
	for (;;) {
		loop();
		if (serialEventRun) serialEventRun();
	}
        
	return 0;
}

何故にwhileを使わず、for(;;) という構文を使っているのか、という疑問はさておき、Arduino のスケッチはこの上のmain.cppに組み込まれるsetup()とloop()関数を定義しているというわけで実際にコンパイルされるのはC++のソースだった。

Arduinoでは多くの周辺デバイスとのインターフェース、通信プロトコルなどはすでにライブラリーで提供されている。 またArduino自体にマイコンチップをプログラムできるような周辺回路およびブートローダーが組み込んてあるからチップにコードを焼くための専用プログラマが必要ない。

下のコードは、入門本で一番最初に出てくるLEDを点滅させるためのスケッチコード

int led = 13;
void setup() {                
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);     
}

void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
}

ところがArduinoのIDEがインストールされたPC環境ではすでに上に述べたようにGCCとかtoolchainとかが導入済みになっているため、 以下のようなプログラムををCで書いて、コマンドラインを使ってコンパイルし、Arduinoへ書き込みをすることが可能になっている。 下のコードでやっているのは上 のスケッチと同じくPin 13を点滅させることだが、ArduinoスケッチのProgramがコンパイルしてアップロードするサイズが1000バイト以上あるのに対し、下のプログラムは200バイト以下になる。abstractionの代償はプログラムのサイズということらしい。


#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>

#define LED      PB5
#define LED_DDR  DDRB
#define LED_PORT PORTB
#define DELAYTIME 500 //delay 500ms. See _delay_ms definition

#define setBit(sfr, bit)     (_SFR_BYTE(sfr) |= (1 << bit))
#define clearBit(sfr, bit)   (_SFR_BYTE(sfr) &= ~(1 << bit))
#define toggleBit(sfr, bit)  (_SFR_BYTE(sfr) ^= (1 << bit))
long i;
int main(void)
{
    // setup()
    setBit(LED_DDR, LED);                      /* set LED pin for output */

    // loop()
    while (1) {

	    setBit(LED_PORT, LED);
	    _delay_ms(DELAYTIME);
	    clearBit(LED_PORT, LED);
		_delay_ms(DELAYTIME);
	    
    }
}

while分がArduinoスケッチのloop()に相当し、その上がsetup()に相当する。
上をblink.c というファイル名で保存し、Arduinoがつながった状態でコマンドラインから以下を実行するとLEDの点滅を始める。(もちろんserial portによってCom5部分は異なる)

>avr-gcc -Os -mmcu=atmega328p blink.c -o blink.o
>avr-objcopy -O ihex blink.o blink.hex
>avrdude -p atmega328p -c arduino -P com5 -U flash:w:blink.hex:i

コマンドライン3行をターミナルモードで打ち込むわけだが、Batch file にしてもよい。その実行はarduinoのアップロード機能を使うのに比べて恐ろしく早い、ということも実感できると思う。
Arduinoを使うのは野球のグローブをつけて裁縫をやるようなものだ、とかなんとか言った人がいる。 抽象化が過ぎてマイコンをプログラムしている気がしない、ということで、たしかに熟練者の目からみればもっともな話かもしれないが、Arduinoの一番の目的はマイコン学習を始めるための第一歩を容易にすることにある。(と思う) 豊富なサンプルコードやライブラリーを見るとその楽ちんさは尋常ではない。ハードとソフトの両方への入門が可能な環境になっている。 ずうっとArduinoとスケッチでいいじゃない、十分だよ、という気にもなってくる。 それにArduino IDEのサンプルメニューを眺めているとわかるが、Arduino自体をAVRマイコンのプログラマにしてしまうスケッチがご丁寧に同梱されている。 Arduinoにものたりなくなってきたら、(入出力が6本以下のマイコンでできることを、何が悲しゅうて28ピンのマイコンプラス不要な回路を載せたボードでやってまんねん、自分はミニマリスト的なアプローチがすきやねんとか思いはじめたら)ATtinyのチップだけ100円で購入してArduinoを使ってプログラムを焼くことも可能になっているわけだ。