AUTHOR: すz TITLE: ブログはじめました。 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 1 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 02/28/2007 18:49:49 ----- BODY: AVR というワンチップマイコンを中心にした電子工作やらプログラミングやらの話題を書きたいと思いブログを立ち上げました。 日記 というカテゴリは、雑多な電子工作についての話題。 USB910A,USB910B というカテゴリは、同名の自作ツールを使った電子工作についての話題で、ある程度 まとまったものを載せていこうと思います。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: USB910A とは STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 1 PRIMARY CATEGORY: CATEGORY: USB910A DATE: 02/28/2007 18:55:24 ----- BODY: AVR の自作書き込み器です。 USB シリアルとして接続できる avr910 互換プロトコルの ISPプログラマで、拡張機能として、I2C マスタ通信機能+αを組み込んであります。 I2C デバイス用プログラムも作成していますので、ホストで プログラミングすることで、ISP を接続したまま各種のデバッグができます。 さらに、USB 接続なので、電源も供給でき、電流測定もできます。それだけではなく、AVR 製作に便利なように 周波数カウンタ、クロック出力、4ch の 電圧測定 ( そのうち 3ch は任意の ch 間の 電圧差の測定も可能)の機能を組み込んでいます。ついでに、チップ内蔵の温度計を読み取ることもできます。 これだけの機能を 20pin の ATtiny861 だけで実現しています。回路も簡単なので、作成も容易です。 問題はまだ ATtiny861 の入手先が限られるということ。 このカテゴリでは、USB910A の機能を使った AVR の実験や電子工作の紹介をしたいと思います。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: USB910B とは STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 1 PRIMARY CATEGORY: CATEGORY: USB910B DATE: 02/28/2007 18:57:46 ----- BODY: AVR の自作書き込み器です。 USB シリアルとして接続できる avr910 互換プロトコルの ISPプログラマで、拡張機能として、I2C マスタ通信機能+αを組み込んであります。 I2C デバイス用プログラムも作成していますので、ホストで プログラミングすることで、ISP を接続したまま各種のデバッグができます。 さらに、USB 接続なので、電源も供給でき、電流測定もできます。ついでに、チップ内蔵の温度計を読み取ることができます。 これだけの機能を 14pin の ATtiny44 だけで実現しています。回路も簡単なので、作成も容易です。 問題はまだ ATtiny44 の入手先が限られるということ。ATtiny44 の温度計はぜんぜん信用できないということ。電流計も なんだかイマイチです。 実は、上位版として USB910A (Advance) というのを既に作っていて、サブセットの機能を ATtiny44 で実現しているので、USB910B (Basic) と名づけています。 このカテゴリでは、USB910B の機能だけを使った AVR の実験や電子工作、それに、USB910B をベースにして作った なにか別のものの紹介をしたいと思います。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: USB910B の回路図 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 1 PRIMARY CATEGORY: CATEGORY: USB910B DATE: 02/28/2007 21:58:20 ----- BODY: USB910B の回路図を以下に示します。 見てもらうとわかると思いますが、いくつかの抵抗とコンデンサを1:1でつないだだけという感じでビギナーでも作れるレベルだと思います。ちなみにISPコネクタ配列はオリジナルです。一列 5pin にしたいので、あえて Atmel 標準を採用していません。
この回路は、3.3V 〜 5V で利用できます。5V で利用する場合は、3.6V のツエナーダイオードが必要です。3.3V-3.6V の場合は、必要ありません。 電源回路については、下に示すように 3.3V のレギュレータを使いスイッチで 5V と 3.3V を切替えるようにするのがお勧めです。
3.3V のレギュレータを使わずに済ませたい場合、下に示すように、5V から ダイオードを2段にして 電圧を落としても OK です。
注意) この回路は、USB の規格からだいぶ外れています。ほとんどでハブで認識できると思いますが、ひょっとすると認識できないハブがあるかも知れません。 おやくそく)この回路図は無保証です。この通り作っても動作することを保証するものではありません。自己責任 でお願いします。高価なPC を壊してしまう可能性もあります。リスクを減らすために電源付きの外付けハブを通して使用することをお勧めします。 プログラムについて 公開準備中です。一部に GPL のソフトを利用していますので ライセンスはGPLになります。なお、Linux 2.4.30 (+ uisp) でしか動作確認をしていません。Windows その他で使えるはずですが、ひょっとしたら動作、しないかも知れません。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: USB910A の回路図 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 1 PRIMARY CATEGORY: CATEGORY: USB910A DATE: 02/28/2007 23:57:37 ----- BODY: USB910A の回路図を以下に示します。この回路図は最初の試作のもので、rev1 です。改良したい点がいくつか出てきているので、rev2 を作る予定。 USB910B よりは複雑ですが、いくつかの部品を1:1でつないだだけという感じでビギナーでも作れるレベルだと思います。ちなみにISPコネクタ配列はオリジナルです。一列 5pin にしたいので、あえて Atmel 標準を採用していません。
電源回路については、下に示すように 3.3V のレギュレータを使いスイッチで 5V と 3.3V を切替えるようにしてください。また、入手が難しいかも知れませんが、3.6V のツエナーダイオードが必要です。
注意) この回路は、USB の規格からだいぶ外れています。ほとんどでハブで認識できると思いますが、ひょっとすると認識できないハブがあるかも知れません。 おやくそく)この回路図は無保証です。この通り作っても動作することを保証するものではありません。自己責任 でお願いします。高価なPC を壊してしまう可能性もあります。リスクを減らすために電源付きの外付けハブを通して使用することをお勧めします。 プログラムについて 公開準備中です。一部に GPL のソフトを利用していますので ライセンスはGPLになります。なお、Linux 2.4.30 (+ uisp) でしか動作確認をしていません。Windows その他で使えるはずですが、ひょっとしたら動作、しないかも知れません。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: USB910Aの設計とデザイン STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 1 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 03/01/2007 04:12:49 ----- BODY: USB910A は、ソフトウェアには詳しいがハードウェアはあまり知らない ... そういう人が電子工作の世界に入るときに敷居が低くなるようにできないかということを考えて設計しています。(それはなぜかということは、また別の機会に書こうと思います。) 敷居を低くするには、したいこと以外のことはお手軽にできること...これが重要です。そういう意味で、USBで書き込みができて電源も供給できるプログラマがまず必要だろうと思います。 そういう装置が安く簡単に作れるということも大事です。このような理由で、AVR だけでUSB シリアルデバイスになるファームウェア AVR-CDCをベースにして、プログラマを作ることにしました。有名なAVRプログラマのプロトコルには、Stk500とAVR910そして、ブートローダ向けのAVR109の3つがあります。その中で最も簡単なAVR910互換にしました。その代償としてやや書き込みが遅くなってしまいました。AVR109互換の拡張をすれば数倍の高速化が可能なのはわかっているので今後改良していきたいと思います。
ちなみに高機能なプログラマ機能だけが必要ならば、製品を買うのが手っ取り早いです。Atmel が出している AVR Dragon が低価格で機能も高くお勧めです。AVR-Dragon は、オプティマイズ/ITプラザでも扱っているようです。自分で作ってみたいなら AVR Doperも良さそうです。 2007/5/24: AVR Doper のサブセット版の基板が つれづれ日記のゆきの研究室から出ました。→ AVR-Doperの小型基板製作。書き込み済み ATmega8 も分けてくれるので、これから AVR を始めたいひとにお勧め。 一方、 AVR Dragon は、電源部分が煙を出して壊れるロットもあるようです。情報収集をした上で購入するかどうか決めたほうが良さそうです。 2007/7/5: ゆきの研究室で USBaspが発表されています。キットになって出るようなので、これから AVR を始めたいひとにお勧め。avrdude-GUIもあり、AVR Studio 4 から直接使えます。あと、#173 COM-SPI ブリッジ AVRライタもお勧めです。こちらは、シリアルポートが必要ですが、USB-シリアル ケーブルでの接続でも 問題ないので、ノートPCでも使えるはず。
さて、プログラミングできて、電源も用意できた後は何が必要か..というと(作ろうとする装置はもちろん必要ですがそれを別にすると)デバッグ手段です。デバッグでは、ホストとお手軽に通信できることが重要です。LED を光らせるのも良いですが、それで得られる情報には限りがあります。そこから進んでいくとやはり大量のデータを見る手段がほしくなります。お手軽にするには、ISP ケーブルをつないだままプログラムを動かせばホストと通信できる必要がありそうです。 それが可能な通信手段は、ターゲットを AVR Tiny シリーズということにすれば、SPI と I2C に絞られます。一見 SPI が良さそうに思えますが、3 本だけで通信するのは実は面倒です。ISP や JTAG 、SDカードといったものは、SPI を採用していますが、信号線は4 本です。SPI はビット列を送るものなので、同期のために もうひとつ信号線が必要なのです。 それに対し I2C は、2 本の線で データのかたまり -- パケットを送受信できます。ということで、I2C でホストと通信する手段を提供することにしました。デバイス側のプログラムも提供しないと実際には通信できませんから、テンプレートを元にしてプログラムをかけば、したいことを簡単にできるような、I2C スレーブドライバの提供も合わせて検討することにします。 さて、それをさらに進めるとどういうものがあると良いでしょう?オシロスコープとかロジックアナライザなんていう以前に動作中にテスタを当てるのが実に面倒です。多くの ADC 入力があってそれらをターゲットに配線してしまえればどうでしょう。いったん配線してしまえば、あとはホストの操作だけで電圧を読み取れるとお手軽ではないでしょうか? そう考えて できるだけ多くの(といっても4本ですが)ADC 入力を提供することにしました。そのうち1つは、周波数も読み取れます。PWMを使って周波数を変更することで状態をホストで読み取るなんてワザも可能です。 さらに進むと、オシロスコープとは言わないまでも 波形が見たくなります。 USB910A は、メモリが少ないので波形を見るレベルにはできませんが、オプションで、波形をキャプチャーするデバイスを装着することを検討しています。
AVR の ADC で キャプチャーしたデータをI2C ROMに一時格納するものを予定しています。あまり性能は高くありませんが、ローコストかつ簡単に作れて音声領域ぐらいの波形は見れるようにしたいと思います。I2C はバスなので、こういうデバイスを追加できるという利点があります。
こうやって設計した USB910A を 実際に使った実験を ぼちぼち紹介していきたいと思います。 予告 電圧と温度を変えて、OSCCAL の値を変化させると どのようにクロックの周波数が変わるかの実験の紹介を予定しています。
こんなグラフも書けています。温度が10℃変わったときの違いより、電圧が 3.3V か 5V かの違いの方が大きいなんてことも分かります。
次に 温度計のテスト。Tiny45 や Tiny44 の温度計は信用できないなんてこと をデータで見せたいと思います。第三は、昇圧DC/DC コンバータの試作と 高電圧シリアルプログラミングの実験。.... あとはまだやっていませんが、 内部基準電圧のキャリブレーション、DCブラシモータの回転数制御の実験とそれに必要なオプションキャプチャーユニットの製作を予定しています。USB910A/B のソフトの公開が先ですが。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: USB910のパーツについて STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 1 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 03/01/2007 06:57:19 ----- BODY: 入手が難しいパーツやお勧めのパーツについてのコメント ATtiny44-20PC , ATtiny861-20PC デジキーで取り扱い開始
ATtiny861はずっと買えるようになるのを待っていたのです。買ったら早速使いたくなってUSB910Aという形になりました。それに対してATtiny44 はおまけ的存在。小さいだけがメリットかも知れません。
QIコネクタ、QI片端圧着済ワイヤー 共立
ISPケーブルを作るのによさそうです。1x5 も 2x3 もあります。圧着は面倒なので、QI片端圧着済ワイヤーも一緒に買うと良いと思います。
カモン USB-05 千石で 231円 カモン USB-08 千石で 263円
両端に QIコネクタ1P x 5がついたシールドケーブルが2本セットになっています。ISPケーブルを作るのに便利。半分に切って中のコードを抜けば、QIコネクタつきケーブルが 16本も得られます。
3.6V ツエナーダイオード 千石でHZ4A−2が10本210円、100本630円。デジキーで 1N5227B が10個95円、共立で 0.5W 15円
低電圧のツエナーダイオードは千石が扱っているのを知らずデジキーでチップタイプを買ってしまいました。
超小型スライドスイッチ IS-1250 秋月で 4 個100円
とても便利です。お勧め
片面ガラスエポキシ・ユニバーサル基板Cタイプ 秋月で60円
スルーホールユニバーサル基板より作りやすいかも。
3端子レギュレータTA48M033F 秋月でコンデンサをセットして100円
定番だと思います。
12MHz 水晶 秋月では、10個500円。
10個もいらないならデジキーでついでに買うという手がありますが、電子工作するなら10個ぐらい買っておいたほうが良いと思います。
ピンソケット(1×14)秋月で50円 基板取付用USBコネクタ(Bタイプ)秋月で50円
在庫切れのこともあるようです。買えるときにいくつか買っておくと良いかも
抵抗 1Ω 1/6W 秋月で 100個100円  
電流測定用で、1/6Wなら400mA まで。これぐらいがちょうどよさそう。電流測定の精度はあまり期待できないので、5% ぐらいで十分。10uF のチップ積層セラミックコンデンサをパラにつなぐと cutoff 16kHz のLPF になるので、ノイズ対策によさそう。
実験で使うかも知れず特殊かも知れないパーツ TL431 秋月で10個100円 基準電圧キャリブレーション用 チップ積層セラミックコンデンサ 10 μF [3216] 6.3 V 秋月で10個100円 基準電圧キャリブレーション用
TL431は、10uF ぐらいをつけないと発振する場合があります。3216サイズなら手配線しやすいので入手しておきましょう。
電流測定用に必要になりました。
チップ積層セラミックコンデンサ 4.7 μF [3216] 25V 秋月で20個100円 12V昇圧回路実験用
16V 耐圧では不安なので、25V 耐圧のこれを買っておくと良いと思います。
マイクロインダクタ 47μH 秋月で10個100円 12V昇圧回路実験用
実験では、高電圧シリアルプログラミングのテストで使ってみました。あまり電圧が高くなるとコンデンサがやばいので、これぐらいからテストするのが良いと思います。ものは、LAL02NA470K max 70mA / 5.8 Ω
LHLZ06NB 100μH 0.57A とか 47μH 0.82A とか。千石で10個270円 
旧製品のLHL06NBと同じ大きさで3倍近い電流が流せる。安いしコンパクトなのでお勧め。実験でも使ってみるつもり。
I2CROM AT24C256(2.7〜5.5V) 秋月で 160円 
I2Cマスタのテストでまず使いました。あと、波形をキャプチャーする一時メモリに使う予定です。
SI91841DT-285 秋月で売っている2.85Vチップレギュレータ。中途半端な電圧ですが、150mA Ultra Low-Noise LDO Regulator だそうです。PWMで音を鳴らしたり、可変の基準電圧を作ってみたりしたいのですが、PWM は電源電圧の変動にもろに影響されるので、こういうので電源供給したらどうかと考えています。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: ソースコード公開 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 1 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 03/05/2007 16:36:24 ----- BODY: ソースコード usb910-0.5.tar.gzusb910-0.5.zipを置きました。 ついでに作った装置の写真を載せときます。 TypeA 試作1号機 秋月C基板を1/2 にして タカチSW-55 に入れようとコンパクトに作ってみたのですが ... ちゃんとケースに入れるのは失敗。それはそれとして、結構いろいろな実験に使えて重宝しています。 TypeB 試作1号機 Tiny44 を使ってみたかったので、機能を省いてコンパクトにしたものを作りました。タカチSW-55 にもきっちり入ってなかなか外観は良いのですが...実験ではTypeA ばかり使うので、まだあまり出番がありません。 実験ボードその1 I2C ROM(左下) の読み書き、8pin AVR (Tiny13,45V) (左上) と Tiny44 (右)の書き込み用のボードです。TypeA を使うと、RC発振器 のキャリブレーション、ADC のキャリブレーションもできます。 実験ボードその2 こちらは、Tiny26/Tiny861 の書き込み、各種キャリブレーション用ボード。それだけでなくて、+12V 昇圧回路と 8pinAVR, Tiny44 の 高電圧シリアルプログラミングの実験ができるようにしています。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: RC発振器のキャリブレーション STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 1 PRIMARY CATEGORY: CATEGORY: USB910A DATE: 03/06/2007 23:17:09 ----- BODY: AVRには、RC発振器の周波数をプログラムから変更できる OSCCAL というレジスタがあります。この値を変更したら周波数がどのように変わるのか?ということについて調べてみました。 測定1 - ATtiny861 で温度と電源電圧を変化させて、発振周波数を調べる。 電源電圧が3.3Vから5.0V になると、周波数は1%ほどあがるようです。これは温度が12℃変わったときの変化より2倍も大きい。初期値は、3Vにあわせてあるようなので、5V で使うときは気にしておいたほうが良いかも知れません。 測定2 - ATtiny44 2つの発振周波数を調べる 手持ちのATtiny44 に#1と#2の名前をつけて区別できるようにしています。同時に買ったのでロットはたぶん同じはず。さて、この2つの特性はどのように違うのか?傾向は同じですが、OSCCALの値と周波数の関係はだいぶ違うようです。特に#1のほうは、電圧差の影響が大きく3%ほども違いました。これぐらい違うとシリアル通信とかクロックの誤差にシビアなものを使うときにキャリブレーションすることを考えたほうがよさそうです。この結果をみてもそうですが、なんだか ATtiny44 はかなりチープな作りのような印象があります。 測定3 - ATtiny26L を調べてみる。 ATtiny26Lは、128 を境にして2つのパラメータがあるのではなくてパラメータは1つだけです。で値をどんどん大きくしていくとあるところを境にして周波数が下がりだしました。ひょっとして他のもこういう傾向があるのかも知れません。気になってきました。 測定4 - ATtiny861 を調べてみる。 こいつにもありました。周波数が下がるポイントが。しかも 3.3V と 5.0V では下がりだす周波数にだいぶずれがあります。 (注意)これは先の測定と違うチップを使いました。#3としています。 測定5 - ATtiny44 を調べてみる。 #1をつかって見ましたが、だいぶ後の方にずれています。5V のときは、240でも下りだしていません。 どのようにこの測定をしたのか クロックに比例した周波数を出力するのは簡単です。PWM を使えばよいわけです。一連の測定では、1/4 の周波数を出力するようにしています。OSCCAL の値を変更するのも簡単で通信すればよいわけです。ただし、シリアルではボーレートも変わってしまうので相当難しいかもしれません。I2C での通信では周波数は関係ないのでまったく気にせずに通信できました。さて、周波数をよみとるのは、周波数カウンタがあればできます。しかし、これぐらいの量の測定をするのにはスクリプトなどで自動化できないとやってられません。USB910A では、通信も周波数カウンタ機能もコマンドが違うだけなので、特に面倒なく測定ができました。 次回 RC発振器のキャリブレーションという主題は興味深いものの実際にはあまり役には立たないかも知れません。つぎもあまり役にたちそうにないのですが、内蔵温度計の測定をしてみます。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: 内部温度計のキャリブレーション STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 1 PRIMARY CATEGORY: CATEGORY: USB910A DATE: 03/07/2007 00:07:21 ----- BODY: ATtiny45,ATtiny44,ATtiny861などは、内部に温度計を持っています。データシートでは、読み取った値が1違えばだいたい1℃の違いになるのであまり役にたつものではなさそうです。その上、誤差は10℃ぐらいあるとも書かれています。さて、実際どんなものなのでしょう。 さまざまな温度で測定する前に、電源電圧 3.3V と 5V でどれぐらい影響を受けるのか調べてみます。 測定1 - ATtiny44#1の温度値の測定 (室温 28.2℃) 電源電圧 3.3V と 5Vで それぞれ100回温度計をよみとりました。それぞれで値の変動は少ないのですが、そもそも 3.3V と 5V でぜんぜん値が違います。20%ほども違う結果になりました。5V の方は USB の電源そのものなので、変動が大きいはずで、それが結果にも出てきて温度計の値も若干変動があるようです。こんなに電源電圧の影響を受けるのでは、温度計として使うのに相当な不安があります。 測定2 - ATtiny44#1のOSCCAL と 温度値の関係 前回の RC発振器の測定のときに同時に 温度計の値もログしていたので、グラフにしてみました。そうしたら、なんとびっくり。驚いたことに、OSCCAL の値と連動して温度計の値が変わるではありませんか。周波数と連動していそうな感じですが、よくよく見るとそうでもありません。いろんなものに影響を受けているようです。何回かやってみましたが同じ傾向があります。他のものもそうなのか?気になって調べてみましたが、#2の方は、OSCCAL にはほとんど影響を受けていませんでした。どうも、この個体だけがおかしいようです。 測定3 - ATtiny861#3の温度値の測定 (室温 27.2℃) ATtiny861 を調べてみました。ATtiny44 とは違って、電源電圧の影響は確実にあるものの値の差は小さく 2 ぐらいでした。でも 2 とはいっても 2℃の誤差ということなので、電源電圧を決めてキャリブレーションしておかないと使い物にならない感じですね。面倒なことをしてもあまり当てにできないので、温度計はないものと思うことにしました。 ちなみに、ATtiny45 も ATtiny44 と同じ傾向があります。比較的まともなのは ATtiny861 だけでした。 次回 温度計があてにならないことは判りました。がそれだけでしょうか?ADC そのものか 内蔵基準電圧があてにならないと困ります。次回は、これらについて調べてみることにします。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: 基準電圧のキャリブレーション STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 1 PRIMARY CATEGORY: CATEGORY: USB910A DATE: 03/07/2007 01:11:32 ----- BODY: 温度計 - 特にATtiny44 はひどいものでした。これが ADC 一般の性質だとたいへん困りそうです。どんなものなのか調べてみることにしました。基準電圧を調べるには、別の基準電圧が必要です。いろいろ検討しましたが、TL431 で作り USB910A に組み込んでしまうことにしました。 USB910A の回路図からの抜粋ですが、こんな感じです。TL431 で、2.495V の基準電圧を作り、それを 1/3 に分圧した測定対象用の 0.83V も作ります。データシートを見ると、かなりの容量を入れないと unstable になるので、10uF のチップ積層セラミックコンデンサを入れることにしました。ただ電解コンデンサを前提にしていると思われるので、ひょっとしたら 2uF 前後でも問題ないかもしれません。これらの基準電圧を ATtiny44/861 の AREF と ADC のどれかにつなぐことにしました。 愛用のテスタで電圧を測定したところ、それぞれo 2.488V, 0.826V になりました。 TL431 は温度補償されているので、安定してこの電圧になることになります。実際なんどもテスタで測定しましたが、常に同じ電圧でした。 この基準電圧と、内蔵基準電圧を使って、0.83V を測定してみます。電源電圧が影響するようなので、3.3V と 5.0V でそれぞれ 100回測定をしてどれぐらい安定しているか見てみることにします。 測定1 - ATtiny44#1 1.1V 内蔵基準電圧で5Vの場合、1.05V とぜんぜん違う値になりました。3.3V のときもかなり高めです。外部基準電圧を使う場合は、実際の値にかなり近いので、ADCそのものの問題ではなく、基準電圧に問題があるようです。温度計のひどさも、基準電圧が第一の原因のように思えます。外部基準電圧を使ったときでも電源電圧の影響は確実にあります。精度がほしいときは、電源電圧によって校正値を変える必要がありそうです。 さて、この#1という個体はそもそもダメダメなのかも知れません。#2でも同じデストをしてみることにします。 測定2 - ATtiny44#2 #2でも同じような傾向でした。ちなみに、ATtiny45 も同じ傾向でした。これらのチップでは、あんまり基準電圧は当てにできそうにありません。温度補償されているかどうかも判らないので、温度差で値が変わるかどうか調べてみる必要がありそうです。温度は自由にならないので、また別の機会に調べてみることにします。 測定3 - ATtiny861#3 いまでの測定では、こいつはかなり良いかんじでした。おそらくATtiny44,45などよりも精度が良いと期待できますが、実際はどうでしょう? 1.1V,2.56V 内蔵基準電圧の両方で、高めの値になりました。そして、電源電圧 3.3V と 5V の差は、2% ぐらい。校正しなくとも 5% ぐらいの誤差に入ってきています。電源電圧を調べなくとも±1% ぐらいに校正できそうです。外部基準電圧を使えば精度は高くなりますが、それでも電源電圧の影響を受けています。精度が必要ならば、電源電圧を 3.3Vにしたほうがよさそうです。 それにしてもTiny44,45 などとはぜんぜん違いますね。Atmel も気合が入っているのでしょうか。 測定4 - ATtiny26L#1 ついでに、手持ちのATtiny26L も調べてみることにしました。 2.56V内蔵基準電圧は、-10%とかなりひどいように見えます。...が、よくみると電源電圧の影響をほとんど受けていません。校正さえしてやればかなり信頼できそうです。外部の場合もわりと良いです。 次回 だいたい ADC の傾向がつかめてきました。でも、シングルエンドのケースだけです。次は、USB910A の電流計を使って、ATtiny861 のディファレンシャル+ゲインつきの特性を調べてみたいと思います。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: 鶏と卵 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 1 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 03/07/2007 02:16:07 ----- BODY: AVR でUSBプログラマを作っても、それ自体にプログラムを書き込むために別のプログラマが必要になってしまいます。プログラマがないとプログラマが作れない... 鶏と卵の関係ではありませんが、困ったことです。 ここでは、ものすごく簡単にできるプログラマを紹介しておきます。 なひたふさんのNAXJPのページで紹介されている ダウンロードケーブル がオリジナルです。このケーブルのGND以外の信号線に 150Ωぐらいの抵抗をいれれば、3.3V電源でも 5V電源でも使えます。DSUB25 pin オスコネクタは、秋月で50円で買えますし、ケーブルには、カモンの USB-05USB-08を使うのが便利です。シールドされているので、80cm の USB-08 でも問題なく書き込みできます。抵抗は1/4Wタイプの大きめのものを使い。ケーブルと半田付けしたあと熱収縮チューブで絶縁+強化しておきます。信号名は、TDO = MISO,TCK = SCK, TDI = MOSI, TMS = RESET と読み替えます。 このケーブルを xilinx JTAGケーブルとして使えばOK。uisp を愛用していますが、これだと -dprog=xil と指定します。 このケーブルは1つあると便利なのですが、パラレルポートを使うので PCによっては使えないかも知れません。また、なんらかのミスでパラレルポートを壊してしまうかも知れません。パラレルポートはあんまり使わないので壊してもあまり困らないかも知れませんが、このケーブル自体が使えなくなってしまいます。だからやっぱりUSBのプログラマが便利なのです。
AVR の世界では、パラレルポートのピンの割り当てが違うSTK200ケーブルというのがあるようですね。ChaNさんのAVR ライタ作品集にある Stk200の簡易版のほうが良いかもしれません。
追記 avrdude で使うには オプションに、-c xil をつけます。
例
# avrdude -p t861 -c xil -t
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e930d
avrdude> q
avrdude: safemode: Fuses OK

avrdude done.  Thank you.
----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: チップ初期化器のアイディア STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 1 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 03/07/2007 04:09:13 ----- BODY: AT90S1200用 内部RC発振回路有効化ボードの製作というのを参考にして、高電圧パラレル/シリアルプログラミングで、チップを初期状態にするものが作れないか。 これを使うケースは、RESET pin まで使いたいとか、ヒューズビット の設定を間違えたとかで、あんまり使用頻度は高くなさそうなので、チップはもっとも安い ATtiny2313 を使いたいし、電源も 5V 単一電源にしたい。 +12V 昇圧の部分は PWM で適当に昇圧して、TL431で+12V までに制限をかければフィードバックもいらず回路が簡単になる。インダクタは、秋月で扱っている マイクロインダクタ LAL02 47uH 専用ということにして、PWM の周波数と Duty を決めうち(250kHz , On-Duty 20%)にすることにすれば、再現性はかなり高くて、電圧が上がりすぎるとかの問題もおきにくいはず。具体的には、次の回路で十分ではないか。 書き込みについては、パラレルとシリアルの両方を試して、正しいシグネチャを返してくるほうでプログラムすることにしてシリアル・パラレル両方とも対応する。 で、問題はピンの数、かなり厳しい。信号線14と VCC, PWM, +12V出力で17pin になってしまう。+12V 出力をあきらめて、PWM スタート = +12出力ということにすれば 1 pin 減らせるが、立ち上がりの時間に条件があるかもしれないので無理かも知れない(大丈夫だと思うが自信なし)。プログラム中インジケータは PWM を流用することにする。+12V 出力制御がなければ +12V までの電圧がかかってしまうが VCCがOffなら問題ないだろう。OK のインジケータは、信号線のどれかを使うことにする。書き込みできれば HI-Z になっているはずなので問題ない。エラーの場合は PWM で点滅させればよいかも知れない。チップを初期状態にするだけなので、電源いれたら自動スタートでよくボタン類も一切なしにしてしまえば、一応 16(or 17) pin で作れることになる。 もし、ATtiny2313 で作れないとなると、ATmega48 が次の候補。ただし、そこまでいくと、ピンもメモリもあまるので、USB で接続して、まともなパラレルプログラマにしたいなんて考え出すことになる。結局作るのが面倒になってしまいそう。 ... というのを作ってみたいとは思っているのですが、あんまり必要性がないので、アイディアのみで終わるかも。
Tiny2313 専用ですが、Tiny2313リセッターというのがあるようです。同じ チップを使って亀の子にするのは手軽でよさそう。
この昇圧回路、電流はほとんど流せません。2-3 mA ってとこみたいです。高電圧プログラミングには、それで十分みたいですが他の目的には使えないでしょう。ちなみに、20% Duty 固定なら、8MHz クロックで、6:30とかすればよいので、どのAVRでも問題ないはず。
----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: Tiny系BootLoader のアイディア STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 1 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 03/07/2007 05:54:25 ----- BODY: Google Code Searchで、ATTiny2313_bootloaderというものを見つけた。これを見ていて考えついたもの。 とりあえずターゲットは8KBのATtiny861とする。普通にプログラムを作りリンク(ld)のオプションに、-Ttext 0x1000 -Tdata 0x800160 とつけると何が起きるか... というと プログラム全体が 4KB のところに移動して、データのアドレスも 256B 後ろにずれる。スタックはメモリの最後を使うようになっているので、前半分は一切使わないようなものになる。もちろん割り込みベクタのアドレスも 後ろにずれるので、できたプログラムを書き込んだだけでは動かない。それは当然だが、たとえば ベクターの部分をコピーして 0 番地から書き込めばどうか。ベクターは rjmp が入っているので、単純なコピーではだめでアドレスも + 0x1000 しておく必要がある。そうするとそのプログラムはちゃんと動くはず。さて、アプリケーションプログラムをATtiny461としてプログラムする。そうすると 4KB以内のプログラムメモリ、(スタックも含めて)256B以内のRAMを使うようにリンクされる。これでお互いにまったく干渉しない2つのプログラムを突っ込めるようになったわけだ。 このままでは、後ろ半分にあるシステムプログラムには制御がわたらない。どうやって制御を渡すか。ひとつは、アプリケーションプログラムが、後ろのシステムプログラムをcallする。0x1000番地にベクタがあって、最初のものは初期化関数へのrjmpになっていることは判っているわけだから、0x1000 番地に jmp すればよい。いったんシステムプログラムに制御がわたれば、アプリケーション側のベクターを書き換えてしまえばよい。そういうやりかたがひとつ。システムプログラムでは、ベクターの領域はいくつかしか使わないのでそのうちのひとつをシステムコール関数へのrjmpにしてしまう。システムコール関数の第一引数を機能番号ということにしておいて、機能番号 0 を 最初のシステムプログラムの呼び出しということにしても良い。こちらの方法ならいくつか機能をいれることができる。また、このrjmp に細工をしてスタックも変更するようにしておけば、アプリケーションのリソース(スタック)を使わずに機能を実行できて都合が良いかも知れない。 いずれにしてもアプリケーションがシステムプログラムをコールしなければならないのは自由度が低いというデメリットがある。システムプログラム側がブートローダー機能をもっていれば、アプリケーションを書き込むときにベクターを最初からフックするようにできるのでアプリケーション側はシステムプログラムの存在を無視して作成することも可能になる。 さて、USBに対応したブートローダーというものを考えてみる。USBの機能を使うためには、INT0 (もしくはINT1)は、ブートローダが占有する必要がある。応答時間の制限という問題があり、アプリケーション側でUSBのコードを入れるのは不可能。また、USBのコードは2.6KB程度あり二重に持つのはコードの無駄。システムコール関数の機能の中にUSBの機能も入れるのが妥当ということになる。アプリケーションがUSB機能を使いたければ、enable する指示を出せばよいし、使いたくなければなにもしなければ良い。ただし、INT0とINT1はアプリケーションでは使えないという制限はつく。 さて、いつブートローダ機能を enalbe にするか。これが問題。アプリケーションが call してくれれば良いが、まったく動かないアプリケーションを作ってしまうこともあり得る。ブートローダenableのpinをひとつアサインしてボタンかなにかをつけ、それを押しながらUSBに挿すといったやりかたがないとマズそう。となると、Port はUSB機能の2pin を加えて 計3 pin ブートローダ側が占有することになる。それ以外ではアプリケーションがなにか明示的に機能をcallする。指示のひとつとして、WDTタイムアウトで ブートローダ機能 enable というのも良いかも知れない。ブートローダ機能の中にRAMの読みだし機能があれば、デバッグにも役に立ちそうだ。 こういうものはいったいどれぐらいのメモリを消費するのか?もともとアプリケーションでUSB機能を使うのならば、USB機能を移動しただけだからメモリを消費するとはいえない。ブートローダ機能だけならば、だいたい1.5KB ぐらいで済みそう。 ...ということを考えていて、いつかUSB910A で USBブートローダ機能を実装してみたいと思っています。ただ、ブートローダenableのpinをどうするかというのが問題。いまのところ、VCC 電圧読み取り用のpin と兼用にしようかと... ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: Windowsで使ってみた STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 1 PRIMARY CATEGORY: CATEGORY: USB910B DATE: 03/08/2007 21:09:58 ----- BODY: 私が開発に使っているのは、Linux です。ライタソフトも長い間 uisp を使ってきて私にはそれで十分だったりするので、Windows の開発環境は使っていません。いまさらですが、Windows で使えるのかどうか試してみました。 準備 COMドライバーの設定 オリジナルのAVR-CDCに含まれている avrcdc.inf をどこかに置いて、置いたディレクトリを指定すれば、COM4 として認識されるようになりました。 テスト1 ハイパーターミナルでの確認 ハイパーターミナルを使って確認してみます。COM4 を指定して新しい接続を作り、画面を開きます。ボーレートに何を指定しても関係ありませんが、57600 bps を指定してみました。S を入力して USB910A と出力されてきました。ちゃんと通信できるようです。 テスト2 AVR Studio 4 で試してみる AVRProg を使って、試してみました。結果は NG。まったく認識しません。どうも Software をチェックしているようです。USB910 では、S コマンドで USB910A または USB910B を返すようにしていましたが、"AVR ISP" (空白必要)に変更したところ、認識するようになりました。ただ、AVR910 プロトコルは、使い勝手が悪いですね。Stk500 プロトコルのほうがツールも使い勝手がよさそうな感じです。 結論 USB910 は そのままでは Windows では使えません。使えるようにしても 使い勝手が悪い上に遅い(7KB で30秒)です。Windows で使うプログラマを作るなら Stk500 プロトコルの AVR-Doperかそのサブセットが良さそうですので、こちらをお勧めします。 こう書いちゃうと USB910はダメダメなものに見えてしまいますね。ターゲットとI2Cで通信するとかそういう機能を使ってはじめて役に立つものなので、まあしょうがないですね。ライターソフトはスクリプトでも作れるはずなので、なにか考えてみようかと思います。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: 昇圧型DC/DCコンバータの特性を調べる STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 1 PRIMARY CATEGORY: CATEGORY: USB910A DATE: 03/09/2007 20:08:08 ----- BODY: 昇圧型 DC/DC コンバータの原理はわかるけれども、どんなコイルで周波数をどれぐらいにして、duty 比率をどうするのが良いのかというのはなんか難しくて、サッパリわかりません。USB910を作ってやってみたかったことのひとつは、それを調べてみること。簡単な回路を作ってPWM周波数とduty比と負荷を変えるとどれぐらの出力になるかを調べてみることにしました。 回路図 作った回路はこんなやつ。はなから大電流を流すことや効率は無視してチープなものにしました。コイルは 秋月で 10個100円の LAL02 (47uH) こいつは 5.3Ωで最大 70mA が定格。スイッチングには、2SC1815GR を使うことにしました。また、整流用のダイオードも 普通はショットキーバリアダイオードを使いますが、今回は 秋月で 50個100円の 1N4148にしています。入力側のコンデンサは最初 1.5uF でいいかと思ってつけたのですが、電流測定でのノイズがひどいようなので、22uF の積層セラミックを追加しました。(あんまり関係なかったかも知れません。でも 10uF ぐらいは必要そうです。) 出力側は、テストで、電圧が上がりすぎるおそれがあるので、50V 耐圧の 4.7uF 電解コンデンサにしています。( やってみたらそんなに電圧を上げられなかったので、16V 耐圧の積層セラミックでも問題なさそう。) トランジスタのベースの電流制限抵抗は 4.7K にしてみました。hFE が 100 あれば 100mA ぐらい電流を流せるはず。それは良いとして、turn-off の特性が悪そうなので、後で ダイオード(D2)を追加しています。 この回路の負荷ですが、まず電圧測定用に 10KΩ+2.2KΩをつけています。2.56基準電圧で 14.2 V まで測定できる計算。それに加えて 出力 On/Off の PNP トランジスタと On 時の出力側に 10K Ωのプルダウン抵抗があります。合計すると 出力 On のとき 4.0 KΩぐらいの負荷になります(load1)。On/Off 以外に抵抗を直接させるようにしていて、そこに 1kΩを入れると 0.93KΩの負荷でこれを load2 としました。 測定1 250KHz の PWM で duty 比を変えていき、入力電流と出力電圧を採取する。(D2 あり/なし) D2 なしの場合、duty比を 20%以上にしてもほどんど電圧が上がらない結果になりました。あまりに早く飽和してしまうので、turn-off の問題だと思い、ダイオードを入れてみたら、40%ぐらいまでは電圧が上がっていくようになりました。 測定2 PWMの周波数を 500KHz にしてみる。 duty 比 40% までしか電圧があがらないのなら周波数をあげればよくなるのではないかと思い 2 倍の周波数にしてみました。そうしたら 65%ぐらいまで電圧がリニアに上がるようになりました。この特性ならば、うまくフィードバックできそうです。 そういえば秋月の1.5V電池☆白色LED投光キットがこれぐらいのバランスですね。D2相当のダイオードが入っていないので、入れてみるとより明るくなるかも知れません。 入力電流を調べてみる いままでの測定の duty比と入力電流の関係です。これをみるといろいろ気になることがあります。まず、duty 0% 相当(スイッチングはしている)のときなんでこんなに電流が流れているのか? 500KHZにしてもそれほど電流は増えていないので、スイッチングのロスは相対的に小さそうです。また、負荷抵抗の分もload2 で 4mA ぐらいなので、あまり大きくありません。そうなると、コントローラに使った tiny861 がこんなに電流を食っていることになります。でもCPUをまわしているだけなら、こんなに食わないはず。それはおいおい調べるとして、次に電流値の振れ、500KHz はあまり振れていないのに、250KHz はかなりひどい。500KHz でなだらかな曲線になっているので、ADC そのものの問題ではなさそうです。電流測定では、1Ωの抵抗の電圧を測定していますが、10uFをパラに入れて cutoff 16KHz の LPFにしています。スイッチングノイズの影響がこんなにあるのか?というのも疑問。ひょっとしたら供給側のレギュレータとの相性なのかも。あと、duty 比と 電流の関係がリニアすぎる。もっと二次曲線的だと思っていたので予想外でした。トランジスタがしょぼいのが原因なのかも知れませんね。 効率を調べてみる それぞれの測定と効率はどのような関係なのか グラフにしてみました。絶対値としての効率は気にしないつもりでしたが、最大で35%といかにも悪いですね。それはともかく、ダイオードは入れたほうが良いというのが一目りょうぜんです。250KHzでは、duty比 30%ぐらいがもっとも良いですが、効率が良い部分の幅が狭い。500KHz では、duty比率 30%ぐらいから65%ぐらいまでで効率がよくなっています。250KHz では 周波数が低すぎるようです。 まとめ これで、なんとなく感じがつかめたような気がします。今回は小電流で12Vぐらいまであげるのを目標にしましたが、だいぶ判ってきたので、もう少し電流を流せるタイプを作って調べてみようと思います。まぁいつになるかわかりませんが。 次回 12V を作ることができたので、高電圧プログラミングの実験をしようかと思います。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: 大失敗 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 1 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 03/14/2007 01:02:06 ----- BODY: i2c rom (at24c256) を使ってキャプチャーするものを作ってみましたが、 うまくいかないのでデータシートをよーく読んでみたら、64バイトのページを書き込む毎に、10ms も待たなければならないことに気が付きました。たとえば 64 バイトの書き込みで、400kbps だとすれば、転送時間はだいたい 1.5ms 。転送時間より書き込み待ちのほうがはるかに長くて、これを加えると 64 バイトで 11.5 ms と桁がかわってしまう。そうなると.. 8bit でデータをとっても 5.5K sps ぐらいでしかロギングできない。しかも 64バイト毎に 待ちが発生するので、バッファは 128B ぐらいはもたないとダメそう。 せっかく作ったので、とりあえず完成はさせたいとは思いますが、だいぶやる気が失せてしまったので、ペースが落ちそう。シリアル ROM だと配線量が少ないので、手軽に作れて良いと思ったんだけど...かなり甘かった。 代替案としては、M25P40 pdfを使うのが良さそうとも思うのだけれども、デジキーで買えるもののチップの入手性がいまいちだし。いっそのこと、AT91SAM7S にしちゃえば、32KのRAMと 533kSPS の ADC と USBデバイスが1チップに内蔵されていて便利そうなんだけども、それはAVRでないし。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: いんちきオシロ STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 1 PRIMARY CATEGORY: CATEGORY: USB910A DATE: 03/14/2007 18:10:38 ----- BODY: 波形をキャプチャーするものを作っていたのですが、とりあえず波形らしきものを取ることに成功しました。 これは、次の回路で 10kHz の PWMで トランジスタをスイッチングして、コレクタの電圧を測定したもの。Tiny44 の ADC で取ったデータを I2C ROM (AT24C256)に書き込んでおいて、後でホストに吸い上げてグラフ化しています。サンプリング間隔は、201 us (5KHz) で、1us づつずらして採取することで、100 点のデータを得て波形にしています。 なにがいんちきかというと..同期部分で、PWMもサンプリングも同一クロックなので、単に計算するだけできっちり合わせられているところです。汎用にするには、いろいろ面倒なことをしなければならないかも知れません。あと波形も実際とはだいぶ違うはずです。 波形については後にして、回路の説明。これは、前に書いた昇圧回路をベースに小型の振動モータを回す回路にしています。電源電圧は、3.3V 。モータは秋月でかつて売っていたもの。先についていたおもりははずしています。(ライターで10秒ほどあぶれば、ラジオベンチで引っこ抜けました。)ADC は、モータの起電力を読み取ろうと思ってつけています。ここでは書いていませんが、I2C ROM を ATtiny44 のあまったポートにつけています。あと(特に必要ではないのですが) 2.5V の基準電圧を VREF に入れています。 波形について これは、モータのかわりに 150Ωの抵抗を入れたとき採取した波形。 本当はそれなりに綺麗な方形波のはずですが、RC LPF に充放電している典型的な波形にしか見えない結果になっています。 4.8kHzぐらいのcut-off周波数になっているので、波形を見るのが目的ならば、1000p かもう少し小さめが良いのではないかと思います。ただし、あんまり小さくすると ADC の Sample and Hold がうまく働かなくなってしまいます。 プログラムについて プログラムは、やっつけで作ったものなので、基本的にたいしたものではありません。USB910のソースに添付した i2cスレーブドライバと USB910で使っている i2c マスタをベースにして、I2C ROM にキャプチャーするところと、HOST から I2C ROM の内容を読み出す機能をつけただけという感じです。後で整理して公開しようと思いますが、基本的にASISです期待しないでください。 ちなみに I2C ROMには、64B のバッファを使って、最大で 5.8KB/sec ぐらいでオーバーフローすることなく書き込みできました。日記で大失敗と書きましたが、役に立たないほどのことはなくてよかった。
usb910-0.2に添付しました。(ディレクトリ capt 以下) ドキュメントがほとんどないですが、とりあえず。
最後に もともと、DCモータの回転数を読み取って制御するものを作ろうとしたのですが、そちらのほうはなんだかうまくいっていません。計画では、PWM の OFF の期間に電圧を読みとれば、回転によるむらが見えると思ったのですが...ノイズにしか見えていません...モータが小さすぎるのか 。もうすこし試行錯誤してみて、成果があれば、載せたいと思います。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: DCモータの回転数検出(1) STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 1 PRIMARY CATEGORY: CATEGORY: USB910A DATE: 03/15/2007 20:40:30 ----- BODY: いんちきオシロで書いたように、100us 間隔の PWM を 201usでサンプリングすると波形が見えてきました。200us でサンプリングするとどうなるか ... というと波形の同じところを見ることになります。波形をよーく見ると、山にあたる部分が右さがりになっています。ここが回転数によって微妙に違ってくるはずです。 これがそのグラフ。duty 比をあげると回転数も上がりますが、回転数に比例してギザギザが増えているように見えます。でも本当なんでしょうか? このグラフの横軸はサンプリングで、200 us 間隔(5kHz)です。duty 35% をみるとなんとなく、山が24個ほどあるように見えます。1 回転について 2 つ山があるとすると、5000 Hz * 24/200/2 * 60 = 18000 rpm になってしまいます。(もちろんそんな高回転では回っていません) 。モータの代わりに抵抗にしてみると一定の値になるので無関係ではなさそうですが、ひょっとしたら別のノイズかも知れない(電源とか)。回転数に比例していたとして、この波形から周波数に変換できるのか?というのも問題。duty 35%の場合、最小値と最大値の幅が狭いので、なかなかうまくいかなさそうです。だいたいの回転数がわかっている常態なら、デジタル処理でBPF をかければ、追従できるだろうなんて安易に考えていました。 実は実際に回転数を制御したいモータがあります。電動ドライバーをばらして出てきた 3.6V 仕様の 380サイズのモータ。なにに使っているかはいずれ日記に書くつもりですが、とりあえず秘密。実験とはかなり違うものなので、ターゲットのモータで試したほうが起電力が大きくて良さそうに思えてきました。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: クロック周波数と消費電流の測定 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 1 PRIMARY CATEGORY: CATEGORY: USB910A DATE: 03/16/2007 23:32:37 ----- BODY: いくつかのテストも兼ねて、ATtiny44 と ATtiny861 のクロック周波数と消費電流の関係について測定してみました。このテストでは、OSCCAL を変更してRC発振器の周波数を変更するだけでなく、CPU クロックのプリスケーラ(CLKPR)も変更しています。 これは、ATtiny44 の周波数と消費電流の関係。USB910Aの電流計の値が振れるので、どれぐらい振れるか見るために1つのOSCALの値について3回測定して全部プロットしています。8MHzで電源電圧が 3.3V→5V になるとだいたい2.5 倍。消費電力なら4倍も違う感じです。それだけでなく、5V のときは周波数を落としてもあまり消費電流が減らない。 こちらは、ATtiny861です。全体的に消費電流が増えているものの似たような傾向です。データシートに書いてある特性と大分ちがいます。ADC や内部基準電圧を Enable にしているので、その影響が大きいのかもしれません。 それはともかく、なにをテストしたかったかというと、1つは I2Cスレーブが CLK/2 の周波数までちゃんと動くのかという点。USB910のI2Cマスタは、I2C ROM の 3.3Vの特性に合わせて 400kHz ぐらいのクロックにしていますので、1MHz 以上なら動く予定でした。実際 1Mz にしても大丈夫なようです。このテストとは別に 3000 回ほどアクセスしてみましたが、ノーエラーでした。ちなみに さらにクロックをさらに落として 0.5Mhz にすると、90%ぐらいはちゃんと通信できるものの、残りの10%ぐらいはダメでした。 もうひとつは電流計のテスト。 付加回路がまったくない ATtiny44 の方を見ることにすると、最小と最大の差がだいたい 0.5 mA ぐらい。フルスケール 80mAですが、ノイズ対策をきっちりやっているわけでもないので、こんなものなのかも知れません。(ちなみに、この測定データはキャリブレーションしていないものです。5V のときは 5%ぐらい高めの値になっているはず。)
電流計の機能をとりあえず作ってみたものの、VCC付近の微小な電圧差をちゃんと測れるのかどうかというのが不安でした。こういうのを測定するには(普通は)rail-to-rail のオペアンプが必要になります。そういうオペアンプは(自作レベルでは)高かったり入手が難しかったりします。それだけでなく、配線も面倒。けっこう信頼できそうなので安心しました。
追記 ATtiny45v の消費電流 ついでなので、ATtiny45v の消費電流もとって見ました。8MHz では、ATtiny44 よりわずかに消費電流が大きいという結果でした。それはともかく、5V でもクロックを落とすと消費電流が落ちていきます。こいつはデータシートに載っているのと同じような特性でした。 追記 ATtiny26L の消費電流 ATtiny26L の消費電流もとって見ました。こっちもデータシートに載っているのと同じような特性でした。 追記 ATtiny26L の消費電流(USB910の typeA と typeBの差) こちらは、同じ測定を typeA と typeB でして値がどれだけ違うかのテスト。typeB は周波数は測定できないので、typeA の測定と同じ周波数だと仮定しています。これみると値がずれていて typeB で使っている ATtiny44 のオフセットが -1mV ぐらいあるような感じ。これってオフセット校正ってのをやれば校正できるのかなぁ? ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: ケースと基板について STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 1 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 03/16/2007 23:39:05 ----- BODY: USB910を作るときコンパクトなケースに入れたいと思いました。最初に選択したのは、タカチ SW-55S です。秋月のC基板(ガラスエポキシ 片面/両面)を 1/2 弱 (33mm x 47mm) に切ったものを愛用しているのですが、このケースに、 それがちょうど入ります。 これは、TypeB 試作1号機ですが、フタに2箇所ネジ止めしています。こうすると配線が保護されるので、触って線が外れたり動かなくなるおそれが(ほとんど)なくなります。高さも 20mm (内寸は13mm) あって、USB B コネクタがぎりぎり収まります。 これは、TypeA 試作1号機なんですが、コネクタを横につけてしまい、ケースがちゃんと止まらないことに後で気づきました。あと無理に押し込んだので、改造とかがやりにくくなってしまいました。 もっと大きな基板でゆったり作った方が良さそうですが、タカチ SWシリーズには 20mm高 のものがなく収まりが悪そうで困っていました。で...千石で見つけたのがテイシンの TB-55シリーズ。現在テイシンのホームページには載っていませんが、20mm高で具合がよさそうです。中でも良さそうなのが、TB-55B(80x50) と TB-56B (95x65) 。TB-55Bのほうは、C 基板を 2mm ぐらい削れば入りそうです。基板を削りたくなけば、TB-56B が良さそう。TB-56B なら秋月で250円で売っているブレッドボードを乗せて試作ベースにするのも良さそう。 さて、基板を削ったり切るのに何を使っているか ... 前は三角のダイヤモンドやすりを使っていたのですが、とっても面倒でした。ホーザンのPCBカッターなんてのもあることは知っていますが、ちと高いうえ場所をとりそう。少しパワーのあるリュータに切断砥石をつけるというのも良いのですが、端を削るならともかく、基板中央を切るのは本体がじゃまで難しいです。あと回転数が高くて粉塵がけっこう出ます。 なにか良いものはないかと思って探して見つかったのが、電動飛行機用のギアダウンユニット -- OK模型 ギヤボックス GBX400 。プロペラ側に 3mm のネジが切ってあるので、ダイソーの 切断砥石とかダイヤモンドカッターをつけることができます。これを使って楽に基板を切ることができるようになりました。 (注意: 試すのは個人の責任でお願いします。試す場合には、メガネと防塵(or花粉症向けフィルター入り)マスクを付けることを強くお勧めします。手袋をする場合、軍手はまきこまれるおそれがあるので避けて、皮か厚手のビニール手袋にしましょう。) ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: 作ってみようと思っている装置 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 03/20/2007 00:14:45 ----- BODY: いまのところ単なるアイディアメモ (1)UNIX もどき USB Key 実はUSB910では、オリジナルのAVR-CDCに手を入れて getc/putc でプログラミングできるようにしていて、USB シリアル装置を手軽に作れるようにしている。で、なにか便利(そう)なものを作ってみようと考えていて思いついたもの。 この装置をUSBにつないでターミナルソフトを立ち上げ、ENTER を入力するとlogin: なんて出る。本当に login できて、いくつかのコマンドが使える。使えるコマンドは、ls と cat ファイル名と cat > ファイル名。あと rm ファイル名 は必要か。なんに使えるかというと、(他の)パスワードとか忘れそうだけれども秘密にしたいものの覚書。ファイルデータは、1件 1KB 以内で、32件までにして、I2C ROM に入れる。I2C ROM だけ抜かれたりしたときの対策に暗号化が必要で、暗号化のキーは本体のEEPROMに覚えさせてロックビットで保護する。最大の問題はコードのサイズ。 4KB に入れるのは無理そうだが、8KB には収めたい。装置単体でのパスワードの変更は無理だろう。で、どうするかというと、データをいったん全部吸い出して、あらためて パスワードと暗号化キーデータを生成して、EEPROM に書き込みデータを書き戻す...そういうホストプログラムがあれば問題ない。 (2)USB アイキャッチャー LinkStationとか玄箱とかを愛用しているのだが、単体ではほとんど何も出力できないし、入力できない。ちょっとした情報でよいので入出力できるデバイスをつけたい。LCDキャラクタ/グラフィックディスプレイとかももちろん良いのだが、もっと小さくて目立つものにしたい。8x8 のドットマトリックスLEDを使ってボタンも2つほどつけて SW-55 のケースに収めることを目標にする。 AVRは、ATmega48 が良いんじゃないかと思う。ホストからコントロールするので、表示はどうにでもなりそう。
USB LCDキャラクタディスプレイを作るならLCD2USBがお勧め。プロトコルをこれにあわせたいとは思っているのですが、どうなるかはまだわかりません。
(3)I2C 高機能電源 PWM で降圧型DC/DC コンバータを作り、定電圧と定電流の機能を持たせてホストから機能設定とか電圧/電流をモニタできるようにする。できれば、NiMHの充電器として使えるようにしたいし、逆に充電したNiMHから昇圧できる機能もつけたい。コイルは共用できるはずでスイッチには Pch+NchのMOS FET を使う。AVR は 手持ちのATtiny26L..でできるとうれしい。なにを選択するにせよ、昇圧時は、自己消費が大きいとあまりうれしくないので、そのあたり工夫してみたい。 (4)I2C で制御する音を出すなにか 電子工作のテーマとして音を出すものを作るのは楽しい。I2Cドライバも作ったので、ATtiny45 (かひょっとすると 85) を複数個つかって音を出すなにかを作ってみたい。プログラム次第で簡単なものから高度なものまで作れると思うが、バーチャルアナログシンセなんてものにもトライしたい。外部クロック入力にして正確な音程を目指すのも良いが、RC発振器をキャリブレーションして使うというのも味があってよいかも知れない。電源ノイズが載るのだけは避けたいので、電源だけは専用の レギューレータをつけてやりたい。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- COMMENT: AUTHOR: otam EMAIL: tamura@recursion.jp IP: 220.210.139.110 URL: http://www.recursion.jp/avrcdc/ DATE: 03/20/2007 02:52:34 tiny44よさそうですね〜。AVR-CDC いろいろ遊んでみてください。 ----- COMMENT: AUTHOR: すz EMAIL: IP: 210.143.35.12 URL: DATE: 03/20/2007 17:44:49 あ、AVR-CDCの作者さんですね。AVR-CDCおいしく使わさせていただいてます。これがあったおかげで、USB910を作ってみようという気になったぐらいです。 そうそう、オリジナルとLinuxの組み合わせで接続時データが消えるのか化けるのかよくわからない問題があったので、AVR-Dorper のコードも参考にして、直しています。 たぶん sendEmptyFrame ってのがみそだと思うんですが、あれこれいじっているうちに問題がなくなったのでホントのところは不明。 ----- -------- AUTHOR: すz TITLE: AVR Studio 4 + WINAVR を使ってみた STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 03/20/2007 23:57:43 ----- BODY: 前にも書きましたが、私の開発環境は Linux です。しかも実は古い。いまだに gcc-3.4 を使っています。AVR Studio + WINAVR を使っているひとが圧倒的に多いと思いますので、AVR Wikiの情報をもとに いまさらながら Windows で build してみることにしました。 tar.gz のファイルを全部コンバートして、Project を作って、Makefile を修正して... 結構面倒ですね。 それだけでなく、typeB のバイナリが4158バイトになって4KBに収まらないという大問題が... オブジェクトのサイズを比べると、小さくなっていたり大きくなっていたり... avr-libc で使っている部分も 32バイトほど大きくなっているようです。usb910conf.h を修正して機能を削れば小さくはできるんですが、あまり削りたくない。... でどうしたか。usbdrv.c のオブジェクトだけがかなり大きくなっているので、gcc-3.4 で作ったアセンブラファイルを持ってきて置き換えたら、なんとか 4094 バイトとぎりぎり収まるようになりました。 こういうことをするのは手間なので、これから zip 版も作ろうと思います。 というわけで、最新版は、usb910-0.3.tar.gzusb910-0.3.zipです。 最新版には、aps ファイルも入れておきます。上で説明したワザを使ってbuild するときは、typeBx.aps を使ってください。あと、RC発振器のキャリブレーションで使ったコードもサンプルとして添付しました。(こっちはASIS) ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: USBアイキャッチャーの設計 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: USBアイキャッチャー DATE: 03/22/2007 12:37:04 ----- BODY: USB シリアル接続で、8x8ドットマトリックスLEDとボタン2つを制御するものを作りたい思っています。玄箱にとりつけて、ちょっとした情報を表示させたりする用途を考えていますが、他にも面白い使い方ができるかも知れません。8x8しか表示できないものをディスプレイとは言い難いのでアイキャッチャーと名づけました。 コンセプト まず、玄箱の上に乗せても違和感のないサイズにするというのが第一。タカチ SW-55に入るようにしたいと思います。たった8x8しか表示できないものにあんまり手間やお金をかけたくないので、次に安く簡単に作れるということを目標にしたいと思います。 部品の選定 8x8ドットマトリックスLEDは、秋月の BU5004-R..このサイズでないとケースに入らない。しかも90円と格安なので文句なし。ボタンは、プッシュスイッチ AJN1B32 ケースに入れるので、背が高いこれにしました。コントローラは、ATmega48。必要ピン数をクリアして最も安いもの。(300円〜350円ぐらい)
ちなみに 200円のBU5004-RGの 中央部のピンを切り取ることで緑バージョンも作れます。ただし電流制限抵抗も変えないと暗めになってしまいます。
部品の配置 仮組みですが、こんな感じになりました。ATmega48をじか付けしないと無理そうです。しかもピン数が多いので↑のようにしか配置できない。逆にBU5004-Rは、ソケットにします。普通に差すとUSBコネクタと同じ高さで、ケースぎりぎり。プッシュスイッチはこの配置にしないと、外観が悪くなってしまいそうです。簡単に作れるのが目標なのに、なんだか配線が辛そうになってしまいました。 ピンの割り当て ATmega48 は、28 pin ですが、電源やリセット、水晶などを除くと自由に使えるピンは、20。USBには2ピン(PD2/PD3) 必要で、16ピンは、ドットマトリックスLEDで使います。のこりは 2。これをボタンに割り当ててしまうと、拡張の余地がなくなってしまうので、ボタンはLEDと兼用することにして..2ピンをあけておくことにします。あけるピンは、TXD/RXD が順当だろうと思います。ドットマトリックス用のピンは極力隣り合ったもの(計10ピンしかないけど)を使うことにします。
具体的に書くとこんな感じ、赤の部分が楽できるところで10ピン。右の部分が変則なのは、ISPのためで COL/ROWをどちらかに統一しないとLEDに電流が流れてしまうのです。 追記: もうひとつ楽できるところがありました。
LEDの制御と電源 ドライバなしで光らせるので流せる電流には限りがあります。複数ドット同時に光らせるとすると、光らせるドット数によって1つのLEDの明るさが変わりムラができてしまう。なので、64ドットを順に光らせる(1/64 duty)ことにします。(これだと確実に同じ明るさになります。) リフレッシュレートを120Hzとすると x64で7.68kHz -- 1dotあたり130 us ほどで切り替える必要があります。この処理を平タスクでやることにします。(USBの応答性を保証しないといけないので、割り込みはちと面倒なのです)。さて、電流はどれぐらい流せるのかというと ... AVR は 40mA流せますし、LEDの方も 1/16 duty 以下なら 60mAほど流せるようです。電源を5Vにして電流制限抵抗を100Ωにすることにします(33mA)。(緑バージョンなら75Ω)。電源に入れるコンデンサは USBの規格上直結だと10uFが最大のようです。...となると光らせる間隔をコントロールするか、リフレッシュレートを上げるかしないといけないかも知れません。
たとえば上半分を光らせるとして普通に制御すると消費電流は、リフレッシュレートと同じ周波数で変動することになります。安定した明るさで光らせるにはそれに見合ったコンデンサをつけないといけないわけです。分散して光らせられるようにすれば、コンデンサも小さくできます。光らせるドットの数がわかっていれば、1/64 に分割した時間のどこで光らせるかを決めるのは難しい処理ではありません。
拡張案 いまのところ、サブ基板でLEDを増やしていけるようなものを考えています。実は過去にこんなの↓を作ったことがあって、サブ基板もそれをベースにモディファイしようと思っています。(もちろんこんないいかげんなものじゃなくて、本体と同じように部品を配置します。)ドットマトリックスLED一個あたりATtiny2313を1個使う前提で良いなら、とても簡単そうです。
↓のように抵抗でつなぐか、直結すればよいわけです。配線を簡単にするためには、あえてTXD/RXDはポートとして使い、余ったICPを通信用(受信ONLYか)にすればよいのではないかと思います。
ベースにするつもりのコードを置いておきます。 bu5004s-0.1.tar.gz と bu5004s-0.1.zip これは、過去に作ったコードを↑のピン配置にあわせただけのもの。EEPROM に設定した8バイトまでのASCIIコードをスクロール表示するものです。ソフトシリアルの部分は作っただけ -- 動かしたこともありませんので信用できません。
回路図案 いまのところこんな風にしようと思います。ボタンは ANODE 側 ROW1 と ROW2 を共用してつけようと思います。ボタンを押していなければ表示にまったく影響しないし、ボタンを押していても 2.2K の負荷が(並列で)増えるだけなので、ほとんど影響ないと思います。ボタンのセンスは LEDを光らせない HI-Z の状態から、ROW1/ROW2 を pullup にして読み取ればOK。
追記:回路図変更しました。 USBのプルアップ抵抗を 配置の都合で抵抗の内側に変更。 ROW1 と ROW2 で作ってしまったのですが、ROW はカソードでした。もう作ってしまったので直す気はないんですが... カソード側だと ボタンを押したときに2.2K の抵抗を通して電流が流れて ROW1 と ROW2 の列がうっすら点灯します。
----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: AVR-CDCの性能 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 03/23/2007 22:26:26 ----- BODY: Low Speed とはいえ 1.5Mbps なんだから転送のオーバヘッドなんて気にしなくて良い ... なんて思っていませんか? それは大きな間違いです。 Low Speed では 1 パケットで最大 8 バイトしか送受信できないので、プロトコルのオーバヘッドの方が大きいのです。AVRusb.ZIPに含まれているAVR309補足を読むと、8 バイトで だいたい 2000 CPUクロックのようです。1byte = 10bit として bps 換算してみると、だいたい 480k bps になります。理論的な上限はだいたい 1/3 になる計算です。 さて、USB910 では、コマンドを送ってリプライを受け取る..というハンドシェークをしています。こういう使い方をする場合、遅延がものすごく大きくて、上の理論値など関係ないようなレベルの性能になってしまいます。 というわけで、いったいどれぐらいの実効性能が出るのか調べてみました。OS は Linux を使い、3 バイトのコマンドを送って Nバイト受信するテストと Nバイトのコマンド+データを送って 1バイト受信するテストをしています。 このグラフは、送信-受信の時間です。もう何バイト転送しようがあんまり関係ないという感じです。 こちらは、送受信のスループットを bps に換算したもの。こういう使い方だと1.5Mbps の1/50 出れば良いほうですね。 AVR910プロトコルと性能 AVR910プロトコルでは、Flash などの書き込みは、1 バイトづつ行います。コマンド+データの 2バイトを送信して、1バイトの結果を受け取るのです。そうすると...上のグラフで 5000 bps のレンジを使っていることになります。計算すると 1KBの書き込みデータを送るのに 4秒かかることになります。実際の書き込み時間は、7KBで30秒弱だったので、ほとんど転送時間が占めていることになります。 AVR910プロトコルは、バッファリングしないことが前提なのでこれを守る限り書き込み時間は早くなりません。ですが、たとえば 8バイト分のデータを一度で書いて、8バイト分の結果を一度に読み込むようにしたら... だいたい 25000 bpsのレンジになり 5倍近く高速化されることになります。もし、ページサイズ分のコマンドを連続して送って結果を一度で読み込むようなことができれば、さらに数倍になりそうです。できるかどうかわかりませんが、一度試してみようと思います。
追記:試してみました。
usb910a のコード 6918バイトの書き込み時間・読み込み時間
   (uisp 使用 , コマンド起動時間を含む)

書き込み
uisp オリジナル:                  29.129秒 
ページ(64バイト)単位書き込み版:    5.729 秒
uisp パラレルポートライタ:         4.763 秒(参考値)

読み込み(ベリファイ)
uisp オリジナル:                  13.939秒 
64バイト単位読み込み版:            3.551 秒
uisp パラレルポートライタ:         4.212 秒(参考値)

コマンド実行時間で5.08 倍になりました。このうち 1.09秒は書き込み待ちで転送時間は 6.0 倍ぐらい?。-- さらに数倍というのは期待しすぎたようです。が、パラレルポートライタにだいぶ近い値。これ以上転送時間をチューニングしても全体の性能はあまりあがらなさそうです。 読み込みはもともと転送量が少ない(コマンド送信+2バイト受信)し書き込み待ちもないので書き込みよりは高速でした。でも十分遅いので、64バイト単位で読み込むようにしたら 3.9 倍に高速化されました。 でも、転送量を元に計算すると 1948 byte/sec -- たいした性能ではありません。ISP の最高クロックを 100 kHz にしているので、ISPの処理の上限が -- 3125 byte/sec。こっちの方がネックかも知れません。
----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: 製作とテスト STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: USBアイキャッチャー DATE: 03/26/2007 16:13:00 ----- BODY: 製作とテストが完了しました。以下レポート 製作 オモテ 表は、わりとすっきりした感じになりました。隠れている右上の部分に、↓のように割とゴミゴミした感じで USB の電流制限抵抗と電圧制限のツエナーダイオードが付いています。ISPコネクタは一列でないと、ISPを付けたまま動作確認ができません。(LED と干渉します) ウラ 裏には、LED の電流制限抵抗が結構あります。中央の 2.2Kは USBのプルアップ。(部品直結以外の)配線は電源入れて16。ほとんど1:1なので楽な方ではないかと思います。↓は抵抗直結の部分の拡大写真。高さを 3mm に抑える必要があるので、こんなつけ方になりました。片側を先に付けて、押し込みながら反対側を付けるというやりかたでなんとかなりました。配線材は色つきのポリウレタン線(UEW) 0.18φ(らしい)。千石(店頭)で買ったやつ -- 色が付いていないと被覆が熔けたかどうか(私には)わからないです。(次は、エレ工房さくらいの 0.2φ(赤)にしようと思います)あと、左端の部分は使っていませんが、これはケースと干渉するためです -- 要注意。 製作時間は 6時間ぐらい。量のわりに時間がかかっているのは、配置をアレコレ考えながら作ったため。 テスト 普通は、LED を点灯させることから入りますが、このケースでは連続点灯はやばいので、USB の動作確認を先にやりました。通信さえできれば、あとは自由に制御できます。まず、端末ソフトを使ってコマンド入力できるようにしました。S を入力すると EYECAT なんてのが帰ってくれば OK 。つぎは点灯コマンドを追加していって確認。点灯コマンドは、z -- 全点灯 、x -- 縦線移動 、c -- 横線移動。あと大事なのは 消灯コマンド(v) やばいと思ったらすぐ消灯できる必要があります。 最初の写真は、全点灯の実行結果。十分かどうかわかりませんが、結構あかるく点灯しました。作ってしまってから思ったのですが、75Ωで作っておいて、電源側にダイオードをソケットでつけられるようにしておくと、緑のLEDと差し替えできてよかったかも知れません。 ボタンのテスト ボタンは、ROW1/ROW2 の線を共用しました。作ってしまってから気がついたのですが ROW は、アノードじゃなくてカソードでした。これだと ボタンを押したとき 2.2Kの抵抗を通して電流がながれて ROW1/ROW2 の1ラインがうっすらと点灯してしまいます。この部分は、(抵抗の切れ端で)直接配線してしまったので、直すの面倒。そのまま使うことにしました。 それはともかく、テストしていたらボタンを誤認識します。どうもプルアップしてから電圧が安定するまでに時間がかかるのが原因らしく、delayを入れたら解決しました。 テストまでのソースコードを eyecat-0.1.tar.gzeyecat-0.1.zipに置いておきます。USBのコードが GPL なので、ライセンスはGPLになります。このテストコードを元にあれこれやったほうが楽しいのではないかと思いますので、完成版のコードは公開しないかも。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: プログラムの説明 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: USBアイキャッチャー DATE: 03/26/2007 21:18:47 ----- BODY: あんまりたいした内容ではないのですが、eyecat-0.1.zipに含まれる eyecat-test.c についてポイントを解説しておきます。
読み手を想定して書いているわけではありません。-- 実はプログラムを引用して説明を書く練習だったりします。
平タスク 平タスクともメインループとも呼ばれる典型的な処理です。いろいろ凝った仕掛けを作ろうかと思ったこともありましたが、最近はもっぱらこの形式で書いています。注意点としては、イベントの中で止まらないようにすること。特にこのプログラムでは、LED の連続点灯になってしまうとマズイので注意が必要です。具体的に書くと getc() は入力データがないとき待ちになってしまうので、 can_getc(1) で読み込めるかどうか確認するとか... あと、イベントに変数を使うときは volatile を付けること。これを忘れるとレジスタにコピーした値をずっと参照して、イベントが上がらないケースがあります。
int main(void)
{

    /* set system_clock pre scaler 1/8 => 1/1 */
    CLKPR = (1<<CLKPCE);
    CLKPR = 0;

    各種初期化

    sei();

    for(;;) {
	wdt_reset();
	poll();

	if (イベント1) {
      イベント1の処理
	}
	if (イベント2) {
      イベント2の処理
	}
         :
    }
}
タイマー処理 一定間隔である処理をさせたいとき使う処理に以下の set_timeout / check_timeout ってのを作って使っています。時間の定義は 最小の時間と最大の時間が int16_t の正の範囲(0-32767)に収まるようにプログラム毎に調整しています。ちなみに、変数とかの型は、uint8_t とか使ってサイズと signed/unsigned を明示するようこころがけています。-- こう書いておくと、プログラムの一部を PC にもっていってテストする場合に便利なのです。
static inline uint16_t get_time() {
	return TCNT1;
}

static void set_timeout(uint8_t chan, uint16_t t) {
	to_time[chan] = t + get_time();
	to_flag[chan] = 1;
}

static int8_t check_timeout(uint8_t chan) {
	if (to_flag[chan] && (to_time[chan] 
         - (int16_t)(get_time()) <= 0)) {
		to_flag[chan] = 0;
	}
	return !to_flag[chan];
}

使用例:
	if(check_timeout(TO_DOT)) {
          :
            set_timeout(TO_DOT, 24);
    }
詳しいコメント: TCNT1を直接使えばよいものを get_time で ラップ(wrap)しているのは、ATtiny861 みたいな HIとLO が別々のレジスタになる拡張に対応できるようにしたため。 to_flagが冗長で無駄のように思えるかも知れません。以前は使っていなかったのですが、そうすると set_timeoutで最初の TIMEOUT を設定しないといけないので、フラグを使うようにしました。1bit の情報を扱うのに 1バイトも!使うのは無駄だと思う場合は、set_timeout/check_timeout を inline 化して to_flag を bitmap にする場合もあります。 timeoutの名前の由来は、UNIX。もともとは、timeout という関数で時間が来れば登録した関数を callするものですが、そこまでするとコードを小さくできないので set_/check_ という プレフィックスを付けた二組の関数にしました。もちろん 定期的な処理だけでなく(名前のとおり)一定の時間が立つのを待ち合わせるのにも使えます。 ボタンの処理
static uint8_t button_read() {
	static uint8_t b1_state;

	b1_state <<=1;
	if (bit_is_clear(ROW2_PIN, ROW2)) {
		b1_state |= 1;
	}
        if (b1_state == 0 || b1_state == 0xff) {
                    :
        }
}
ざっくり簡略化すると上のような処理になっています。これはチャタリング除去の処理で、8回連続(120Hz なので、66ms の間)同じ値なら採用するというもの。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: AVR910プロトコルとデバイスコード STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: USB910B DATE: 03/27/2007 05:32:50 ----- BODY: AVR910では、t コマンドでサポートされているデバイスの一覧を返し、T コマンドでデバイスを選択するという仕様になっています。そして、定義されているデバイスは、AT90S2313とか ATtiny26 とか ATmega8 ぐらいまでで、新しいデバイスは定義されていません。 このデバイス一覧にないものはサポートできないと思われるかも知れません。が、新しいデバイスに対応できる仕組みは用意されていて、いくつかの書き込みソフトはそれに対応しています。 仕組みその1 -- T コマンドで 0 を指定する。
uisp の場合 -dpart=auto と指定することでこの動作になります。 avrdude の場合 -F を指定することで warning は出ますがこの動作になります。
仕組みその2 -- . コマンド(ニューユニバーサルコマンド)
4バイトのデータを送り、最後の1バイトを読み込みリターンするコマンドで、すべてのISPコマンドを実行できる拡張です。avrdude や uisp では (AVR910で定義されていない)上位ヒューズバイトの書き込みなどはこのコマンドを使って実装しています。
それなら デバイスの一覧なんて必要ないんじゃないか?と思われるかも知れません。それはほぼ正しいです。 デバイスコードの役割は、2つあります。 役割1:シリアルプログラミングモードに入る方法の指定
AT90S1200だけ 特別扱いしているようです。他のはシリアルプログラミング許可命令で 第3バイト目が 0x53 かどうか確認していますが、AT90S1200 は確認なしです。
役割2:遅延の時間指定
ページモードを持っていないデバイスでは、1バイト書き込む毎に遅延をいれていたりします。
これらの処理は、はっきり言って新しいデバイスでは関係なさそうです。0 が指定できなくて、なにか指定しなければならない場合 0x20 -- AT90S2313でも指定しておけば良いのではないかと思います。(というより、AVR910そのものを使う場合は、0 より 0x20 が良いかも知れません。)。ライタソフトは、普通 デバイスコードより、シグネチャーで制御すると思います。( 少なくとも avrdude, uisp はそうなっています。) USB910はどうしているか? USB910では、新しいデバイス専用です。AT90S1200 をはじめとして、ページモードを持たないもの(AT90S8515、AT90S8535、AT90S4433 ) は、はなから切捨てています。デバイスリストは、互換性の点から 0x20 のみ返しています。T コマンドでなにがきても動作には関係ありません。 ページ書き込みの時間は 一律 10ms 取っています。これ以上の時間が必要なデバイスはわずかなので対応していません。もし ATmega163 とか該当するものを使いたい場合ソースコードの twd_xx を修正してビルドしなおす必要があります。 というわけで、AVR910は新しいデバイスに対応できないというのは、誤解だと思います。(といってもあまりに古いのはダメです。すくなくとも . コマンドに対応している必要があります。) ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: avrdude-1.5.3 を使ってみた STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: USB910B DATE: 03/28/2007 00:08:09 ----- BODY: uisp を修正しながら使い続けているので、avrdude も実は使ったことありません。前に USB910は windowsでは使えないなんて書きましたが、windows も対応している avrdude で使えるか(Linuxですが)試してみることにしました。 -F オプションに加えて -u オプションが必要でした。
# avrdude -F -u -p t861 -c avr910 -P /dev/ttyACM0 -U flash:w:usb910a.hex
Found programmer: Id = "USB910A"; type = S
    Software Version = 2.4; Hardware Version = 2.4
Programmer supports auto addr increment.

Programmer supports the following devices:
    Device code: 0x20 = ATtiny84

avrdude: warning: selected device is not supported by programmer: t861
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e930d
avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed
             To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "usb910a.hex"
avrdude: input file usb910a.hex auto detected as Intel Hex
avrdude: writing flash (6946 bytes):

Writing | ################################################## | 100% 30.38s

avrdude: 6976 bytes of flash written
avrdude: verifying flash memory against usb910a.hex:
avrdude: load data flash data from input file usb910a.hex:
avrdude: input file usb910a.hex auto detected as Intel Hex
avrdude: input file usb910a.hex contains 6946 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 13.90s

avrdude: verifying ...
avrdude: 6946 bytes of flash verified

avrdude done.  Thank you.
...一応は動くようです。ちょっと気になるのが、"Device code: 0x20 = ATtiny84" というところ、avrdude.conf をみたら、あちこちに、"Try the AT90S2313 devcode" なんて書いて 0x20 に無理やりしています。ATtiny84 はたまたま最後に定義されたものみたいです。 さて、書き込み時間が 30.38秒 ベリファイ時間は、13.90秒のようです。これは uisp もほぼ同じで予想通りです。... ということで uisp でやったように 高速化できるかやってみました。 結果は、書き込み時間が 6.58秒 で4.61倍高速化、ベリファイ時間は、3.49秒で 3.98 倍高速になりました。 ところで、ヒューズビットはどうやってアクセスするのだろう? ...どうやってもできません。コードを見ると ... usbasp.c とかは read_byte メソッドに avr_read_byte_default を使っているのに、avr910.c は 使っていない。これだと avrdude.conf に何を書こうが無理ですね。 というわけでちょっと直したら使えるようになりました。
# avrdude -F -p t861 -c avr910 -P /dev/ttyACM0 -t
Found programmer: Id = "USB910A"; type = S
    Software Version = 2.4; Hardware Version = 2.4
Programmer supports auto addr increment.

Programmer supports the following devices:
    Device code: 0x20 = ATtiny84

avrdude: warning: selected device is not supported by programmer: t861
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e930d
avrdude> dump lfuse
0000  62                                                |b               
avrdude> q

avrdude: safemode: Fuses OK

avrdude done.  Thank you.
これで -u オプションも不要になりました。 例によって 改造部分のパッチ avrdude-5.3.1-usb910.patch,avrdude-5.3.1-avr910d.patchと、おまけでソースRPM avrdude-5.3.1-suz2.src.rpm、さらにおまけで 使っている uisp の ソースRPM uisp-20040311-1suz4.src.rpmを置いておきます。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: Windows で avrdude STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: USB910B DATE: 03/28/2007 19:01:19 ----- BODY: USB910 向けに高速化した Windows 用 avrdude を作ってみることにしました。 ビルド環境は、MinGW/MSYS を使うことにします。 linux向けに作ったパッチをあてて configure したら (一行だけ修正が必要でしたが)ビルドできてしまいました。uisp と違ってこういうところはいいですね。(作る側が楽)。 さて本当に動くのか確認。avrdude.exe と avrdude.conf を同じディレクトリに置いて動かしてみます。
D:\>avrdude -F -p t861 -c avr910 -P COM4 -U flash:w:usb910a.hex
Found programmer: Id = "USB910A"; type = S
    Software Version = 2.4; Hardware Version = 2.4
Programmer supports auto addr increment.

Programmer supports the following devices:
    Device code: 0x20 = ATtiny84

avrdude: warning: selected device is not supported by programmer: t861
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.02s

avrdude: Device signature = 0x1e930d
avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed
             To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "usb910a.hex"
avrdude: input file usb910a.hex auto detected as Intel Hex
avrdude: writing flash (6946 bytes):

Writing | ################################################## | 100% 14.05s

avrdude: 6976 bytes of flash written
avrdude: verifying flash memory against usb910a.hex:
avrdude: load data flash data from input file usb910a.hex:
avrdude: input file usb910a.hex auto detected as Intel Hex
avrdude: input file usb910a.hex contains 6946 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 5.28s

avrdude: verifying ...
avrdude: 6946 bytes of flash verified

avrdude: safemode: Fuses OK

avrdude done.  Thank you.
...なんか動いてしまいました。違うのは性能だけ。
                      書き込み        ベリファイ
Windows 高速化なし    15.58s           7.47s
Windows 高速化版        14.05s           5.28s
Linux 高速化なし        30.38s          13.90s
Linux 高速化版           6.58s           3.49s
Windows はなにもしなくてもソコソコ早いかわりに、チューニングがほとんど効かない。Linux は、なにもしないとすごく遅いけど、チューニングすると何倍も早くなる結果でした。-- OS の性質がもろ出ているようで面白いですね。 ビルドしたものを avrdude-usb910.zipとして置いておきます。(必要ない人も多いと思いますが、GPL なのでソースもまるごと入れました。) もし、USB910を Windows で使いたい人がいれば使ってみてください。
追記1: MinGW/MSYS はビルド環境です。この avrdude.exe を動かすだけならインストールする必要はありません。 追記2: これをビルドした環境も実は古かったので、最新版 MinGW-5.1.3/MSYS-1.0.10 を試してみました。なぜか libhid 関係で undefine のエラーが出て make でエラーになりました。 ser_avrdoper.c で #undef HAVE_LIBHID を入れると ビルドできました。参考まで。 追記3: WinAVR を使っていれば、それに添付されている avrdude にパスが通っています。混同しないように avrdude-910 とか rename して、WinAVR/bin に置くのが良さそうです。
----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: Windows で テストプログラムを動かす STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: USB910B DATE: 03/30/2007 03:09:38 ----- BODY: MinGW/MSYS で avrdude をビルドできたので、USB910用のテストプログラムを移植することにしました。 もともと簡単なものなので、移植するのは次の2点だけです。 1)シリアルポートの制御 open/close/read/write を使うことにして、ファイルディスクリプタを使ってシリアルポートの設定をする 関数を別に用意することにします。ファイルディスクリプタからハンドルへの変換は、_get_osfhandle が使えました。 シリアルポート設定自体は、avrdude を参考に作りました。あと、open のオプションに O_BINARY が必要でした。 2)usleep の作成 WIN32API には、ms 単位の Sleep があるので、単位を変換して usleep を作ることにしました。 あと、性能を測るために、double dtime() という関数を作りました。Linux だと gettimeofday を使えばよいわけですが、WIN32API だと TimeGetTime() 。この関数を使うには、リンカオプションで -lwinmm が必要でした。 MinGW でも getopt が使えるようなので、ついでにオプションの処理を整理。 テスト1 AVR-CDC 性能測定に使った、テストプログラムを使って長時間エラーなしに使えるかやってみました。百万回ほど通信しましたが OK でした。 変な形ですが、何回やってもこうなります。ドライバの作りと カーネルのイベントの処理の特性だと思っていますが、ひょっとしたら USBのコントローラとかハードウェアの違いでこうなるのかも知れません。 もっと I/O サイズを大きくしたらどうなるか興味が出てきました。別途テストしてみたいと思います。 テスト2 RC発振器のキャリブレーションで使ったプログラムが動くか確認。このプログラムは、I2Cで通信しています。I2Cの通信では、BUSY のときは、−2 を返して通信できない仕様にしているので、タイミングも関係あります。もとのテストプログラムがいいかげんだったので、結構ハマリました。−2が返ってきたときはリトライするコードを入れることで(って仕様どおりにしただけなんですが)一応ちゃんと動くようになりました。 最新版は、 usb910-0.4.tar.gzusb910-0.4.zipです。MinGW/MSYS でビルドする場合、tar.gz の方を使ってください。 注意点 ... テストプログラムは自由につかっても良いですが、-Wall すると山のように Warning が出ます。その程度のものですので、あまり信用しないように。 まだ問題はあるかも知れませんが、とりあえずは Windows でも USB910 を使えるようにしました。よかったら USB910 で遊んでみてください。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: AVR-CDCの性能(2) STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 04/06/2007 01:44:24 ----- BODY: 今回は、通信に使うコマンドを変えて send:recv の比率が 1:2 または 2:1になるようにして、I/O サイズによってどれぐらい性能が変わるのかを測定してみました。 I/OサイズとTAT I/Oサイズとスループット これをみると、すくなくともこの条件では Windows の方が圧倒的に早い。スループットで、2-3倍もあります。 I/Oサイズを大きくしていけば性能が上がっていく、レイテンシ(遅延)を隠すことができるので当然といえば当然ですが、実は他にレイテンシを隠す方法があります。 それは、ソフトウェアパイプライニングという手法で、一般にはCPUのチューニングに使われているものです。send と recv をずらすことで、レイテンシを隠すやりかたです。 さて、これを使うと性能がどうなるか見てみることにします。 I/OサイズとTAT (Linux) I/Oサイズとスループット(Linux) これは Linux の場合。TAT が短くなっています。スループットでみるとI/Oサイズが小さくてもピーク性能が出るようになりました。 I/OサイズとTAT (Windows) I/Oサイズとスループット(Windows) Windows の場合も 同じような効果はあるようです。 このパイプライングのコードを avrdude で試してみました。早くなったかというと ... Windows では全然変わらず。Linux では、Read(ベリファイ)は早くなったものの、Write は逆に遅くなってしまいました。 こういったことをいろいろやっていたのは、Windows で avrdude が遅いのをなんとかしようとしたためです。残念ながら、なかなか思うようにいかない結果になってしまいました。 追記 タイミングを変えてみようと思い、ISP書き込みのクロック周波数を上げてみたところ、Windows で (ISP書き込みの時間短縮以上に)高速化できることがわかりました。Windows は、↑のテストのようにすぐさまレスポンスを返す場合は早いけれども、ちょっとレスポンスに時間がかかる場合はかえって遅くなってしまう特性なのかも知れません。Linux では、なにやっても書き込み時間はこれ以上早くならない感じですが、読み込みは、まだ高速化できるようです。 パイプライニングの効果も確認できています。
                              書き込み        ベリファイ
Windows 高速化版(100kHz)        14.05s           5.28s
Windows 高速化版(200kHz)         9.31s           3.25s
Windows パイプライニング(200kHz) 9.72s           3.19s
Linux 高速化版(100kHz)           6.58s           3.49s
Linux 高速化版(200kHz)           6.85s           2.40s
Linux パイプライニング(200kHz)   6.54s           1.81s
----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- COMMENT: AUTHOR: otam EMAIL: tamura@recursion.jp IP: 219.102.203.43 URL: http://www.recursion.jp/avrcdc/ DATE: 04/07/2007 17:44:21 AVR-CDC のシリアル通信は半二重で 115Kbps ぐらいが限界のようです。UHCI系のホストだとCPU依存が大きいですね。 AVR-USB がアップデートしたので昨晩 AVR-CDC も入れ替えました。usbtiny を参考に改良したとのことです。 ----- COMMENT: AUTHOR: EMAIL: IP: 210.143.35.13 URL: DATE: 04/14/2007 02:08:23 USB910も AVR-CDC の新バージョンをマージしました。 独自に入れた制御を捨てて、同じ制御にしてみましたが、Linux/Windows で問題なく動作しているようです。 ----- -------- AUTHOR: すz TITLE: USBNIXの構想 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: USBNIX DATE: 05/17/2007 16:55:57 ----- BODY: はじめに 作ってみようと思っている装置の記事で UNIX もどき USB Key 実はUSB910では、オリジナルのAVR-CDCに手を入れて getc/putc でプログラミングできるようにしていて、USB シリアル装置を手軽に作れるようにしている。で、なにか便利(そう)なものを作ってみようと考えていて思いついたもの。 この装置をUSBにつないでターミナルソフトを立ち上げ、ENTER を入力すると login: なんて出る。本当に login できて、いくつかのコマンドが使える。使えるコマンドは、ls と cat ファイル名と cat > ファイル名。あと rm ファイル名 は必要か。なんに使えるかというと、(他の)パスワードとか忘れそうだけれども秘密にしたいものの覚書。ファイルデータは、1件 1KB 以内で、32件までにして、I2C ROM に入れる。I2C ROM だけ抜かれたりしたときの対策に暗号化が必要で、暗号化のキーは本体のEEPROMに覚えさせてロックビットで保護する。最大の問題はコードのサイズ。 4KB に入れるのは無理そうだが、8KB には収めたい。装置単体でのパスワードの変更は無理だろう。で、どうするかというと、データをいったん全部吸い出して、あらためて パスワードと暗号化キーデータを生成して、EEPROM に書き込みデータを書き戻す...そういうホストプログラムがあれば問題ない。 と書いた。これを実際に作ってみることにする。USB Key ではなにのことかわからないので、USB + UNIX の意味で USBNIX と名前をつけた。超々簡易版ではあるが、UNIX のコマンドを使って操作する。説明なしにデモすれば、UNIX or Linux が動いているように見えて驚かれるかもしれない。 暗号化のコードをどうするか DES や AES といったものを移植するという方法はコードが大きくなりすぎる(はずな)ので、最初からあきらめている。実は、UNIX V7 のコード usr/src/cmd/crypt.c を使おうと思っていた。で、(ライセンスにしたがって)このプログラムは、UNIX のコードを使用しています...なんてシャレで書こうと思っていたのだが、実際にコードを見てみると、char の配列が256x3 もあることがわかった。これでは tinyシリーズでは無理だし、mega88 とかでも厳しいので、それもあきらめて、自作することにした。eeprom にkeyを入れて ロックビットを設定してやれば、弱い(てきとうな)アルゴリズムでもまぁ大丈夫に違いない。 ところで、UNIX V7 の crypt.c のコメントが興味深かったので紹介。
A one-rotor machine designed along the lines of Enigma but considrably trivialized.
だそうだ。要するに有名なエニグマ(第二次世界大戦のときのドイツの暗号装置)の簡易版ということらしい。 構造とかAPIとか md5 などと同じように、コンテキストを持っていて入力ストリームによって状態を変化させていく。で、コンテキストと入力ストリームの XOR を取ってエンコードする。デコードもほとんど同じで、状態を再現して、XOR で元に戻す。md5 とかは、コンテキストを変化させる部分が非常に複雑になっているけども、ここを思いっきり簡単化すれば、8KBのAVRで使えるものになりそう。 具体的には、
typedef union mc_context {
    struct {
	uint32_t A;
	uint32_t B;
	uint32_t C;
	uint32_t D;
     };
     uint8_t buf[16];
} mc_context_t;

mc_context_t mc_context;

static void mc_rotate(uint32_t *x) {
	/* pseudo random generator */
	*x <<= 1;
	if ( (!(*x & (1L<<31)) && (*x & (1L<<28)) )
	     || ((*x & (1L<<31)) && !(*x & (1L<<28))) ) {
		*x |= 1;
	}
	/* netbsd rand() algorism */
	*x = *x * 1103515245 + 12345;
}

static void mc_xor(uint8_t *dst, uint8_t *src) {
	uint8_t i;
	for (i=0; i< 16; i++) {
		*dst = *dst ^ *src;
		dst++;
		src++;
	}
}

oid mc_encrypt(uint8_t *block) {
	mc_xor(block,mc_context.buf);
	mc_rotate(&mc_context.A);
	mc_rotate(&mc_context.B);
	mc_rotate(&mc_context.C);
	mc_rotate(&mc_context.D);
	mc_xor(mc_context.buf, block);
}

void mc_decrypt(uint8_t *block) {
	uint8_t tmp[16];
	memcpy(tmp, block, 16);
	mc_xor(block,mc_context.buf);
	mc_rotate(&mc_context.A);
	mc_rotate(&mc_context.B);
	mc_rotate(&mc_context.C);
	mc_rotate(&mc_context.D);
	mc_xor(mc_context.buf, tmp);
}
こんな風にしようとしている。mc という prefix は mini crypt の略。mc_rotateの上の部分は、ホワイトノイズ生成とかで使われている 擬似乱数(pseudo random)ジェネレータ 。下の部分は、netbsd の rand() のアルゴリズム。最初は下の部分だけでよいと思ったが逆関数がつくれてしまいそうなので、上の部分もあわせて使うことにした。これでかき混ぜておいて 入力データとの XOR で新たな 状態を作る。コンテキストの初期状態は、
void mc_setkey(const uint8_t *key);
で設定することにする。eeprom に 16 バイト x 8 の乱数を格納しておいて、 ファイル毎に Key を変える。 これぐらいしておけば、素人みえには他の暗号化アルゴリズムと遜色なさそうなデータになるのではないかと思う。ただし、アルゴリズムを知っている上でまじめに解析されればわりと簡単に解けてしまうかもしれない。 パスワード UNIX もどきなので、user と password を入力させようと思う。ただし、user という概念はないので、user と password をくっつけたデータをパスワードとみなす。格納するデータは、平文ではなく、暗号化したデータでもない。一方向関数によって生成したダイジェストである。これを mc_setkey と mc_encrypt を使って生成することにする。
	mc_setkey(line_buf);
	for (pos=0; pos<128; pos+=16) {
		eeprom_read_block(line_buf, (void *)pos, 16);
		mc_encrypt(line_buf);
	}
ようするに、パスワードを初期状態にし、乱数テーブルでかきまわしたデータ。これを eeprom に格納しておく。同じ処理をおこなって同じデータになれば、login を許すことにする。ちなみに、パスワードデータを PCで生成する予定だったが、それはやめて、実機で行うようにするつもり。 おわりに このシステムで、暗号化をどうするかが最大のポイントだった。全体で8KBに入る見込みがなければ、作るのをあきらめようとさえ思っていた。 いまいち不安ではあるものの、次のように 474 バイトとコンパクトな暗号化モジュールができた。
   text	   data	    bss	    dec	    hex	filename
    474	      0	      0	    474	    1da	minicrypt.o
これさえ目処が立てば、あとはプログラムを作るのみである。USB910A と 実験ボードその1 を使って評価できるので、ボードも作る必要はない。 といっても、最初から実機でテストするつもりはない。Linux でプロトタイプを動かして満足できるものに仕上げてから、実機に移植する予定。次回は、その製作をレポートしたいと思う。 追記 つれづれ日記からコメントをいただいた。更新を久しくしていなかったのに、すかさずコメントをもらえて嬉しい限り。 コメントではじめて知ったのだが、Crypto-avr-libというのがあって、各種暗号化アルゴリズムを AVR に移植しているそうだ。はっきりはわからないが、 メモリが厳しいものの MD5 とか SHA とか載らないわけでもないかも知れない。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: USBNIX Linux 版 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: USBNIX DATE: 05/17/2007 23:01:36 ----- BODY: なんかそれらしいもの → usbnix-0.1.tar.gzができあがった。 make usbnix とすると linux 版ができてテストすることができる。AVR のビルド環境があれば、make で AVR 版もビルドされる。ただし、プログラムサイズをみるためだけのもので動作しない。 実行例
$ ./usbnix
login: suz
New password: 
Retype new password:    #最初のloginは、パスワードを設定する
# ls
# cat > test1               # これでしかファイルを作れない。
aaa bbb ccc                 # ^D か 行頭の .で EOF 
# ls      
test1
# cat test1
aaa bbb ccc
# exit
login: suz
Password:                    # 2回目からは正しいパスワードが必要
# ls
test1
# rm test1
# ls
# rm aaa
No such file or directory
# passwd                     # 初期化するだけのいんちき passwd 
login: suz
New password: 
Retype new password: 
login: suz                   # Retype で間違えれば、やりなおし。
New password: 
Retype new password: 
# 
こんなところでどうだろう。ちなみに AVR 版のサイズは、まだ 5516 バイト。エラー処理とかのブラッシュアップで多少大きくなるだろうが、まだ拡張できそう。 ちなみに、プログラムを動かすとカレントディレクトリに、eeprom のイメージファイル key.img と i2crom のイメージファイル i2crom.img ができる。このファイルを消さなければ、作ったファイルは保存される。(eeprom イメージは、他人に見えないようにパーミッションを設定しないと危険なので注意。実用として使う人はいないと思うが一応。 ) i2crom.img の中身
FILE: i2crom.img (32768) - ASCII
PAGE: 0 (0)
    x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf     0123456789abcdef

    00: 74 65 73 74 31 00 00 00 00 00 00 00 00 00 00 00      test1...........
    01: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00      ................
    02: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00      ................
    03: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00      ................
    04: d3 26 a9 ed dc 53 ec 9c c9 77 fb 30 eb 00 00 00      .&...S...w.0....
    05: d0 f3 ca 49 1f 42 a7 52 9b c8 88 6e 48 8c cb fb      ...I.B.R...nH...
    06: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00      ................
    07: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00      ................
    08: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00      ................
32KB を 1KB 毎にわけて、その1KB の頭 64B までに ファイル名が平文で入る。64B のオフセットから、ファイルの中身が 暗号化されてはいる。 16B 単位でデータをセットするので、後ろのほうは初期値のまま。 TODO 1) rm では、ファイル名しか消去していない。ファイルイメージも消去する必要がある。 2) 消せないファイルができてしまう可能性がある。ls で inode 番号(?ファイルの場所を示すインデックス)を表示して、rm で inode番号を指定できるようにするとか工夫が必要。 3) コマンドライン入力の cooked モードが貧弱で漢字などを入力した場合 BS で文字化けする(はず)。なんか対策を考えたい。 4) Linux 版だけではなく、MinGW 版もつくってみたい。いまは、/dev/urandom とか使っているので、動かない。keyにつかうランダムデータをどう生成するかが問題だが、それは AVR 版の初期データ生成にも共通する問題なので、解決する必要がある。一般の乱数で生成するのは、データに関連性ができてしまうので望ましくない。 おわりに 着想の段階では、8KB ではとても入らないだろうと思っていたが、作ってみたら、わずか 5.5KB に機能が入ってしまった。このサイズで USB を制御し、簡単ながらファイルという概念をもっていて、login できて、コマンド処理もし、暗号化までしているわけだ。 USBNIX というのも面白いものだと思うが、工夫しだいでもっといろんなものが作れそうな気がしてきた。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: 続 USBNIX Linux 版 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: USBNIX DATE: 05/18/2007 20:29:39 ----- BODY: USBNIX をバージョンアップした。 → usbnix-0.2.tar.gz いくつか大きな改造をしたのでそれについて書こうと思う。 暗号化のキー(ランダムデータ)をどうやって生成するか 最初の版は、/dev/urandom から取ってくるという安直な方法を取った。これだと MinGW環境では使えないし、実機のデータを生成する環境も限られてしまう。 困ってしまったのだが、結局はストレートに実機で作るということにした。 そもそも、キーが変わるとファイルが読めなくなる..というより化け化けのデータが読めてしまう。i2crom の初期化もキーの変更に同期しなければならないのだが、キーを外部で用意することにすると、i2crom の初期データもロードしなければならなくなる。それはとっても面倒そうなので、実機でキーを作り、そのタイミングで i2crom も初期化することにした。 そのデータをどうやって作るかについて、いろいろ検討したのだが結局、キーを 64 回入力してもらって、受け取るタイミングで 16bit TIMER の値をとってくるということにした。12MHz/65536 = 183Hz なので、十分ランダムといえる値を生成することができそうだ。 ちなみに、i386 の場合は次のようにした。
uint16_t get_seed() {
	uint16_t seed;
	__asm__ __volatile__("rdtsc" : "=A" (seed));
	return seed;
}
TSC という 64bit のタイマーがあって、CPU クロックでカウントアップされている。(キーが入力されたタイミングで)そのTSC の下位 16bit だけ取ってくる。Linux(いまどき Pentium III!) でしか確認していないが、Windows でもたぶん大丈夫だろう。 inode番号指定のオペレーション TODO にも書いたが、文字化けしたファイル名のファイルができてしまったとき、どうやってファイルを読んだり、消したりするかという問題がある。これについては、ls -i というオプション(UNIX には昔からあるもの)をサポートして ファイルの ID(UNIX ではinode番号という) とファイル名を表示するようにして、rm と cat に -数字 というオプション(これは USBNIXオリジナル)を作り、inode番号指定で操作できるようにした。幸い avr-libc には、atoi() があったのでそれを利用することができた。ちなみに、ls -i での番号表示は、サイズとか見栄えの理由で、itoa や printf でなく自作のコードにしている。 エラーメッセージ エラー処理をみなおして、できるだけちゃんとしたメッセージが出るようにした。ないファイルを指定すれば、(ディレクトリなんてないのだが)"No such file or directory" 32個を超えるファイルを作ろうとすれば、"No space left on device" ...なんて伝統的なメッセージが出る。 内部処理も Linux 流に -エラー番号 を使うようにした。 パスワード処理 前に、userとパスワードをつなげたものをパスワードとして扱うと書いたが、合計で 15バイトまでしか使えなったのを それぞれ 15 バイトに拡張した。こんな処理。
      mc_setkey(user);
      mc_encrypt(password);
      for (i=0; i<128; i+=16) {
             eeprom_read_block(line_buf, (const void *)i, 16);
             mc_encrypt(line_buf);
      }
メモリが使えないし、API がシンプルなので、こんな些細な改造でも、実は苦労した。...ところで今まで ターゲットの ATtiny861 の RAM が 256 バイトだと思い込んでいた。念のため確認したら 512バイトだった。stack が足りないんじゃないかと心配していたのだが、これで心配はなくなった。なんか得した気分。 TODOその2 5)login 時のメッセージ表示 UNIX では、(V7 のときから) login 時に /etc/motd の内容を表示するようになっている。その機能をなんとかしたい。ディレクトリがないので、motd というファイルがあったらそれを表示することにしよう。それに Welcome to ナントカカントカ と書いておけば、雰囲気が出るだろう。 ちなみに motd は、"message of the day" の略だそうだ。...実はいままで知らなかった。 おわりに だいぶ満足のいくものになってきた。そろそろ実機で動かすことを考えたい。ソースコードはほとんど共通なのであまり苦労しないはず。ちなみにいまのプログラムサイズは、
   text	   data	    bss	    dec	    hex	filename
   6562      12     200    6774    1a76 usbnix.elf
必要なコードはすべていれてのサイズ。デバックすれば多少大きくなるだろうが、8KB 以内は楽勝の見込み。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: 実機テスト STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: USBNIX DATE: 05/22/2007 00:34:35 ----- BODY: 実機テストが完了! → usbnix-0.3.tar.gz まぁ当然ながら、いくつか問題があった。それらについて書こうと思う。 1)USBに接続しただけで、リセットを繰り返す これでは、全然デバッグができない。とりあえず エコーバックだけするコードを動かしてみた。これは問題なく動いた。いろいろ試行錯誤したところ、最初に "login:" を表示するとリセットしてしまうことがわかった。メインループに入る前に usbcdc_getc() で1文字入力を入れたら、とりあえず "login:" が出るようになった。 AVR-CDC そのものか AVR-CDC の最新版をマージしたときのバグらしい。いまは、USBNIX を動かしたいので、(バグを追求しないで)最初に入力するという回避策のままにすることにした。
追記: ひといきついたので、改めて動作を調べてみた。 最初にいきなり Type any.. という 38バイトのメッセージを出力していたのだが、その動作にしたら再現した。(Linux 2.4.31 + UCHI ) これを "login: "の 6バイトにした場合、 ほとんど正常に動作する。正常といっても、"login: "のメッセージを全部または一部ロストする場合がある。 それはともかく、デバイス側がいきなりデータを垂れ流すという設計は普通しない。デバイスはホストから要求があって初めてなんらかの動作を開始するようにするのが普通。 というわけで、↑は回避策ではなく正しい設計にしただけなのだ。
2)ENTER で改行ができない なさけないミス。Linux 版は、ICRNL が効いていたので、ENTER が LF だったが、ターミナルソフトでは、CR 。 3)I2C ROM の READ/WRITE が動かない 0.2では、適当に書いただけのものだったので、これはある意味予定どおり。 デバッグがなかなか面倒で、結局 I2C ROM にデータを書くコマンド と ダンプするコマンドを作ってテストすることになった。あと、エラー処理を全然していなかったので、どこでエラーになっているかわからなかった。プリミティブだけでも エラーコードが判るようにしてデバッグすることになった。 本来の処理ではまだエラー処理ができていない。これはボチボチやっていくことにして、先に進むことにした。 4)EEPROM が勝手に書き換わる これは、低電圧検出リセットを有効にしていないため。...というのは知っていた。しかし、2回に1回ぐらいの高い頻度で EEPROM が書き換わるとは思っていなかった。USBNIX は、EEPROM が少しでも違えば login できなくなるしくみなので、書き換わったのがよくわかる。 あといくつか改良をしたが、問題点としてはこんなところ。あともうすこしで完成か。 ちなみにいまのプログラムサイズは、
   text	   data	    bss	    dec	    hex	filename
   7228      32     234    7494    1d46 usbnix.elf(+デバッグコマンド)
   6790      32     234    7056    1b90 usbnix.elf
だいぶ厳しくなってきた。 TODO 1) 最初に文字出力するケースのバグの修正 2)MinGW 版 (キー入力を termios から WIN32API に変更して、バイナリファイルの指定をいれるぐらいで OK のはず) 3)I2CROM の I/O エラー対応 EIO をエラーコードに追加して、ちゃんと処理する。 4)ハイパーターミナルでの漢字の扱い 上で書かなかったけども、ハイパーターミナルで漢字が扱えていない。Linux では、ファイル名やデータに漢字が使えている。(といっても 8bit スルーなだけで環境が変わると文字化けしてしまう)
追記: ちゃんと漢字は扱えた -- 勘違い。ところで、ハイパーターミナルの漢字コードは、SJIS デフォルトだし、Linux でも問題なく SJIS は扱えるから、SJIS 専用ということにして、文字化け対策をしたほうがよいかも知れない。 追記2:ちなみに、TeraTerm Proや後継ソフトである UTF-8 TeraTerm Pro with TTSSH2 も期待どおりに動作した。(SJISのみ評価)
5)format コマンド 低電圧検出リセットを有効にしても EEPROM が本当に書き換わらないか自信がない。EEPROM が書き換わるとデータがすべて失われてしまうので、EEPROM はバックアップしておいたほうが良さそうだ。... そうなると I2CROM との整合性について保証できなくなる。せめて I2CROM を初期化するコマンドはつけておきたい。ただし、オペミスで format してしまう可能性をなくすために、yes を入力させるとかの考慮は必要か。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: MinGW+MSYS とコンソール STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: USBNIX DATE: 05/22/2007 23:01:12 ----- BODY: MinGW+MSYS で USBNIX を動かそうとしたのだが、コンソール入力がなかなかうまくいかない。その顛末記。 USBNIX は、まず Linux で開発して、基本的な動作を確認し、その後で AVRで動かしている。AVR 版は、動くことが判っているパーツの割合が大きいので、(比較的)すみやかに動かすことができた。MinGW でも同じことができれば、AVR-CDCベースでなにかを作ろうとする人の参考になるだろうし、USBNIX を Windowsで動かしてみて、なにか作ってみようと思ってくれる人も出てくるかも知れない。そういう意味で、MinGW版を作りたいと思っている。 さて、MinGW というのは、WIN32API (のみ)を使うので dll のインストールが必要なく便利な開発環境だ。当然 USBNIX のキーボード入力をコンソールに対応すれば(細かいところは別にして)それだけで移植が終わると思っていた。 方針としては、WIN32API のコンソールAPIをすなおに使う。具体的には、エラー処理とか省いて簡略化すると次のようなかんじ。
#include <windows.h>
#include $lt;wincon.h>

初期化:
HANDLE conin;
DWORD conin_mode = 0;

conin = GetStdHandle(STD_INPUT_HANDLE);
GetConsoleMode(conin, &conin_mode);
conin_mode &= ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
SetConsoleMode(conin, conin_mode);

char usbcdc_getc(void) {
    char buf[3];
    DWORD nrec = 0;
    while (!ReadConsole(conin, buf, 1 , &nrec, NULL) 
                                        || nrec == 0)
        ;
    return buf[0];
}
これが全然うごかない。でも、ためしに "コマンドプロンプト" の上で動かすと動いてしまったのだ。どうも MSYS のコンソール(rxvt) は、WIN32API で扱えるコンソールではないらしい。 WIN32API でコンソールとして扱うにはどうしたらよいのか? と考えてしまったので、はまりにはまった。結局、rxvt のソースを見たら MinGW のAPIとして提供していない termios を使っていたことがわかった。 これだと、cygwin の環境がなければ、移植できない。逆に cygwin さえあれば簡単で、termios のインターフェイスで OK ということになるのかも知れないい。でも、MSYSという環境は結構気に入っているので、コンソールアプリもそこでビルドし、かつ動かしたいところ。 WIN32APIはよく知らないが、CreateConsoleScreenBufferで コンソールを作って、イベントを送り込むようなことをすれば、 rxvt のコンソールを WIN32API で扱えるようにできるのかもしれない。まぁ、そこまでする気力はないので、termios.h と MinGW で使える tcsetattr/tcgetattr が用意できれば、対応できるようにだけはしておくけれども、通常は MSYS で実行したら GetConsoleMode がエラーになってアボートする程度にしておいた。 というわけで、中途半端ながら、最新版。→usbnix-0.4.tar.gz 参考になったページ(リンク) MSYS/MINGW 環境設定、その1 MSYS/MINGW 環境設定、その2 Msysで日本語 追記: MSYSのソースコード一式(msys-1.0.10-src.tar.bz2)をダウンロードしてみた。 その中の   msys/1.0/10/rt/src/winsup/cygwin/include/sys/termios.h が、どうも 正しいヘッダファイルらしい。 あと、   msys/1.0/10/rt/src/winsup/cygwin/termios.cc が、正しくコンパイルできれば、MSYSコンソール(rxvt)で動く USBNIX が作れそうだ。ただし、ビルドの方法はまだよくわかっていない。 ただ、termios.cc (のさらに一部)のために、18MB近いソースを扱うのはどうかという気がする。できれば、必要なものだけをシンプルにまとめて、USBNIX に添付したい。 追記2: msys の bin にある msys-1.0.dll に termios で使用している関数 tcgetattr/tcsetattr が含まれていることがわかった。でこれを Google Code Search調べる と libmsys-1.0.dll.a を使ってリンクすることがわかった。これは、結局 Msysで日本語に書かれていた msysDVLPR-1.0.0-alpha-1.tar.gzに含まれていた。
lib/gcc-lib/i686-pc-msys/2.95.3-1/include/sys/termios.h 
lib/crt0.o
lib/libmsys-1.0.dll.a 
を取り出し、termios.h 48行目の CTRL のバグを修正する。 次に usbnix-0.4 の usbnix.c の tcsetattr/tcgetattr の defineをコメントにしておいて、
gcc -DHAVE_TERMIOS -I. -nostdlib crt0.o usbnix.c minicrypt.c \
    libmsys-1.0.dll.a -L/d/MinGW/lib -lmingw32 -luser32      \
     -lkernel32 -lgcc -lmoldname -lmingwex -lmsvcrt 
としてコンパイルすると ... MSYSコンソール(rxvt)の上で動くようになった。 そして、MSYS/MINGW 環境設定、その1 で知った日本語対応 ...
/d/msys/1.0/msys.bat で指定しているフォントを 
   Courier-12 → Terminal-14に変更する
を試してみたら、USBNIX で漢字が使えるようになった!
注意: msys-1.0.dllを使えるようにした .. というのは、逆にいうと msys-1.0.dll がなければ動作しないということです。cygwin で動作したというのと意味的にはあまり変わりません。ものとしても msys-1.0.dll は、cygwin1.dll から枝分かれしたものです。MSYSのコンソールで動くようになったのと引き換えに、動作には MSYS を必要としますので注意してください。
追記2おわりに 追記2は内容からいって独立した記事にすべきだったかもしれない。でも、あまり取り上げると AVR研究から MSYS+MinGW研究にしたくなるので、追記にしておいた。それはともかく、termios が動き漢字も使えるのなら、ちょっとしたものをビルドしたり作ったりするのは、楽しそうだ。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: I2CSND:はじめに STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: I2CSND DATE: 05/23/2007 21:38:53 ----- BODY: 作ってみようと思っている装置で書いた (4)I2C で制御する音を出すなにか 電子工作のテーマとして音を出すものを作るのは楽しい。I2Cドライバも作ったので、ATtiny45 (かひょっとすると 85) を複数個つかって音を出すなにかを作ってみたい。 プログラム次第で簡単なものから高度なものまで作れると思うが、バーチャルアナログシンセなんてものにもトライしたい。外部クロック入力にして正確なA音程を目指すのも良いが、RC発振器をキャリブレーションして使うというのも味があってよいかも知れない。電源ノイズが載るのだけは避けたいので、電源だけは専用のレギューレータをつけてやりたい。 についてボチボチ取り組みたいと思う。 バーチャルアナログシンセについて 一言で書くと、DSP でアナログシンセをシミューレートするタイプのシンセサイザ。WikiPedia には、こういう説明がある。 AVR でバーチャルアナログシンセを作った草分け的な作品は、SYN8535で、8MHz の AT90S8535 の上で作られていた。今は、ATmega16/ATmega32 に移植されて、AVRSYNに進化している。 AVRマイコンによるMIDIシンセサイザーの製作なんていうページもある。バーチャルアナログシンセについて、わかりやすく説明されているので紹介しておく。 どんなものを作りたいのか USB や I2C が自由に扱えるようになったので、 AVRマイコンによるMIDIシンセサイザーの製作のようなPWMでサウンドを生成するものを、I2C スレーブとして実装して、複数のスレーブをマスターコントローラに接続し、USB で PCと接続して制御するようなものを作りたいと思う。 もちろん本格的なバーチャルアナログシンセを作るわけではない。音作りそのものを楽しむなら、PC で作ったほうがよさそうだ。ググるとZynAddSubFXなんていうオープンソースのものも見つかるし、他にもあるだろう。 本格的なものを作るなら、AVR では力不足で、AT90SAM7Sなどで作るのが良さそうだ。
ちなみに、AT90SAM7SはDMAを持っているので、シリアルDACに接続してもCPUの負荷にならないし、内蔵メモリも多い。AT90ARM7S開発ボードとしては、ベストテクロノジーの BTC090や Olimex の SAM7-H256(ソリトンウェーブが扱っている。)あたりがよさげ。
でも、AVRという限られたリソースでどれぐらいのものが作れるのか挑戦したい。そのために、まずはベースとなるものを作る。バーチャルアナログシンセそのものは、すぐには完成しないだろう。..というかいくらでも工夫の余地がありそうなので、完成しないかも知れない。 追記: オープンソースのシンセサイザで、設計するとき参考になりそうなものをピックアップしてみた。 the Linux MIDI-HOWTOを見て、spiralmodular。 Source Forge で検索してみつけた TetraHead Sound System。Java で書かれている。(英語ですらないが)pdf のドキュメントがあって、わかりやすくまとめられていて参考になりそうだ。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: I2CSND:構想 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: I2CSND DATE: 05/25/2007 18:20:52 ----- BODY: マスターコントローラ 当面開発用 マスターコントローラには、USB910A を使う。これを使って 肝心のデバイス側をデバッグする。スタンドアローンにするとか、MIDI インターフェイスを持たせるとかは、スレーブができてしまったから考えればよいだろう。 USB910A をつかえば、スレーブ側の発振周波数のキャリブレーションもできるし、スレーブ側のCPU使用率も測定可能だ。 スレーブ側のCPU使用率を測定するのは簡単で、ポートを1つ使って、実行しているとき H 、そうでないときに L にするようにしておいて、RC LPFを通した後の電圧を測定すればよい。 スレーブ側が間に合わなければ、想定した音にならない。それを判断するのに 、スレーブ側のCPU使用率を測定できることは重要ではないかと思う。 スレーブ側AVRの選択 サウンドを生成する処理では、非常に多くのかけ算を使う。なので、8bit 乗算命令があるMEGAシリーズを選ぶのが妥当なのだが ... いくつか大きな問題がある。
1) TWI 版 I2C デバイスドライバのコードを持っていない。 MEGA シリーズは、USI は持っていなくて、TWI インターフェイスを使う。なので、TWI 版のドライバを作るところから始めないといけない。そこから始めるのはちょっとつらい。ある程度できあがって、勢いがついたところで ドライバを作りMEGA に移行したいところ。 2) 高周波 PWM を持っていない。 最初から DAC を付けることは考えていなくて PWM を使おうと思っている。PWM の周波数は高ければ高いほど良いのだが、64MHz の 高周波 PWM を持っているのは、8 pin の ATtiny45系 と 20 pin の ATtiny461系 。これでいったいどんな音がでるのか興味があるのだ。
... というわけで、はじめは、ATtiny45系 と 20 pin の ATtiny461系 を ターゲットにしようと思う。 手持ちは、ATtiny45 と ATtiny861。ATtiny45 で動けば、複数デバイスにしたとき楽なので、ATtiny45 からスタートしようかと思う。そして、プログラムがあふれたり、10 bit 高周波 PWM をためしたくなれば、ATtiny861 に移行して、複数のデバイスでのテストは、ATtiny45/85 にもどるつもり。 8bit 乗算命令がないというデメリットは、できるだけ周波数を上げることで 少しでもカバーしたい。ひょっとしたら 32MHz で動くかもしれないので、それもためしてみたい。 ところで、外部から正確なクロックを入力できるようにするかどうかに ついては保留。当面は 内部RC発振器を使うことにしたい。 サウンド出力 1つのデバイスは、単音のみしか考えないことにする。もともと複数付けるつもりなのだし、ポリフォニックにする余裕があるなら、スペックを上げた方が良いだろう。インターフェイス的にも割り切った方がすっきりする。 単音だけだが、アナログミキサなんて考えたくないので、ステレオ出力にはしようと思う。 アナログ部 PWM は、0V - 電源の間の矩形波を生成するので、電源の変動が出力に載って来てしまう。それでは面白くないので、PWM と アナログ変換(RC LPF) の間にバッファを入れ、バッファの電源は専用のもの(3V前後)を用意する。それを オペアンプで増幅して ヘッドホン出力にする予定。オペアンプには負帰還がかかるので電源に気を使う必要はなく、5V を使う。 バッファには、普通の 74HC シリーズではなく、入力の電源側にクランプダイオードが入っていない 74VHC シリーズが良いのではないかと思う。VHC04 とかなんでも良いのだが、74VHC244F ならば、秋月で5個100円だし。これを使えばどうか。専用電源には、秋月で扱っているSI91841DT-285が良さそう。 といっても、最初のうちは動作しているかモニタできれば良く、さらにミキシングなど考えなくても良いので、AVRのPWM 出力を 直接 LC フィルタ にかけるだけで済ませるかもしれない。 マスタースレーブ間の通信プロトコル 結局のところマスター側では MIDI をサポートするだろうから、MIDIそのものでなくとも MIDI から変換しやすいようなものにすべきだろう。 といっても、音色のパラメータテーブルのようなものは内部に持たせず、マスターからパラメータそのものを送り込む。プログラムメモリを食うし、どういう値にすればよいか当初は皆目わからないから。 Linux版/MinGW+MSYS版 例によって デバッグのために Linux版も作るつもり、できたら MinGW+MSYS版も作りたい。これができると PC で作る音とどれぐらい違うのか比較できるだろうし、新しい機能を入れるときに PC でまず試すことができる。( 実機だと チューニングしないと 入れたい処理がこなせないかも知れない ) サウンド生成処理 TetraHeadから TetraHead-v.1.0.tar.gz をダウンロードすると、一連のドキュメントが pdf で入っている。肝となるフィルターのアルゴリズムについても www.musicdsp.com の膨大なアーカイブからピックアップしたものが、filtres.pdf にまとめられている。LFOやVCOなどのコンポーネントの仕様も conseption.pdf にきっちり書いてある。これらのドキュメントを参考にして設計したいと思う。...といってもソースコードを流用するわけでも、アルゴリズムをそのまま使うわけでもない。ソースコードが Java だからではない。AVRでは力不足で使いたくても使えないのだ。 おわりに とまぁ、好きなことを書いてみたらずいぶんな大風呂敷になってしまいました。こういうものを短期間で全部作るということではありません。こういう構想のもとに、(しょぼいかもしれない)サブセットからスタートして、興味が赴くままに拡張していくつもりです。あと、次回はなにか形になったら書くつもりなので、時間がかかりそう。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: VCOの設計とテスト STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: I2CSND DATE: 06/06/2007 23:07:49 ----- BODY: 正弦波と三角波、鋸波を生成するVCOが一応できた。 コードは次のようなもの。
prog_char sintab[64] = {
    0,    3,    6,    9,   12,   15,   18,   21,
   24,   27,   30,   33,   36,   39,   42,   45,
   48,   51,   54,   57,   59,   62,   65,   67,
   70,   73,   75,   78,   80,   82,   85,   87,
   89,   91,   94,   96,   98,  100,  102,  103,
  105,  107,  108,  110,  112,  113,  114,  116,
  117,  118,  119,  120,  121,  122,  123,  123,
  124,  125,  125,  126,  126,  126,  126,  126,
};

struct VCO {
	uint16_t wave_pos;
	int16_t wave_inc;
	int8_t lfo_inc;
	uint8_t wave_type;
} vco;

static void generate_snd() {
	uint8_t pos;
	int8_t rev = 0;
	int8_t v;
	vco.wave_pos += vco.wave_inc + vco.lfo_inc;
	pos = vco.wave_pos >> 8;
	if (pos >= 128) {
		rev = 1;
		pos = 255 - pos;
	}
	if (vco.wave_type == WAVE_SAW) {
		v = 127 - pos;
	} else {
		if (pos >= 64) {
			pos = 127 - pos;
		}
		if (vco.wave_type == WAVE_TRI) {
			v = pos*2;
		} else 
			v = __LPM(sintab+pos);
	}
	if (rev) v = -v;
	sndout(v);
}
サンプリングレートで、この関数を call すると、そのときの出力を計算して sndout() で出力する。アルゴリズムは、DDS(ダイレクトデジタルシンサイザ)。 メインループはこんなかんじ↓。can_sndout() で バッファーが空いていれば、generate_snd() で次のデータを作ってバッファーに詰め込む。
for (;;) {
	if (can_sndout()) {
		generate_snd();
		continue;
	}
	if (usbcdc_can_getc(1)) {
		c = usbcdc_getc();
		change_note(c);
	}
}
周波数 HZ の波形を出力したい場合は、
  vco.wave_inc = HZ * 256 * 256 / SAMPLE_RATE;
となるようにすれば良い。 ちなみに、vco.lfo_inc は、LFO で周波数を揺らすためのものだが LFOはまだできていない。 もちろん、音階に対応した vco.wave_inc の値はあらかじめ作っておく。
prog_uint16_t note_tab[12] = {
	 8572944/ SAMPLE_RATE,
	 9082717/ SAMPLE_RATE,
	 9622802/ SAMPLE_RATE,
	10195003/ SAMPLE_RATE,
	10801229/ SAMPLE_RATE,
	11443502/ SAMPLE_RATE,
	12123967/ SAMPLE_RATE,
	12844895/ SAMPLE_RATE,
	13608690/ SAMPLE_RATE,
	14417904/ SAMPLE_RATE, // A3 220 Hz
	15275236/ SAMPLE_RATE,
	16183547/ SAMPLE_RATE,
};
ちなみにこの値は、220 Hz * 256 * 256 をもとに、2の12乗根 1.059463 を乗除して作ったもの。uint16_t に収まる必要があるので、表現できる最大の周波数は、SAMPLE_RATE ということになる。 ずいぶんはしょってしまったが、本題はこれから。はたして、これで進めてしまってよいのだろうか? グラフ化した波形(先頭のグラフ)はそれなりにまともに見えるが、いったいどんな音になるのだろう -- 確かめてから先に進みたい。 Linuxのサウンド出力 というわけで、Linux でどのようにサウンドを出力するのか調べて作ってみたのが次のコード(説明のためにエラー処理はすべて除いた)。
int sndout_fd;
int audio_buf_size;

static void sndout_init() {
	int arg;
	struct audio_buf_info info;

	sndout_fd = open("/dev/dsp",O_RDWR);
	arg = 16;
	ioctl(sndout_fd, SOUND_PCM_WRITE_BITS, &arg);
	arg = 2;
	ioctl(sndout_fd, SOUND_PCM_WRITE_CHANNELS, &arg);
	arg = SAMPLE_RATE;
	ioctl(sndout_fd, SOUND_PCM_WRITE_RATE, &arg);
	arg = 0x0008000c; // fragstotal 8 fragsize 4096 
	ioctl(sndout_fd, SOUND_PCM_SETFRAGMENT, &arg);
	ioctl(sndout_fd, SOUND_PCM_GETOSPACE, &info);
	audio_buf_size = info.bytes;
}

static int can_sndout() {
	struct audio_buf_info info;
	r = ioctl(sndout_fd, SOUND_PCM_GETOSPACE, &info);
	if (audio_buf_size - info.bytes >= info.fragsize * 2) {
		return 0;
	}
	return 1;
}

static void sndout(int8_t d) {
	int16_t buf[2];
	buf[0] = (int16_t)d <<8;
	buf[1] = (int16_t)d <<8;
	write(sndout_fd, buf, 4);
}
ポイントは、fragsizeを小さくした上で、バッファーが一杯残っている段階で FULL と認識して詰め込みすぎないようにすること。そうしないと、パラメータを変更したときの追従性が悪くなってしまう。 参考にしたのは、 Linux Sound programming with OSS API(リアルタイム性を考慮する) Linux Sound programming with OSS API(/dev/dsp の機能を調べる)
追記: 私の環境では、どうも 2ch/16 BitParSample (S16LE) 以外設定できないようで、4倍の周波数(32K Hz)になってしまっていました。なので、S16LE 用のコードに変更しました。
Windowsのサウンド出力
#include <mmsystem.h>

#define WAVEBUF_SIZE	1024
#define NR_WAVEHDR	8

HWAVEOUT HWaveOut = NULL;
uint8_t *WaveBuf;
WAVEHDR WaveHdr[NR_WAVEHDR];
int cur_wavehdr = 0;
int cur_wavebuf_len = 0;
WAVEFORMATEX waveFmt;

static void sndout_init() {
	int r,i;
	waveFmt.wFormatTag = (WORD)0x0001; // PCM
	waveFmt.nChannels = 1;
	waveFmt.nSamplesPerSec = SAMPLE_RATE;
	waveFmt.nAvgBytesPerSec = SAMPLE_RATE*1;
	waveFmt.nBlockAlign = 1;
	waveFmt.wBitsPerSample = 8;
	waveFmt.cbSize = (WORD)0;

	WaveBuf = GlobalAlloc(GPTR, NR_WAVEHDR * WAVEBUF_SIZE);
	memset(WaveHdr, 0, sizeof(WAVEHDR) * NR_WAVEHDR);
	for (i=0; i<NR_WAVEHDR; i++) {
		WaveHdr[i].lpData = WaveBuf+ i * WAVEBUF_SIZE;
		WaveHdr[i].dwBufferLength = WAVEBUF_SIZE;
	}

	 waveOutOpen(&HWaveOut, WAVE_MAPPER, &waveFmt, 0, 0, CALLBACK_NULL);
	for (i=0; i<NR_WAVEHDR; i++) {
		waveOutPrepareHeader(HWaveOut,WaveHdr + i, sizeof(WAVEHDR));
	}
}

static void sndout(int8_t d) {
	int next;

	next = cur_wavehdr + 1;
	if (next >= NR_WAVEHDR) next -= NR_WAVEHDR;
	if (cur_wavebuf_len >= WAVEBUF_SIZE) {
		while (!(WaveHdr[next].dwFlags & WHDR_DONE)
		       && (WaveHdr[next].dwFlags != WHDR_PREPARED)) {
			fprintf(stderr,"wave buffer overflow\n");
			exit(1);
		}
		waveOutWrite(HWaveOut, WaveHdr + cur_wavehdr, sizeof(WAVEHDR));
		cur_wavehdr = next;
		cur_wavebuf_len = 0;
	}
	WaveHdr[cur_wavehdr].lpData[cur_wavebuf_len++] = d+128;
}

static int can_sndout() {
	int prev;

	prev = cur_wavehdr - 3;
	if (prev < 0) prev += NR_WAVEHDR;
	if  (WaveHdr[prev].dwFlags == WHDR_PREPARED) return 1;
	if  (WaveHdr[prev].dwFlags & WHDR_DONE) return 1;
	return 0;
}
Windows の場合は、自分で fragment を作らないといけないので若干面倒。あと、fragment の数とか サイズ、詰め込みすぎないようにするところとか、Linux 版にあわせてみた。 Windows版で参考にしたのは、oggdecのソースコードとかportaudioとか
追記: バグがありました。nBlockAlignには、waveFmt.nChannels * waveFmt.wBitsPerSample/8 (=1) を入れるべきで、あと、8 BitPerSample では、値が 0 〜 255 なので +128 してやる必要があります。(参考:WAVEデータの作成と再生
視聴してみて 聞いてみたらそれなりに聞こえたので、8bit から拡張するとか補完を入れて精度を上げるとかあまり考えずにゴリゴリいきたいと思う。そういうことはできてから考えれば良さそうだ。 おわりに なんかコードばっかりのページになってしまった。ほとんどおまじないみたいなものなので、解説も微妙に書きにくい。もしもっと知りたいなら、ここに出てきたキーワードでググッてみてほしい。 ちなみに、実行可能なコードのソース ddstest1.cも置いておくので、どんな音になるか興味がある人は動かしてみてほしい。(注意: ddstest1 はバグっています。ddstest2a.cが機能拡張+バグ修正版なのですが、(キー入力の問題で)MinGWの環境ではまともに動きません。) ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- COMMENT: AUTHOR: pcm1723 EMAIL: pcm1723@yahoo.co.jp IP: 220.147.29.52 URL: http://www.geocities.jp/pcm1723/ DATE: 06/07/2007 02:09:11 まだ LFO はできていないとのことですが、このインプリメントでは vco.lfo_inc は、発生する音階によって変化させる必要があり、具体的には vco.lfo_inc = vco.wave_inc * lfo_modulation_depth * lfo_value; みたいな形になると思うのですが、その辺は考慮されているのでしょうか? ----- COMMENT: AUTHOR: すz EMAIL: IP: 210.143.35.17 URL: DATE: 06/07/2007 19:18:07 コメントありがとうございます。FM音源を自作されているのですね。FM音源的な使い方*も*できることを知らなかったので、今のもの ddstest2.c は、サンプリング周波数の 1/16の頻度で上のような計算をするようにしています。音作りは全然経験がないので、またご教授ください。 ----- -------- AUTHOR: すz TITLE: LFOとEGの設計とテスト STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: I2CSND DATE: 06/07/2007 20:42:41 ----- BODY: ddstest1.c に LFOとEGを組み込んでみた。→ ddstest2.c(修正版:ddstest2a.c) EG サンプル↓ LFO と EG は高い頻度で動かす必要がない(と思った)ので、↓のように、1/16 の頻度に落としてCPUを節約している。(あと負荷を分散させるよう工夫もしている)
ただ、LFO もサンプリングレートで動かしてやれば、2オペレータのFM音源にもなるかも知れない。(参考:JO-MIDI-FM) 今は、VCFをどう入れられるかが興味の対象なのだが、一段落したらFM音源化にもチャレンジしてみたい。
static void generate_snd() {
	static uint8_t cnt;
	  :
	cnt++;
	if (cnt >= 16) {
		do_lfo();
		cnt = 0;
	} else if (cnt == 8) {
		do_eg();
	}
}
LFO の本体はこんな具合。VCO を 正弦波専用に単純化して、VCOのパラメータを変更するコード。
static void do_lfo() {
	uint8_t pos;
	int8_t rev = 0;
	int8_t v;
	int16_t v2;
	lfo.wave_pos += lfo.wave_inc;
	pos = lfo.wave_pos >> 8;
	if (pos >= 128) {
		rev = 1;
		pos = 255 - pos;
	}
	if (pos >= 64) {
		pos = 127 - pos;
	}
	v = __LPM(sintab+pos);
	if (rev) v = -v;
	v2 = (int16_t)v * lfo.intensity;
	vco.lfo_inc = fmulsu16(v2, vco.wave_inc)>>4;
}
EG はちょっと長いけれども、全部載せるとこんなかんじ。
static void do_eg() {
	uint8_t state = eg.state;
	if (state == EG_NOTEOFF) {
		eg.intval = (0 << 8);
	}
	if (state == EG_NOTEON) {
		eg.sustain_cnt = 0;
		if (eg.attack == 0) {
			eg.intval = eg.sustain_lvl;
			eg.state = state = EG_SUSTAIN;
		} else {
			eg.intval = 0;
			eg.state = state = EG_ATTACK;
		}
	}
	if (state == EG_ATTACK) {
		if ((uint32_t)eg.intval + eg.attack >= 
                            (255<<8)) { // overflow
			eg.intval = (255 << 8);
			if (eg.sustain_lvl == 0) {
				eg.state = EG_RELEASE;
			} else {
				eg.state = EG_DECAY;
			}
		} else {
			eg.intval += eg.attack;
		}
	} else if (state == EG_DECAY) {
		eg.intval = fmul16(eg.intval, eg.decay);
		if (eg.intval <= eg.sustain_lvl) {
			eg.intval = eg.sustain_lvl;
			if (eg.sustain_time == 0) {
				eg.state = EG_RELEASE;
			} else {
				eg.state = EG_SUSTAIN;
			}
		}
	} else if (state == EG_SUSTAIN) {
		eg.sustain_cnt ++;
		if (eg.sustain_cnt == eg.sustain_time) {
			eg.state = EG_RELEASE;
		}
	} else if (state == EG_RELEASE) {
		eg.intval = fmul16(eg.intval, eg.release);
		if (eg.intval < (1 << 8)) {
			eg.intval = 0;
			eg.state = EG_NOTEOFF;
		}
	}
	eg.out = eg.intval << 8;
}
内部的には、16bit で値を計算して、上位8bit だけを出力としている。 ATTACK は、(計算が楽なので)線形で立ち上げることにした。DECAYは、減衰曲線で sustain_lvlになるまで減衰させる。SUSTAIN が終われば、RELEASEで減衰させるが、一応 DECAY と別のパラメータにした。 特別な処理としては、ATTACK のパラメータが 0 なら、SUSTAIN から入る。とか sustain_lvl が 0 なら ATTACK - RELEASE になるとか。ちなみに、CASE 文を使わないのは、(今使っている) avr-gcc(version 3.4) ではコード量が大きくなってしまうから。(CASE 文を使わないくせがついてしまった) あと、fmul16()とかfmulsu16()とか出てくるが、実機では、アセンブラ化するつもりで関数化している。 おわりに EG が付いたので、なんだか楽器らしくなってきて音を鳴らすのが楽しくなってきた。デジタルフィルタの VCF を作れば、一応コンポーネントは揃うことになる。もう一息なのだが、VCF は計算量が多く実機とすりあわせていかないといけないので、作るのはひとまずおいておいて ... 実機のコードと それにあわせた評価環境を作ろうと思う。 今のコードは、簡単なUIとサウンドジェネレータが一体になっているので、これを2つに分ける。Linux や Windows でもテストしたいので、プログラム間は、TCP/IP で通信する予定。
追記: Linux/Windows の両方でバグがあったので、ddstest2.c を修正して、ddstest2a.c にアップデートしました。
----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: Server-Client化と通信プロトコル STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: I2CSND DATE: 06/08/2007 18:56:38 ----- BODY: いままで作ってきたプログラムは、サウンドジェネレータの動作確認のためのものだった。これをもとに、AVR で I2Cスレーブとして動くプログラムと、それをコントロールするプログラムを作っていくことにする。もちろん、実機だけで動くものではなく、Linux/Windows で評価できるものにしていくのが前提。 AVR側 は、I2CデバイスドライバのAPI でコマンドパケットを受け取り処理する構造にして、コントローラ側は、コマンドパケットを生成して送信する構造にすることになる。そして ... (評価環境では)その間をつなぐものが必要。 このつなぐところを、どうするか...というと TCP/IP による通信にしてしまうのが、実は最も簡単で便利。便利というのは、Socket API は、Linux , Windows で同じように使えるのでコードを1つ作ればよいというのが理由。コントローラ側/デバイス側の構造を変に変えなくて良いという理由もある。 コントローラ側の処理の流れ メインループは次のように キーが入力されるとそれに対応した処理になるようにしている。もはや AVR-CDC とは関係ないのだが、getchar() に相当する関数が、いままでの経緯で usbcdc_getc() になっている。( ちなみに、プログラムを2つに分けた利点がもう1つあある。前のコードは、MinGW の環境で問題があったが、このコードなら Linux と同じように動く。)
	for (;;) {
		c = usbcdc_getc();
		change_note(c);
	}
change_note() はなにするかというと、キーに応じて関数を call するだけのもの。
static void change_note(uint8_t c) {
   const uint8_t note_base = 36+24; // C1
   static int oct;
    switch(c) {
    case 'z': oct --; break;
    case 'x': oct ++; break;
    case 'q': exit(0);
    case 'w': set_param(PARAM_VCO_WAVE, WAVE_SIN); break; 
    case 'e': set_param(PARAM_VCO_WAVE, WAVE_TRI); break; 
    case 'r': set_param(PARAM_VCO_WAVE, WAVE_SAW); break; 
    case 'a': note_on(note_base + 12*oct +0, 127); break;
    case 's': note_on(note_base + 12*oct +2, 127); break;
    case 'd': note_on(note_base + 12*oct +4, 127); break;
    case 'f': note_on(note_base + 12*oct +5, 127); break;
    case 'g': note_on(note_base + 12*oct +7, 127); break;
    case 'h': note_on(note_base + 12*oct +9, 127); break;
    case 'j': note_on(note_base + 12*oct +11, 127); break;
    case 'k': note_on(note_base + 12*oct +12, 127); break;
    case 'l': note_on(note_base + 12*oct +14, 127); break;
    }
}
で、たとえば note_on() は何をするかというと、パケットを作って、i2c_send() で 送信する。
static void note_on(uint8_t note, uint8_t verosity) {
	ext_buf[0] = CMD_NOTEON;
	ext_buf[1] = note;
	ext_buf[2] = verosity;
	ext_buf[3] = 0;
	i2c_send(0x20, 4);
}
i2c_send は、以前作った I2Cホストドライバの API で、これにあわせて、TCP/IP で通信するモジュールを作る。この API にあわせて USB910A の I2C 機能を利用するモジュールを作れば、そのまま実機テストできるし、AVR のコントローラを作った場合でも 利用できるのだ。 ちなみに、コマンドは MIDI もどきにする。CMD_NOTEON は、0x90 で、ローカルな機能には、MIDI に決して MAP されない 0x00 〜 0x7f を使う。 デバイス側(AVR 側)の処理の流れ
	for (;;) {
		if (can_sndout()) {
			generate_snd();
			continue;
		}
		if (i2cdev_can_getc(1)) {
			command_proc();
			i2cdev_flush();
		}
	}
メインループはこんなもの。バッファーが FULL でなければサウンドを生成して詰め込み、I2C経由でコマンドがくればその処理をする。 さて、このコードは バッファーが FULL になった状態でコマンドがこなければ無限に回ってしまう。AVR のときは、それでよいのだが、Linux/Windows のときは、それではまずい。CPU を離すしくみを入れる必要があり、それを入れるとすれば、i2cdev_can_getc() 以外にない。 実際どうしているかというと、select() を使って通信がないときも、0.05 秒だけ待ち合わせるようにしている。逆にここで止まるので、音が途切れないだけの量は、バッファーに溜めておかなければならない。
static void command_proc() {
	uint8_t cmd,p1,p2,p3; 
	cmd = i2cdev_getc() & 0xf0;
	p1 = i2cdev_getc();
	p2 = i2cdev_getc();
	p3 = i2cdev_getc();
	if (cmd == CMD_NOTEON) {
		note_on(p1,p2);
	} else if (cmd == CMD_NOTEOFF) {
		note_off();
	} else if (cmd == CMD_SETPARAM) {
		switch(p1) {
		case PARAM_LFO_FREQ:
			lfo.wave_inc = ((int16_t)p3 << 8)|p2;
                        break;
		case PARAM_LFO_INTENSITY:
			lfo.intensity = p2; break;
		case PARAM_VCO_WAVE:
			vco.wave_type = p2; break;
        :
                :
		}
	}
}
さて、コマンド処理はこんなかんじ。いまのところ 4 バイト固定のパケットが来るとして処理している。あと、内部に持っているパラメータは、CMD_SETPARAMで全部設定可能なようにしている。他のコマンド/機能はまだ実装していないが、簡単に追加していけそうだ。 AVR 側の処理とサイズ ずいぶん回り道した感があるが、実は AVR 固有の機能で作らないといけないのは、PWM で 出力する部分だけ。サンプリングレートで割り込みが起きるようにして、PWM のレジスタにデータをセットするだけのものを作れば、Linux/Windows 版と同等になる。 いきなり動作するとは思えないが、一応作ってみてサイズを見てみた。
   text	   data	    bss	    dec	    hex	filename
   2032	      0	     89	   2121	    849	i2csnd.elf
なんと..まだ 2KB 。これなら機能を充実させていっても ATtiny45 に入りそうだ。...ちなみに これなら ATtiny2313で何か作れるのでは?と考えては決していけない。最小限度必要なものを埋めていって 2KB ... スタート地点ですでに 2KB なのだから、なにかが作れたとしてもコードを縮小することばかりに追われてしまう。 プログラムについて ここまでのプログラムを i2csnd-0.1.tar.gzにおいておく。今度は大丈夫だと思うので、どんな音が出るか興味がある人は動かしてみてほしい。 linux でビルドする場合は、cd lin; make。 MinGW+MSYS の場合は、cd lin; make -f win.mk 。 動かし方は、Window を2つ用意して、1つで i2csnd を実行し、もうひとつで、sndtest を実行する。i2csnd は、MSYS コンソールでも動作するが、sndtest は、コマンドプロンプトでしか動作しない。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: 回路の検討 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: I2CSND DATE: 06/11/2007 14:44:50 ----- BODY: ターゲットのチップは、ATtiny45 ということにした。次に回路を検討することにする。 まず最初に作る チップ1個のシンプル版は次のようにしようと思う。 シンプル版(I2CSND-S) シリアルプログラミングできる範囲のピンのみを使う。... とすれば使えるピンは、RESET/VCC/GND あと I2C 用の SCL/SDA を除いて 3つのみとなる。ステレオにするつもりなので、出力は、OC1B/OC1A の2つに決まる。あとひとつは、CPU 使用率測定用。このピンは、CLKI 機能もあるので、外部クロック化にも使える。クロックソースは、マスタを水晶発振にして、その CLKOUT にすれば良いだろう。これで全部埋まった。機能として 周波数キャリブレーションも作るつもりだが、これは OC1B を兼用する。-- PWM の周波数を測定するので、無音レベルでも測定できるはず。 さて、どうやって DA変換するか ... アンプ を使わない簡単なやりかたがある。LC フィルタをかませて DA 変換し、コンデンサで直流分を除いて 出力制限抵抗で 出力レベルを調整すれば良い。 16 Ωの ヘッドホンを使うとして ... 75 Ωの 出力制限抵抗を入れれば、最大出力が 34 mW になる。最大電流も 19 mA と 問題ないレベルに収まる。低抵抗のボリュームは持っていないので、出力制限抵抗は差し替えて変更するつもり、最初決めたら変更することはないと思うので、それで困らないはず。 LC LPF の周波数は、(将来的にサンプリング周波数を 16kHzにしたいので)8kHz 弱にしてみた。いまのバージョンではサンプリング周波数は 8KHz なのでちょっとやばいかも知れない。ただ、PWM の周波数は、250 kHz なので、内部の処理次第でなんとかなるような気がする。なんともならないなら、すなおに、LPF の周波数を下げれば良い。コンデンサを 47 uF にすればよさそうだ。 コイルは、秋月で10個100円の LAL02NA470K が使えるかも知れない。max 70mA / 5.8 Ω の定格なので、電流的には大丈夫。それで全然ダメなようなら、千石で10個270円の LHLZ06NBを使ってみたい。こういったフェライトコアのコイルは、波形が歪むらしい。ただ、歪みも含めて(この装置の)特性だと割り切ってしまえばいいと思うので気にしないことにする。 ところで、このシンプル版は、出力に電源ノイズが載る。電源があまりに弱いと(USB の 5V を使う予定でたぶんすごく弱い)CPU の処理の変化までも、音となって出力されて来そうだ。3.3V のレギュレータを通して使えば、多少マシになるかもしれない。ただ、この回路はあくまで開発テスト用と位置づけて、あまり期待しないほうがよさそうだ。 ついでに小型スピーカーを鳴らすこともオプションとして考えておく。 2 つの出力を使って逆相にして 出力を得る。(BTL) 。この場合、直流分をカットするコンデンサは必要ない。16 Ωの 小型スピーカを使うとして ... 75 Ωの 出力制限抵抗を入れれば、最大電流は、38 mA と ぎりぎり OK。最大出力は 4 倍 の 137 mW になる。 もちろんプログラムで対応しなければならないが、これぐらいの改造でスピーカが鳴らせるのなら、対応する意味もあるだろう。 ちなみに、相手がスピーカなので、ELM - WaveTable電子オルゴール の回路のように LC LPF を取ってしまっても良いかも知れない。 マルチチップ版(I2CSND-D) 2 個のデバイスを使うマルチチップ版(i2CSND-D) の回路も考えてみた。 全部の ISP は付けるつもりはないが、1 つぐらいはあったほうが良いだろうということで、最初のチップだけ ISP をサポート。あと、I2C は終端抵抗をちゃんと付けることにする。周波数キャリブレーションもサポートしたいので、抵抗を間に入れて、MIX することにする。マルチチップ版では、PWM の出力も止めないといけないのでプログラムで対応が必要。 マルチチップ版では、デジタルの出力を アナログ部にある Buffer まで引っ張る。ここで波形を整えて、DA 変換する。DA 変換の際に ( オペアンプに高い周波数が渡らないように ) RC LPF もかけておく。オペアンプの後 LC フィルタを入れようと思う。これで良いのかどうか ... 不安なところもあるが、コイルやコンデンサを選択する楽しみもあるかも知れないので、これで行こうと思う。 この回路を N 個に拡張するのは簡単だ。ATtiny45 をデイジーチェーンして、Buffer に入力すれば良い。Buffer に使うチップは、VHC/VHCT シリーズである必要がある。HC シリーズだと クランプダイオードが入っているので、出力レベルが入力のレベルの影響を受ける。入力レベルを 落とす工夫が必要で、抵抗2つ使って 1/2 とかに分圧すればよいのだが、配線はそれなりに面倒。(参考:東芝のFAQ) ちなみに、(負論理の)インバーターでも(正論理の)バッファーでも良い。秋月で扱っているのは、VHCT540AFVHC244F。ちなみに VHC04F(フラット) は、千石扱っている。気合を入れて作るなら 一方向に 8 つ並んでいる VHCT540AF が良さそうだが、VHC244Fの片方向だけ使うのも手配線が楽そうで悪くはない。
次のようにすれば、1ピンを浮かすだけで ユニバーサル基板に半田づけできて、4bit の Buffer として使えるのだ。
オペアンプは、NJM4580D を使うのが無難。秋月で安く売っている LM358 でも十分かも知れない。スピーカーを鳴らしたいなら、オペアンプの変わりに秋月で安く売っている MC34119 を使うのも良いかも知れない。 マルチチップ版の回路は、いまのところ考えただけ。プログラムに影響があるところだけ、決めておけばよく、実際につくるときに、検討しなおすかも知れない。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: シンプル版の製作とテスト STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: I2CSND DATE: 06/13/2007 16:14:27 ----- BODY: 前回検討した 回路のうち シンプル版(I2CSND-S) を作ってテストした。 写真は改造後のもの。スイッチを後で追加している。 回路は、回路図そのものにした。回路図に現れないところの工夫では、丸ピンICソケット を割ったものを使って、出力の制限抵抗R2,R3 の交換とフィルター用 コイル L1,L2 の交換、それにフィルター用のコンデンサ C4,C6 の容量追加 が できるようにしている。 ちなみに、丸ピンICソケットは シングルのもの が綺麗に仕上る...のだが、安く買い置きしてある 40pin のものをニッパで割って使っている。 フィルター用のコイルは、LAL02NA470Kにして、フィルター用のコンデンサ には、積層セラミックの 10uF (±10%)使った。 あと、出力の制限抵抗 R2,R3 は、75 Ωでは音が大きすぎるので、150 Ωにしている。(これでもまだ若干大きい。自分的には、3.3V のとき 220 Ωが良いかも知れない。) この回路、そのままでは、ISP で書き込みできないという問題点がある。 MISO の先に LC フィルタが付いているため、波形が歪んで ISP の通信ができない。まだステレオ対応はしていないので、R 側の コイルを取ってしまったが、スライドスイッチで LC フィルタを切り離せるようにすべきだ。 L 側は、周波数カウンタにつなげて、クロックのキャリブレーションができるようにしているが、こちらは 無音 (PWM は ON だが 一定値) か 音が小さいときならちゃんと動作するようだ。 (後述するが)CPU 使用率測定機能も 値がばらつくものの有用なことを確認できた。 はまった点 EG の ATTACK の上限処理で 次のようにしていた。
if ((uint32_t)eg.intval + eg.attack >= (255<<8)) 
これが、(Windows/Linux で動いても) AVR (gcc-3.4.0) では動かない。ちなみに
if ((uint16_t)eg.intval + eg.attack < eg.intval) 
は、Windows/Linux で動かない。
if ((uint16_t)(eg.intval + eg.attack) < eg.intval) 
これは動くのだが、コード効率も悪そうなので、今は、
uint16_t next = eg.intval + eg.attack;
if (next < eg.intval) 
という風にしている。どこが動かないのか すぐにはわからずに、結構はまった。 乗算のコスト さて、このはまった過程で たかが 8bitX8bit 乗算 が非常に重いことを目のあたりにした。
CPU使用率は、電圧として出てくるので、USB910A の機能で簡単に読み取ることができる。
fcnt result     244625 x4     978500
    06:VCC     AUTO : 0021772 0x550c   3401.875
    02:AIN3    AUTO : 0002304 0x0900    360.000
fcnt result     244625 x4     978500
    06:VCC     AUTO : 0021772 0x550c   3401.875
    02:AIN3    AUTO : 0002336 0x0920    365.000
fcnt result     244625 x4     978500
    06:VCC     AUTO : 0021772 0x550c   3401.875
    02:AIN3    AUTO : 0002304 0x0900    360.000
fcnt result     244625 x4     978500
    06:VCC     AUTO : 0021772 0x550c   3401.875
    02:AIN3    AUTO : 0002192 0x0890    342.500
244625 というのは、PWM 周波数で、AIN3 が CPU使用率をあらわす電圧。こんなふうに多少ばらつく。以下精度が 0.1% のように書いているが、自分の感覚で読み取ったものであり、厳密ではない。
EG なし LFO ありの状態だと CPU 使用率が 6.3 % 前後なのだが、サンプリングレート(8000 Hz) 毎に 8bitX8bit 乗算 fmusu8_8() を入れるだけで15.8 % にまでなるのだ。 元のコードは、
static inline int8_t fmulsu8_8(int8_t a, uint8_t b) {
        int16_t v;
        v = (int16_t)a * b;
        return (int8_t)(v >> 8);
}
で、8bitX8bit をして、上位 8 bit だけ取り出すもの。固定小数点演算の意味で fmulxx としている 。C 的には、16bitX16bit にするしかないので重いわけだ。 アセンブラ化しようと思ったのだが、なかなか面倒。8bit×8bit 乗算(符号なし/符号あり)などを眺めていたのだが、ふと 思い付いて アセンブラでやっていることをC で書いてみた。
static inline int8_t fmulsu8_8(int8_t a, uint8_t b) {
        uint8_t i;
        int16_t __c , __a;
        __c = 0;
        __a = a;

        for (i=0; i<8; i++) {
                if (b & 1) {
                        __c += __a;
                }
                b>>=1;
                __a <<= 1;
        }
        return __c>>8;
}
これで 15.8 % が 10.3 % 程度まで下がった。 サンプリングレート毎に行う 8bitX8bit 乗算のコスト が 9.5 % から 4.0 % にまで下がったことになる。乗数が 16bit から 8bit に半減したおかげだ。(ちなみに、16bitx8bit 乗算もよくつかっているが同じコスト)。 おなじようにして、C 版の 16bitX16bit 乗算 のコストを調べたところ 12.1 % になった。被乗数 の方も 32bit に増えているので、3 倍というのは妥当だろう。サンプリング毎のCPUクロック数 は、2000 なので、12.1 % は、242 クロック(平均)ということになる。 LFO/EG のコスト EG を入れると、DECAY が効いている状態で 11.8 % になった。もとが 10.3 % なので、1.5 % という計算。16bitX16bit と 16bitx8bit 乗算が 1/16 の頻度だから (12% + 4% )/16 = 1.0% 。+それ以外の処理で 1.5 % は妥当なところか。 ステレオ化のコスト 結局 8bitX8bit 乗算 がもうひとつ増えるので、4.0 % 増える計算 。EG も乗算 2 つ余計に入る予定で 1.0 % ぐらい増えるはず。 フィルターのコスト AVRマイコンによるMIDIシンセサイザーの製作 にある フィルターだと
y[i] = y[i-1] + m * (x[i] - y[i-1])
で サンプリングレート(8000 Hz) 毎に 16bitx16bit 乗算がはいりそうだ。この場合 12.1 % のコストで、16bitx8bitで済ませれば 4.0 % のコスト。 どのように拡張できそうか ここまで合計すると、EG あり 11.8 % + ステレオ 5.0 % + フィルタ 12.1 % で 合計 28.9 % 。 このバランスだと サンプリング周波数を 倍の 16kHz にしてもいけそうだが ... フィルタを凝れば 8KHz でも厳しいか。もともとフィルターを凝るのが目的なので、サンプリングレートをあげるのは二の次にして、進めていきたい。 ところで、FM音源化について考察しておく。各オペレータには、EG が付く。EG あり LFO なしだと だいたい 10.5% ぐらいだろう。これに対して 16bitx8bit 乗算が1つ余分に付く見込みで、合計はだいたい15% 。あと最終的な出力のボリューム 8bitx8bit 乗算が 2 つほど必要なので 8% がさらに必要。計算上は 6オペレータ分はいるが、たぶん無理で 4 オペレータが妥当そうだ。 ホスト側のプログラム ホストには、USB910A を使う。以前使った コードを改造してi2c_send()/i2c_recv()を作り、sndtest.c が使えるようにした。 USB910A の FW は、version 0.5 ではうまくない。ちゃんとつながるのだが、いったん CLOSE すると 再接続ができない。、version 0.4 を使えば ちゃんと動く。 0.5 は、機能的には 0.4 と変わらないのだが、ベースコードを最新にしていて コードが 小さくなっている。原因はボチボチ調べることにして、とりあえず、version 0.4 を使うことにする。 試聴 まずノイズについて、USB の 5V で動かすと たいへんひどい。本体 PC でエディットするときのカーソル移動がノイズになってあらわれるぐらい。3.3V もあまり期待していなかったのだが ... こちらは全然ノイズが聞こえない。これぐらいなら十分実用になりそうだ。 スプリアスについて 正弦波の場合、高調波が(あまり)ないので、結構高音までいける。 三角波も おなじような感じ。それに反して のこぎり波は、ちょっと高音になると スプリアスのために、変な音がまじってくる。 逆に 正弦波でかなり低音にすると、(時間軸の)量子化ノイズのために、へんな音がまじってくる。 サンプリングレートを倍にすれば、1 オクターブ上まで OK ということになるのだろう。ただし、低音の問題は解決しない。 PC(の 8bit 8Khz) と比較して なんだか音がはっきりしている気がする。余計なものが一切なくダイレクトにヘッドホンを駆動しているせいかも知れない。同じコードで同じ波形を作っているので、それぐらいしか違いはわからなかった。 判断するだけの経験がないので、あまり具体的にはかけなかった。興味があるかたは、ぜひ自作してみてほしい。ここまでのコードは、→ i2csnd-0.2.tar.gzおわりに これで、実機の環境も Windows/Linux に追いついたことになる。これをベースに次は完成向けて機能を作りこんでいこうと思う。その際 個別機能の構造体 VCO とかは、ひとつの構造体(名前は OPERATOR ?)に押し込めて、整理しようと思う。こうしないと評価環境でのマルチチップシミュレーションが作りづらい。実機でのポリフォニックは(あまり)考えていないが、FM音源版の準備という要素もある。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: USB910のJTAG拡張案 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 06/14/2007 00:31:23 ----- BODY: デザインウェーブマガジン 2007年7月号 (2480円)には、付録に 250K ゲート相当 のFPGA Spartan-3E XC3S250E 基板が付いて来る。いままで、FPGA の付録は買ってきたが、実際になにかを作ったり動かしたりしたことはなかった。今度こそなにか動かしたいものだと思う。 FPGA のプログラミングはともかくとして、その前に USB910 を拡張して JTAG ケーブル 機能をつけてみたい。 USB の JTAG 関係で 参考になるものはないかと思い、sourceforge を JTAG で 検索すると ... xilprg というものが見付かった。
xilprg is a Xilinx FPGA/PROM/CPLD JTAG programmer tool for Win32/Linux. Supports Parallel III cable, Digilent USB. cblsrv is a Open-Source CableServer for Xilinx Impact.
だそうだ。Digilent の JTAG-USB を サポートしていて、コンフィグレーションできるだけではなく、CableServer を使うと Xilinx のツールである iMPACT から直接書き込みできるようになるらしい。 というわけで、TAG-USB がどのようなプロトコルで通信しているか興味をもった。それは、xilprg の コードを見ればわかるわけだ。 前置きが長くなってしまったが、この JTAG-USB のプロトコルを紹介。 この JTAG-USB は、バルク転送で パケットをやりとりする。パケットの形式は、フラグ 4bit/コマンド 4bit , サイズ 16bit , データ (61 バイト)で、パケット全体が 64 バイトになるようになっている。 サイズの 16bit は、ビッグエンディアン で HI - LO の順。データ転送の場合、サイズには bit 数を入れる。データ転送でない場合は、バイトのようだ。 送信パケットのコマンドは、6 種類で 、受信パケットのコマンドは 1種類(0x06 固定)。送信パケットは、16 個まで連続して送ることができる。
送信パケット詳細
コマンド NULL (0x00) 
   サイズ 0 
   データ 0 バイト

   受信パケット要求のコマンド。このコマンドを発行
   したときだけ、受信パケットが送られてくる。

コマンド ENABLE (0x01)
   サイズ 1
   データ 1 バイト
           0 : DISABLE
           1 : ENABLE

   初期化と終了コマンド

コマンド SET (0x02)
   サイズ 1
   データ 1 バイト
      ビットマップになっていて bit の意味は以下のとおり
           1 : TDI を HI
           2 : TMS を HI
           4 : TCK を HI

コマンド PUT_TDI_BITS (0x03)
   フラグ  RECIEVE(0x40) , TMS_HIGH(0x20)
   サイズ bit数
   データ (bit数 + 7)/8

       TDI にビット列を送り込む。バイト内の並び順は
    LSB first
       フラグには、受信データを用意する要求(?) の 
       RECIEVE と TMS の状態をセットする TMS_HIGH がある。
       RECIEVE フラグを立て、コマンド NULL で要求して
       はじめて、受信できる。

コマンド PUT_TMS_TDI_BITS (0x04)
   フラグ  RECIEVE(0x40) 
   サイズ bit数
   データ (bit数 + 3)/4
        PUT_TDI_BITS より高機能で、TMS の状態も 1bit
        書き込み毎に設定する。(データの並び順は、TDI TMS
        .... で 総bit数は、サイズで指定した bit数x2)

        データには、TDI の状態 と TMS の状態が含まれる。
   
コマンド GET_TDO_BITS (0x05)
   フラグ  TDI_HIGH(0x10) , TMS_HIGH(0x20)
   サイズ bit数
   データ 0
       TDI/TMS の状態を設定して TDO を読み取る。
       受信するためのコマンドで、RECIEVE フラグは必要ない
       が、コマンド NULL で要求してはじめて、受信できる。
こういうプロトコルなら、USBの遅延を隠蔽できるので、かなりのスループットが実際に出ると思う。また、JTAG だけでなく (標準的な)SPI にも使える。 よく考えられていると思うので、参考にして、USB910 の拡張をしようと思う。 コマンドは 数字('0' 〜 '5') を使いパケットは可変長にする。bit 数の 最大は 64 バイト分(512bit)かもうすこし大きめ。bitmap は USIを使う場合も考えて、MSB first。 こうやって USB910 を拡張して、xilprg を digilent 版ベースで改造すれば、iMPACT で使えるものになるはずだ。 それは良いのだが ... Digilent のものは、専用の USB インターフェイスがあるので、高速だ。それに対して、USB910 は 最大でも 80kbps ぐらいしか出ない。FPGA のコンフィグレーションとかは、それでがまんするしかないのだが、JTAG のバウンダリスキャン を使ってバスの状態を設定して、バスの上の FLASH ROM を書き換える用途などでは遅くて使えない。
たとえば、bit 数が 512 ほどあって、1 バイトのデータを書くのに 3 回 512 bit 送らなければならないとすれば、80kbps 出たとしても FLASH の書き込みは、52 バイト/sec になってしまう。FLASH が 4MBでも 22 時間もかかってしまう。
もうひとひねり必要だ。... 更新するデータだけを送り、複数の JTAG 転送をしてくれるような機能がないと使えない。そしてメモリもあまりない。 この部分は、まだどうしたら良いか思い付いていない。 なんだか USB910で無理やり機能をつけているからこうなってしまう気もする。AVRでの電子工作にこだわったとしても、ATmega88 と、FT245RL USBパラレル変換モジュールを組み合わせれば高速なものが作れると思うし、AT90USB162(pdf) なら、デジキーで購入可能で自由に高速なものを作れそうだ。そもそも、実用的かつ安価なものを求めるなら、Digilent の JTAG-USB を買うのも良いわけだ。 それでも、USB910(と AVR-CDC) にこだわりたい、USB910はいつも傍らにあるし、プログラムを作るだけでよいのだ。(ただし、Spartan-3E のJTAG は、2.5V なので、レベル変換は必要)。このブログのネタにもなるし、工夫の余地があって楽しくもある。
とはいえ、ATtiny861/ATtiny44 はまだどこでも入手できるチップではないので、いまは他の人に使ってもらうという立場ではない。 付録基板を USB から使いたい and/or I2CSND を使いたいという人のために、なにか考えようかと思う。 今のところFT245RL USBパラレル変換モジュール+ATtiny2313 を使って、USB910から I2C と JTAG拡張だけ抜き出したものが良さそうだと思っている。秋月で全部そろうし、USB910よりずっとJTAG の性能が良さそうだ。プロトコルをあわせておいて、xilprgの改造もする。あと、AVRDUDE とか UISP も改造すれば、AVR910の機能がなくともライタとして使えるはず。もしくは、ATmega88向けに USB910+JTAG拡張機能を BUILD できるようにするか... I2CSND 向けに シングルエンド ADC 機能と周波数カウンタ機能は移植したいところだ。
おわりに デザインウェーブマガジン 付録の話題は、ネタふりにだけ使ってしまった。まぁ、実際なにか作りたいとは思う。だけれども、FPGA ならではのもので、あまり複雑な外付け回路を必要とせず、なにかの役に立つという条件を付けるとあまり作れるものがない。最近 I2CSND を作っているので、思いついたのだが、256〜384オペレータの FM音源で USBかMIDIインターフェイスを持っていてΣΔで DA変換(ウィキベディアの説明)してサウンドを出力する..とかはどうだろう。...といってもそこまでのものは、設計できる実力はない。設計する能力さえあれば、Spartan-3E XC3S250E はハード的にこれぐらいは可能だと思う。18bit 乗算器とブロックメモリが 12 個もあるし、PicoBlaze 12 個乗せてそれぞれ 32 オペレータ担当させれば、意外と簡単に作れるのかも知れない。が、なにしろ未経験なのでよくわからない。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: DWM付録FPGA基板用USB-JTAGケーブルの構想 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: SERJTAG DATE: 06/15/2007 18:46:13 ----- BODY: デザインウェーブマガジン 2007年7月号 (2480円)には、付録に 250K ゲート相当 のFPGA Spartan-3E XC3S250E 基板が付いて来る。こいつで使え、簡単に作れる USB-JTAG ケーブルを設計してみようと思う。 私にとって簡単なのは、USB910A に JTAG 機能を付けることが最も簡単だ。Spartan-3E の JTAG の電圧は 2.5V だが、前に Spartan-3 がDWM付録になったときのなひたふさんのコメント -- Spartan3 の使い方 によると、3.3V I/O電圧 でも 100Ωぐらいの抵抗を入れれば OK らしい。... USB910A は 3.3V モードがあって、150Ωの抵抗もすでに入っているので改造をする必要がなく、FW のソフトと書き込みソフトだけをなんとかすればよいのだ。 それはもちろんやるとして、部品の入手性に問題がなく、もっと簡単に作れて、さらに速いものにしたい。もちろん AVR を使い、FWは (拡張した)USB910 のサプセットにする。
補足: JTAG 用なので、速くなければ使いにくい/使えない場合がある。 端的な例がバウンダリスキャンを使っての FLASH 書き込み。以前 玄箱の FW を壊してしまって、簡単な Serial-JTAG ケーブルを作って書き換えたのだが、バスの状態を設定するのに、507 ビットの転送が必要、書き込むために、バスの状態を 3 回変更するので、1500 bit ほどの転送をする。これで FLASH の 1 バイトしか書き込めないのだから、実に 187 倍もの転送量になるのだ。 作ったやつはスループットも出なかったので日が暮れるどころの騒ぎではなく、実に大変な目にあった。
USB910が遅いのは、ひとつには LOW SPEED であることが原因だ。AVR-CDC ではなく、専用のチップを使えば転送速度があがるはずだ。USB-シリアル変換だと シリアル自体が性能ネックになりそうなので、パラレルの FT245RL を使う。データシートによれば、専用ドライバで 1MB/sec 、汎用のシリアルドライバでも 300KB/sec 出るそうだ。もちろんこれだけが速くなっても性能は出ない。プロトコルとか、AVR のコードも最適化する必要がある。がんばりたいとは思うが、AVR の限界もあって、市販のものと比べる程の性能は出ない(かも知れない)。 簡単に作れるようにするために、FT245RL USBパラレル変換モジュールを使う。同種のモジュールと比べても安価な方だと思うし、USB コネクタも付いている。 本体のAVRは、ATtiny2313V を使う。秋月で入手できるし、安価だ。 プログラムメモリは 2KB しかないが、JTAG とI2C の機能だけなら、問題なく移植できる。ATtiny2313V、FT245RL ともに 1.8V まで動作電圧(FT245RL の場合は I/O電圧) を下げることができる。2.5V の場合は 3.3V +抵抗でもなんとかなるが、今後のためにもっと低い電圧もサポートしておきたい。 .. というようなことを考えて回路を考えてみたのが↓ 回路図といえるほどのものではなく、配線図という感じだ。ただ、ATtiny2313V のピンは全部使うので、配線は面倒かも知れない。
製作例: ダイオードは、2個連のところを1つだけにしてみた。あと PWREN# は無接続
書き込みソフトについて オープンソースで、xilprgというものがある。これは、Digilent の JTAG-USB を サポートしていて、コンフィグレーションできるだけではなく、CableServer を使うと Xilinx のツールである iMPACT から直接書き込みできるようなるものらしい。 こいつに作った SERJTAG のコードを追加して、JTAG として使えるようにする予定。(その状況もこのカテゴリに書いていく。) プロトコルは、Digilent の JTAG-USB用のコードを研究して、決めた。当然ながら、Digilent の プロトコルに(論理的には)似ていて、JTAG-USB用のコードを改造して作るのも容易(なはずだ)。
補足: Digilent の プロトコルは、バルク転送向けなので同じようにはできない。また AVR で性能を出すために変更しなければならない所もある。さらに、USB910 に組み込む前提なので、USB910 のプロトコルともすり合わせる必要があった。 ちなみに、決めたプロトコルは、シリアル向けのものなので、Serial Jtag という意味で SERJTAG と名づけた。SERJTAG はプロトコル名のつもりなので、USB910 の拡張の話題もこのカテゴリに書くつもり。
(FT245RL版 )SERJTAG は、USB910 の I2C 機能も入れる。なので、I2CSND でも使える予定。 あと、JTAG ケーブルというのは、汎用 SPI にも使えるので、AVR ISP にも対応可能だ。AVRDUDE とか UISP とかの AVRライタソフトにも対応させようと思う。 デバッグ前だが、プログラム → serjtag-0.1.tar.gz チューニングできるところはしたつもり、サイズは、1.8KB ほどなのでまだ余裕がある。(ちなみに WinAVR の gcc-4.1.1 だと 1654 バイトと 1 割近く小さくなる。) DWM付録FPGA基板に関するその他の話題 ●クロックについて ググっていて、Sim's blog というところを見つけた。FPGA の話題も多く参考になりそうだ。FPGA でなにかを作ろうとすれば、クロックは必要だが ... DWM付録基板のクロックによると、SG-645PCP(33MHz) (4個 300円) が使えるそうだ。そういえば、FT245R に OSCO というピンがある。12MHz でよければ 供給できるかも知れない。
OSCO は無接続だったのでクロック供給は、無理そうだ。以前 現品.com で5個200円で入手した KOYO(光陽精密)の KCO-700シリーズ (pdf) 32.000 Mhz を接続した。
●BitBangModeについて FT245R(など) は、何もつけなくとも I2C/JTAG/SPI として使えるらしい。Programming Guidesに、それらのAPI が載っている。...こんなモノ(SERJTAG)を付けるよりずっと性能が良かったりするかも知れない。それはともかく、SPI もサポートしているから、FT245RL USBパラレル変換モジュールはそのままでAVRライタになるわけか。
訂正: I2C/JTAG/SPI として使えるのは、the Multi-Protocol Synchronous Serial Engine (MPSSE) を持っている FT2232 だけということが判った。秋月でこのチップを扱っているもののモジュールはない。APIも MPSSE 専用。 補足: ガセを書いてしまって申し訳ないので、D2XXのプログラミングガイドと FT232R/FT245R の BitBangModes のドキュメントを読んでみた。 これと FT2232 は、同期 BitBangMode というのを持っている。なにが同期かというと、FT_Write で値を変更する前の状態を(自動で)取り込み、FT_Read で読める。WriteとRead が同期しているわけだ。もちろん、入力ピン出力ビンの設定もできるから、I2Cは無理としても、JTAG や SPI には使えそうだ。ちなみに、非同期モードは、同期しないと、正しい状態が読めない。だから更新前の情報が必要な JTAG/SPI は遅い。 あと、転送レートを FT_SetBaudRate で指定する。この値 x 16 のデータが流れる(8bit x 往復?) ので、最大で 500kbps 。CLK 上げ下げとデータセットが必要そうだから、JTAG/SPI のビットレートは最大で 166kbps 。最大性能だと 8Mbps の帯域を使ってしまうから、 80kbps ぐらいが実効性能として妥当だろう。...これぐらいなら USB910版の SERJTAG でも出せそうだ。... といっても AVR のライタとしては十分な性能。avrdude に移植されているか..といえばされていないわけでもないらしい。→ ftbb.c。ただし、非同期モードを使っているので、すごく遅いはずだ。 この ftbb.c を同期モードで書き直せば、一応実用的な速度で動きそうだ。これだけ調べたけれども I2C もサポートする SERJTAGを作りたいので、これには手を出さない(かもしれない)。 追記:設計メモ FT245R/FT232R は BitBangMode を持っているわけだが、FT232R の方は、入出力の初期状態が決まっている。なので、BitBangMode を使う場合 FT232R にあわせて設計したほうが良い。 ELM COMポート制御ISPアダプタ のピン配置を参考にすると
                 chip pin#   BitBang bit
                              ( = FT245R D#)
   MISO   RxD       5        1
   SCK    RTS       3        0
   MOSI   TxD       1        2
   RESET  DTR       2        4
あたりが妥当か。ただし、avrdude では、avrdude.conf で ピンの配置を自由に設定できるので、単にデフォルトと思えばよい。
●オプション5Vレギュレータについて DWM付録FPGA基板を5Vで使うときは、LM317系の可変型3端子レギュレータを付けられるが、秋月で扱っているのは、どれも大きい。ひょっとして、AZ1117H−ADJ (表面実装型、10個300円)が付くのではないだろうか? FT245Rを注文したついでに買ったので、試してみたい。
追記:接続はできるようだ↓。(ただし未通電)
----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- COMMENT: AUTHOR: N EMAIL: N@ IP: 61.205.39.221 URL: DATE: 11/19/2007 12:27:44 FT2232Cは利用可能な唯一のデバイスFTCI2C FTCJTAG FTCSPI のdllがあるらしい http://www.ftdichip.com/Projects/MPSSE/FTCJTAG.htm ----- COMMENT: AUTHOR: N EMAIL: N@ IP: 61.205.39.221 URL: DATE: 11/19/2007 13:10:17 「Mprog」というのを使いますと FT232RLはCBUS0-TXLED、CBUS1-RXLED、CBUS2、CBUS3、CBUS4を TXDEN、PWREN#、TXRXLED、SLEEP、 48MHz、24MHz、12MHz、6Hz-CLKOUTにプログラムできます。 D2XXとVCPは統一されました。 http://www.ftdichip.com/Support/Knowledgebase/index.html?jtagintroduction.htm http://www.ftdichip.com/Documents/AppNotes.htm ----- COMMENT: AUTHOR: すz EMAIL: IP: unknown URL: DATE: 11/20/2007 08:09:09 情報ありがとうございます。 Mprog と ドキュメントは、http://www.ftdichip.com/Resources/Utilities.htm からダウンロードできました。 FT245RL は、C4 しか空いていませんが、 CLKOUT にできるとなにかと便利かも知れませんね。 FT232RL は、CBUS BitBang Modeがあるようなので、C0-C3をファームウェア書き換え用に使って、C4 をやはり CLKOUT にするのが良いのかも知れません。 ..といっても、CBUS BitBang Mode は、非同期なので、avrdude などでサポートされたとしても、すごく遅いものになりそうです。 ----- COMMENT: AUTHOR: N EMAIL: IP: 61.205.55.78 URL: DATE: 11/20/2007 18:14:59 ビットバンは非同期モード? ボーレートで決まり16ビット1ワードらしい、16Xボーと言う記述もありどちらか不明。 62バイトの整数倍〜63488バイト以下? 一度オープンして後は連続にアクセスしないとWinのスケジュールに引っかかって遅くなるようです。 VCPは仮想COMモードでも遅いようですが、(LatencyTimerで速度が決まる?1は駄目で2以上16がデフォルト) D2XXは同期モードでもビットバンモードでも使えるのでしょうか? (ここが不明です) ----- COMMENT: AUTHOR: すz EMAIL: IP: unknown URL: DATE: 11/20/2007 20:22:58 FT232RL は、ビットバンモードに、同期と非同期、そしてCBUS の3種類があります。どれを使うかは、FT_SetBitMode の第三パラメータで指定します。ヘッダーファイルにdefineされていなくて分かりにくいのですが、0x1 = 非同期 , 0x4 = 同期 , 0x20 = CBUS です。ドキュメントは、D2XX Programmer's Guide 。 ちなみに、VCPドライバをダウンロードして使っています。 ----- COMMENT: AUTHOR: すz EMAIL: IP: unknown URL: DATE: 11/20/2007 20:34:37 VCP ドライバのリンクからダウンロードしたのですが、D2XX ドライバのリンクでも同じ CDMなんとか をダウンロードすることになるのですね。統合されたという意味がやっとわかりました。 ...だとすると FTD2XX.dll を使っているので、D2XX で使用していることになるようです。 ----- COMMENT: AUTHOR: すz EMAIL: IP: unknown URL: DATE: 11/20/2007 21:00:01 FT_SetBaudRate と 実際の転送速度について 実は私もよくわかりませんが、同期モードで実験した限りは、どうも ボーレート x 4 が 実際の転送速度のようです。ただし、2400, 4800... と ヘッダーに定義されているボーレートを選択する必要があるようでした。 ----- COMMENT: AUTHOR: N EMAIL: IP: 219.94.235.42 URL: DATE: 12/01/2007 00:30:25 次にJTAGのマニュアルを見つけたのですが英文なので良くわかりません。 以前読まれたものと同じでしょうか? FT2232CはFT232BM and FT245BMを複合したもののようですか? http://www.ftdichip.com/Projects/MPSSE/FT2232C-Proj03_v11.pdf ----- COMMENT: AUTHOR: N EMAIL: IP: 61.205.36.196 URL: DATE: 12/01/2007 17:39:10 回路図がありました。 http://www.ftdichip.com/Documents/DataSheets/DLP/dlp2232m-v14-ds.pdf ----- COMMENT: AUTHOR: N EMAIL: IP: 61.205.45.26 URL: DATE: 12/02/2007 18:29:02 速度は次まで出るらしい。 MPSSE is capable of a maximum sustained data rate of 5.6 Mega bits / s. しかし  トラ技12月号、p211にFT232RLの場合は 変化のたびにビット情報を送らず 63488バイト以下でひとまとめにして送ると早いそうです。 ----- COMMENT: AUTHOR: すz EMAIL: IP: unknown URL: DATE: 12/03/2007 20:28:13 本文にも書きましたが、MPSSE(the Multi-Protocol Synchronous Serial Engine)を持っているのは、FT2232 だけのようです。APIも MPSSE 専用。 なので AM(BM) や RL と 別物と思ったほうが良いと思います。 ----- COMMENT: AUTHOR: N EMAIL: IP: 219.94.232.245 URL: DATE: 12/04/2007 10:49:48 最近はJTAGと言うインターフェースでPICやAVR、果てはCPLDやFPGAまで操作プログラムできるらしい。(まだ解らないことばかり) そのJTAGにはFT232RLやFT245RL、FT2322、R8C、AVRなどが使えるらしい、(これも極めていません) これらのうち共通互換性や高速性を満足できるものを作ろうと検討しています。 (あんましたくさん作っても直ぐ何処かへ行ってしまう?ので) まだこれに決定というのがないのですが、決まったら作ろうと思っています。 ----- COMMENT: AUTHOR: N EMAIL: IP: 61.205.44.243 URL: DATE: 12/05/2007 00:55:56 JTAGアダプタに2322が使われているのが見つかりました。USB 2.0 (最大12Mbit/sec) 最大バウンダリスキャンレート6Mbit/sec らしいです。 ソフト関係のことも載っていました。 http://www.besttechnology.co.jp/download/INETPDF/BTE067%20TINY%20JTAG-ICE.pdf ----- -------- AUTHOR: すz TITLE: 製作とavrdude改造..そしてチューニング STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: SERJTAG DATE: 06/18/2007 23:13:24 ----- BODY: SERJTAG FT245RL USBパラレル変換モジュール版 を製作し、動作の確認を行った。確認には avrdude に対応させて、AVR へのプログラミングを行って確認している。だいたいの機能は確認できたはずだが、8bit 単位でない転送など確認できていない機能もある。 製作編 ほぼ、前回の記事の回路図通り、違う点は 2 つで、PWREN# を無接続にしたのと、電圧調整用ダイオードのうち 2連になっているところを 1 つにした。 例によって、SW-55 に入れるつもりで作ったのだが ... (作ってから)モジュールが高すぎて、入らないことがわかった。IC ソケットを使わないようにしないと、13mm (20mm - 上 2mm/下 5mm) に収まらないので注意。 ケーブルは、カモン USB-05を切って作った。 シールドも使うと コネクタ付きの線が 5 本になるので、JTAG/AVR ISP に使える。コネクタが 1pin 単位なので、いろんな PIN 配置に対応できて便利。しかも安い。千石で通販しているし、店頭でも売っている。PC関係のパーツ屋でも扱っていると思うが、千石だと 263円と安い。 ちなみに、3.3V 出力を外に出している。全部で 50 mA しか流せないが、AVR プログラミング用には十分。 avrdude 改造 作ったからには、AVR のプログラミングもできるようにしたい。テストも兼ねて、avrdude を改造することにした。 avr910.c と usbasp.c の2つをにらみながら serjtag.h と serjtag.c を作った。シリアルの制御と初期化でのコマンド発行は、 avr910.c をベースにして、chip_erase の処理は、usbasp.c をベースにしたうえで、他の処理も参考にした。avrdude は、基本的に cmd を使って いろんな処理をしてくれるので、paged_write と paged_load に注力すればよく、作るのは楽だった。( paged_write/paged_load を作らなくても動く。ただし、汎用の cmd() を使うのですごく遅い。) 。ただ、paged_write と paged_load は、FLASH だけではなく、EEPROM にも対応しなければならない。EEPROM までまじめに作るのは面倒なので、avr.c の共通ルーチンをベースにした。 新しいプログラマを組み込むには、Makefile.in を修正するのはもちろんだが、それ以外に config_gram.y , lexer.l , avrdude.conf.in にも修正が必要だった。 テストとデバッグ 動かすまでは大変ではあったが、ざっくり省略。1つだけ教訓がある。 それは、ぎりぎりの SCK クロックで動かすなということ。途中でコマンドが化けて FUSE BIT を書き換えてしまうかも知れない。 avrdude は良くできていて、最後に FUSE BIT をチェックしてくれて、FUSE BIT が(意図に反して)書き換わってしまったら、元に戻すか聞いてくれる。メッセージをよく読まないでアボートしてしまうと、高電圧プログラミングでないと戻せない状態になってしまう場合がある。(ターゲットに ATtiny44 を使っていたのだが、アボートしてしまい、書き込みできない状態にしてしまった。2 つダメにして、そういうことかと後で気が付いた。) 簡単にダメにしてしまったのは、もうひとつ原因がある。CPU クロックを 1/8 にする設定がデフォルトだが、これだと 1MHz で、ISP 書き込みのクロックは、1/4 の 250kHz を超えないようにしなければならない。 1/8 にするのを DISABLE にすれば、2MHz まで OKで、高速化しない限りなかなかその周波数にまではいかない。 ちなみに、HSV で元に戻すボードとプログラムはあるので、ダメにした ATtiny44 は元に戻せるはずだが、ちょっと面倒。 チューニング paged_write と paged_load を作らないバージョンは、4072 バイトの書き込みに、66.54 秒、ベリファイに 63.13 秒もかかった。1バイトの書き込みに 4バイトの送信と受信をするので、(転送量はともかく)受信の遅延のために時間がかかるのだ。(計算すると遅延は、15 ms ぐらい) さて、paged_write と paged_load を すなおなコードで作ってみた。書き込み時間は、1.72 秒、ベリファイ時間は、4.66 秒になった。SERJTAG では、SPI の結果を(デバイスが)送信しないようにできるため 1ページ分は受信が必要なく送信を連続してできる。なので、書き込みは結構速い。しかし、ベリファイが予想以上に遅い。 そこで、paged_load については、 AVR-CDCの性能(2)で書いたように ソフトウェアパイプライニングを使ったチューニングをすることにした。 ちょっと長いが、ポイントとなるコードを載せて説明しようと思う。
static struct serjtag_request {
	int addr;
	int bytes;
	int n;
	struct serjtag_request *next;
} *req_head,*req_tail,*req_pool;

static void put_request(int addr, int bytes, int n)
{
  struct serjtag_request *p;
  if (req_pool) {
     p = req_pool;
     req_pool = p->next;
  } else {
     p = malloc(sizeof(struct serjtag_request));
     if (!p) {
       fprintf(stderr, "can't alloc memory\n");
       exit(1);
     }
  }
  memset(p, 0, sizeof(struct serjtag_request));
  p->addr = addr;
  p->bytes = bytes;
  p->n = n;
  if (req_tail) {
     req_tail->next = p;
     req_tail = p;
  } else {
     req_head = req_tail = p;
  }
}

static int do_request(PROGRAMMER * pgm, AVRMEM *m)
{
  struct serjtag_request *p;
  int addr, bytes, j, n;
  char buf[128];

  if (!req_head) return 0;
  p = req_head;
  req_head = p->next;
  if (!req_head) req_tail = req_head;

  addr = p->addr;
  bytes = p->bytes;
  n = p->n;
  memset(p, 0, sizeof(struct serjtag_request));
  p->next = req_pool;
  req_pool = p;

  serjtag_recv_j(pgm, buf, bytes + 3, 0);
  for (j=0; j<n; j++) {
     m->buf[addr++] = buf[3 + 4*j + 3];
  }
  return 1;
}
受信のリクエストを出したら、put_request() を使って、受信処理(のパラメータ)を登録(キューイング)する。で、do_request() は、キューから1つ取り出して、受信処理を行う。 put_request()を出したその後ですぐ do_request()を call するならば、普通の処理と変わらない。コードで書くならこう。
   for (i=0; i< LOOP_COUNT; i++) {
            :
       put_request(...);
       do_request(...);
   }
そこから、最初の N 回は、put_request()を出しておくが、do_request() を call しないようにする。そして、最後に do_request() が 1 を返す間 call してキューイングされた分を刈り取る。
   for (i=0; i< LOOP_COUNT; i++) {
            :
       put_request(...);
       if (i >= N) do_request(...);
   }
   while (do_request(...))
        ;
こうするわけだ。これで送信と受信が N ずれる。 N を 0 から増やしていくと .. ベリファイ時間は次のようになった。
   N
       0    4.66 秒
       1    2.79 秒
       2    1.93 秒
       3    1.50 秒
       4    1.22 秒
       5
       6    0.94 秒
       7    0.87 秒
       8    0.48 秒
       9    0.28 秒
      10    0.27 秒
      11
      12    0.27 秒
      13
      14    0.27 秒
こうすることで、4.66 秒が、最終的に、0.27 秒まで高速化できたのだ。1バイト書くのに 32bit の送信と受信をしている。JTAG 的には 片側 480 Kbps (帯域的には、960kbps) が出ていることになる。FT245R の BitBangMode の想定性能の 2 倍ぐらい?(8Mbps / 16 / 2 = 250 Kbps ) が実効性能として出ているし、目標とした性能(500kbps 〜 1Mbps) のレンジにかなり近い。性能的には満足だ。
ちなみに 480kbps 出たとして、玄箱の FLASH を書き換えるとすればどうなるか ... 480000 / (507 * 3) = 315 (byte/sec) 。... 64KB 書き換えるのに 209 秒 、 4MB なら 3.7 時間。 JTAG Cable としても、使える範囲に入ってきていると思う。
ベリファイはこれだけ速くなるが、書き込みの高速化は難しい。1ページ書き込み毎に delay を保証しないといけない。write を直接出すのではなく、バッファリングすることで、1.72 秒が、1.28 秒にまで短縮したが、それ以上は無理そうだ。 なお、これらのテストは、Linux (2.4.31) で行った。avrdude のパラメータは、
avrdude -pt44 -c serjtag -P /dev/ttyUSB0 -b 3000000 \ 
        -B 4000000 -U flash:w:usb910j44.hex 
としている。-b は、ボーレートの指定。あまり関係なさそうだが、avrdude も改造して、できるだけ大きくした。-B は、SCK のクロック値。4Mhz 以上に設定すると、(プロトコル上) 一切の遅延をしないようになる。(といっても、テストのために、serjtag のプログラム側で nop() などで遅延して、2MHz 以上にしないようにしている。serjtag は USI を使っていて、本当は 4Mhz。)ちなみに、-B を指定しないと、250 kHz 以下になり、8Mhz RC クロックの 1/8 の設定でも問題ないようにしている。
ちなみに、usb910j44.hex は、USB910版。ATtiny44 の typeB の回路ベース。FLASH が足りないので、 AVR910 プロトコルは サポートしていない。すでに USB910 と言えないが、それはさておき、USB910版は、書き込み 7.00 秒・ベリファイ 7.19 秒だった。詳しくは次回に書く予定。
以上のプログラムは、serjtag-0.2.tar.gzに置いた。avrdude-5.3.1 へのパッチも同梱している。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: USB910の拡張と Windows でのテスト STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: SERJTAG DATE: 06/19/2007 20:31:23 ----- BODY: FT245R 版 SERJTAG は、もともと USB910 のプロトコル拡張をして、それを移植したものだ。FT245R でだいたいの評価ができたので、USB910 へコードをフィードバックして、評価をしてみることにする。 ちなみに、TypeA はプログラム領域が余っていたのでプロトコルの追加で問題ないのだが、TypeB は、AVR910 プロトコルの部分を削らないと入らない...それはすでに USB910 とはいい難いのだが、typeJ44 として作ることにした。この、AVR910 プロトコルを削ってしまったものは、'S' コマンドが返すソフトウェア名を USB910B ではなく SERJTAG に変更した。 Linux での性能評価 同じバイナリ(usb910j44.hex) 4072 バイトの書き込みにどれぐらい時間がかかるか、評価を兼ねて調べてみた。
                          書き込み   ベリファイ  実効性能(bps) 
   FT245R 版 (SERJTAG)     1.27 秒     0.27 秒     482607
   USB910A AVR910     3.99 秒     1.41 秒      
   USB910A SERJTAG         7.00 秒     6.39 秒      20391
注)実効性能 は、バイト数 x 4 バイト/ベリファイ時間
これを見ると、SERJTAG が全然遅い。AVR910 での書き込みでは、2 バイトの送信 + 1 バイトの受信なのだが、SERJTAG では、4 バイトの送信になる。 また、ベリファイでは、AVR910 は、1バイトの送信と 2バイトの受信で 2 バイト読める。それに対して SERJTAG は 1バイトを読むのに、4 バイトの送信と 4バイトの受信が必要。転送性能が限界の場合 4 倍ぐらい遅くとも妥当ではある。 Windows での性能評価 Windows でも同じような傾向なのだろうか? FT245R 版 SERJTAG と一緒に Windows で評価してみることにする。 準備1: ドライバのインストール FT245R 版を動かすにはドライバが必要。VCPドライバをダウンロードして展開しておく、ハードウェアウイザードが出たら、展開したディレクトリを指定してインストールする。 準備2:avrdude のビルド avrdude もビルドする。前に 高速化 USB910 版を作ったが、それに SERJTAG のパッチを当ててビルドした。 さて準備はできた。同じ 4072 バイトのバイナリを書き込んでみる。
                          書き込み   ベリファイ  実効性能(bps)
   FT245R 版 (SERJTAG)     1.03 秒     0.73 秒      178498
   USB910A AVR910     4.72 秒     1.66 秒
   USB910A SERJTAG         2.66 秒     3.55 秒       36705
AVR910 は、Linux より遅くなったが、SERJTAG は速くなった。特にWrite は速く Linux AVR910 より速い。Windows では、転送性能には余裕があり、遅延が性能ネックだったことを示している。 FT245R 版については、書き込みが若干速くなったものの、ベリファイは 2 倍以上遅い結果になった。AVR のプログラマとしては問題ないぐらい速いが、JTAG Cable としては、速ければ速いほど良く Linux より 2 倍も遅いのは問題だ。 送信と受信が ずれ N の値は 10 にしているが、これをさらに大きくすればどうなるか調べてみた。
   N
      10    0.73 秒
      20    0.50 秒
      30    0.47 秒
      40    0.41 秒
      50    
      60    0.38 秒
      70    0.31 秒
      80    動作せず
10 から 70 まで増やせて、性能がゆるやかに上がっていく結果になった。しかし、0.27 秒に肉薄するほどの性能にはならない。 ドライバの設定をみてみることにする。デバイスマネージャからドライバのプロパティを開き、Port Settings の Advanced を開いて見ると ... Read/Write のバッファサイズは 4096 バイトで、Latancy Timer は 16ms だった。ちなみに N = 80 で動作しないのは、受信バッファが FULL になったためだろう。 Latancy Timer を 5ms にしてみる Windows で遅いのは、遅延が原因なので、16 ms を 5ms にしたらどうなるか見てみた。 まず、書き込み時間が 1.03 秒 から 0.5 秒まで高速化した。
   N
      10    0.73 秒   0.44 秒
      20    0.50 秒   0.36 秒
      30    0.47 秒   0.34 秒
      40    0.41 秒   0.34 秒
ベリファイ時間も短くなる。Timer を 5ms にするのは有効だ。ただし、N=30 程度で頭打ちになっていてこれ以上性能は上がらなさそうだ。 どうも遅延を短くすると、スループットが落ちる。良いところ取りはできないらしい。一般的にいってもそうだが、USB でもまたそうであった。 ソースコード 最新版 usb910-0.6.tar.gz  と usb910-0.6.zip  あと更新した serjtag-0.2.tar.gz と serjtag-0.2.zip 今回から、avrdudeのパッチと Windows 版 avrdude バイナリを同梱することにした。serjtag にも同じものを同梱する。 USB910-0.6 での変更点
  o typeA SERJTAG プロトコルの追加
  o typeJ44 サポート 
     (typeB ハードの AVR910⇔SERJTAG 入れ替え版)
  o AVR-CDC のバージョンダウン 
     0.5 でバージョンアップしたが、不具合が出たので、
     バージョンダウンして、パッチを notyet/verup.patch に
   置くことにした。
  o (AVR910) 初期化での SCK クロック自動変更をやめた。
     初期化で SCK クロックを変更してたまたま動いても、
     意味がないことがわかったのでクロックを妥当な値で固定。
       222 kHz で 8M RC x 1/8 向け。(それ以下は危険。)
  o avrdude-5.3.1 へのパッチの同梱(Windows 版バイナリも)
おわりに FT245R 版 SERJTAG は、なかなか高速で良いものができたと思う。このプロトコル用に JTAG のソフトウェアをそろえていきたい。 まずは、DWM付録用を xilprg でなんとかして、あと玄箱の FLASH 書き換え用もなんとかしたい。ちなみに 玄箱用の JTAG ソフトであれば、OpenWinCE のJTAGツール を改造したものが実績がある。→ FLASH 書き換え成功 (MOTOUJTAG未使用)。以前FLASH を書き換えたときは、この記事を見て、某所から CVS 版を落として... 自作のシリアルJTAG変換ケーブルに対応させて... とやったのだが、ひょっとしたら今はもっといいものがあるかも知れない。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: FT245R/FT232R で avrdude STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 06/21/2007 00:55:25 ----- BODY: avrdude で FT245R/FT232R をサポートしてしまった。 鶏と卵 で書いたように、最初 の AVR ライタ をどうするかという問題があって、それは、パラレルポートを持ってさえいれば簡単に解決する。ただ今後レガシーインターフェイスがない PC も増えてくるだろうし、なにか良い方法はないかと日ごろ思っていた。SERJTAGは、FT245RL USBパラレル変換モジュール+ATtiny2313 を使った自作の高速な JTAG インターフェイスだが、作っているうちに、FT245R/FT232R BitBang 版 avrdude を作れるだけの知識が付いてしまった。鶏と卵 問題の解決にもなるし、BitBang と SERJTAG の性能比較もできるし ... ということで作ってみることにしてしまった。
BitBangMode の使い方は秘密にされていて、オープンソースになっていない。実をいうと、FTDI が供給するバイナリを使わないと使えないのが気に入らないので、積極的にサポートしたくはないのだ。..でもレガシーレスのPCで本当になにも手段がないときに使えるものは、コレぐらいしかないのだ。 追記:つれづれ日記からコメントをもらった。自分は AVR ライタをいくつも持っているのに、最初 の AVR ライタ を気にするのは、より多くの人に AVR での電子工作の世界に入ってきてほしいためだ。ローコストでAVRライタが手に入れば敷居が下がる。その結果、人が増えれば、自分の記事の有用性が増す。
ものは、serjtag-0.3.tar.gz と serjtag-0.3.zip。 SERJTAG に同梱した。対応したバイナリも同梱している。(USB910 は次のバージョンで同梱する予定) この avrdude.exe を使えば、 FT245RL USBパラレル変換モジュールを用意するだけで、AVR へ書き込みができるようになる。ブレッドボードがあるなら、電源も AVR を書き込む程度 (30mA ?) ぐらいなら供給できるし、本当に他になにもいらない。 ちゃんとしたISP ケーブルを作るとしても、カモン USB-05を切って使えば簡単につくれる。前にも書いたと思うが、サポートしているのは、FT245R/FT232R (と FT2232) だけである。FT245BM(AM)/FT232BM(AM) は、Synchronus BitBangMode をサポートしていないので使えない。FTDI ならなんでも良いわけではないので注意。 ちなみに、ピン配置は次のようにした。
                 chip pin#   BitBang bit
                              ( = FT245R D#)
   MISO   RxD       5        1
   SCK    RTS       3        0
   MOSI   TxD       1        2
   RESET  DTR       2        4
これは、avrdude.conf で定義しているので、ft245r の記述を参考に変更すれば、他のピン配置にも対応できる。 秋月のもの以外では、ストロベリーリナックスの FT232RL USB→シリアル変換モジュールキット、wS☆Nakの#121A USB DIPアダプタ (FT232RL)などが良さそうだ。電子工作では、mini-B コネクタより、B コネクタの方が電流が流せて良い場合もある。秋月のは、ピン・プラグが最初から付いていて、ケーブルにするには、それがかえって使いにくい。アイテムラボのピッチ変換基板SOP28-P65(2)を使って作るのも良いだろう。FT245RL/FT232RL はほとんど外付け部品がいらない。必要なのは、パスコンぐらいで、それは変換基板に付けられる。 使い方は、-c オプション プログラマ名 に ft245r を指定し、-P オプション ポート名 に ft0 を指定する。あと -B ビットクロック オプションも対応していて、500 kHz 程度まで指定できる。(ただし 指定した周波数以下にするだけの意味 ) さて、例によって 4072 バイトのバイナリの書き込み/ベリファイ性能を見てみる。
                    書き込み  ベリファイ  実効性能 (bps)
FT245R Synchronous BitBang
       -B   4800      28.75 秒  27.50 秒      4738
       -B   9600      14.86 秒  13.69 秒      9518
       -B  19200       8.06 秒   7.00 秒     18614
       -B  28800       5.67 秒   4.61 秒     28265
       -B  38400       4.50 秒   3.47 秒     37551
       -B 115200       2.36 秒   1.34 秒     97241
       -B 230400       2.06 秒   1.08 秒    120651
       -B 460800       1.63 秒   0.64 秒    203600

SERJTAG(FT245R 版)
  - Linux              1.27 秒   0.27 秒    482607
  - Windows            0.50 秒   0.44 秒    296145

注1)実効性能 は、バイト数 x 4 バイト/ベリファイ時間
注2)FT245R ドライバは、遅延タイマを 16ms から 5ms に設定変更
AVR ライタとしては、かなりの性能だと思う。だがしかし、SERJTAG はそれ以上の性能にできた。これでこそ作った意味があるというものだ。それはともかく、AVR ライタを持っていない人は、これを機会にぜひ AVR で遊んでみてほしい。プログラマをすでに持っている人もエマージェンシー用に使えるし、ひとつ持っていると良いかもしれない。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- COMMENT: AUTHOR: senshu EMAIL: senshu@astro.yamagata-cit.ac.jp IP: 202.35.250.132 URL: http://www-ice.yamagata-cit.ac.jp/ken/senshu/sitedev/ DATE: 07/04/2007 09:21:15 SERJTAGは非常に興味深い取り組みだと思います。 最近は秋月電子でもFT245をモジュールにしたものが購入できます(使ってみました)。 これでAVRライタも良いのですが、更に安価に製作できるものを企画中です。 興味があれば、以下のURLを参照ください。 (書き込み済のAVRと専用基板を安価(予定では部品一式で1,000円未満を予定)に提供する方法でAVRユーザをふやそうという試みです。果たして功を奏するでしょうか、、。) http://www-ice.yamagata-cit.ac.jp/ken/senshu/sitedev/index.php?memo%2FAVRSP ----- COMMENT: AUTHOR: すz EMAIL: IP: 210.143.35.14 URL: DATE: 07/04/2007 10:41:12 ChaNさんの、COM-SPI ブリッジのAVRライタですね。USBシリアルケーブルを通しても遅くならないのでレガシーレスのPCでも使えます。書き込み済のAVRも提供されるのであれば、最初のライタとしてもお勧めだと思います。 ----- COMMENT: AUTHOR: senshu EMAIL: senshu@astro.yamagata-cit.ac.jp IP: 202.35.250.132 URL: http://www-ice.yamagata-cit.ac.jp/ken/senshu/sitedev/ DATE: 07/11/2007 14:18:31 先日紹介したAVR関係の基板の発売が確定しました。 http://www.wsnak.com/kit/new.php AVRライタだけでなく、mega168やATtiny2313などの基板も安価に購入できます。 何とかAVRの普及につながればと考えています。 ----- COMMENT: AUTHOR: ☜신청하시면 보내드립니다 EMAIL: sorry2@live.co.krr IP: 61.152.144.32 URL: DATE: 02/26/2008 06:10:09
이미지를 클릭하시면 신청하실수 있습니다.

(왼쪽:공인중개사 오른쪽:주택관리사)




게시물 수신거부

@수신거부 이메일 sorry2@live.co.krA광고성 정보에 대하여 삭제 1234

도메인 주소를 꼭 적어주셔야 수신거부 처리됩니다!
----- -------- AUTHOR: すz TITLE: オリジナル基板の検討 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 06/22/2007 13:03:51 ----- BODY: つれづれ日記で知ったのだが、国内では、基板PROというところが安いらしい。 いったいどういう風にすれば有効に使えるか検討してみた。 対象とするものは、タカチ SW-55(55x40x20) or テイシン TB-55B(80x50x20) に入る基板。
   枚数                1        6        12        30

 33 x 47             22,438円 23,245円 28,675円  45,471円
(タカチ SW-55 用)

 45 x 75             23,226円 24,061円 29,682円  47,067円
(テイシン TB-55B用) 
どうも 6 枚までなら、あまり値段が変わらないようだ。それにしても 1 種類の基板に 趣味で 24000 円も出すのはちょっと高い。 ルータ切り出し(面付け)というのを考えてみる。これは1枚の基板をきってくれるオプション。それぞれの基板が同じものである必要がなく、5 種類 までの基板を一度に作れる。
ルータ切り出し(5面付け)
   枚数                  1(5)        6(30)      

 (33x5+4) x 47         30,051円     30,943円
(タカチ SW-55 用)
 (45x5+4) x 75         35,721円     36,817円
(テイシン TB-55B用) 
ちょっと値段があがるが、5 種 6 枚つづ作れるならこの値段でもいいかなという気がしてくる。 格安なOlimexという選択枝もないわけではない。なにしろ 160mmx100mm(320mmx200mm)で $33($132) + shipping $9 (airmail) 、しかも面付けは無料。
   
                     DSS(160x100)   DSQ(320x200)  
  (33+1) x 47             8 枚        36 枚
(タカチ SW-55 用)
  (45+1) x 75             4 枚        16 枚
(テイシン TB-55B用) 
ただ、仕上がりが雑でも良く、気長に待てる必要がある。あとクレジットカードを持っていて海外FAXできる必要もある(決してクレジットカードのIDをメールしてはいけない)。また、枚数が増えるにしたがい値段的なメリットもなくなってくる。
ファックスを持っていなくても、海外ファックスは、ローソンのファックスか、クロネコ@ファックスを使えばよいらしい。
せっかくオリジナル基板を作るなら、仕上げのきれいな 国内で頼みたいところ。問題は、5 種類もつくるべきものがあるか... というところか。
追記: EzPCB というところもあるらしい。場所は中国。 詳しくは、EzPCBへの基板発注を参照。
オリジナル基板検討つづき オリジナル基板を5種類作るなら、まず USB910A を作りたい。次に、単体で USBNIX を動かせるものとして、USB910B に I2CROM ソケットを追加したもの。そして、高電圧チップイレーサー(HCERASER) で とりあえず 3種 決まった。 幅というか、Y (高さ)は 47mm に統一して 1/2 C 基板をベースにする。HCERASER は、C 基板サイズになりそうだ。 あと2つはまだ決めていない。幅は 300 mm までなので、C 基板サイズ x 2 でも OK 。複数あっても困らない実用的なもの か 配線が複雑になってしまって手作りが面倒なもの が良い。前者だと いまだ影も形もない 作ってみようと思っている装置その(3) I2C 高機能電源 か。あと、Sim's blog サイキット小液晶... で知った 8x2キャラクタ液晶を使ったなにかの装置というのも良いかも知れない。このサイズなら 基板のサイズと折り合いが付きそうだ。(ちなみに、この液晶 デジキーでも扱っている(/た?) DMC-50448N の互換品のようだ。)。グラフィック液晶も心ひかれるものがあるが、別の機会に考えることにする。 ちなみに、I2C 高機能電源はかなり前から作りたかったもの。Nch+Pch 8-SOIC タイプのパワーMOS FETを使う。Pch だけ使って降圧型にしても良いし、Nch だけ使って、逆方向の昇圧ができるようにもしたい。目的はバッテリーへの充電とバッテリーからの昇圧。それ以外に電圧・定電流電源にもなってI2Cで設定や監視ができる。逆方向の昇圧が必要なければ、Pch+Pch の FDS4935とかを使っても良い。 ATtiny26Lでも、I2C スレーブと OC1A/OC1B は両立するし、OC1A 側を切り離せれば ISP にも対応できる。ただし、Pch と Nchを同時に動かすのは難しい。...とまぁこんなことを考えてチップは購入済みなのだ。ただ、8-SOIC タイプのパワーMOS FETは、(電流を流せるようにするには)手配線では厳しい。あと、パーツを変えていろいろ実験してみたいこともあって基板を作るなら是非入れたいのだ。
追記: 詳しくは、新しいカテゴリを作って I2CPWR:はじめにに書いた。
どうせ作るなら、USB 関係は、ミニ B と 標準 B コネクタを選択可能にしたい。ミニ B は、モレックスの 54819-0578 /54819-572 が入手可能。(RSオンライン / デジキー ) 追記: 実は、AVR 関係でなければ作ってみたい基板はある。AT91SAM7Sシリーズ(AT91SAM7S64 〜 AT91SAM7S512) と CPLD CoolRunner 2 (VQFP44(0.8mmピッチ) の XC2C32A/XC2C64A) を組み合わせたもの。AT91SAM7S はシリアルのDMA を持っていて、これを CPLD でインターフェイスして他の装置につなげられるようにする。 たとえばグラフィック液晶(たとえばコレ:(参考)なる研)につなげれば、(CPU を使わない)フレームバッファになりそうだ。特に AT91SAM7S512は RAM を 128KB も持っていて 16bpp 400x96 ならいける。CoolRunner 2 は、1.8V 電源だが、AT91SAM7S から供給できる。その他にも面白いものが作れそうな気がしていて、基板を作るついでに作ってみたい気がする。ただ、これは AVR ではない。AVR のネタがなくなるまで手を付けないかも知れない。
(ちなみにその1)XC2C32A/XC2C64A はデジキーで扱っていて結構安い(162円/317円) 。単独で使うなら 1.8V のレギュレータが必要で NCP553 が結構安いようだ。ただ小さいので、NCP585の方がいいかも。 (ちなみにその2)AT91SAM7SをUSBからブートするには、水晶が 18.432 Mhz である必要がある。AT91SAM7S をデジキーで買うならついでに買うのが良い。
----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: 高電圧チップイレーサー STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: HCERASER DATE: 06/25/2007 20:19:59 ----- BODY: 前に チップ初期化器のアイディアという記事を書いた。 これを実際に作ってみることにした。 作ろうと思ったのは、オリジナル基板の検討をしていて、作るならこれも入れたいと思ったから。AVR をはじめたばかり だと ヒューズビットを間違えて設定してしまうことはありがちだ。これがあれば、シリアルプログラミングできなくなったチップを救える。おかしくなったチップが 4 つも 溜ったのも理由のひとつだったりする。 回路図↓。 12V 電源は、LAL02NA470K(max 70mA / 5.8 Ω ) を使った DC-DC コンバータで作る。250KHz Duty 50% で スイッチングして、TL431で 12 V に制限する。スイッチングには、デジタルトランジスタのDTC143TSA を使ってみた。出力コントロールにも、DTA143TSA/DTC143TSA を使ってみている。
DTA143TSA/DTC143TSA は、パーツフォレストで 50個250円で入手した。2SC1815GR / 2SA1015GR でも抵抗さえ入れれば問題ないはず。
この DC-DC コンバータは、5V → 12V に合うように設計してある。LAL02NA470K 以外のものをコイルに使うのは勧められない。ちなみに 3.3V だと 10V 前後の出力になってしまう。ただ、AVR によってはこれでも書き込めるようだ。 コントローラは、格安の ATtiny2313 を使う。パラレルプログラミングするには、信号線が少ないのだが、高電圧シリアルプログラミングもサポートした上で、インジケータも付けることができた。書き込み中は 赤。初期化成功は 緑。失敗した場合 赤が点滅する。ただし、シグネチャーが読めるが対応していないチップの場合は、対応した FW を作れば 初期化できるかも知れないので、 緑を点滅させて区別できるようにしている。 初期化スタートのボタンは付けられなかった。電源を入れて 3 秒後に自動でスタートする。 すごく簡単そうだが、書き込む AVR への配線は別。配線は↓の信号線を全部つなげる。必要なチップ用だけ配線しても良い。(写真の配線をみればわかるように、実際 ATtiny2313 系と ATmega88 系は接続していなかったりする。) これだけの配線をするのはとても面倒だし、手配線だと 知らない間に壊れてしまうかも知れない。オリジナル基板を作るなら是非これも入れたい理由。 とりあえず作ったプログラムは、hceraser-0.1tar.gz 今のところ配線は、ATtiny44 系 / ATtiny45 系 , ATtiny461 系のみにしてテストしている。動作が不安定で完成には遠い。 おかしくなった、ATtiny44 2 つのうち 1 つは救えた。もうひとつはダメ。ATtiny861 は 2 つあるが、2 つとも救えない。ただし、正常な ATtiny26L は OK だったので、全然ダメというわけもないらしい。 あと 回路図も不安な点がある。ATmega88 系では、XA1/BS2 が XA1 と BS2 に分かれている。両方に XA1/BS2 を入れているがそれで良いのか未確認。ちなみに、PAGEL も独立しているが、FLASH に書き込むわけではないので、こちらは 常に L で良い(はず)。 追記: だめだった ATtiny44 と ATtiny861 x 2 がなんとか復旧できた。ただし、数回に1回しか成功せず、何回も電源On/Off を繰り返した。 最新のプログラムは、hceraser-0.2.tar.gz。(回路図も変更したので注意) 失敗するときは、ほぼ100% パラレルプログラミングモードに入れずシグネチャーが読めない。ATtiny2313 の PORT 出力 を ターゲットのVCC にしていたが、それがマズいのではないかということで、PNP トランジスタのスイッチを入れ、出力にコンデンサをつなぐことにした。これで、(絶対壊れていると思っていた) ATtiny44 をつないだら 緑のLED が点灯した!。ATtiny861 も OK だった。VCC の立ち上がりが問題だったのだろう。 数回に1回しか成功しないのは、別の問題もあるかも知れないが、たぶん電源投入のタイミングだろう。何回かやって成功するのであれば、プログラムでうまくリトライすれば面倒が減るので、次は対応しようと思う。 実は、失敗した理由には他に2つの問題があった。1つは、知らない間に配線がはずれていたこと。疑心暗鬼になりながらテストするのはなかなかつらかった。もうひとつは、ISP ケーブルをつないだままテストしていたこと。HSV だと ISP ケーブルと干渉しないように設計したので問題ないのだが、パラレルプログラミングだと、干渉する。Tiny26L は、出力が強い(?)のか ISP ケーブルがあっても書き込みできてしまう(場合が多かった)ので安心してしまった。 オリジナル基板検討つづき オリジナル基板を5種類作るなら、まず USB910A を作りたい。次に、単体で USBNIX を動かせるものとして、USB910B に I2CROM ソケットを追加したもの。そして、これ(HCERASER) で 3種 決まった。 幅というか、Y (高さ)は 47mm に統一して 1/2 C 基板をベースにする。これ(HCERASER) は、C 基板サイズになりそうだ。 あと2つはまだ決めていない。幅は 300 mm までなので、C 基板サイズ x 2 でも OK 。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- COMMENT: AUTHOR: victories EMAIL: IP: 220.40.176.30 URL: DATE: 03/19/2008 16:06:06 はじめまして。有用なものを公開してくださってありがとうございます。どうしてもmega8を救いたかったので作ってみました。 新品のmega88を使って試したのですが、BS2をXA1に接続するとプログラミングモードに入れていないような挙動でした。試しにXA0に接続するとアクセスできるようになりました。mega8のBS2をXA0に接続しプログラムを書き換えてmega8系の時だけBS2=XA0としてアクセスすると、手持ちのmega88/mega8/tiny2313の全てで動作を確認出来ました。書き換えに失敗する事もありません。 最初はtiny2313でも成功しなかったのですが、どうもRESET電圧がかなり低かったようで、Tr1を低ON抵抗のMOSFETに変更してPWMを60% DUTYで動かすと正常に動くようになりました。「数回に一回しか成功しない」というのはもしかしたらこの辺に原因があるのかもしれませんね。 ちなみに、救いたかったmega8は壊れていたようで、どうにもならないので一度もプログラムを書き込まれることなくゴミ箱へ行きました… ----- -------- AUTHOR: すz TITLE: I2CPWR:はじめに STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: I2CPWR DATE: 06/27/2007 20:23:36 ----- BODY: 作ってみようと思っている装置の記事で
(3)I2C 高機能電源 PWM で降圧型DC/DC コンバータを作り、定電圧と定電流の機能を持たせてホストから機能設定とか電圧/電流をモニタできるようにする。できれば、NiMHの充電器として使えるようにしたいし、逆に充電したNiMHから昇圧できる機能もつけたい。コイルは共用できるはずでスイッチには Pch+NchのMOS FET を使う。AVR は 手持ちのATtiny26L..でできるとうれしい。なにを選択するにせよ、昇圧時は、自己消費が大きいとあまりうれしくないので、そのあたり工夫してみたい。
と書いた。いますぐ作るつもりはないのだが、基板を起こしたときのために、回路だけは考えておこうと思う。 なぜこういうものを作りたいかというと、電源系が電子工作で作品を作るうえでのひとつのネックだと思えるからだ。携帯できるものを考えたとき、電源専用 IC を使えば比較的簡単に解決できるのかも知れない。ただ、たぶん(作った時点でも)入手性が悪い。時間が立てばさらに入手性が悪くなる。もし、AVR で電源系を自由にできれば、長期間有用だ。なにより、電源用 IC を入手するために苦労しなくて良い。そういう理由で 電源制御をライブラリとして持ちたいと考えていた。
たとえば、かつて 現品.com で MAX722を 3 個100円と格安で入手したのだが、Digi-key ではすごく高い(しかも 最低 50個単位)。 そういうものを電子工作の作品で使うと、だれも作ろうとは思わないだろう。だから、適当な試作ならともかく、作品では使えないことになる。
USB910Aのカテゴリで、AVR の ADC の特性だの 消費電流だのを調べたり、小さなDC-DC コンバータの実験をしていたが、実は、電源制御をライブラリとして持つための予備調査だったりする。作ってみようと思っている装置のなかで、これだけ作れていないが、実は一番思い入れがあるのだ。 どんな回路を考えているか
いわゆる のハーフブリッジの回路を考えてみる。 PWM1 だけ動作させた場合は、IN → OUT の降圧型 DC-DC コンバータだ。
PWM2 だけ動作させた場合は、OUT → IN の昇圧型 DC-DC コンバータになる。
この基本的な回路をベースに、制御の方法を変えて多目的に使おうというわけだ。 どんな部品を考えているか パワーMOS FET は、8-SOIC で Pch と Nch が入っている製品がある。私が持っているのは、HAT3006R と FDS8958A。どちらもかつて現品.com で購入したものだ。ラジコン四駆とかサーボモータ(の改造)でよく使われている/た ものなので、型番を知っている人も多いかも知れない。もし 昇圧・降圧のどちらかしか使わないのであれば、入手性の良い Pch+Pch型のFDS4935とか Nch+Nch型のNDS9936μPA2753GRを使っても良い。間違って On しないように使わないほうはパターンカットできると良いかも知れない。 ただし、使わないほうの Source をチップ側でカットする必要がある。(ダイオードがあるのを忘れていた) 小電流しか流さず、効率が落ちて良い場合は、パワーMOS FET 内の ダイオードを流用できる。大電流を流したり、効率を良くしたい場合は、ショットキーバリアダイオードを外付けする。 ショットキーバリアダイオードは、RB051L-40 を入手している。3A 流せて VF がかなり低い。これも かつて現品.com で購入したもの。1A でよければ、秋月の RB160L-40が良さそうだ。 コイルは22uH 〜 47uH を考えているのだが、最近入手性が良くなった。秋月では、TSL0709S 22 uH(max 1.3A) が 4 個 100円だし、千石でも LHLC10NB 22uH(max 2.8A) が 1個 84 円で買える。このあたりをターゲットにしたい。そういえば、LHLZ06NB 22uHは、max 1.2A だ。こんなに小さくて大丈夫なのか不安だが、秋月のと同程度に使えるかも知れない。 電流測定用の抵抗も、現品.com で入手済みだったりする。チップ抵抗の 0.1 Ω(MCR25)、0.3 Ω(MCR100)、0.82 Ω(MCR100)。0.1 Ωだけ 1/4W だが、これでも 2.5A 測定できる。大電流の場合は、これを使う予定だが、秋月で扱っている40mΩチップ抵抗も考慮しておきたい。 大電流がながれるところは、表面実装の部品ばかりだが、表面実装の部品が性能的に良いと思うし、第一それしか入手性がよくない。 例外はコイルだが、表面実装なら高さを低く作れる。実は、コイルも 6.6mm 角 3.2mm 高の ミツミ C6-K3L 22uH (max 1.1A) (pdf)を入手済み。これまた 現品.com で、今どこで入手できるかわからない。LHLZ06NB 22uHが使えるなら別に使う必要はないのだが、こういうのが使えるようパターンを工夫しようと思う。 ちなみに 千石ではスミダの表面実装コイルを(高いものの)扱っている。この中で、CDR104R (pdf)ぐらいは対応できたほうが良いかも知れない。 制御する AVR は、250k Hz の PWM を持っている ATtiny461 系 を前提にする。基板を作るとき DIP じゃなくて SOIC にするかも知れない。機能を落とせば ATtiny45 系でも使えるはずだ。あと できれば ATtiny26L でも使えるものにしておきたい。 内蔵基準電源は、あてにならないことがわかったので TL431を使う。 どんな機能を考えているか I2C デバイスとして機能するようにするのが前提で、その機能さえあれば、ソフト次第で、ホストから機能を設定したり、ログを取ったり自由にできる。いまはこの機能については検討しない。 入力側 電圧 ... これは 5V を想定する。ただ 12V を入力したいときもあるかも知れないので、AVR にレギュレータを付けられるようにしておくと良いかも知れない。 出力側 電圧 ... 0V 〜 5V の範囲のみにする。 降圧型 DC-DC 出力電流 ... これはコイルに依存する。3A 以上のものは入手性が悪いので、3A 以内だけ考えておく。 降圧型 DC-DC 制御機能 ... 定電流や定電圧 制御はあたりまえとして、1〜3 セル バッテリー充電も範囲に入れる。できたらモータ制御も考慮したい。 昇圧型 DC-DC 制御機能 ... バッテリーからの昇圧だけ考える。1 セルは無理そうなので、2〜3 セル がターゲット。 基本制御のための 入出力 PWM1 と PWM2 は、OC1A , OC1B を使う。PWM1 は 出力側が無接続なら安全なので、ISP と兼用の OC1A 。PWM2 は専用の OC0B。 入力と出力電圧測定用にまず ADC を 2 つ。基準電圧は 2.5V なので、分圧する。 次に 出力電流測定用に 差動入力の ADC を 1ペア(2つ)。昇圧時は逆に電流が流れることになる。ATtiny461系なら +/- を逆にできるし、符号付きの機能もあるので問題ない。ただし、ATtiny26L だと 3pin 必要なので、それを考慮するかも知れない。 これらの値を測定して、PWM の制御にフィードバックをかければ、DC-DC コンバータの機能は作れるはずだ。 電流モード制御のための 入出力 同期整流ははなからあきらめているのだが、オプションとして、電流モード制御ができるように考えておきたい。 電流モード制御とは、コイルに流れる電流も測定して制御に組み込むもので、普通は敷居値を超えたら (その瞬間に)PWM を OFF にするとかになる。ADC では追いつかないから、コンパレータを使って割り込みを起こす。250 kHz で毎回割り込みを起こしていたらたいへん(というか無理)なので、敷居値超えの割り込みで回数だけ記録しておいて、パラメータを調整して起きないようにしていくとかそういう制御になるだろう。 昇圧型 DC-DC では、FET と GND の間に抵抗をいれて、その電圧と敷居値の電圧を コンパレータに入力する。この電圧は TL431 の基準電圧から分圧して作っても良いのだが、調整が面倒だ。ATtiny461系なら、もうひとつ PWM が使えるので、PWM で敷居値用の電圧を作ったらどうか。LPF の カットオフ周波数をおもいっきり低くして、ときどき ADC で実際の電圧を測定すれば問題ないはずだ。ちなみに ATtiny461系では、コンパレータとADCを共用できる。 回路図案 というようなことを考えて整理すると次のような感じになる。
このピンを ATtiny26L も考慮して、どうわりあてるか決めていけば、基板は起こせるはず。 追記: (1)できるだけ、無駄な電流を消費しないようにしておきたい。そういうことを考えると TL431 の電源は、VCC 直結ではなく、PORT にすべきだと思う。忘れそうなのでメモ。 (2)上の回路だと、バッテリー駆動時 OUT の電圧がそのまま IN に出てきてしまう。そのため、出力制御の PNP Tr か Pch パワー MOS FET がもうひとつ必要になる。これも忘れそうなので、メモ。ただのスイッチでスイッチング特性とか関係ない。SC-59 の PNP Tr 2SA1313(max 500mA) とか、Pch パワー MOS FET 2SJ557(max 2.5A) とか選択できるようにしておけばよいだろう。(他にも PMV65XP(max 3.9A) とか IRLML6402PbF(max 3.7A) とか良いものは何種類もある)あと、スイッチを IN の外側に付けるとして、スイッチのさらに外に電圧センスがほしくなりそうだ。電源が供給されていれば、On にすべきだし、されていなければ昇圧した電圧が上がってきてはじめて On にすべきだ。 (3)上の回路には、コントローラのVCC をどこから取るか書いていない。IN の電圧(スイッチの外、5V 以上ならレギュレータを通した後) と OUT の電圧の高いほう? そうすると、昇圧時 スイッチをOn するまで高い電圧にならない。それは困るので、スイッチの外、内 の電圧の高いほうを レギュレータに通して それと OUT の電圧の高いほうにしないといけない。 追記:回路図案2 上に書いたことを再度整理して、ピンを割り当ててみた。ATtiny461のピンを全部割り当てることになった。そのままだと、ATtiny26L で IN→OUT の電流測定ができなくなるので、3 つめのPWM で作るAIN(-) 電圧 と、ADC2 (ADC1-ADC2 差動用) を共用することにした。3 つ目の PWM はそもそも ATtiny26L はもっていないから、問題ない。 あと、12V 入力はパス。回路図書いていて面倒になってしまった。 IN のスイッチの回路は、FET が書いてあるが トランジスタ用。FET を使う場合は、ダイオードを省略できる。
追記2:パワーMOS FET の選択について Pch+Nch の 8-SOIC タイプのパワーMOS FET を使おうと思った理由は、ずいぶん前に 現品.com で安く入手できたからだ。1種類だけ買っておけば、ハーフブリッジとして使う以外にも Pch にも使えるし、Nch にも使える。ストックするのに最適だ...なんて考えたためだ。今でも FDS8958Aとかは、2種類買うより安い。 でも、NTMD2C02R2 や IRF7338PbF みたいな新しいものを入手するのは難しい。SOT-23(SC-59)タイプなら、Nch の PMV30UN( max 5.7A) とか NTR4501N( max 3.2A) とか Pch の PMV65XP( max 3.9A) とか いろいろ選択枝がある。すなおに、2種類買ってストックした方が良いような気もしてきた。 そうそう、ミニッツレーサ?(ラジコン四駆?)の改造では、Pch+Nch の SP8M4がはやりらしい。これを2段にしたりもするらしい。確かにこのタイプで最も電流が流せるようだ。ただ、ゲート電圧が高そうで、昇圧型 DC-DC で使おうというのは無理かもしれない。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: AVRで1セル昇圧は可能か? STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: I2CPWR DATE: 07/02/2007 16:58:13 ----- BODY: 前の記事 I2CPWR:はじめにで、1 セルは無理そうと書いた。本当に無理なのか検討してみることにする。 NiMH 1セルからの昇圧の場合、普通の ショットキーバリアダイオード(SBD)を使うと Vf が 0.3V ぐらいなので、0.9V で AVR が動く必要がある。あと重要なのがスイッチングに使うデバイス。低いゲート電圧(VGS)でスイッチングできる必要がある。電圧が上がるにつれ、VGS も上がるので、最初は電圧を上げていく分だけしか電流を流せなくても良い。ターゲットとした パワー MOS FET のデータシートを見てみると ... HAT3006R は、全然無理そうだ。2セルからの昇圧ですら厳しいかもしれない。FDS8958A の方が、低いゲート電圧で電流を流せるのだが、さすがに 0.9V は無理そうなかんじ。低ゲート電圧のものがないかというと、そうでもない。(どうやって入手できるかわからないが)、ON セミの NTMD2C02R2は、 1.5V でも 3A 近い電流を流せるので、0.9V でもかなり電流を流せそうだ。あと、IRF7338PbF も良さそう(こちらも入手方法不明)。 0.9VでAVRは起動するか? もともと、ATtiny45V とか V の付いたシリーズでも、スペックは、1.8V 〜になっている。だから 0.9V で起動するかというのは、そもそも無理な話だ。でも、AVR のマージンはかなり広い。個体によっては、それより(ずっと)低電圧で動くかも知れない。 これを調べるために、まず 0.9V前後を出力できる電源が必要だ。それは、LM358Nを使って、(データシートにも書いてある)ボルテージフォロワで作った。最大で 20mA だが、AVR を動かすだけなので十分。AVR は、ATtiny45V を選択した。AVR の動作確認は、PORT に LED を (ドライバを通して)接続し、プログラムで 1Hz で 点滅 させることで行った。ドライバにはトランジスタを使ったが、LM358N のあまった 1つを使って作ることもできる。 内蔵RC発振器 8MHz の場合 1.45V までしか無理だった。1.40V だと起動する場合があるが LED の On/Off が途中で止まってしまったりした。-- 暴走しているということだ。 内蔵RC発振器 2MHz の場合 1.10V ぐらいまでしか無理だった。しかも LED の点滅の周期がやたら(10 倍ぐらい?)長くなる。内蔵RC発振器は電圧が下がれば周波数が落ちていくが、1.2〜1.1V ぐらいまで下がると急激に周波数が落ちるようだ。1.1V までなのは、VPOT(ONリセット閾値電圧)に引っかかったためのようだ。 結論は、0.9Vでは起動しない。しかし、NiMH1セル昇圧は絶対無理なのだろうか? どうすればNiMH1セル昇圧が可能になるか? まず、極低 Vf の SBD を使うのが重要。普通の半分だとすれば 0.15V も稼げることになり、ずいぶん楽になる。RB051L(max 3A)とかMBR120VLS(max 1A)とか良さそうだ。ちなみに普通といっているのは 11EQS04とか。 あと(海外では)一般的に 1A の SBD は、どうも 1N5819が定番らしい。いくつものメーカが出しているが、中には性能が良いものもある。ただし、MBR120VLS の方が Vf が低い。 次に、出力側のコンデンサの電荷だけで起動してしまうことを考える。出力側のコンデンサがフル充電されれば電流はほとんど流れない。そういう状態では Vf もかなり低くなっているので、0.9V よりは高い電圧のはずだ。 あと、電圧が上がりきるまで余計な負荷をかけないように出力スイッチが必要だ。 出力側のコンデンサの電荷だけで起動してしまうことを考えるなら、スイッチングには、高hFEのトランジスタが良さそうだ。たとえば、白色LED用昇圧回路によく使われる 2SC2500Cとか (hFE 300〜450) 。(2SC2500D の方が hFE が高く (420〜600) 入手できるならそちらの方が良い。)。Nch パワーMOS FET なら 低ゲート電圧のもの PMV30UN(SOT-23/SC-59, max 5.7A) とか良さそう。 あと、プログラムにも相当の工夫が必要そうだ。 まず、安全な電圧に達したかどうか判断する手段が必要だ。ADC は無理。試したところ、アナログコンパレータは OK そうだ。VCC 測定用の 1/2 VCC と 1.1V 基準電圧を比べてみると、2.2V を超えたときはじめて 1.1V 基準電圧の方が低くなるようだ。 安全な電圧に達すれば、ADC も使えるし、PLL発振器も使えるので普通に処理すればよい。そして、安全な電圧に達するまでは、特別な処理にして、電圧を上げることだけに専念する。 電圧を上げる処理では、CLKPR を設定して、1MHz か 2MHz で動かす。もちろん スタート時に 1/8 にする ヒューズビットの設定をはずしてはいけない。そして、クロックが1/10 に落ちているかも知れないことを考慮する必要がある。ひょっとしたらウォッチドックタイマは、内蔵RC発信器と特性が違うかも知れない。その特性の差を利用すれば、クロック周波数が (精度が悪くとも)わかるかも知れない。その上で、On 時間が長くなりすぎないようPWM の設定を変える。 あと、暴走対策も必要だし、電圧を上げるのに失敗したときのリトライ処理も工夫が必要そうだ。暴走対策について書いておくと、いついかなるときも暴走しても大丈夫なようにすることは、無理なはずだ。でも、暴走が想定されるパターンでほとんど安全に電源を切る(= スイッチングデバイスをOff にする)ぐらいのことはできるかも知れない。よくよく考えないとそれすら難しく、プログラムを考えるのは難易度が高い。 おわりに 実は、ちょっと実験していて、11EQS04と 2SC2500C を使って試したところ、充電直後の電池で無負荷なら昇圧できた。極低 Vf のSBDを使えばもっと安定しそうだし、上で書いたことを考慮すれば、もっと安定するだろう。NiMH1セルから昇圧できる可能性はあるのだ。まだ全然だめなので詳しくは載せないが進展があったら載せたいと思う。ちなみに、LMC555を補助的に使えば、スタートアップ時の問題はクリアできそうだ。しかし、部品点数が増えてしまうので AVR だけでやりたい。
もうすこしコメント。最も簡単な構成の専用ICの例として 共立が扱っている HT77XX シリーズがある。これと比べて極端に部品点数を増やしたくない。スイッチングデバイスと、電圧測定のための 抵抗2つはやむを得ない。出力スイッチは設計の都合でつけるが、HT77XX にない機能を付けるのでまぁ良いだろう。それ以外には(機能を付けるのは別として)部品を付けたくないのだ。使える ピン数を減らしたくないのが最も大きな理由。あまり基板の面積を使いたくないというのが次の理由。そうでなければライブラリとして意味がなくなってしまう。
それとは別に、乾電池をダイレクトにつなげば、1セルで AVR は動かせそうだ。その電圧でもアナログコンパレータぐらいは使えそうだ。NiMH 1セルだと、内蔵RC発振器の周波数が問題になる。セラミック発振子を使えば周波数が安定するが、1Mhz だと動かないかも知れない。いっそのこと ウォッチドックタイマ用の 128KHz 発振器で動かすことを考えた方が良いかもしれない。ATtiny2313V あたりを使って、1セルで長時間動かすような、なにか面白いものが作れるかも知れない。 あと、1.2V 〜 1.4V ぐらいで RC発振器の周波数がかなり変動する。この特性を利用して、AVR の CPU の機能を使わず CLK出力の機能だけ使って 8MHz までの VCO になるかも知れない。それがどういう場面で役に立つかわからないが ...
VCO .. といえば、PLL IC の 4046。SN74LV4046A なら 3.3V で 38Mhz まで 使えるらしい。↑の使い方を勧めるわけではないので誤解なきよう。
----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- COMMENT: AUTHOR: ぱど EMAIL: IP: 210.173.226.180 URL: DATE: 07/03/2007 00:26:58 ATtiny45VのVPOTは0.7V〜1.4V(TYP 1.0V)なので VCCが1V以下では使えないと考えた方がいいと思います。 ----- COMMENT: AUTHOR: すz EMAIL: IP: 210.143.35.17 URL: DATE: 07/03/2007 18:51:41 なるほど、1.1V からしか動かないのは、VPOT(ONリセット閾値電圧) が関係していそうですね。そもそもこの記事は無理なのを承知でやるとどうなるか...というつもりで書いたのですが、誤解されるかも知れないですね。冒頭に説明を載せることにします。 ----- COMMENT: AUTHOR: ぱど EMAIL: IP: 210.189.114.60 URL: DATE: 07/05/2007 00:15:27 回答ありがとうございます。 >無理なのを承知でやるとどうなるか... もちろん理解しておりますが VPOTについては言及されていなかったので余計とは思いながら差出口を挟ませて頂きました。 これからも更新楽しみにしております。 ----- COMMENT: AUTHOR: EMAIL: IP: 218.45.21.199 URL: DATE: 11/16/2007 00:12:38 スイッチングTrにタクトスイッチをパラで付けて、手動クランキング(?)スタート、という話をhackadayかなんかで見たことがあるような。 ----- COMMENT: AUTHOR: すz EMAIL: IP: unknown URL: DATE: 11/20/2007 17:17:46 ショートさせても大丈夫なように大きな内部抵抗で、mHクラスのコイルを使うならいけるかも。 たとえば LHLC10NB 1mHだと、1.8Ω/480mA なので、1.2V - 0.2V(Tr分) でショートさせても 最大 550mA で、たぶん大丈夫。 ----- -------- AUTHOR: すz TITLE: フランクリン型発振回路 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 07/10/2007 19:00:40 ----- BODY: CMOS インバータを使ったフランクリン型発振回路というものがある。ググってもあまりヒットしないので、防忘をかねて紹介してみる。 回路例:
左の回路は、トランジスタ技術 Special増刊 OPアンプによる実用回路設計に載っていたもので、右の回路は、トランジスタ技術 2003年8月号に載っていたものらしい(未確認)。 ほぼ、LC共振回路の共振周波数で発振するので、LC メータとか、電波時計のアンテナ同調とかに使えるのではないかと思う。 また、LC共振回路からきれいな正弦波が出てくるので、バリキャップ(1SV149とか)と組み合わせれば、正弦波用のVCO にもなるのではないかと思う。
追記:ゆきの研究室/つれづれ日記で試してくれました。左の回路はダメで、右の回路はOKだったそうです。
回路案:
これで何を作りたいか まず作りたいのは、LCメータ。C を測定できるテスターはあるので、温度補償用コンデンサさえあれば、安価に作れるはず。 次に作りたいのは、電波時計のアンテナ。電波時計を自作してみたかったのだが、アンテナを同調するのが面倒なので、手を付けられていなかった。できれば下の回路を使って自動で同調するものが作れたらと考えている。ただし、1SV149 は せいぜい 500 pF ぐらいなので、数十 mH のバーアンテナを自作する必要がある。 あとは、PLL用のVCO。中間タップが必要なく、市販のインダクタが使えるので、コイルを自作しなくて済み再現性の高いものができるかも知れない。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- COMMENT: AUTHOR: ゆき EMAIL: IP: 211.19.16.165 URL: http://yuki-lab.jp/ DATE: 07/01/2008 21:49:06 お世話様です。 すzさんのページの画像ファイルがことごとく 404 Not Found になっているみたいなんですがどうなさったのでしょうか。 有用なデータがもったいないですー。 ----- COMMENT: AUTHOR: すz EMAIL: IP: unknown URL: DATE: 07/03/2008 00:05:58 連絡ありがとうございます。気が付きませんでした。調べたらどうもファイル置き場のサーバが障害かメンテナンスで、サービス停止中のようです。しばらくしたら復旧すると思います。 ----- PING: TITLE: フランクリン発振器をシミュレートしてみる URL: http://blog.goo.ne.jp/sim00/e/90e056416a131e4a1bc924602606836c IP: 210.165.9.64 BLOG NAME: Sim's blog DATE: 02/09/2008 00:20:18 LCメータでググっていたら、フランクリン発振器というので作っておられる方がいました。おっさん工房さんです。ネットワークアナライザとか自作してたりしてすごいです。LM311というコンパレータを使っています。Linear Technologyだと後継のLT1011というICが互換になります。LTSpiceにもLT1011は入っているのですが、うまく発振しませんでした。 よく分からなかったのでフランクリン発振器でググったらすzのAVR研究さんにたどり着きました。2種類のフランクリン発振器を紹介されています。こちらはうまく発振しました。 左側の回路図です。 74HCU04は昨日のと同じです。 シミュレーション結果です。 拡大します。 結構きれいな正弦波が出ています。 FFTすると1.5MHzで発振しているようです。 計算では1.59MHzなので結構正確です。 右側の回路図です。 出力は似たような感じなので省略します。こちらの回路はコンデンサが小さいと発振しませんでした。大きくすると発振しました。 正確なコンデンサがあると発振周波数からインダクタンスが分かるという仕組みです。ピアースも発振でしたが、こちらはコンデンサが1個でいいのがお得です。 ----- -------- AUTHOR: すz TITLE: 作ってみたい装置(その2) STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 10/17/2007 20:47:31 ----- BODY: 以前、作ってみようと思っている装置という記事を書いたが、今回はちょっと弱く作ってみたい装置。作らないかも知れないので、ネタとして紹介。 (1) USB制御 ファンコン センサ付きのファンの制御をするもの。あまり有用ではないかも知れないが、簡単そうなので作ってみるのも面白いかも知れない。 以下メモ
センサの出力について センサの出力は、ただのオープンコレクタ出力らしい。プルアップすることで、デジタル入力できる。注意する点としては、1回転に付き 2回の ON/OFF になること。 PWM 制御について DCブラシレスファンは、内部に回路があって制御しているので、単純な PWM 制御ではダメ。降圧型 DC/DC コンバータにしなければならない。といっても、回転数でフィードバックをかけるので、電圧センスなどは必要ない。スイッチングは、500mA ぐらい流せる PNP トランジスタを使い、インダクタには、LHLZ06NB 100uH 0.56Aあたりを使うのが良いのではないかと思う。 制御について 温度計とペアにして、温度によって回転数を制御するものにしたい。で、USB でパラメータ設定と、温度、回転数のセンスができるようにする。複数のファンを制御したいところだが、ATtiny861 を使うとして、2ch ぐらいが妥当かも知れない。温度センサは、カモン MB用温度センサ OND-S(千石で 263円)を使えるようにすると装着が楽になりそう。ちなみにこれの素子は、石塚電子 103JT-025(千石で 137円)と同じJTサーミスタではないかと思う。自分で加工するなら、特性のはっきりした(25℃で 10.0KΩ・85℃で1.451KΩ B定数3435K)こちらを使ったほうが良いかも知れない。 OND-S: 103JT-050:(自分で加工したもの) ところで、サーミスタは 抵抗値を測定して logを取るなど面倒な計算をしないと正しい温度は得られないらしい。ただ、近似値でよいなら、サーミスタの使い方2の通りにやれば四則演算だけでなんとかなるらしい。... と思ったのだが、1つの直線で近似するのは無理がありそう。すなおに、R/(R + Rth) の値と 温度の対応表を作り、N 個の直線で近似したほうが良さそうに思える。ちなみに、対応表はデータシートに載っているが、B定数を元に計算することもできる。
おまけ:サーミスタの温度計測方法について 石塚電子 103JT 用(たぶん カモン MB用温度センサ OND-Sも同じ) 1) 次の回路で分圧比を測定する。分圧比を測定するだけなので、VCC=Vref で十分。
2) 次の式を使って、作った表にもとづいて 温度に変換。 1/32, 2/32 , 30/32の分圧比と温度のグラフができるので、1/32 〜 30/32 の範囲の値は、それぞれの区間で線形補完する。(0〜1/32, 30/32〜1の範囲は変換できない。)
#include <math.h>
#include <stdio.h>
#define RES	32
#define R10K   (10000.0)
main() {
	int i;
	double r1,r2,t1,t2,b;

	r1 = 10000.0;
	t1 = 25.0 + 273.15;
	for (i=1; i<(RES-1); i++) {
		if (i < RES/2) 
			b = 3238.6;
		else
			b = 3435.4;
		r2 = R10K * RES/i - R10K;
		t2 = 1.0 / ( (log(r2) - log(r1)) / b + 1/t1 ); 
		printf("%4.3f  %10.4f\n"
		            ,1.0 /RES * i, t2 - 273.15);
	}
}
上の計算式で作成した値とデータシートにある実測値のグラフ 注意とコメント) 上のグラフは、B定数を2つ使用している。25℃以上は 25℃,85℃のデータから作成したB定数。25℃以下は、-40℃,25℃から作成したB定数。B定数の算出は次のプログラムを使った。
#include <math.h>
#include <stdio.h>
main() {
	double r1,r2,t1,t2,b;

	t1 = -40.0 + 273.15;
	t2 = 25.0 + 273.15;
	r1 = 204.7 * 1000;
	r2 = 10.0 * 1000.0;
	b = (log(r2) - log(r1)) / ( 1/t2 - 1/t1);
	printf("b = %10.4f\n",b);
}
注意点: 10K の抵抗値はできるだけ精度を良くして、25℃のとき 0.5 になるようにすること。抵抗の値を精度良く測定できるなら、その値をもとに表を作り直しても良い。 校正方法案: もし、カモン OND-SのB定数が全然違うならたとえば次のようにする。0 ℃と 100℃の サーミスタ抵抗値と(室温での)10Kの分圧測定用抵抗を同じテスターで測定する。次に その2つの値からB定数を算出して、最初のプログラムの t1,r1,b,R10Kを差し替えて表を作り直す。 校正方法案2: 25℃前後の室温と100℃の2点の方が使用範囲での精度が良いと思えるので、信頼できる温度計を1つ用意して、室温と抵抗値を測定する。そしてこの2点だけで、全部のパラメータを決める。 基準にする温度計については、DE-20W 500円が安価でお勧め(低消費電力タイプは反応がすごく悪いので、実験用には高速応答タイプがおすすめ)。100℃の方は、沸騰したお湯に付けて 抵抗値を測定する。ただ 正確に100℃なのかどうか分からない。ちなみに DE-20Wは 99.8 ℃を示した。 誤差について 上のグラフは、B定数 3400K(0℃,90℃)赤, 3435K(25℃,85℃)緑,3238K(-40℃,25℃)青 で近似したときの実測値との差。2つのB定数を使った最初のグラフは、青と緑を 0.5 で切り替えている。全域で±1℃には入りそうだが そんなに高い精度ではないようだ。赤は、0℃,100℃で校正したらどのようになりそうか見るために作成した。-20 ℃以下を除けば一応±1℃に入っているようだが、校正したとしても、これ以上精度を上げるのは難しいようだ。 (2) USB 電力計 サンワ ワットチェッカー TAP-TST5 というのが商品として有名で、そんなに高いものではない(5−7千円) 。それを買えばよいのだが、高機能(多チャンネル、PC との通信)なものを作ってみるのも良さそう。 (技術資料)交流電流センサの基本コンセプトをみると、交流電流センサはすごい簡単な構造だとわかる。復活した 現品.com にも 非接触 電流検出ユニットとして単価 70円で売っているし、適当なノイズフィルタ用のコアで自作することすらできそうだ。ただし注意点がある。(技術資料)交流電流センサ解説1(出力特性図の見方)にあるように、飽和領域と微小電流領域で直線性が悪くなること。特にフェライトコアを使った場合、微小電流は測定できないと思ったほうが良さそう。 自作するにせよ、現品.com のを使うにせよ 出力特性など判らないから、カットアンドトライで調整しないといけない。そのこと自体を楽しみとできないと、まともなものを作ることは厳しそうだ。 あと、出力も交流なので、交流電圧を測定するための回路も必要だ。50-60Hz と周波数が低いので、オペアンプを使った 絶対値回路か理想ダイオードで整流し、RC フィルタを通して ADコンバータに入力すればよさそうだ。 回路案:
回路図で説明してみることにする。理想ダイオードはダイオードが2つ入っている中央のブロック。低周波数ならリニアな半波整流をしてくれる。(参考:電子回路の豆知識)2段目のブロックは反転した出力をさらに反転させるためのもの(なんとなく入れてみたけど増幅しないなら必要ない)、最後にRCフィルタを通して差動入力のADCで受ける。こんな感じでよいのではないかと思う。オペアンプは、たぶん何でも良い。RC フィルタは 1Hz とかの cut-off で良いと思う。R1 は現物にあわせで決めるしかない。
この回路あまり良くないかも知れない。まず、センサ入力の片側が仮想GNDになっているが、GND にして、R2の手前にコンデンサを入れて交流結合にしたほうが良さそう。あと、入力は微分したものなので、積分器を入れると良いかも知れないが必要らしい。具体的には、二段目の反転増幅器を一段目の前にもってきて、R5 と並列にコンデンサを入れる。また、R1 の値は小さいほうが良さそうなので、一段目、二段目でゲインをかけたほうが良さそう。
ちなみに、ちゃんとした部品を使うならば、上で紹介した技術資料を載せている U_RD というメーカのものが結局は安いらしい。それでも単価1000円ぐらいで結構高いものだそうだ。
参考:現品.com に出ている 交流電流センサ(らしきもの)07/10/18 現在  非接触 電圧検出ユニット 単価 70円  コイル 13.3 x 9.8 x 2.1 単価 50円 (注意)買ってみたがサイズは、もっと大きい -- 厚さ6mm / 直径16 mm 、貫通穴径φ6 、最大幅 24mm ぐらい。
現品.com のコイル↑を試してみた。抵抗を取り付け テスタで 抵抗の AC 電圧を測定してみると、50Ωの場合、11W で 7mV , 100Ωの場合 , 11W で 16 mV という感じだった。 400W では、50Ωのとき 0.25V ぐらい、100Ωのとき 0.30V ぐらいだった。ただし、100Ωのときは飽和している。50Ωのときも飽和しているかもしれない。あまり高い電力の測定はできないようだ。10Ωぐらいまで抵抗値を下げるべきかも知れない。 さらに、機器によっては ワットチェッカーと全然違う低い値になる場合があった。かんがえてみれば、電流の変化(微分したもの)を測定しているだけなので、波形が崩れればそうなるのかも知れない。なかなか奥が深い。 測定用に製作した電源コード:
(3) 温度特性測定用 簡易恒温槽 アナログ系の電子工作をしていると温度特性が気になる。それを調べるために、高温・低温の環境を作りたい。いまのところ安い温冷庫 (これとか)を使えば良いのではないかと思う。ただこの手のものは制御が単純で、保温時のみサーモスタットで 65℃/OFF、50℃/ONの制御をするらしい。そのままでも使えそうに思えるけれど、きめ細やかな制御をして温度を一定に保つようにしてみたい。 (4)鉛バッテリー用 デサルフェーターと放電特性を測定する装置 効果があるかどうかわからない(わからないがゆえに効果を調べてみたい)のだが、劣化した鉛バッテリーの復活させるデサルフェーターという装置があるらしい。(参考:デサルフェーターの作り方The Low Power Desulfator)。これを設計して作ってみたい。効果を調べるには、放電特性も測定しなければならない。回路図をみると、バッテリーから LC フィルタを通してコンデンサに充電し、それを昇圧してバッテリーに戻すようなものらしい。昇圧側はコンデンサで平滑せずダイオードを通すだけにする。LC フィルタを通しているので、高電圧のパルスがバッテリーに出力されても、回路には(パルスが入力されず)定電圧が入力されるというのがミソらしい。 昇圧回路のスイッチングが 555タイマでされているために、ちゃんと調整しないとコイルが飽和して焼けてしまうという問題がある。そのような問題点は電流モード制御をすれば解決する。AVR で作れそうだが、手っ取り早く効果を確認するために、最初は、手持ちの DC/DC コンバータ IC M5291FPを使ってみようかと思う。 コイルに流す電流を制限できるし、周波数もコンデンサひとつで制御できる。そして、うまくいけば、入手性が悪い専用ICを AVR に置き換えて、機能も追加したものを作ってみたいし、NiMH とかにも有効なのか確認してみたい。放電特性を測定すること自体は セメント抵抗+放熱器を使い放電し、USB910A で電圧を計測をすればよいので問題ないが、過放電しないように終端電圧になったら放電をとめる機能は必要だろう。 M5291FP回路案:
上の説明ではイメージが伝わらないので回路例をもとに説明してみることにする。右の部分 100uF を電源としてスイッチングして、昇圧回路を通す。出力にはコンデンサがないので、かなり高圧のパルスが出力される(はず)。そして、右の部分 1000uH と 100uF(25V) で cut-off 周波数 500 Hz ぐらいの LPF になっているので、出力のパルスは入力に入らない。スイッチングには、電流モード制御ができるDC/DCコンバータIC M5291FP を使う。Rsc の電圧降下が 0.3V になると On→Off になる。たとえば 2A のコイルを使うなら Rsc を 0.15 Ωにすればそれだけで On タイムは最適になる。定格が同じなら、違うインダクタンス・性質のコイルでも動作する。Off タイムの調整は、発振周波数で行う。Ct の値によって 周波数を設定できる。10KHz 程度が良いらしいが良くわからない。またこの回路は、12V 専用ではない。24V でも、6V でも使えそうだ。3-4セルの NiMH でも使えるかも知れない。回路図には書いてないが、電圧センス機能は当然あるので、一定電圧以上になるととめる機能は付けられる。(参考ページを見ると、18V以上でとめるみたいな話があるので必要なのかも知れない。それはともかく過放電保護のために一定電圧以下でとめる機能はほしい。だが、これを作るのはちと面倒。)まぁこんな感じなのだが、大問題がある。M5291FP はかつて 現品.com で購入したものだが、入手性がすごく悪い。今どこに売っているかも分からないのだ。電流モード制御の DC/DC コンバータICなら上と同じことはできるはずなので、代替は可能。使ったことはないが、TL3842P とかが使えるのではないかと思う。(デジキーで109円) ただ、この程度の制御は、コンパレータ(と基準となる電圧)とタイマーでできる。AVR で作ることも可能なはずだ。 AVR回路案:
ちょっと説明しづらいので回路図を出すと、Rsc は、トランジスタのエミッタ側に移動させる。トランジスタに流れる電流=ONのときコイルに流れる電流なのでこれでも問題ない。で、コンパレータがONになる回数を割り込みでカウントするようにしておいて、その回数があまり増えないように PWM のパルス幅を調整する。あと、5V のレギューレーターが必要になり部品が増える。 コイルの選択と入手先: 共立エレショップ -- 各種安価なトロイダルコアがある。 千石 -- ラジアルリードのLHLC10NBシリーズが安価 いずれにしても 220uH なら1Aぐらい。2A なんてものは入手が難しいようだ。1A 用に回路設計して、いくつかのコイルを試すのが良いかもしれない。 スイッチングトランジスタの選択について: 注意)この回路例は、説明するために作成したもので動作確認したものではありません。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- COMMENT: AUTHOR: 久我 EMAIL: gdh00074@nifty.ne.jp IP: 219.104.103.80 URL: DATE: 11/26/2007 10:58:48 始めまして M5291FP って 構成見ると MC34063,NJM2360と 一緒ですね。 コイル電流1A程度でよければ 内蔵TRでいけそう。 ----- COMMENT: AUTHOR: すz EMAIL: IP: unknown URL: DATE: 11/26/2007 17:32:22 情報ありがとうございます。 データシートみたら、MC34063,NJM2360 も電流制限ができるのですね。できないものとばかり思っていました。なら、1.5A 流せるしこちらの方が良いと思います。 ----- -------- AUTHOR: すz TITLE: 鉛バッテリーの放電特性の測定 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: バッテリー関係 DATE: 10/29/2007 15:08:36 ----- BODY: 鉛バッテリーが手元にいくつかある。そのうちの2つは、2年ほど前、秋月で売っていたジャンクUPS+新品バッテリーの格安セットを購入したとき入手した。ジャンクUPSにもともと入っていたバッテリー(YUASA Reliart RE 7-12, 7AH) は劣化しているということで、新品バッテリー(LONG WP8-12 ,8AH) が付いていた。そのときから、劣化したバッテリーを デサルフェータで復活させてみたいと思っていた。劣化しているのかどうか・復活したかどうか確認するには、放電特性を測定しなければならない。 また、最近シリコン・バッテリーというのに魅かれて、GREENSAVER SP6-12(8.5AH @20H放電,6AH@2H放電) を購入してしまった。シリコンバッテリーの輸入元のページでは、こんなセールストークがされている。本当に性能が良いのか、その中のいくつかの点でも調べてみたい。(興味があるのは自己放電のすくなさ) ..というわけで、まずは、鉛バッテリーの放電器を作ることにした。 10Ωのセメント抵抗を6つ、昔のCPU放熱器にエポキシパテで貼り付けて、2直列3並列(6.66Ω)にし、電流測定用に 0.3 Ωの抵抗を 2並列にしたものを GND 側に付けて、負荷にした。それに加えて、TL431 + FDS4675で過放電対策をしている。放電特性は、USB910A を接続して、電流と電圧をログすることにした。 回路全体では、 7.21Ωの抵抗値で 12V のときは、1.66A 程度が流れる。放熱器は 74℃(周囲温度 24℃)ほどになった。手で触れないぐらいの熱さだが、まだ大丈夫だろう。(いちばんやばいのは、負荷抵抗の足に直接付けた FET ,抵抗の熱が回ってきて放熱器と同じぐらい熱い)
過放電対策について TL431 は、REF が約 2.5V以上だと、K が +2V程度になる。そうでなければ、電源電圧 。Pch MOS FET / PNPトランジスタを使うと、ある電圧以上で ON になるようにできる。2K2 x 3: 2K2 で分圧しているので、約10V 以下になると OFF になるはず。バッテリ電圧10V以上ある間は、10V で完全に OFF にならず、100 mA 程度の電流が流れているようだ。 最終的には 10.0V 前後で ほとんど電流が流れなくなる。
回路図: YUASA Reliart RE 7-12, 7AH と LONG WP8-12 の放電特性
WP8-12は、データシートの特性と結構似ているので、妥当だと思える。さて、RE 7-12 の方、容量がかなり見劣りするが、そもそも開始時の電圧が低い。RE 7-12 は、とりあえず充電できた状態で測定したが、WP8-12 は UPS でずっとトリクル充電していた。公平な比較ではなさそうだ。100%に充電していたらもっと持ったと思える。... ということは、ほとんど劣化していないかも知れない。 YUASA Reliart RE 7-12, 7AH と LONG WP8-12 と GREENSAVER SP6-12 の放電特性
LONG WP8-12 を再度測定して、GREENSAVER SP6-12 も測定した。 WP8-12 は、完全なフル充電ではなく、他のバッテリと同じようにある程度充電できた状態でスタートするようにした。 それでも、WP8-12は電圧が高い。バッテリーの性質なのだろうか? SP6-12 は、電圧が下がる傾きが緩やかで RE-7(54WH) と同じ電圧から開始したのにもかかわらず、76WH まで伸びた。RE-7 の1.4倍の容量があることになる。やはり RE-7 は 劣化していて 2-3割容量が落ちていそうだ。 メモ 
LONG WP8-12 (データシートから)
 容量 1C放電 3.6AH 5H放電 6.8AH 10H放電 8AH 20H放電 8AH
  容量維持 1ヶ月 92% 3ヶ月 90% 6ヶ月 80%
 バッテリー充電方法
  充電電圧 14.4 〜 15.0V、最大充電電流 2.4A
  フロート充電電圧 13.50 〜 13.80V (電流制限必要なし)

GREENSAVER SP6-8
 容量 2H放電 6AH 5H放電 7AH 10H放電 8AH 20H放電 8.5AH
  容量維持 わずか?
 バッテリー充電方法
  充電電圧 14.8 〜 15.0V、推奨充電電流 2A〜3A
----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: 交流電流センサ(1) STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: センサ関係 DATE: 10/29/2007 21:11:28 ----- BODY: 現品.com に 交流電流センサらしきものが、単価 50円で出ている。(07/10/18 現在。名称は、コイル 13.3 x 9.8 x 2.1 ) 安価なので、これを使って電力計を作ってみようと思う。ただ、製品もわからないのでどういう特性があるかは自分で調べなければならない。 交流電流センサについては、(技術資料)交流電流センサの基本コンセプトに説明があるが、非常に簡単な構造。中央の穴に測定する電流がながれるケーブルを通すと、電流の変化がセンサの出力に出てくる。ちゃんと測定するには、オペアンプで作った積分器を通す必要があるが、電熱器やはんだごてみたいなものは、積分器がなくても測定可能。 注意点としては、(技術資料)交流電流センサ解説1(出力特性図の見方)にあるように、飽和領域と微小電流領域で直線性が悪くなること。センサの両端につなぐ抵抗は小さいほど(大電流で)直線性が良くなるようだが、あまりに出力が小さいと微小電流領域が測定できなくなる。 特性を調べる まずは、↓のようなケーブルを作る。 そして、出力に抵抗をつなぎテスターのAC電圧測定モードでいろんな機器の電圧を測定してみる。機器そのものの消費電力を知るために、結局 サンワ ワットチェッカー TAP-TST5を使っている。
出力(AC mA)/W           10Ω      50Ω      100Ω      1KΩ
はんだごて              1/11      7/11      15/11    114/11
(15W)      
17inch ディスプレー    10/92     53/92     106/92    365/92
(ブラウン管)
ホットカーベット1/2    44/333   221/326    301/323  368/320
(300W)
パネルヒーター         53/396   250/395    302/395  368/394        
(400W)
ホットカーペット       87/622   253/613    304/609  369/604   
(600W)
グラフ(log scale x,y)
データを log scale でグラフ化してみた。1KΩは、92W で既に飽和している。線形部分の傾きがみな同じとすれば、30W ぐらいまでしか線形でなさそうだ。 100Ωでは、200W ぐらいまで。50 Ωになると、飽和するところが測定できていて、300W まで線形だと判る。 10Ωは確かに 直線性が良い、1KW は測定できそうだ。
このグラフは、50Ωと 10Ωについて、log scale をはずして表示したもの。50Ωは 0.68 AC mV/W , 10Ωは 0.14 AC mV/W 。 抵抗値の比と同じで 5倍もの差がある。 回路の設計(その1)
抵抗の両端に 10Ω〜50Ωの抵抗を接続し片側を グランドにして、交流結合で一段目のオペアンプに入力する。0.2〜0.3V が最大出力らしいので、2倍ぐらいのゲインもかける。さらに 積分器となるように、コンデンサを負帰還の抵抗に並列に接続する。 2段目は、理想ダイオードにして、半波整流する。(参考:電子回路の豆知識)ここでも 2倍ぐらいのゲインをかける。 最後に、RFフィルタで整流して差動入力のADCで受ける。 R=50Ωの場合、最大で 250 AC mV とすると、ゲイン 4 倍で 1.0 AC V 仮想グランド 1/2 VCC からの最大振幅は、1.41 V、3.3V 電源で OK そうだ。半波整流なので、ADC への入力は最大 0.5V 。 ADC 基準電圧を 0.5V にすればフルスケールで測定できる。 R=10Ωの場合、最大電圧はさほど変わらないので、基本は 同じ回路で良さそう。低電流のときどうするかがポイント。アナログスイッチを使ってゲインを切り替えられる プレアンプを置く? オペアンプの選択 LMV358を使おうと思う。そのままでは、使いにくいので、変換基板で 8PIN DIP に変換して使う。理由は、単価が安い。3.3V で使える。RAIL-to-RAIL 出力が得られる(入力は違う点に注意)ことの3点。性能は 1V/μsのスルーレートでそれなりだが問題ないだろう。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: 鉛バッテリー充電器 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: バッテリー関係 DATE: 10/30/2007 15:19:19 ----- BODY: 鉛バッテリーに充電できる装置は1つしかもっていない。しかも専用機ではなく、UPS そのもの。もともと ジャンクUPSなので、充電器として使っていて良いのだが、当然ながら使いづらい。 1つ簡単な鉛バッテリー充電器を作ろうと思う。 13.5V〜13.8Vの定電圧の電源で 1A〜 2.5A ぐらいの電流制限が付いていれば、鉛バッテリー充電器として使えるらしい。
Panasonic の鉛バッテリーのページにある 充電について(pdf)を読むと、定電圧定電流充電方式というらしい。フロート充電(浮動充電)は、車など負荷がバッテリーと並列につながったシステム(フロート)のための充電システムということで、充電方式自体を指すわけではないらしい。
案1)トランス型 AC アダプタ 12V 1A + 可変型レギュレータ PQ20RX11 たまたま 12V 1A のトランス型 AC アダプタを持っているので、これを使ってみたい。この AC アダプタは、無負荷で 16V ぐらいになる。負荷をかけると電圧が落ちていく。ためしにバッテリーにつないでみると 12.X V まで電圧が落ちて、500mA ぐらいの電流が流れた。(自分で監視すれば)そのままでも充電はできるが、13.8V の上限になるよう レギュレータを入れると 性能は低いものの立派な充電器になりそうだ。 16V で 13.8V 制限をかけるので、レギュレータは低ドロップタイプでなければならない。 ちなみに、PQ20RX11は、過電流保護回路があり、1.5A で制限される。また、設定した出力電圧と実際の電圧の電圧差 が大きくなると(Δ2.3V ?)、出力電流が急速に落ちる(フの字特性)。本当に Δ2.3V で出力電流が落ちるなら 11.5V 以下になってしまったバッテリーは充電できない。 許容損失は放熱器なしで 1.5W 。たぶん電源電圧の方が先に落ちるので、出力電圧差は、0.5Vになるはず。なので 放熱器は必要ない。 トランス型 AC アダプタではなく、たとえば 15V 1.6A の AC アダプタを使った場合どうなるのだろう? 1.5A の過電流保護があり、AC アダプタの定格も超えないので、11.5V 〜 13.8V まで 最大 1.5A きちんと流れるはず。ただし損失は、11.5V で 5.25W --- 放熱器は必要。それ以下で充電できるかどうかは、出力電流が落ちる電圧がいくつなのかが問題。 鉛バッテリーの放電特性の測定では、10V まで測定するが、測定後しばらくすれば、11.5V ぐらいまでは復活していたと思う。11.5Vをきる状況というのは、実はあまりないのかも知れない。 案2)12V 電源 + 昇圧型 DC/DC コンバータ 本来は、19V AC アダプタなどを電源に使って、降圧型 DC/DC コンバータで作るものだと思う。しかし、19V 電源は買うつもりはなく、12V 電源はたくさん持っている。 そういうわけで、昇圧型で作ってみたい。デサルフェータの機能も付けてみたいという理由もある。たぶん、簡単なものではなくなるので、レギュレータ版の後。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: ATtiny861,ATtiny44 が買える店 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 10/31/2007 13:00:28 ----- BODY: USB910A/B で使用している ATtiny861,ATtiny44 が買える店を紹介しておこうと思う。 マルツパーツ館WepShop ATtiny44(DIP) 388円 マイクロファン ネットショップ ATtiny861/861V(DIP) 420円 残念ながら、この両方を扱っているところは国内では、なさそうだ。(07/11現在)
もちろん デジキーでは、両方扱っている。ATtiny44(DIP) 261円、ATtiny861/861V(DIP) 376円 (07/11)。 ただし、送料・手数料が高いので 注意
----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: エンジンONで入るスイッチ STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: バッテリー関係 DATE: 10/31/2007 14:37:32 ----- BODY: バイクには、ヘッドライトをON/OFFするスイッチが付いていないことをご存知だろうか? そのこと自体は別に問題ではないのだが、エンジンが OFF のときでもヘッドライトが点灯してしまう。バッテリーが弱ってきて、エンジンがかかりにくい状況でもヘッドライトは点灯している。ついにはエンジンがかからなくなったときでも... ヘッドライトに流れる電流はかなり大きい。100W なら 8.3A だ。これだけの電流を常時流さなければ、エンジンはかかったかも知れないと思ってしまう。(私のバイクはセル専用でバッテリーがあがればどうにもならない。そして...こういう経験が、2度ある。) エンジンONを検出して、そのときだけヘッドライトを点灯するようにしたいと思っていた。そのようなものを作るにはどうすればよいか今まで分からなかったが、バッテリーの特性を調べてみたら実は簡単なのではないか ..と思えてきた。 車やバイクの充電方法は、フロート充電で 13.5〜13.8V の定電圧充電だ。すなわち エンジンONのときは、この電圧になる。 そして、鉛バッテリーの放電特性の測定で調べたように、フル充電の状態でも多少電流を流せば 12.4〜12.9V ぐらいの電圧にすぐ落ちる。ということは、13.0V以上 で ON/それ以下で OFFになるような回路があればよい。そしてその回路は TL431と Pch FET で簡単に作れる。それも実験済み。 FET の ON抵抗は低くければ低いほどよい。放電器で使った FDS4675は、11A 流せて ON抵抗は 13mΩ そのときの自己損失は 0.14W に過ぎないからこれで十分。放熱器も必要ない。 回路図案: 放電器と回路をベースに、コンデンサを入れ RC LPF を通すことにした。100uF なら cut-off 周波数は 約1Hz になる。これでも反応がよすぎるなら 1000uF を使ってみるのもよいかも知れない。 調整案) 適当な電源(5Vとか)をつないでみて、入力電圧と TL431のRef電圧をテスタで測定する。その比率が 13.0:2.49 になるようにVR(半固定抵抗)を調整する。 予想動作) イグニションキーを ON にした瞬間、フル充電されている状態なら、数秒? ヘッドライトが点灯する。しばらくエンジンをかけていなければ、(たぶん)まったく点灯しない。エンジンをかけると少しの間を置いてヘッドライトが点灯する。 注意)このスイッチは、12V バッテリーでヘッドライトを点灯させるタイプでしか使えません。ジェネレータから直接配線されているようなものはだめです。(そもそもこのスイッチの必要性もないはずですが ...)。 ちなみに、6V バッテリー用には抵抗を変えればよいはず。HID で使えるかどうか(問題がないか)については分かりません。 いずれにせよ、自己責任でお願いします。 おまけ バイクの充電システムの例 ジェネレータは、三相交流。整流してバッテリーに直接接続。電圧制御は、SCR(サイリスタ)によっておこなう。余分な電力は、GND にショートすることによって、ジェネレータに返す。また、LOAD(負荷)も イグニッションキーが ON のとき バッテリーと並列に接続される。 バッテリーの充電電流を制限しているところは回路上なく、たぶんバッテリーの内部抵抗だけで充電電流の上限が決まる。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: セリア充電器 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 11/05/2007 15:11:27 ----- BODY: 近所にセリアがオープンしているのを発見したので、電気・電池コーナを物色してきた。有名なセリア充電器を発見したので、3つばかり購入。もちろんこんな怪しげなものを実用として使うつもりはまったくない。 まずは、1つ分解。回路図はつぎのようなもの
これが開放電圧 約 AC 4.3V のトランスに接続されているだけ。 ダイオード1つで半波整流して電流制限の抵抗がはいるだけ。面白いのは、もうひとつの電池は、逆に接続していること。それはともかく、こんなしょぼい回路では、過充電が怖い。
追記: 過放電してしまった電池は高速充電器では充電できないときがある。そういうときにこれでちょっと充電してやると高速充電器にかかるらしい。こんなものでも 役に立つ状況はあるものだ。
実用として使わずに何に使うかというと、充電器用 電池ケースとして使うつもり。上半分を別のケースにマウントして、高機能の 充放電器を作るのだ。 回路案として2つ考えてみた。 案1)2つの電池を別々に制御する充放電器。
上の回路を 2 つ作り、AREF にちゃんとした基準電圧を入れる。全部で 9 pin 必要。ATtiny44 なら 2pin あまるので、I2C スレーブを付けられる。ATtiny861 なら、6 pin あまるので、USB 制御ができる(clock 2 + USB 2)。あまった 2pin は、LED か、温度センサに使えばよいだろう。温度センサを使う場合は、サーミスタを使い、電池のー側の電極を付けているハンダあたりに貼り付ける。 Pch の FET には、FDS4675か、デュアルのFDS4935を使い、Nch の FET には、uPA2753GRを使う。 22uH の インダクタは、TSL0709S-220Kを使う予定。これは、86mΩ 定格電流 1.3A(飽和するのは 1.4A)。最大 1.4A。充電電流は 1/2 の最大 700mAまでしか流せないことになる。
ON してから 最大の 1.4A になる時間は、(内部抵抗を無視すると)
 i = Vt/L 
 の関係を使って、1.4 * 22 / ( 5 - 1.2) で 8.1 uS 。出力電圧は ON Duty 比で決まるらしいので、ON 1.2 : ON+OFF 5 、8MHz として ON 時間 65clock , ON+Off 時間 270 clock を目安にして設計する。電流を減らす場合は、ON 時間固定で Off 時間を長くする。
案2)1系統しかないかわり高機能な充放電器 上の回路は、1セル急速充放電ができるだけのものだが、3セルのNiMHを充放電したいのと、デサルフェータ機能 or バルス充電機能を付けてみたいので、こんな回路を考えてみた。
鉛バッテリーではないので、サルフェーションそのものはあり得ない。デサルフェータ機能というのは変。リフレッシュ機能というべきなのか? ただ、普通リフレッシュ機能というのは、深放電する放電機能のことらしいのでややこしい。 ちなみに、ニッカド電池にメモリ効果というものがあり、これは復活できないらしい。NiMH の場合は、深放電と充電を繰り返せば普通復活するので、ニッカド電池とおなじ意味のメモリ効果はない。 ここでいうデサルフェータ機能とは、10kHz ぐらいの高い周波数で充電と放電を繰り返すもので、サルフェーションで弱った鉛バッテリーを復活させるには有効らしい。NiMH でも同じことをすれば、復活できるかも知れないので試しに作ろうとしているもの。効果があるかどうかは、作って試すのだ。
デサルフェータとして使う場合は、電源供給を Off にして、昇圧回路を動かす。電池から電源を供給して、昇圧して返す。パルス充電の場合は、電源も供給して、昇圧回路の 周波数を上げる。 B-C 間の電流(と向き)を測定すれば、うまく制御できるのではないかと思う。放電機能は、電池側に移動し、負荷抵抗も外付けにしようと思う。 820uH は、手持ちの LHL10TB821K を使おうと思う。これは以前 現品.com で入手したもので、1.4Ω 定格電流 420 mA 。昇圧回路を動かさずに普通に充電するときは、420mAまでにしなければならない。 ちなみに LHLC 10NB 102J は、1mH / 1.8Ω / 480mA になっているので、こちらの方がよいかも知れない。
パルス側のPWM は、最大 ON 時間 1.4 * 22 / 5 = 6.16 uS ( 49 clock) を目安にする。電流を流したければ、ON 時間固定で Off 時間を短くする。ただし ON Duty は 6/7 ぐらいまで。 パルスをどのように制御しようが、流れこんだ電流は出て行くので、パルス側の出力が低ければ上の L を通って電池に流れる。パルス側の出力が上がりすぎれば、逆に上のLを通って電池から流れ込んでくるはず。充電しているときにそうなってしまうのはやりすぎだが、B-C 間の電圧と向きで制御すればよいのだろう。
ちなみに電圧のセンスは、ADC に直接接続せずに、抵抗で分圧したものを入力する。3セルで精度良く測定したいというのも理由だが、パルス充電中に 電池がはずれたときの保護も理由。
----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: 電波時計 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 11/05/2007 23:40:22 ----- BODY: いまのところアイディアのみ。 PSoCをつかったワンチップ電波時計の製作なんてものがある。なるほど PSoC を使えば ほとんど外付け回路なしで作れるのかも知れない。 では、AVR で、できるだけ外付け回路なしで済ませるには、どうしたらよいのだろうと考えてみた。 PC用では、Soft66 なる ソフトラジオがある。CQ出版の付録にも付いたので知っている人もいるだろう。それをまねすることを考える。
アナログスイッチで アンテナ出力を 39 kHz の周波数で、IN/VGND , VGND/IN になるよう切り替える。2つの出力を 差動入力 ADC で受けると... IN / -IN が入力になる。この入力は 40kHz (+ 38kHz)を 1kHz に周波数変換したものになっている。差動入力なので、ATtiny861 なら ゲインも一応 4 段階に切り替えられる。 5 kHz ぐらいで データを取り込んでデジタル処理してやれば、電波時計の 1/0 の信号ぐらいはなんとかなるに違いない。
ちなみに、オペアンプを2個追加して、ATmega88を使うという手もある。1 個は 差動増幅器。もう一個は ゲイン切り替えつき増幅に使う。ゲインの切り替えはあまった 4066 で 4段階が可能。 例: 追記: この差動増幅器は万能ではない。他の回路で使う場合は、電子回路の豆知識がわかりやすいので参照のこと。 Soft66 では、RFアンプがなく、アンテナ入力を直接アナログスイッチに入力している。高周波の増幅をしないで、オペアンプだけで済ますというのが Soft66 のキモのひとつではあるが、はたしてこれで大丈夫なのか?という不安がある。ただ、アンプを付ければ済む話なので、ダメと分かってから考えればよいだろう。 アナログスイッチの ON抵抗は、ものによって違うが 200〜300 Ωほどである。これが 初段のアンプの入力についていると思えばよい。 増幅率は、5.1K/(200〜300) なので、17〜25倍程度。この程度で十分なのか?という疑問もある。PC の 16bit とか 24bit の ADC ならば、ダイナミックレンジが広いので問題ないのかも知れない。ATtiny861 だと x8,x20,x32 の増幅が内部でできるのでたぶん大丈夫だとは思うが、5.1kHz を 10kΩとかにした方がよいかもしれない。これだと cut-off 周波数も 1kHz になる。
あと、これがうまくいくようであれば、AM ラジオにも応用可能だと思う。PWM で 1MHz 前後の周波数は精度は悪いが発振できる。そして、どれぐらいずれているか分かっているので、デジタル処理の方で補正できる。ただ、40kHz に変換するとしても、それを AVR でデジタル処理をするのは相当に厳しそう。 後記: こういう電子工作をしていると、オシロスコープで波形を見たくなる。PC の オーディオ入力を利用したものはないかと思い、ぐぐってみたらHandyOscillo というのがあることがわかった。... →PCM2906 オーディオ帯域オシロに移動 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: 交流電流センサ(2) STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: センサ関係 DATE: 11/06/2007 18:27:15 ----- BODY: 交流電流センサ(1)で、回路を考えてみたが、再考してみた。 いままでの成果
現品.com の電流センサは、電流を微分した出力で
   10Ωを両端につけると 約 0.14 (AC) mV / W の起電力がある。
ADC に入れる前に増幅したり、整流したりしているが... 直接差動入力ADC に入れたらどうなるのだろう?
AREF = 2.49V の ATtiny861 を前提とする。ATtiny861の差動入力ADC は、±の値が得られるバイポーラモードと x8,x20,x32 の増幅機能がある。 x32 の場合分解能は、0.15mV 。そして、0.14 (AC) mV の P-P 電圧は、0.399 mV。1W(相当) の分解能で電流を知りたいだけならば、ADC 側は十分な分解能があることになる。 どのような処理をするか? 差動入力ADC を使って 数 KHzでサンプリングする。得られたデータは微分したものだから、積分しなければならない。単純に加算していけばよいのではないかと思う。たぶん平均が 0 からずれていくことになるが、測定期間を決めてその間でオーバフローしなければよしとする。 そのデータに対してフィルタをかける。DC 成分は HPF でとり、LPF もかけて 高周波も取り除く。これで電流値が得られるはずだ。 AC 電流値への変換は、フィルタリングしたデータを絶対値にして、平均値を計算する。 電圧は? これで電流は分かる。が、電圧は分からない。 電圧を測定するには、出力電圧が低いトランスを用意して電圧を測定すればよいのだろう。セリア充電器のトランスを使うという手もある。 ADC でサンプリングしたものを 絶対値にして、平均値を計算すれば OK 。 ただし、こんな簡単な回路でも、AC 電源を扱うので、面倒なことになる。製作には十分注意する必要があるのは当然として、PSE安全規格を取得しなければ、人にゆずったりすることもできない。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: PCM2906 オーディオ帯域オシロ STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 11/09/2007 18:49:55 ----- BODY: 電波時計や各種センサなどアナログ系の電子工作をしていると、波形を見たくなる。AVR は 8 bit なら 80kHz でサンプリングできて波形入力は精度が低いものの一応できるのだが、それを外部に出力するとなるとメモリが少なかったりして面倒なことになる。そのうえソフトも自分で作らないといけないという問題がある。 PCのオーディオ入力を使うと、ハンディ・オシロスコープをはじめとするソフトが使え、高精度でしかも 2ch 同時サンプリングができる。 安くなった ヘッドセット用のUSBオーディオデバイス( HAMU02とか)を使ってマイク入力の部分を改造して、測定用に使えるものにできるかも知れない。 ただどんなチップを使いどんな回路になっているか分からないので、いっそのこと 1000円前後で手にはいる USB オーディオチップを使って自作を考えてみようと思う。 PCM2906/PCM2904 は、デジキーで入手可能。 S/PDIF は使わないので、PCM2904 でも OK。0.65 mm ピッチだが、変換基板がアイテムラボ秋月で入手できるから、手配線でもなんとかなりそうだ。 データシートを見てみると、基準電圧そのものはないようだ。その代わり、内部で使用している仮想グラウンドが出力されていて(VCOM)、ADC/DAC の電源を分離できるようになっている(VCCCI: 3.3V?レギュレータ出力なので、それ以上の電圧を入力する)。 入力範囲は、1/2 VCCCI(= VCOM) を中心にして、± 0.3 x VCCCI 。VCCCI = 3.6V とすれば、± 1.08V 。反転増幅器を使い、たとえばゲインを 1/5 にすれば VCOM を中心に ± 5.4V が入力できるから、-3.6V〜7.2Vが入力範囲。 そのときの分解能は、0.165 mV これがこのまま精度というわけではないが、ゲイン切り替えを付けなくても十分だと思う。また、交流結合のコンデンサは外して、直流結合にする。 ちなみに、反転増幅器が1つのみだと、反転された値が PC への入力になる。その上 VCOM 分 オフセットされているので注意。
後記:IC内部にHPFが内蔵されていて、直流成分はカットされるとのこと。交流結合のコンデンサは外す意味はない。入力オペアンプの入力にも交流結合のコンデンサを入れて単に 10.8V P-P としたほうが良いかもしれない。
ぐぐって参考になりそうな自作例も発見できた。→ PCM2906, USBオーディオ(2) LPFの効果
この回路から、まず DAC 部分は全部外してしまう。 LPF が必要になった理由はアナログ電源のような気がする。データシートのサンプル回路では、VCOM に 10uF を入れることになっているが、なにも入っていない。VCCCI の方も 10uF と書いてあるが、1uF になっている。 VCCCI に入るアナログ電源部分は、PQ20RX11を使ったらどうか。低ドロップ型なので、3.8V まで上げても問題ないし、電流を流せる。温度特性は、25℃→75℃で 基準電圧が -5mV ぐらい下がる(-1.3%)。あと USB 側にある LCフィルタを VCCCI 側に移動したら良いのではないか。
回路図案(一部) ここまで考察してきて、 HAMU02とかの回路がどうなっているか気になってきた。PCM2904そのものを使っていたとしてもおかしくない。違うチップだとしても DAC 側にオペアンプが入っていれば、VCOM 相当はあるはず。だとすれば、入力側に反転増幅器を入れるのも難しくないように思う。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- COMMENT: AUTHOR: pcm1723 EMAIL: IP: 220.147.28.212 URL: DATE: 11/09/2007 23:19:56 PCM2904/PCM2906 のデータシートの 16 ページの 「ADC DIGITAL HIGH-PASS FILTER FREQUENCY RESPONSE」 のグラフを見ると、3 dB 落ちの周波数が 5 Hz くらいで あることが読み取れます。 これは IC 内部のフィルタなので、回避することはできません。 これに限らず、AC97 コーデックや、HD Audio コーデックでも 大抵、ディジタル HPF が内蔵されていて、残念ですが直流付近の 測定には使えません。 ----- COMMENT: AUTHOR: すz EMAIL: IP: unknown URL: DATE: 11/12/2007 14:36:00 コメントありがとうございます。DC は無理なんですね。それなら安易にUSBヘッドセットでいいかも知れない。あやうく、デジキーに注文するところでした。 ----- -------- AUTHOR: すz TITLE: オーディオ帯域オシロ(その2) STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 11/12/2007 16:30:39 ----- BODY: とりあえず、近所のPCパーツ屋を扱っている店で エレコムの USB-SAV51 を買ってみた。(それしかなかったので) 。買って気が付いたのだが、マイク入力しかないから ADC は 1ch のみ。 Windows XP では何の問題もなく使えそうだ。Linux は微妙。2.4.31 では、Mixer が使えないっぽいし、前に使ったプログラムで出力してみると 1ch でしか 出力できない。(ioctl がエラーになる。)。入力はプログラムも持っていないので、これから。 さて、どんな回路でどんなICなのか調査。 VID/PID 0x0d8c/0x000c -- C-Media CM109 だった。データシート(pdf) マイク入力周りはこんな回路。 1.0uF を介して、マイク入力端子に直接接続されている。内部で +20db(10倍) のアンプを通りさらに +22.5〜0db(16ステップ)のPGAを通って 16bit ADC(44kHz/44.1kHz サンプリング)に接続される。 VREF は、2.25V となっている。VREF が ADCの基準電圧そのものかどうか分からないが、そうだとすれば、入力範囲は最大で 0.225V P-P 最小なら 16.8 mV P-P ということになる。 出力の方は、220uF のコンデンサを通して、ヘッドホーン出力に接続されていた。外付けアンプ用に VREF をボルテージフォワードした出力 LOBS もある。これを 仮想グラウンドにしてアンプを接続すればよいらしい。 入力特性もデータシートにある。マイク入力用にチューニングされているのかフラットではない。微妙に右肩上がり。HPF が入っているらしく、200 Hz 以下になると だんだん落ちて 25Hz あたりで -3db になる。 とりあえず波形がどんな形なのか見るだけなら、これでも十分かも知れない。 ところで、データシートを見ていたら、CM109は結構いろいろな機能を持っていることに気が付いた。ひとつは、I2C スレーブ機能。I2C マスター機能があるコントローラと、CM109 (+USBホスト)間で通信できる。あと 5x4 のキーバッド。興味を引いたが単品では入手できそうにないし、0.5mm ピッチなので、ピンを引き出すのも面倒 -- とりあえず使ってみるのはあきらめる。ただプロトコルの参考にはなるかも知れない。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: デサルフェータの試作と効果について STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: バッテリー関係 DATE: 11/12/2007 19:39:58 ----- BODY: 作ってみたい装置(その2)(4)鉛バッテリー用 デサルフェーターを作ってみて、効果があるか試してみた。 デサルフェータ1号機(M5291FP版)回路:
手軽に作りたかったので、M5291FP という DC-DC コンバータICを使用した。他の部品も手持ちのもので選択。 いろんな点が思惑と違って、予定どおりではなかったが、効果はあったらしい。 鉛バッテリーの放電特性の測定を行った結果(使用前 vs 使用後) (LONG は、劣化していないバッテリーの例) after1 は、劣化しているバッテリー Reliart を デサルフェータで 1日放電させた後測定、after2 は、さらにもう一回デサルフェータで放電させた後のもの。グラフを見るかぎり相当な効果があったように見えてしまう。 ただ、after1/2 ともに フル充電できている状態から放電させたのに対して、使用前はフル充電かどうか自信がない。フル充電とほとんど変わらないはずなのだが、これほどの差になると、怪しい感じがする。まぁ、after1/2 の間でも若干の差があるから、効果はあったのだと思う。 何が予定どおりでなかったか デサルフェータは一般に 50mA ほどの電流を消費して、バッテリーに付けておくものだが、これは、400mA ほども消費する。そのうちいくらかは充電されるはずだが、5割も充電されるとは思えない。実際に 1日〜2日ぐらいでバッテリーは放電してしまう。 コイルに流す最大電流は、0.41 Ωが 0.3V になる値なので、0.73A ぐらい。それにかかる時間(ON time) は、i=Vt/L の関係から計算すると 4us かそこらのはず。周期は 10kHz なので 100us 。ON time の平均電流は、400 mAでもおかしくないが、ON+Off の平均電流が 400mA にもなっている。予定より 20倍ほど消費電流が多いのだ。あと発振周波数も予定と違う。10kHz なら 0.005 uF ほどのはずが、0.012 uFでないと 10kHz まで落ちてくれない。なんか変なのだが、68uH のコイルとダイオードは、ある程度発熱しているので、仕事はしているようだ。 よくわからない特性になってしまったが、放電器+デサルフェータと考えることにして、1日〜2日放置してどうなるかまずは見てみることにしたわけだ。 もし2号機を作るなら まず、効果より消費電力を優先して設計する。そのために、On time / Off time を正確に制御したほうが良いと思う。あと過放電対策をちゃんといれる。 コイルは、できたら 2A のものを使ってみたい。たぶん 220uH もいらないだろう。68uH 〜 100uH 2A で良いのではないか。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: AVR32 UC3シリーズ STATUS: Draft ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 11/15/2007 17:00:04 ----- BODY: AVR32 UC3シリーズを知り興味がわいたので紹介。 doc7919 (pdf,4pages)に分かりやすい概要が(Atmelにしては珍しく日本語で!)載っている。 ざっと見ると、AT91SAM7S の AVR32 版という感じ。ワンチップマイコンなのに、DMA が使え、内蔵デバイスも AT91SAM7S ±α。
core 1.8V/IO 3.3V の2電源だが、レギュレータがあり 3.3V 単一電源も OK 。消費電流は、60Mhz で 23mA (AT91SAM7S よりちょっと低い程度) 2〜4 個の USART, TWI, 1〜2個の SPI, 6chの16bitPWM,6〜8個の10bit ADC がありさらに... UC3B1X は TQFP48(0.5 mmピッチ) で USB デバイスになる。UC3B0X は、64 pin になってしまうが、OTG 機能もあり、さらに SSC(同期シリアルコントローラ) が載っていて I2C サウンド入出力ができたりする。UC3A1X は、100 pin だが、さらに 100Mイーサが付いている。UC3A0X になると、144 pin になり、SDRAM も付けられる。 注)100Mイーサといっても MAC までなので、DP83848など PHY が必要。
開発環境は、AVR32 Studio が無償で使えて、GNU ツール・チェインも提供される。リアルタイムOS は、FreeRTOSが利用できるそうだ。 今デジキーで入手できるのは、残念ながら、評価ボードのATEVK1100だけ。しかも 約16000円でちょっと高い。ATNGW100の方が安いぐらいだ。
ATNGW100 については、AVR32 NGW試食が参考になる。 8bit AVR に飽き足らなくなったら、AT91SAM7S にしようと思っていたのだが、 AVR32 UC3シリーズも(入手可能にさえなれば)良いかも知れない。 ただ、AT91SAM7Sと違って、SAM-BA boot のようなものがない、JTAG がないと書き込みができない。
----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: LMC555で1セル昇圧 STATUS: Draft ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: I2CPWR DATE: 11/20/2007 15:36:06 ----- BODY: AVRで1セル昇圧は可能か?の記事で試したが、NiMH 1セルでAVRは起動させるのは無理という結論だった。その記事で、LMC555を補助的に使えばなんとかなるようなことを書いたが、その回路について。
この回路は、データシートに載っている 50% デューティ・サイクル・オシレータをベースにしたもの。Disch 出力は、オープンドレインなので、昇圧回路のスイッチングに使える。といっても Disch は、最大 100mA 、小電流しか流せない。インダクタも それにあわせて、LAL02NA470Kを使う。 47uH で 70mA しか流さないとして、ON タイムは 47 /1.2 * 0.07 = 2.74 us。50% duty なので、周波数は 180 kHz 以上。それにあわせて RC を選んでみた。 さて、いくら電流が少ししか流せないとしても、消費が なければ電圧は上がり続けてしまう。そのため、電圧が上がりすぎると発振を止める必要があるのだが、Reset は、Disch=1 になってしまうので、使えない。発振を止めるために、NPNトランジスタを使って、Thresh = Trigger を 0V にすることにした。 3.3V にあわせているが、トランジスタなので温度の変化で電圧が変わるので注意。 どれぐらい電流がながせるか? まず、1.2V から流れ込む平均電流は、周波数・Duty比を最適にできたとしても 三角形の波形になるから、70mA の 1/2 になる。35 mA しかないわけだ。Duty 比率 50% 固定なので、最適にできるはずもないので、たぶん 1/3 程度 ... 23 mA ぐらいか。 効率が 80% ぐらいあると仮定して、3.3V まで昇圧するとすれば、6.7 mA ぐらい。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: オーディオ帯域オシロ(その3) STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 11/20/2007 19:29:58 ----- BODY: 安価なヘッドセット用のUSBオーディオアダプタは、CM109とかを使っていてマイク入力しかなく、2ch 同時に取り込むことはできないようだ。 やはり、PCM2904/6 で自作というのが良いようだ。...といっても直流付近は扱えない。 いっそのこと、AT91SAM7S に 好きな ADC つなげて 2ch 同時に取り込みとかできないかググッたところ、ARM MP3/AAC Player - www.mikrocontroller.netなんてページを見つけた。 これは、MP3プレイヤーだが、AUDIO DAC として、TLV320AIC23Bを使っている。デジキーでも扱っていて、745円と安価なようだ。 データシートを見てみると、24bit 96kHz ステレオ DAC 以外に、24 bit 96kHz ステレオ ADC も持っている。デジタルのHPFは入っていないように思える。ひょっとしてどこかに書いてあるのかも知れないし、常識化していて書くまでもないことになっているのかも知れないとも思うが、直流が扱えると嬉しい。
後記: ADC high-pass fileter に関する(親切な)説明はないが、Digital Audio Path Control レジスタの ADCHP で disable にできるようだ。
AT91SAM7SやAT32UC3B(AT91SAM7S の AVR32版(概要、日本語pdf))と組み合わせて MP3Player とか 高機能なUSBオーディオアダプタ=オーディオ帯域オシロを作るのも面白いかも知れない。 といっても、このクラスはお手軽にというわけにはいかないし、このブログでは扱わないのだ。でも、せっかく調べたので、報告ということで。 (後記) TLV320AIC23Bは、HPF を Off にでき、普通のADC のように使えるかもしれないということで、がぜん気に入ってしまった。 0.65 mm ピッチの 28-TSSOPなので、安価な変換基板で DIPにもでき扱い易いし、安価。 さて、普通は、32bit のプロセッサで扱うものだと思うが、フル機能でなくても良いから AVR でお手軽に扱えないだろうか。 コントロールは、Port ベースの I2C (or SPI)で扱えるので問題ない。 TLV320AIC23Bは、master/slave 両方できる。ADC の場合は、同期が一度とれてしまえば、バイト単位で受信するだけでよい SPI スレーブを使うのが良いかもしれない。(CPUCLOCK > BCLK x 4 に注意) SPI を持っているATmega88 系+FT245RLでなんとかなるかも知れない。 (後記2) TLV320AIC23Bは、4種類のフォーマットを扱える。I2S もあるが、DSP モードというのがある。そして、DSP モードは、SPI そのものに思える。SPIスレーブで ADC データを受信するのは楽そうなのだが、DAC は無理。SPI マスターの方で実装すれば、DAC も扱えそう。 FT245RL で使うことを想定すると、ATtiny2313 では pin 数が足りないので、ATmega88 を使うことにする。クロックは一応 12MHz 水晶として検討してみる。 TLV320AIC23Bは、外部クロックも受け付けるので、ATmega88 の CLKOUT を 使う。同じクロックソースにすれば、タイミングを完全に合わせられる。TLV320IAIC23B は、クロック 12MHz or 24MHz のとき、USB モードというのを使用する。タイミングは、48ksps = 250clock , 44.1ksps = 272 clock。 SPI は CPUCLOCK/4 の 3MHz にすると、48ksps = 62.5 clock 。16bit x 2 でも 24bit x 2 でも 間に合う計算になる。AVR の処理も 24 clock で 1 バイトの処理をすればよいので、間に合うと思う。間に合わなければ 24MHz にすれば大丈夫だし、間に合えば 24MHz で 96ksps も OKということになる。 以上は、AVR 側の話。FT245RL がデータを切らさずに送受信できるかどうかというのは別になる。96ksps で 24bitx2 だと、ADC だけでも 567kbyte/sec 出せないといけない。仮想COMポートは無理だと思う。48ksps で 16bit x 2 なら 192 kbyte/sec で仮想COMポートでもいけるのではないかと思う。 (後記3) 基準電圧は、AVDD で決まる。AVDD/2 が仮想グラウンドになるし、3.3V のとき 入出力ともフルスイングで 1.0Vrms = 2.828 Vp-p だそうだ。 LINEIN は、内部に 32段階のプログラマブルゲインアンプがあり、+12.0db 〜 -34.5 db まで -1.5db 刻み。(デフォルトは 0db) ブロック図をみるかぎり、AVDDは、基準電圧を決めているだけのように見える。2.7V〜3.6V ということになっているが、TL431を使った2.5Vでも良いのではないだろうか? キャリブレーションにも使えるし。ちなみに、どうせならTL431の高精度版? LT1009CLPとか使ったらどうだろう。
電源をどうするのが良いかついては、やはりよくわからない。Ultra Low-Noise とうたっている 2.85V レギュレータ SI91841DT-285でアナログ系全部供給した方が良いかも知れないし、すなおに 3.3V レギュレータ MCP1700-3302Eとかで全電源供給して、AVDD だけ LC フィルタ入れるだけでも良いのかも知れない。
(後記4) ひょっとしたら、FT232RL + ATtiny2313でも扱えるかも知れない。pin の数は足りると思し、処理自体は単純だから 2K に入るかも知れない。USIで取り込みUSARTに直接書き込む処理を割り込み禁止で回せば、48ksps 16bit x 2 なら間に合うかも知れない。間に合わなければ 32ksps とかサンプリングレートを落とせばよいだろう。 FT232RL は、3Mbps に設定するが、その速度でコマンド処理はできないので、コマンドは、2バイトまでにしてハンドシェークする。このあたりは、AVR910とかと同じ考えで良さそう。送信は、3Mbps でほとんど連続して送ることになるはず。FT232RL 側でそれができないと難しいかも知れない。 (後記5) できたら、AT90USB162 を使ったものを作りたいと思っているのだが、その前に ...FT245RL + ATmega48 で実験してみたいと思っている。SPI マスターにする場合、SPI より USART で代替したほうが性能が出せるのではないかという気がしている。それを実験してみたい。うまくいくなら、SERJTAG も作り直したい。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- COMMENT: AUTHOR: pcm1723 EMAIL: IP: 220.147.28.212 URL: DATE: 11/20/2007 22:15:38 残念ながら、データシートの 3-11 ページ 3.3.3 Digital Filter Characteristics ADC High-Pass Filter Characteristics の項に、fs=48 kHz の場合 4.0 Hz で -3 dB と なることが明記されています。 この IC に限らず、マイクアンプ等の高ゲインの アンプを内蔵している ADC は HPF は不可避で あると思います。 ----- COMMENT: AUTHOR: すz EMAIL: IP: unknown URL: DATE: 11/21/2007 11:52:17 む、ADC High-Pass filter で検索してみたら、ADCHP というパラメータで Disable にできるようです。あんまり自信ありませんが、どうでしょう。 ----- COMMENT: AUTHOR: PEN^2 EMAIL: IP: 58.89.114.171 URL: DATE: 11/26/2007 12:29:14 >ひょっとしたら、FT232RL + ATtiny2313でも扱えるかも知れない。 無理にAVRを使うよりも、I2S信号をSPDIF信号に変換する「デジタル・オーディオ・トランスミッタ」を使った方が確実では? もっともPC側にSPDIF入力が無いとダメですが。 Digi-Keyで入手可能なものは、CS8405,CS8406,DIT4096,DIT4192 といった所でしょうか。 ----- COMMENT: AUTHOR: すz EMAIL: IP: unknown URL: DATE: 11/26/2007 17:40:57 制御だけAVRでやって、データはSPDIFで、というのもひとつの方法かも知れません。 ただ、私のPCは、SPDIFがないのです。 私の発想だと、無理のない設計=AT91SAM7S でということになるんですが ... 無理にAVRを使うというのが、このブログのテーマだったりもするので、トライはしてみたいと思っています。 といっても、さすがに、FT232RL + ATtiny2313 は無理そうだし、第一 3 chip の構成が気に入りません。できたら、AT90USB162 でやってみたいなと思っています。 ----- -------- AUTHOR: すz TITLE: MC34063/NJM2360版デサルフェータ(案) STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: バッテリー関係 DATE: 11/27/2007 02:17:19 ----- BODY: M5291FP は、MC34063,NJM2360 とほとんど同じという情報をもらったので、MC34063/NJM2360版デサルフェータの案だけ書いてみることにした。 MC34063,NJM2360は、100円シガーライターソケット用 DC-DCダウンコンバータに使われていたりして、有名な IC らしい。NJM2360 は日本語のデータシートがあるが詳しくない。M5291FP のデータシートに詳しい説明が載っているので、NJM2360 のデータシートと比較しながら見ると 理解が深まると思う。 回路図(案) M5291FPと違って、電流を流せるので、外付け Tr が必要なくなり、回路は簡単になった。 L1/L2 は、千石で扱っている LHLC10NBが良いのではないかと思う。昇圧用のL2 は、1.5A まで流せる 100uH のものを使い、L1 は 1mH で良いのではないかと思う。 周波数を決める Ct は 0.12 uF にしてみたが、良く分からない。この値ぐらいからはじめて、10kHz になるよう調整したらよいと思う。 電流制限用の抵抗は、最初は大きな 値で試したほうが良さそうなので、一応 0.41 Ωとしてみたが、1.5A まで流すなら、0.2 Ωにする。L1 や コンデンサが熱くなるようなら、電流を流しすぎていると思う。テスターで Rsc の電圧を測定して、平均電流を調べながら調整すると良いだろう。 回路図では、5 番ピンのINVin を GND にしてしまっているが、上限が16Vぐらいになるよう分圧抵抗を入れたほうが良いと思う。 さらにいうと、TL431 + トランジスタ(かなにか)を使って 10V が下限になるように工夫したほうが良いと思う。 追記:07/11/30 秋月の シガープラグ 6V (200円) も MC34063使っていますね。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- COMMENT: AUTHOR: 久我 EMAIL: IP: 218.229.188.15 URL: DATE: 12/02/2007 18:13:01 NJM2360で組んでみました UPSのバッテリー回復しないかな〜 ----- -------- AUTHOR: すz TITLE: AT90USB162メモ STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 11/27/2007 16:21:55 ----- BODY: Atmel から USB インターフェイスが付いた AVR として AT90USB162 が出ている。32 TQFP のパッケージがあってわりと手軽に扱えて、値段も デジキーで520円と安価。 ブートローダが、最初から FLASH に載っているので Windows や Linux から ソフトだけで書き込みできる。水晶は必須で、FT232RL 並とはいえないが、わずかな外付け部品で動かせる。 AVR-CDC のようなドライバさえ充実したら、かなり使い易いものになりそう。 というわけで、こいつで少しばかり遊んでみたいと思っている。
USB のデバイスクラスのうち、CDC とか AUDIO とかを扱えるようになりたいと思っているんだが... デバイスクラスの定義は膨大で正攻法ではなかなか難しそうだ。 最初は、AVR-CDC のコードを移植することから始めれば、一応動かせるものが出来上がるに違いない。で、知識レベルが上がったところで、Atmel のコードを見ながら AUDIO に挑戦するという手順か。
配線メモ アイテムラボ変換基板ベース
チップ入手先
デジキー520円 マイクロファン840円
評価基板
OLIMEX AVR-USB-162
サンプルコード・ドキュメント
AVR USB Software Packages Free USB firmware for Micro-Controller
AT90USB1287用だが参考になる
USB Device Class 定義ドキュメント(www.usb.org) HERO'S Downloadにある、AVRusb.ZIP に含まれる USB概説(USBspecs.PDF) MAX3420Eアプリケーションノート(日本語)にある、アプリケーションノート3690 MAX3420EのUSBエニュメレーションコード(およびその他) -- USBの解説がすばらしい。
DFU (Device Firmware Update) ブートローダと対応プログラマ
USB DFU Bootloader Datasheet (pdf) -- データシートのページの下の方 AT90USB162 USB Bootloader v1.0.1 (HEX ファイル) -- Tools & Softwareのページの下の方 dfu-programmer -- Linux で使える DFU 用のプログラマ STK526評価キットのページ Hardware User Guide の回路図に、ブートローダを(強制?)起動するボタンがある。OLIMUX AVR-USB-162 も PD7 に ボタンが接続されてて同じ。...データシートにもちゃんと載っていた。キーワードは HWB
WinAVR-20070525 / gcc-4.2.[12] + avr-libc-1.4.7 の問題点 AT90USB162/AT90USB82 が avr5 になっている。avr5 だと AT90USB162/AT90USB82 が持っていない 乗算命令を使ってしまう。 正しくは avr3 にしなければならないが、gcc も avr-libc もバグっている。当面は、乗算を使用しないようにして、乗算命令が出ていないか avr-objdump -d でアセンブラリストを出力し、チェック(mul を grep)する必要がある。 乗算命令が出るようなコードにしてしまったら、コードをなんとか変更する。それでもダメなら 次のオプションでコンパイルしてみると良いかもしれない。
 -mmcu=at90usb162 
       ↓
 -mmcu=avr3 -D__AVR_AT90USB162__
avr-libc で乗算命令を使うものをリンクしてしまった場合、 まず リンクのオプションを次のように変更する。
 -mmcu=at90usb162 
       ↓
 -mmcu=avr3 -Tdata=0x800100 -v
これだけでは、だめで、このときの ld のオプションを調べ、avr3/crtm103.o となっているところを avr5/crtusb162.o に変更して、ld を直接実行する。
WinAVR プロジェクトには、このバグについて だいぶ前に報告されている。次のリリースでは修正されると思う。 WinAVR-20070525 の gcc のビルド方法が分かったので、ためしにat90usb162/at90usb82 のアーキクラスを avr3 に変更する avr-gcc.exe を作ってみた。→ usb162-gcckit-0.1.zip フロントエンドの avr-gcc.exe のみなので、サイズは小さいです (270KB)。もし困っている人がいれば、使ってみてください。
カテゴリ USB162につづく。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- COMMENT: AUTHOR: すん EMAIL: IP: 219.111.149.153 URL: http://ekousaku.web.fc2.com/ DATE: 11/29/2007 21:41:19 私の掲示板にこちらのページをリンクさせていただきました。AT90USB162をマイクロファンに注文したのですが、他に製作記事がなく、こちらのページが参考になります。ありがとうございます。 http://www.style-21.jp/bbs/ekousaku/index.html ----- COMMENT: AUTHOR: すz EMAIL: IP: unknown URL: DATE: 11/30/2007 05:21:19 avr-gcc + avr-libc でコードを書くなら、USB_GEN_vect とか使うはずなんでググってみたんですが、まったく見つかりません。 というわけで、気長にやりましょう。 ----- -------- AUTHOR: すz TITLE: CDC クラス調査(1) STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: USB162 DATE: 11/30/2007 01:10:48 ----- BODY: AT90USB162メモからの続き AVR-CDC と Atmel のコードを読み、CDC クラスがどういうものかまとめることにする。( 用語はコードのものをベースにするので、正式なものとは限らない点に注意) CDC のディスクリプタ USB デバイスを作る場合、ディスクリプタを作る必要がある。CDC の場合どういうものを作るのかについて CDC では、大きくわけて次の 7 つのディスクリプタを作らなければならない。
Configuration Descriptor
   Interface 0 descriptor              (CDC ACM Comm)
       CDC Class-Specific descriptor
       Endpoint 3 descriptor           (Interrupt IN)
   Interface 1 descriptor              (CDC ACM Data)
       Endpoint 1 descriptor           (Bulk IN)
       Endpoint 2 descriptor           (Bulk OUT)
Comm と Data という 2 つのインターフェイスがあって、それぞれに 1つ,2つ 合計 3 つのエンドポイントがある。 次にそれぞれの定義がどうなっているかについて。 Atmel のコードをベースにして、AVR-CDC で違う部分は、[]でコメントを入れる。(ただし記述の順番が違うだけのものは違いとみなさない) Configuration Descriptor
    Size                      9
    Type                      0x02  (Config)
    ExternalConfig Size       0x0043
    # of Interfaces           2
    Index                     1     (#1)
    StringIndex               0
    Attribute                 0x80(BUSPOWER)
    MAX Power                 50 (100mA)   [ 100 (200mA)]
Interface 0 descriptor (CDC ACM Comm)
  Size                      9
  Type                      0x04  (Interface)
    Interface Index           0     (#1)
    Alternate Setting         0
    # of Endpoints            1
    Interface Class           0x02  (CDC ACM Comm)
    Interface SubClass        2
    Interface Protocol        1
    Interface String Index    0
CDC Class-Specific descriptor
Atmel の場合 16進数が並んでいるだけ、おまじないと思えばよいかも知れない。4 つのデータが含まれている。意味はわからないが、若干差異がある。
    5,  0x24, 0x00, 0x10, 0x01
    5,  0x24, 0x01, 0x03, 0x01
    4,  0x24, 0x02, 0x06             [ 4, 0x24, 0x02, 0x02 ]
    5,  0x24, 0x06, 0x00, 0x01
Endpoint 3 descriptor (Interrupt IN)
  Size                      7
  Type                      0x05  (Endpoint)
    Endpoint Type/Index       080 | 0x3  (IN,#3)
    Endpoint Attribute        0x03       (Interrupt)
    Max Packet Size           32         [ 8 ]
    Interval (ms)             255        [100]
Interface 1 descriptor (CDC ACM Data)
  Size                      9
  Type                      0x04  (Interface)
    Interface Index           1     (#2)
    Alternate Setting         0
    # of Endpoints            2
    Interface Class           0x0a  (CDC ACM Data)
    Interface SubClass        0
    Interface Protocol        0
    Interface String Index    0
Endpoint 1 descriptor (Bulk IN)
  Size                      7
  Type                      0x05  (Endpoint)
    Endpoint Type/Index       080 | 0x1  (IN,#1)
    Endpoint Attribute        0x02       (Bulk)
    Max Packet Size           32         [ 8 ]
    Interval (ms)             0
Endpoint 2 descriptor (Bulk OUT)
  Size                      7
  Type                      0x05  (Endpoint)
    Endpoint Type/Index       0 | 0x2    (OUT,#2)
    Endpoint Attribute        0x02       (Bulk)
    Max Packet Size           32         [ 1 or 6 ]
    Interval (ms)             0
このように、ディスクリプタのレベルでは、ほとんど同じになっている。ちなみに、AVR-CDC の Max Packet Size が最大 8 になっているのは、Low-Speed の上限が 8 のため。 そういえば、ベンダーとかデバイスID は? これは、Configuration ディスクリプタではなく、デバイスディスクリプタに記述するらしい。
  Size                      18
  Type                      0x01  (Device)
    USB Version               0x0200    [ 0x0101 ]
    Class                     2
    SubClass                  0
    Protocol                  0
    Max Packet Size           32        [ 8 ] 
    VENDER_ID                 0x03EB    [ 0x16c0 ]
    PRODUCT_ID                0x2018    [ 0x05e1 ]
    RELEASE_NUMBER            0x1000    [ 0x0100 ]
    VENDER String Index       0         [1:www.recursion.jp]
    PRODUCT String Index      0         [2:USB-232]             
    Serial# String Index      0
    # of CONFIG               1
おおざっぱにいうと、これらディスクリプタを定義して、エンドポイントを 3 つ作り、それぞれに対して、処理を作れば、CDC ドライバになるはず。 (続き) 次に、いったいどんな処理をしなければならないのか? AVR-CDC が使っている usbdrv ドライバのコードを見てみると、usbProcessRx() という関数がある。これが受信すべての入り口らしい。 まず、usbRxToken が USBPID_SETUP の場合 2つの処理に分けられる。bmRequestType が、USBRQ_TYPE_STANDARD の場合、次のリクエストに対応した処理をしなければならない。
   SET_STATUS                0x0
   SET_ADDRESS               0x5
   GET_DESCRIPTOR            0x6
   GET_CONFIGURATION         0x8
   SET_CONFIGURATION         0x9
   GET_INTERFACE             0xa
   CLEAR_FEATURE             0x1    
   SET_FEATURE               0x3
   SET_INTERFACE             0xb
   
   SET_DESCRIPTOR            0x7   (NOP)
   SYNCH_FRAME               0xc   (NOP)
USBRQ_TYPE_STANDARDでない場合は、usbFuntionSetup() を callしていて、CDC の場合
   GET_LINE_CODING           0x20
   SET_LINE_CODING           0x21
   SET_CONTROL_LINE_STATE    0x22
   SEND_BREAK                0x23  (NOP)
の処理があるようだ。 また、usbRxToken & 0x80 の場合、HOST から送信データが来ているので、usbFunctionWriteOut() 関数が呼び出されて、usbcdc.c で受信処理をしている。( データを Buffer に格納するだけ ) ちなみに、HOST への送信はどうしているかというとusbBuildTxBlock() 関数で 送信データを作成しておいて、HOST からリクエストがきたとき送るようにしているらしい。AT90USB162 では、エンドポイントにデータを格納すればよいように思う。 さて、Atmel のコードについて、受信処理を上のキーワードをたよりに探すと、modules/usb/device_chap9/usb_standart_request.c にあることが分かった。 ここらあたりを足がかりにして、AT90USB162 のコードをくみ上げれば良さそう。
見ているコードは、at90usb162-cdc-1_0_1.zip。 ちなみに AT90USB128 用の AUDIO Class のコード at90usb128-demo-audio-1_0_2.zip も同じような構造をしている。メモリとか chip のリソース量の問題がなければ、AT90USB162 でも使えるかも知れない。
ここまでざっと見た感じでは、USBインターフェイスを持っていてもプロトコル処理は 同じようにしなければならない。コードの量は全体で 1000 line 弱で 2KB 程度になりそうだ。 作り方としては、できるだけ usbdrv.c のリプレースになるようにして、usbcdc.c で変更が必要な部分を 切り分けるのが良さそうな気がしている。
これは保留。getc/putc のインターフェイスさえあれば良いので、Atmel のコードで必要なものを集めて、いったんコンパイル可能なものにしてから、書き直すようなことをするかも。
(続き) Atmel コード解析 エンドポイント設定
No   Desc           Type      IN/OUT size   bank  timing
#0 Control         CONTROL    OUT    32      1  SYS_INIT,USB_RESET
#3 Interrupt IN    INTERRUPT  IN     32      1  SET_CONFIG
#1 Bulk IN         BULK       IN     32      1  SET_CONFIG
#2 Bulk OUT        BULK       OUT    32      1  SET_CONFIG
0 番のエンドポイントは、明示的に作らなければならない。そのため、合計4つのエンドポイントを定義している。 バッファに使えるメモリの合計は 176 バイト。そのうち 32x4 = 128 バイト使っていることになる。 バンク数=1 は、いわゆるシングルバッファと同じ。処理中に 受信・送信をオーバラップしてできるように、ダブルバッファの機能があるが、使っていない。
割り込み 割り込みは、USB装置割り込みしか使っていない。どうも、エンドポイントの処理はポーリングのようだ。 データの送受信をしているコードが見当たらないので、はずしているのかも知れない。...が、エンドポイントアクセスのためには、UENUM を設定してアクセスするエンドポイントを選択しなければならないのだが、その部分について割り込み禁止にしていない。..ということは、割り込みでエンドポイントにアクセスしないということになるはず。 割り込みで処理しているのは、RESET の処理のみ。その場で処理するというより、イベントを介して、ポーリングでの処理の中で RESET 処理をしているように見える。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: テスト用ボードの作成 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: USB162 DATE: 12/03/2007 18:31:27 ----- BODY: テスト用にボードを作ってみた。 写真: 回路図: アイテムラボの変換基板を使用。 USBの D+/D- に付ける抵抗は、データシートには、22Ω(±5%) と書いてあるが、手持ちの関係で 33Ωにしてみた。リセットボタンは省略。HWB ボタンはちゃんと付けた。あと、外部接続用 兼 ISP用 コネクタも作った。 テスト ISP で使えるかどうか調べるために、USB に接続してみたところ、ホストの Linux 側でなにか動作した。 見てみたら、DFU ブートローダが起動して、USB 機器として認識されていた。

T:  Bus=01 Lev=02 Prnt=02 Port=01 Cnt=02 Dev#= 34 Spd=12  MxCh= 0
D:  Ver=20.00 Cls=fe(app. ) Sub=01 Prot=00 MxPS=32 #Cfgs=  1
P:  Vendor=03eb ProdID=2ffa Rev= 0.00
S:  Manufacturer=ATMEL
S:  Product=AT90USB162 DFU
S:  SerialNumber=1.0.0
ISP を接続して、ヒューズビットを見てみると、データシートの通り、下位バイト 0x5E, 上位バイト 0xD9。内蔵RC オシレータでちゃんとUSB 接続ができているらしい。 訂正:CLKSELは、1110 なので、水晶が選択されている。内蔵RC オシレータは、0010 。 ためしに FLASH 領域をみてみたが、全部 0xff で見えなかった。ロックビットが設定されているらしい。
これは、データシートにも記載されていた。
dfu-programmer を試す
#dfu-programmer at90usb162 get manufacturer
Manufacturer Code: 0x58 (88)

#dfu-programmer at90usb162 get product-name
Product Name: 0x94 (148)

#dfu-programmer at90usb162 get bootloader-version
Bootloader Version: 0x00 (0)

#dfu-programmer at90usb162 frash test1.hex
Validating...
336 bytes used (2.73%)
こんな感じで書き込みできた。test1.hex は無限ループするだけのプログラム。 つぎからは、test1.hex が起動するので、ブートローダは動かない。 さて、いったん USB をはずし、HWB ボタンを押しながら USB に接続すると ブートローダが起動するはず ... なのだが、なぜか動かない。わからなくなったので、ISP で chip erase してしまった。 次に、Atmel から出ているブートローダを書き込もうとした。... のだが 書き込めない。... フォーマットがなにか変。奇数ではじまっていたりするのはともかく、チェックサムが全部合わないのだ。しょうがないので初期値 0xff として正規化したものを作り書き込んだ。 再度試す。 Bootloader Version が 0 から 1 になっている。 HWB ボタンを押しながら USB に接続してみたところ、ちゃんと接続できた。(4 秒ぐらい かかった。)
もはや元に戻せないのではっきりしたことは分からないが、Version 0 では二度と書き込みできないのかも知れないし、なにかおまじないをすればよかったのかも知れない。それ以前に、私がなにか勘違いしていた可能性もある。 とにかく当面は、ブートローダのみに依存せずに ISP も使えるようにしておいたほうが無難だろう。 後記: どうも、HWB ボタンを押しながらの USB 接続が、操作的に難しいのが原因らしい。何回か失敗したが、ISP でのリセットを併用したら確実になった。リセットボタンを付ければよいのだが、場所をとるし..スライドスイッチの方が良いかも知れない。
ともあれ、Bootloader での書き込みが問題なくできるようになったので、安心して開発できる。 どうやって開発するか? Google Code Search で S. Salewski 氏の Free USB firmware for Micro-Controllera というのを発見した。
FIFOCON というキーワードで検索すると avr-libc 以外にはこれしか見つからない。AT90USB1287 用のようだが、唯一公開されているソースかも知れない。
GPL で公開されていて、tar ファイルもあるので、見てみたところ、1 ディレクトリに全部が入っていて avr-gcc でビルドできた。コードも Atmel のよりずっと分かりやすい感じ。また Atmel になかった エンドポイント割り込みの処理が入っている。 まずは、これをみて、処理を考えてみようと思う。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: USB ミニBコネクタ STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 12/03/2007 19:29:02 ----- BODY: ちょっと思い立って、FT232RL のボードを作ってみた。 写真: アイテムラボの変換基板を使い、FT232RL と 10uF のコンデンサ 2 個、それに USBミニBコネクタを載せて、それだけで使えるようにしてみた。 苦労したのは、ミニBコネクタ周り 0.65 mm ピッチで、自分の技量ではケーブルをハンダ付けできそうにない。しょうがないので、1,3,5 pin を立てて みたら、うまくハンダ付けできた。 ピンの接続は
  1   VBUS
  2   D-
  3   D+
  4   NC
  5   GND
浮かした 1,3,5 pin は外れても 直せるが、2 pin は難しいのでしっかり付ける必要がある。ちなみに、下に見えている黄色いのは、絶縁に使ったポリミドテーブ。熱を加えないので耐熱である必要はないのだが、持っているので使ってみた。
ちなみに、ポリミドテープは、 例えば 電子電気店で入手可能。 (本題とは関係ないが 電子電気店は意外にも、電子部品セットが充実している。抵抗セット、セラミックコンデンサセットあたりはお勧め。) 使ったミニBコネクタは、モレックス製だが、秋月で ヒロセ電気製が 3 個 200円で 入手可能
後記 一応作ってみたが、FT232RL を使う場合は、秋月のFT232RL USBシリアル変換モジュール 950円の方が良いかも知れない。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: ドライバの設計とテスト(1) STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: USB162 DATE: 12/04/2007 21:28:11 ----- BODY: 最初の目標 まずは、なんでも良いから動かすことを目標にする。コードを綺麗にする(著作権のクリアとか構造化なんてもの)は後回し。 参考にするのは、AVR-CDC のコードと usbdrv あと Atmel のコードと さらに S. Salewski 氏の Free USB firmware。 ドキュメントは、USB の基本知識として HERO'S Download の AVRusb.ZIP に含まれる USB概説、AT90USB162 の日本語データシート。さらに(なぜか)MAX3420E のアプリケーションノートAN3690(日本語)。
AN3690 には、”少しわかりにくいですが、これが USB と HID仕様 のすべてです。” -- なんて自信たっぷりな記述がある。USB バストレースの図まで載っていて、イメージがつかめた。 非常に分かりやすいのでお勧め。 これらのリンクは、USB162メモにまとめておく。
プログラムの作成方針 Atmel のコードと S. Salewski 氏の Free USB firmware は、ひとつひとつの操作がマクロ化されていて、実際にどのような操作をしているのか分かりにくい。趣味に合わないので、マクロを全部なしにして、直接操作するようなコードで re-write することにした。 デスクリプターの記述については、AVR-CDC をベースにして楽をする。あと、ヘッダも AVR-CDC (と usbdrv) の一部を借りる。 割り込み処理は、USB装置割り込みのみを使用して、Atmel 流に ポーリングをベースにすることにした。 こんな感じで、まずは コードをでっちあげることにした。 外部インターフェイス USB910 とかで使っている XXX_init() ,XXX_poll() ,XXX_getc() ,XXX_putc() を基本のインターフェイスにする。 これさえ揃えば、いままで作ってきた AVR-CDC を使ったコードを動かすことができるはず。 エコーバックさせるこんなプログラムで、テストする。
  main() {
     XXX_init();

     for (;;) {
        XXX_poll();
        XXX_putc(XXX_getc());
     }
  }
エンドポイント処理 (OUT=受信) エンドポイントの 1バイト データ取り出しは、(UENUM を設定した後)UEDATX を読み込むことでできる。XXX_getc() で直接この処理をすることにして、中間バッファを持たないことにする。 バッファが空でないことを知る方法は 2 つある。ひとつは、UEINTX の RWAL ビット、もうひとつは、UEBCLX(エンドポイントバイト数レジスタ)。 バッファが空になったら、UEINTX の FIFOCON をクリアすることで、次の受信ができるようになる。 受信したら、UEINTX の RXOUTI ビットがセットされる。FIFOCON をクリアする前にクリアしなければならないらしい。XXX_poll() で 常に RXOUTI ビットをクリアすることにする。(たぶん問題ないはず) エンドポイント処理 (IN=送信) OUT=受信と対のような感じ。 エンドポイントの 1バイト データ書き込みは、(UENUM を設定した後)UEDATX に書き込むことでできる。XXX_putc() で直接この処理をすることにして、中間バッファを持たないことにする。 バッファが一杯でないことを知る方法は 2 つある。ひとつは、UEINTX の RWAL ビット、もうひとつは、UEBCLX(エンドポイントバイト数レジスタ)。 UEINTX の FIFOCON をクリアすることで、バッファの送信が行われる。 送信したら、UEINTX の TXINI ビットがセットされる。FIFOCON をクリアする前にクリアしなければならないらしい。XXX_poll() で 常に TXINI ビットをクリアすることにする。(たぶん問題ないはず) さて、受信と違うのは、いつ送信するかということ。1 バイトづつ送信することもできるし、フルになるまで溜めることもできる。 これは、スループットとレスポンスのトレードオフで決めるべきことなのだが、とりあえずは、XXX_poll() で送信してしまうことにする。 エンドポイント処理 (SETUP) これが肝心なのだが、SETUP の処理は良く分からなかった。 プログラム自身はわりと簡単で、XXX_poll() で エンドポイント 0 に SETUP が来ていたら usb_process_setup 関数で処理させるぐらい。でも、どのような処理をすればよいかが分からないのだ。 とりあえずは、S. Salewski 氏の コードの処理をベースにして Atmel のコードの処理を参考にしてでっち上げた。
でっちあげるのは良いが、基本的なことを理解していないので全然動かせなかった。動かせる気もしなかった。MAX3420E のドキュメントを読んでようやく動かせる気になったわけだ。
装置割り込み 本当は、SUSPEND やら WAKEUP やら RESUME やらの処理をすべきなのだが、とりあえず RESET のみ対処することにする。 ... と思ったのだが、USB のリセットで CPU をしまう方法があることが分かったので、割り込みを受けるだけのコードになってしまった。たぶん今のところ意味なし。 初期化 これも実によくわからない。#0 以外の エンドポイントの初期化や クロックのスタートなどが、最初ではなくて SETUP や割り込みで動くようになっている。 消費電力の低減や 再初期化のためにそうするほうが良いのかも知れないのだが、どういうタイミングで動くかもわからないので、最初にするようにした。手順を変えることで動かなくなるんじゃないかとか気を揉んだが大丈夫のようだ。 デバッグ方針 LED もなにも付けていないのでどうするか悩んだのだが、できるだけ EEPROM を使ってデバッグすることにした。 どうにもならなくなったら、FT232RL にシリアルを接続し、デバッグメッセージを 垂れ流すことにする。 プログラムの作成状況 現在コードの規模はこんな感じ
ソースサイズ:
    62 usb.h
    44 desc.h
     7 usb162.h
   283 desc.c
   361 usb162.c
    59 test1.c
   816 合計

バイナリサイズ:
   text    data     bss     dec     hex filename
   1868       0      20    1888     760 test1.elf
機能的に足りないものもあるが、だいたい予定どおりか。 一応 Linux で USB デバイスとして認識できるところまでこぎつけた。 /proc/bus/usb/devices:
 T:  Bus=01 Lev=02 Prnt=03 Port=02 Cnt=02 Dev#= 41 Spd=12  MxCh= 0
 D:  Ver= 1.01 Cls=02(comm.) Sub=00 Prot=00 MxPS=32 #Cfgs=  1
 P:  Vendor=16c0 ProdID=05e1 Rev= 1.00
 S:  Manufacturer=www.recursion.jp
 S:  Product=USB-232
 C:* #Ifs= 2 Cfg#= 1 Atr=80 MxPwr=100mA
 I:  If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=02 Prot=01 Driver=acm
 E:  Ad=83(I) Atr=03(Int.) MxPS=  32 Ivl=100ms
 I:  If#= 1 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=acm
 E:  Ad=81(I) Atr=02(Bulk) MxPS=  32 Ivl=0ms
 E:  Ad=02(O) Atr=02(Bulk) MxPS=  32 Ivl=0ms
dmesg:
 hub.c: new USB device 00:1f.2-1.3, assigned address 41
 usb.c: USB device 41 (vend/prod 0x16c0/0x5e1) is not claimed by any active driver.
 usb.c: registered new driver acm
 ttyACM0: USB ACM device
 acm.c: v0.21:USB Abstract Control Model driver for USB modems and ISDN adapters
ACM ドライバまで組み込まれているが、実際に動かしていないし、たぶん動かない。 でもあと少しで動かせそうだ。 参考までにここまでのコード usb162-test1.tgzを提示しておく。作成途中なのでライセンスは設定しない 追記: 最初につくったこのプログラムを Linux で試してみた。 エコーバックされるので、一応動いているようだ。ただし、レスポンスが非常に悪いうえに、文字が抜ける。ちゃんと動いているわけではない。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: ドライバの設計とテスト(2) STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: USB162 DATE: 12/06/2007 00:07:12 ----- BODY: ターミナルソフトで動くようになった。(Linux で確認) 気を良くして、ダブルバンクにも対応。 エンドポイントの割り当て
 エンドポイント       サイズ   UECFG0X  UECFG1X
  #0  CONTROL            8        0x00     0x02
  #1  INTERRUPT IN       8        0xc1     0x02
  #2    ----
  #3  BULK IN           32(DUAL)  0x81     0x26
  #4  BULK OUT          32(DUAL)  0x80     0x26
あまり詳しく書いてないのでわからなかったのだが、DUAL BANK にできるエンドポイントは、#3,#4 のみということが分かった。なので、番号を移動した。割り当てたメモリは、176 バイトのうち、144 バイト。32バイトしか余っていないので、BULK IN/OUT のサイズはこれ以上増やせない。 動作の確認 SETUP EEPROM にログを残すようにして、どのような SETUP が来たかトレースしてみた。
Linux ACM ドライバの場合
 ↓ TYPE/REQUEST/VALUE(L)/VALUE(H)
00 05 5a 00   SET_ADDRESS (address = 0x5a)
80 06 00 01   GET_DESCRIPTOR (DEVICE)
80 06 00 01   GET_DESCRIPTOR (DEVICE)
80 06 00 02   GET_DESCRIPTOR (CONFIG)
80 06 00 02   GET_DESCRIPTOR (CONFIG)
00 09 01 00   SET_CONFIGURATION (#1)
00 09 01 00   SET_CONFIGURATION (#1)
21 22 00 00   SET_CONTROL_LINE_STATE
21 20 00 00   SET_LINE_CODING
   --- Linux ドライバ 組み込みまで
21 22 03 00   SET_CONTROL_LINE_STATE
21 20 00 00   SET_LINE_CODING
   --- ターミナルソフト起動まで
21 22 00 00   SET_CONTROL_LINE_STATE
   --- ターミナルソフト終了
このような動きだった。SET_ADDRESS の前に たぶん GET_DESCRIPTOR が 来て USBのリセットが来ているはずだが、USBのリセットで CPU もリセットするようにしているので、分からない。 SET_CONFIGURATION も含めて 2 回づつ来ているのが気になる。なにかマズイところがあるのかも知れない。 動作の確認 TX/RX
ログデータ   送・受(バンク#) バイト数(UEBCLX)
41  受信(BANK=0)  1 
01                     送信(BANK=0)  1
40  受信(BANK=0)  0
21                     送信(BANK=1)  1
60   受信(BANK=1)  0
01                     送信(BANK=0)  1
40   受信(BANK=0)  0
21                     送信(BANK=1)  1
60   受信(BANK=1)  0
01                     送信(BANK=0)  1
61   受信(BANK=1)  1
21                     送信(BANK=1)  1
これは、a a a と 3バイト入力したときのログ。ちゃんとエコーバックされる(= 正しくデータを受け渡しできている)のだが、なにか変。バイト数(UEBCLX) が期待したものと違うようだ。 ベンチマークとテスト データを大量に送受信して、ちゃんと送ったデータがエコーバックされてくるかどうかを調べてみた。
テスト1) 4 バイト送受信 x 10回

    いちおう動いた。しかし 2回目から動かない。

テスト2)  4 バイト送受信 x 200回

    うごかない。100 回なら OK 。
まだまだダメみたいだ。次はこのテストを動かすことに目標にする。 (続き) 原因が分かって、まともに動くようになった。 2 回目から動かないのは、SET_CONTROL_LINE_STATE の後 0 バイトを HOST に送信する必要がある。これは usbcdc と同じ処ような理 にすることでクリアできた。 ちゃんと動かないのは、バイト数(UEBCLX)の意味を誤解していたため。UEBCLX は、バンク1,2 の合計のバイト数。RWAL フラグをみて FIFOCON の操作をするべきだった。 Windows でのテスト
Windows XP の場合
 ↓ TYPE/REQUEST/VALUE(L)/VALUE(H)
00 05 02 00   SET_ADDRESS (address = 0x02)
80 06 00 01   GET_DESCRIPTOR (DEVICE)
80 06 00 02   GET_DESCRIPTOR (CONFIG)
80 06 00 02   GET_DESCRIPTOR (CONFIG)
80 06 00 03   GET_DESCRIPTOR (STRING)
80 06 02 03   GET_DESCRIPTOR (STRING #2)
80 06 00 03   GET_DESCRIPTOR (STRING)
80 06 02 03   GET_DESCRIPTOR (STRING #2)
80 06 00 01   GET_DESCRIPTOR (DEVICE)
80 06 00 02   GET_DESCRIPTOR (CONFIG)
00 09 01 00   SET_CONFIGURATION (#1)
a1 21 00 00   GET_LINE_CODING
21 22 03 00   SET_CONTROL_LINE_STATE
Linux とシーケンスが少し違った。
テスト1) 4 バイト送受信 x 10回 OK
テスト2)  4 バイト送受信 x 200回 OK
テスト3)  32 バイト送受信 x 1000回 
  ダメ。read で 0 が返ってくる。
 ちなみに 31 バイト x 1000 回、
 33 バイト x1000 回は OK。
まだなにかあるようだ。
原因が分かった。データを送ったら、0 バイトを HOST に送信する必要がある。SET_CONTROL_LINE_STATE のときだけではなかった。そして、その処理は usbcdc でもやっていた。
参考までにここまでのコード usb162-test2.tgzを提示しておく。作成途中なのでライセンスは設定しない ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: ドライバの設計とテスト(3) STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: USB162 DATE: 12/06/2007 21:05:25 ----- BODY: だいぶ動いて来たので、そろそろ 性能を見てみることにする。 やりたいことは、定期的にサンプリングしたデータを PC に取り込むような装置を作りたいということなので、それにあわせたテストをしてみる。 一回のサンプリングで、16bit 2ch 分のデータを取り込む。今は ADC が付いていないので、データとして タイマ1 の値を使う。-- こうしておいて値を調べれば、どれぐらいちゃんとサンプリングできているか分かるはず。 これは、その結果。サンプリングレートが低いときは、ちゃんと送れているが、高くなるにつれて実効サンプリングレートが落ちてくる。最後には頭打ちになる。 これを見ると、52000 Hzぐらいで頭打ちになっている。K bytes/sec で言うなら 200 kB/sec あたりが上限ということだ。 ただし、サンプリングレートと実効サンプリングレートが一致しないということは、データを取りこぼしているということだ。シリアルの場合は時間情報も一緒にいれるか .. それとも AUDIO クラスにちゃんと対応するかしないと 低いレートでもまともに使えないかも知れない。まだまだ工夫が必要だ。 参考までにここまでのコード usb162-test3.tgzを提示しておく。作成途中なのでライセンスは設定しない
ちなみに、このテスト用に ファームウェア(test2.c)と 測定プログラム(perf_test2.c)を新たに作っている。
エコーバックの性能 pingpong は、IO SIZE を write して、IO SIZE を read する性能。性能表示は Bytes/sec で片道分。(帯域は 2倍使用している)。 pipelining は、pingpong の read を N ずらしたもの。レイテンシが隠れるので、普通は性能が上がる。 おもしろいことに、pingpong の場合、32バイトのときだけ飛びぬけて性能が高い。pinelining すると、性能が安定して出るようになる。... といっても 17K bytes/sec 程度しか出ていない。もっとチューニングが必要だ。 追記 上のテストは、BULK OUT(PC→USB162)の設定が 32バイトDUAL_BANK のときのもの。これを 64バイト ONE_BANK にしてみた。 なんだか変な特性になった。pipelining のときも 32,64,128,256 バイトのときに性能が高くなる。そして上限がだいたい 64KB/sec +α。1ms 毎に 64 バイト 送信(OUT , PC→USB162) する性能がだいたいの上限を決めているように思える。 WRITE ONLY テスト では、送信のみしたときはどうか? (USB162が)定期的にサンプリングして、データを読み込むテストをしてみた。これは、DAC データを送るような用途。OUT の設定を 64バイトx1 と 32バイトx2 で試してみた。 結構でるようだ。最高で 250 KB/sec ぐらい。ということは、1ms 毎に 64 バイトしか PC側が送らない。と思ったのは間違い。 そして、32バイトx2 の方が性能が良い。連続で受信する場合は OUT のサイズはあまり関係なく、バッファリングしている点が有利なのだろう。 ここまでのコードは、 usb162-test4.tgz。しつこいようだが、作成途中なのでライセンスは設定しないので注意。次あたりのバージョンで、ちゃんとライセンスできるようにしようと思う。 追記 write+read の性能 write して read する場合の性能をとることができた。だいたい 30kHz で 4バイトを writeしてread することができる。帯域としては read/write の合計で 250KB/sec ぐらい。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: usb162-0.1 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: USB162 DATE: 12/10/2007 23:57:31 ----- BODY: いままでのコードは、とりあえず動くことだけを目指したものだった。そろそろ動いてきたので、リリースに必要だと思う変更をして version 0.1 として usb162-0.1.tar.gzを公開する。 ライセンス とりあえずライセンスは、GPL にした。もっと自由に使ってもらえるライセンスにしたいとも思ったのだが、全部を自分で作ったわけでもないので、無理かも知れない。 それ以前に、勝手に AVR-CDC の ID を使用している。まずいかも。 構造の変更 いままでのコードをベースに、できだけきれいな構造にした。

 desc.h    -- デスクリプタ定義で使う define など
 desc_cdc.c   -- CDC 用 デスクリプタ定義

 cdc162.h     -- CDC の API 定義 (usbcdc_init など)
 cdc162.c     -- CDC の処理

 usb162.h     -- USB 一般の 定義 
 usb162.c     -- USB コントロール処理

 usbconfig.h  -- 全体の定義

こんな感じ。ちなみに usb162 の処理は、(できるだけ)ディスクリプタ自体をみて処理をするようにしている。グローバルな定義の数を減らすのが目的。 ソフトリセット 実はこれが最も大変な話だった。いままで USB RESET がくると CPU もリセットするようにしていたが、EEPROM を使ったデバッグをしたりすることで、遅延が大きくなり Windows で認識されにくくなっていた。 そのため、USB RESET での CPU リセットをしないようにして、RESET の処理を作り直すことにした。 まだ変な気もするのだが、一応動いているので、とりあえず FIXしておく。
初期化のシーケンス(Windows XP)
 aa aa aa aa  USB RESET
 aa aa aa aa  USB RESET
 80 06 00 01  GET_DESCRIPTOR (Device)
 aa aa aa aa  USB RESET
 00 05 02 00  SET_ADDRESS
 80 06 00 01  GET_DESCRIPTOR (Device)
 80 06 00 02  GET_DESCRIPTOR (Config)
 80 06 00 02  GET_DESCRIPTOR (Config)
 80 06 00 03  GET_DESCRIPTOR (String)
 80 06 02 03  GET_DESCRIPTOR (String)
 80 06 00 03  GET_DESCRIPTOR (String)
 80 06 02 03  GET_DESCRIPTOR (String)
 80 06 00 01  GET_DESCRIPTOR (Device)
 80 06 00 02  GET_DESCRIPTOR (Config)
 00 09 01 00  SET_CONFIGURATION 
 a1 21 00 00  COMM_GET_LINE
 21 22 00 00  COMM_SET_CONTROL
初期化のシーケンス(Linux 2.4.31)
 aa aa aa aa   USB RESET
 aa aa aa aa   USB RESET
 00 05 3b 00   SET_ADDRESS
 80 06 00 01   GET_DESCRIPTOR (Device)
 80 06 00 01   GET_DESCRIPTOR (Device)
 80 06 00 02   GET_DESCRIPTOR (Config)
 80 06 00 02   GET_DESCRIPTOR (Config)
 00 09 01 00   SET_CONFIGURATION
 00 09 01 00   SET_CONFIGURATION
 21 22 00 00   COMM_SET_CONTROL
 21 20 00 00   COMM_SET_LINE
Windows は、まずは GET_DESCRIPTOR を行って、エンドポイントのサイズを取得する。その後 いったん USB RESET を行ってから設定に入る。Linux では、GET_DESCRIPTOR を行わずに SET_ADDRESS し、それから 8バイトで GET_DESCRIPTORを行い、エンドポイントのサイズを知り、再度取り直している。Linux がなぜ 2回 SET_CONFIGURATION をしているのかはまだ判らない。 POWERON RESET そのものや、EEPROM の 初期化をしているので、USB RESET は最初に1回来るのはやむを得ないのだが、2 回目の理由はわからない。Linux の dmesg を見ると、SET_ADDRESS を投げているはずなのだが、USB162 側は認識していない。 EEPROM_DEBUG を undef するとレスポンスが速くなってエラーなしに接続できているようだ。でも情報が取れないので正確なところは判らない。
サンプルプログラム サンプルはいままでどおり echo するだけの test1.c と 定期的にサンプリングする test2.c の2つ。それぞれの性能を測定するプログラムを perf/perf_test.c と perf/perf_test2.c に付けている。 おわりに 実用として使えるプログラムは、まだない。いままで Windows の性能ばかり書いて Linux の性能を書いていないことも関係するのだが、Linux(2.4.31) の ACM-CDC ドライバの性能がすごく悪い問題がある。 そもそも AT90USB162 を使う理由は、高速なものが作れることを期待したため。高速でなければ、AVR-CDC でも良いわけだ。そういうわけで、Linux でも高速に使えるものでなければ、実際の装置を作る気がしない。 次のステップは、Linux の ACM-CDC ドライバの性能がなぜ悪いのかを調べててチューニングする。その結果 速くなれば、CDC を使った実際の装置を作ろうと思う。そうでなければ、速くできる方法を探すつもり。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: Linux CDC-ACM ドライバの性能 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: USB162 DATE: 12/11/2007 06:24:17 ----- BODY: いままで、AVR-CDC の性能を調べてきたが、Windows に比べて Linux が遅い場合が多かった。単に Linux のマシンのスペックが悪いからだと思っていたのだが、どうも違うらしい。 USB162 を動かしてみると、Windows に比べて Linux が圧倒的に遅い。どうもドライバの作り自体に問題がありそうだ。 ちょっと、Linux ドライバのソースを眺めてみた。 linux-2.4 ACM ドライバ urb というデータ構造を使って、I/O を行っている。その urb は read/write に1つづつアロケートし、バッファのサイズは エンドポイントの パケットサイズ。 要するに、read/write ともに 32バイト単位で I/O を行い、それらの I/O が完了しないと、次の I/O ができない。 USB は、1ms 毎に処理を行うようだ。そのようなデータ構造だと、どうやっても 32KB/sec を超えられないように思える。 では、他のドライバはどうなっているのだろう? linux-2.6 CDC-ACM ドライバ Linux-2.6 ではどうなっているのか見てみた。 ACM_NRU,ACM_NWB という define があり、それぞれ 32,2 になっている。 write については、urb は 1つだが、ACM_NWB 数 の バッファを切り替えている。バッファのサイズは、エンドポイントの パケットサイズ。 よくわからないが、バッファが 2 つあるので 高速そうな感じだ。
後記: バッファを用意して、write が終わったらすぐに次の write を出せるようにしているだけだった。多重に write を出さなければ、高速にはならないようだ。重に write を出すときは、flags にUSB_QUEUE_BULK を指定する必要がある。
read については、urb を ACM_NRB数 生成している。そして、バッファのサイズは、エンドポイントの パケットサイズ x 2 。--- パケットサイズ にあわせなくとも良いらしい。 2.4 カーネルと比べれば 2 倍のバッファサイズで 16倍の多重度ということになる。これなら全然性能が違うのではないか? linux-2.6 FTDI ドライバ 枯れていると思われる FTDI のドライバはいったいどうなっているのか? ついでに見てみた。 write では、tx_outstanding_urbs という変数があり、その最大値が 42 ! になっている。バッファのサイズは、64 バイト - αのようだ。 read では、urb もバッファも 1 つしかないが、バッファのサイズは 512 バイト。 チューニングしてみる1 readsize を変更しても動かなくなることはなさそうなので、とりあえず readsize を 4倍、16倍にしてみた。 readsize を 4倍の 128バイトにすると 性能が数割あがった。16倍にしても、若干上がるだけでそれ以上の性能向上はないようだ。 ...といっても基本となる性能は、Windows の 50kHz のレンジと比べれば 1/10 程度。 では、write もサイズを大きくしてみることができるのか? 他のドライバは、そういうコードになっていないので、無理という気がするが、まぁやってみることにする。 結果は、read と良く似たかんじ。4 倍にするだけでずいぶんと性能があがる。16 倍にしたからといって、大幅に性能があがるわけではない。 ... それは良いのだが、16 倍は実はおかしい。1 回測定すると 2回目が動かない。抜き差しして初期化すると 1回の測定が通った。やはりなにかあるらしい。 さて、オリジナルの性能は、最高で 4KHz 程度。1 回に 4バイトなので、1ms 毎の平均パケットサイズは、16バイトにしか過ぎない。USB162 の方は、32バイト詰め込んでいるはずだ。... ということは 動いていないときがあるということだ。 サンプリングしたデータは、タイマ1 の値なので、どのように動いているのか見ることができる。 このグラフは、サンプリングした時刻とサンプリング数の関係。HOST がデータを read しない時間帯があれば、横ばいになる。20 ms の間に 6 回そういう時間帯があったということ。ちなみにこのデータは、readsize を 128 バイト、8KHz サンプリング(1ms あたり 32バイト)でのデータ。常に read しているわけではなく、ときどきとまっていると見てよいはずだ。 Linux-2.6.17 CDC-ACM ドライバの性能 Linux-2.6 のマシンは、玄箱/HG しかもっていない。これでどうなるか見てみた。 read は、Windows 並の性能が出ている。それに対し write は、8k Hz (1ms に 32バイト) が上限になっている。ACM_NWB を 16にしてみたが、性能は変わらなかった。read はちゃんとできているが、write は、FTDI のような処理にしないと性能が出ないように思える。 おわりに 結論としては、Linux-2.4 の CDC-ACM ドライバの出来は悪い。2.6 になれば read は良くなっているが、write はさほどでもない。ftdi のように ちゃんとしたものしなければ、Windows 並の性能にならない。 最初に作ろうと思っている、ADC からデータを吸い上げる装置は 48kHz 16bit x 2 までなら Windows XP か Linux-2.6 を使えば、CDC でいけそうだが、次に作ろうと思っている、JTAG とか SPI のような write して read するアプリケーションの場合、Linux は遅いことになる。 どのようにドライバを改造すればよいか、少し判ってきたような気がするので、当面は CDC にこだわってみようと思う。 (続き) チューニングしてみる 2 まずは、2.4 の CDC-ACM ドライバの write をFTDI のコードを参考にして、チューニングしてみる。 バッファのサイズはそのままで、多重に I/O をかける。そのための urb は 16 個で試してみる。 write の要求が来たら、urb がある限り usb_submit_urb するだけ。urb の管理が面倒だが、ロジックとしては簡単そうだ。 すこし変なところがあるが、Windows 並の 250 KB/sec ぐらい出るようになった。 read は、実はよくわからない。(多重に read をかけていない)オオリジナルがどうやっているか? ちょっと整理してみる。
 ○初期化(xx_open):
     無条件に read をかける。

 ○read 完了(callback):
     throttle == 0 の間、tty_insert_flip_char で 
     read したデータを tty の flipbuf ? に移動
     (移動している間に throttle == 1 になる場合あり)
     throttle == 1 の場合は、urb にデータを残して return
     throttle == 0 の場合、全部を移動したので 
     次の read をかける。
 ○throttle = 0 の変化
     xx_throttle callback 関数が call される。その中で
     read 完了と同じ関数を call して 未処理の データを
     tty の flipbuf に移動。
まあなんだか良くわからないがこんな感じだ。 filpbuf に移動しきれなかった場合、read がかけられないので、性能が低下しているように見える。 read を多重に出すというよりは、read 済みの データのバッファリングをなんとかすれば性能が出るのではないかと思えてきた。urb を多数もっていて、リングバッファのように使うコードにして、read 多重度 1 で制御するようなコードを作ればなんとかなるような気がしてきた。
多重度 1 ではダメだった。多重度 N で制御できるようにした上で、全体の URB 数 16 , 多重度 8 ぐらいにしたら、性能が出るようになった。
おわりに その2 いまさら、2.4カーネルの1ドライバのチューニングの話を書いてもしょうがないので、これで終わりにする。ただ、2.6 カーネルの CDC-ACM ドライバもイマイチなことは判ったし、チューニングの方法もだいぶわかった。いずれのドライバもちゃんとチューニングすれば、Windows と同等の性能になる。 目安としては、read/write/write+read とも 帯域はだいたい 250KB/sec ( write+read の片道の性能は 1/2)ぐらい。bps にすると 2M bps にすぎない。USB162 + CDC を使った場合、それ以上の性能を出すのは ホスト側にとって厳しい。 ADC の取り込み/DAC への出力なら、48KHz 16bit x 2 サンプリングが上限。...だが 取りこぼしが出そうなレンジ。44.1 kHz あたりが無難そうだ。 JTAG /SPI なら、1M bps での write+read が上限になりそうだ。 追記 一応動いているようなので、Linux-2.4 ドライバと 性能グラフ ソースコード: acm.c パッチ: acm-2.4.31.patch.gz コメント:
○このソース は、2.4.31 - 2.4.35 で同一なので、2.4 最新版でも使える。 ○USB162 でしか試していないので、AVR-CDC でも試す予定。
----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: CDC-ACMドライバチューニング STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: USB162 DATE: 12/13/2007 21:24:21 ----- BODY: Linux の CDC-ACM ドライバのチューニングが完了した。 2.4 カーネル用だけではなく、2.6 カーネル用も作成できたので、公開しておく。2.4 用は、2.4.31前後に対応。2.6 用は 2.6.17と2.6.23に対応(しているはず:間のバージョンは若干の手直しが必要) 一応動いたが、安定して動くかどうかは怪しい。特に open/close 時 や USB 切り離しのときに なにか問題がおきるかも知れないので注意。
acm-driver-0.1.tar.gz
注意)このドライバを更新情報はこのページに載せますので、最新版を使うようにしてください。なんの保証もできませんが、問題があれば直します。 おねがい)このドライバのバグを見つけたら、このページにコメントをお願いします。
USB162(test1/test2 FW)を使っての性能評価 オリジナルはあまりにひどい性能なので、Windows XP と性能を比較してみた。ちなみに 2.6 版は 玄箱/HG ! での評価。 pingpong テスト N バイトを write してエコーバックされてくるおなじ N バイトのデータを read するスループット。 おもしろいことに、2.4 版と Windows XP の特性がほとんど同じになった。2.6 版は、飛びぬけて速いところがないかわりに、リニアに性能があがる。2.4 や XPは、基本的にギクシャクしながら動いていて、つぼにはまると高い性能がでる。それに対して 2.6 はなめらかに動いているというところか。 pipelining テスト 処理データ量は pingpong と同じだが、write と read を 3回分ずらしてパイプライン処理にしたもの。 このようにソフトをチューニングすると、2.6 は安定して高い性能になる。スケジューリングの勝利と言えそうだ。 read スループット テスト ADC 取り込みのシミュレーション、USB162 の test2 ファームウェアを使い定期的にデータを発生させる。データ量は、1サンプリングあたり4バイト。ホストは、1KB単位で read をかけている。 2.6 も 2.4 も同じ性能になった。このテストでは、バッファリングがしっかりしていれば、スケジューリングはあまり関係なくなる。 write スループット テスト こんどは逆に DAC への出力のシミュレーション。ホストは 1KB 単位で write をかける。write が終了したら USBに送られたことを確認せず終了しているので、実際より若干高めの値になる。 2.6 と 2.4 は同じ性能。同じバッファ量なので当然かも知れない。バッファに余裕があるので、ピーク性能まで直線的に性能があがる。XP はバッファが若干足りないのかも知れない。 write + read スループット テスト 1KB 単位で write して read する。ここでも パイプライン処理にしていて、1 回ずらしている。 これもまた、2.4 2.6 ともに同じ性能。そして XP より若干良い。 AVR-CDC 編 さて、AVR-CDC の性能はどうなったのか? Windows XP と比べてみることにする。 最初は test1/test2 ファームウェアを移植するつもりだったが、コンパイル環境を gcc-4.2 ベースにしたら、AVR-CDC が動かなくなってしまった。しょうがないので、"p" コマンド → "S" を使って pingpong/pilelining テストのみをすることにした。 pingpong テスト 8バイトまでのデータは、1パケットの遅延時間に依存していると言える。結果を見ると、3 つに分かれる、Linux-2.6 オリジナル・チューンド ドライバ 、Linux-2.4 チューンド・Windows XP 、2.4 オリジナル。2.6 が良いのはスケジューリングが良いためで、2.4 オリジナルが悪いのはドライバの出来が悪いため。 16 バイトを超えると、スケジューリングの影響は減り 2.4 オリジナル以外はだいたい同じ性能に落ち着くようだ。 pipelining テスト 2.4 オリジナルは論外として、おおざっぱに言うと Windows vs Linux という感じ。Windows はピーク性能が高く、Linux は、小さなI/O サイズでの性能(レスポンス)が良い。ピーク性能とレスポンスの両立は難しい。設計ポリシーの違いと思えば良いかも知れない。 AVR-CDC まとめ AVR-CDCでは、2.4 オリジナルドライバの性能は論外に低かった。チューニングしたドライバに変更すると 2倍〜3倍程度性能が上がる。2.6 の場合は、AVR-CDCを使うだけなら、ドライバを変更しても性能は変わらない。 AVR-CDC スループット AVR-CDC 用 test2 fw をビルドできるようになったので、スループットを測定してみた。Linux のドライバは、チューニング版。 read スループット テスト 一応両者とも 4kHz = 16KB/sec のピーク性能。 Windows XP は綺麗な曲線になったが、Linux は 2.6 でさえガタガタ。これは CPU スケジューリングではなく、1ms の間にパケットを1個読むのか2個読むのかの判断がうまくないためだろう。 write スループット テスト 今回は、write 終了後コマンドを送ってそのレスポンスを待ち合わせるようにした。すなわち、ズルい値ではなく正しい性能。 2.4 では、3kHz = 12KB/sec で頭打ちだが、2.6 と Windows は 16KB/sec 以上に伸びている。また、おもしろいことに特性が似ている。たぶん両者とも最高の処理になっているのだろう。 write & read スループット テスト これが重要なのだ。最高にソフトウェアをチューニングして、JTAG / SPI の処理をさせたらどうなるかの指標になる。 2.4 と Windows は、2kHZ = 8KB/sec での write & read が出来ている。これも帯域としては、16KB/sec ということになる。なぜか 2.6 は若干性能が低い。 この性能だと、USI ではなく SPI を使った AVR ライタを作るとすれば、4B の write & read で 1バイトを読み込めるので、 2KB/sec ぐらいで ベリファイできるだろう。(Write は 2倍弱 か?)USI or Port 制御だと、1割か2割落ちそうだ。 また read で 16KB/sec 出ている。2 バイトのデータをキャプチャーするとすれば、5K sps ぐらいなら取り込めそうだ。ただし、データの取りこぼしは絶対起きる。時刻 or シーケンス番号の情報を載せた方が良いだろう。どうやってそれができるか良くわかっていないが、タイマーが2つあるのだからなんとかなるに違いない。時刻情報が含まれていて、くり返し波形をキャプチャーするならソフト次第で もっと高い周波数(80k sps -- 40kHz ぐらい?)の波形が見れるはず。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: 秋月フルカラーLCDメモ STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: USB162 DATE: 12/17/2007 15:58:46 ----- BODY: 秋月で 単体 300円の格安な 400x96フルカラーLCDが売られている。(インバータ付きのセットは、1000円) 詳細資料がないのでこの値段なのだが、最初になる研での解析が行われ、さらに xcrosgs2wy 氏によるより詳細な解析も行われている。 これでどのように制御すれば良いかについてはわかる。しかし、0.5 mm ピッチのコネクタの扱いが大きな壁だ。
ちなみにフレキケーブルは、Aitendo で 480円で購入することは可能だ(在庫は36P 80 mm)。日米商事とかジャンクなら 20円で手に入るかも知れない。 しかし...フレキが手に入っても、そのフレキを半田付けしなければならない。
ためしにフレキのコネクタをはずし、直接 ケーブルを半田付けしてみた。0.5 mm ピッチのチップを半田付けするよりはるかに難しい。-- なにしろランドよりケーブルのほうが太い -- 私の技術では、0.5 mm ピッチで全部半田付けするのは無理というのが結論。 ただ、空き - 2 本 - 空き のケースならなんとか半田付けが可能だった。要するに、1(TEST),2(NCLK),4(HSYNC),5(VSYNC),8(B5),9(B4), 15(G5),14(G4),22(R5),23(R4),29(VCPP_ADJ) だけなら私でも半田付け可能。 電源系は、秋月の資料(pdf)にあるとおり、チップ抵抗/チップコンデンサに直につければよいので問題ない。
秋月の写真をみると、アナログ系の電源は、コンデンサの前に 1.0 Ωの抵抗と 10uH のコイルが入っている。目的はノイズ低減。安定化した電源を使えば多少ノイズがあっても大丈夫そうだ。
さて、次の問題は、±9V の電源。これは RS232C レベル変換ICを使えば簡単そうだ。チャージポンプのコンデンサは、普通 0.1uF を使うが、出力が足りなければ 数 uF にすればよいだろう。(ADM3202ANの資料では、10uF まで OKと書いてある)
注意)±9Vでは、フレームレートを高くする必要があるらしい。今回のように遅いフレームレートの場合±12Vにするのが良いとのこと。ひょっとしたら ±15V の方が良いのかも知れない。 xcrosgs2wy 氏 の ページが参考になりそう。 といっても、既に回路を組んでしまった。-- どうしよう。
(ここまでの写真掲載予定) AT90USB162 を使っての制御方法(案) データは B2,G2,R2 の合計 6bit しかない。HSYNC/VSYNC を加えての 8bit を PORT(D or B) に割り当てて、タイミングも含めて PC から送ってもらえばよいだろう。 1番ピンから順に割り当てるとして、
 Port 7 HSYNC
 Port 6 VSYNC
 Port 5 B5
 Port 4 B4 
 Port 3 G5
 Port 2 G4
 Port 1 R5
 Port 0 R4
でどうか。 このやりかただと、1フレーム(最小 410x96 clock)に 約 40KB 必要。CDC を使っても 最大で 280KB/sec ぐらいになるので、7fps ぐらいになるだろう。7fps あればなんとか見れるのではないか? ダメなら 専用の Bulk OUT エンドポイントを割り当てることで 2-3 倍になると思う。ただし、ドライバー・ライブラリをどうするのが良いかについては知らない。
ちなみに、8bit だけなので、FT245RL を使うという手もある。CLK は(Mprog で設定すれば)、FT245RL から取れるので、Flip-Flop 1 個あればインターフェイスできそうだ。(タイマIC を使うという手もある。) Windows からしかまともに使えないが、D2XX インターフェイスを使えば 1M Bytes/sec 可能なのがメリット。 さらにいうと、AT90USB162 ではなく、普通のATmega で制御してゲームをはじめとして、いろいろなものを作ることは可能だろう。もちろん、そういう使い方でも、AT90USB162 を使うことができるはず -- PC でプロトタイプを作り、AT90USB162 で ターゲットAVR のプロトタイプを作れるというのが AT90USB162 のメリットと言える。
注意点 1) NCLK を長時間停止したままにしていると、液晶が損傷するらしい。1秒ぐらい? PC からデータが来ていないときは、 モードを移行して NCLK を ON/OFF するようにする必要がある。 その他の機能について USB を使うなら LCD 側の電源を On/Off できたほうが良いと思う。LCD の +5V 入力を一ヶ所に集めて PNP トランジスタ か Pch MOS FET でスイッチする。突入電流が流れないように、LC フィルタが必要なはず。インダクタは、千石の LHLZ06NBの33uH 〜 100uH が良いと思う。 また、VCPP_ADJ は、0V 〜 3V 程度でよいらしいので、これも PWM で作ると良いのではないかと思う。PWM 可能な端子に LC フィルタを付けて VCPP_ADJ に供給すればよい。インダクタはいつもの LAL02NA470K(47uH)、コンデンサは 10uF で良いだろう。cutoff は 7.3 kHz なので 1/1 プリスケール(62.5kHz@16Mhz)で十分そうだ。ただ、電流が流れすぎないかちょっと不安。ポートと LC フィルタの間に 100 Ωぐらいの抵抗を入れておくと良いかも知れない。 追記:16bit化の案 FT245RL で 1MB/sec でるならば、1ピクセルに 2バイト使っても 12.5 fps で表示できることになる。 AT90USB162 では専用ドライバがない限りここまでの性能は出ないし、半田付けが無理とみて、8bit 版の案を紹介したのだが、16bit 化についてもついでに紹介してみる。
            ラッチ
 Port 7 SELECT       空き
 Port 6 VSYNC            HSYNC
 Port 5 B5               B3
 Port 4 B4               B2
 Port 3 G5               G3
 Port 2 G4               G2
 Port 1 R5               R3
 Port 0 R4               R2
ラッチを1つ追加して、SELECT = 1 のとき ラッチにロードすることにする。 で、SELECT = 0 のときだけ NCLKを↓する。こうすることで 4096 色化が可能だと思う。 もし、AT90USB162 を使うならば、Port を 2 組(D and B) 使う。HSYNC を 最初のポートの bit 7 と 2つ目のポートの bit 6 両方につないでしまう。これでモード切替えるだけで、8bit 版と 16bit版の両方に対応できるようになるはず。 ちなみに HSYNC /VSYNC を内部で生成して、色をさらに割り当てるのは難しい。1MB/sec 出すつもりならば 16MHz でも 16 cpu clock しかないのだ。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- COMMENT: AUTHOR: jujurou EMAIL: IP: 164.71.1.148 URL: http://www.geocities.jp/chako_ratta/ DATE: 12/17/2007 16:45:21 5月の時点では鈴商にFFC(0.5mm)コネクタ36Pが@50円で売られていました。 現時点であるかは不明ですが、秋葉原に行けるようでしたら覗いてみてはいかがでしょうか? 私は部品を集めて以降、別計画が立上りフルカラーLCDは優先順位がかなり下がった状態です。 ----- COMMENT: AUTHOR: すz EMAIL: IP: unknown URL: DATE: 12/17/2007 19:30:50 ホームページ拝見しました。フレームバッファを使った本格的なものを計画されてる(た?)のですね。 私も発売後すぐ買った口なのですが、いままで放置していました。 簡単なものでよいから作ってみようと割り切ってはじめて今回の記事にすることができました。 ----- -------- AUTHOR: すz TITLE: gcc-3.4.6 にデバイスを追加するには STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 12/18/2007 00:22:17 ----- BODY: AT90USB162 を使うために gcc-4.2 にあげてみたのだが、どうもおかしい。さらに ATtiny861とか USB910 も動かなくなってしまった。 しょうがないので、gcc-3.4.6 にデバイスを追加することにした。 準備) 前提として、binutils-2.18 を使うことにするので先にインストールしておく必要がある。 また、avr-libc-1.4.7 を使う。avr-libc でサポートされていないデバイスまで gcc に組み込むと 面倒なので、サポートされていることを確認しておく。 gcc へのデバイス追加) gcc にデバイスを追加するには、gcc/config/avr の avr.c , avr.h t-avr の3つのファイルを編集する。基本的には他のデバイスのマネをすればよい。 avr.c : ○ avr_mcu_types にデバイスを追加する。デバイス名とデバイスの define は、avr-libc と一致させる必要がある。 ATtiny は、ARCHタイプ 2 にする。ATmega は普通 4 or 5 。8KB を超えるものは、5 を使う。 ちなみに、gcc-4.X では ARCHタイプ 25 が追加されている。このARCHタイプ は、新しいATtinyシリーズのように movw があるものに使用する。 ARCHタイプ3は、乗算命令がないが、8KBを超えるものに使用する。AT90USB162 はこれに該当。
8KB を超えると RCALL/RJMP命令が届かない場合が出てくる。同一ファイルにない関数呼び出しは、CALL命令を使用しなけばならないので、ARCH2 と ARCH3 , ARCH4 と ARCH5 の違いが必要。 AT90USB162 用に本当は、ARCH35が欲しいところだが、ないものは仕方がないので、ARCH3 にするわけだ。
avr.h : ○ LINK_SPEC にデバイスを追加する。-m avr1 〜 -m avr5 のどれかに追加し、さらに ATmega や AT90USB , AT90PWM などは、-Tdata =0x800100 のところにも追加する必要がある。 ○ CRT_BINUTILS_SPECS に crtXXX.o の名前を追加する。適当に付けてはいけない。必ず avr-libc と同じ名前を付けること。 t-avr : ○ MULTILIB_MATCHES にデバイス名を追加する。 avr-libc-1.4.7の変更) 実は、at90usb162 , at90usb82 の定義が間違っている。乗算命令を持っていないので、avr5 ではなく avr3にしなくてはならない。 (当然だが)まず、avr5 → avr3 に変更した gcc をインストールしてから、次の変更をした avr-libc をビルドしなければならない。 ○ at90usb162 と at90usb82 を avr/lib/avr5 から avr/lib/avr3 に移動した上で、avr/lib/avr5 , avr/lib/avr3 の Makefile.* および at90usb162 と at90usb82 の Makefile.* を書き換える必要がある。 ○ さらに、configure.ac , configure も avr5 → avr3 の変更が必要。
この問題は、WinAVR-20070525 でも存在する。at90usb162 で期待どおりに動かない場合、乗算命令を使っている可能性がある。 生成した xxx.elf ファイルに対して、avr-objdump -d でアセンブルリストを作成し、mul を grep することでチェックすべし。
おまけ) 参考までにパッチを提示しておく。このパッチはあくまで参考。動作確認もできていないし、デバイスも適当に選択している。 ○ gcc-3_4_6-avr-new-devs2.patchavr-libc-1.4.7-usb162.patch
注)ディレクトリを移動したので patch のサイズが大きくなっている。パッチを当てた上で avr5 のもとの Makefile.* と比較すると変更点が分かる。
おまけ2) WinAVR-20070525 で at90usb162 を正しく コンパイルするには、コンパイルのオプションを次のように変更する。ただし、リンクは、-mmcu=at90usb162 のまま変更しない。
 -mmcu=at90usb162 
       ↓
 -mmcu=avr3 -D__AVR_AT90USB162__
乗算命令を使用しているライブラリを使わないことが前提なので注意。
なお、WinAVR プロジェクトには、このバグについて だいぶ前に報告されている。次のリリースでは修正されると思う。
追記:WinAVR と同じ gcc を作るには WinAVR は、ソースを管理しているのではなく、パッチを管理している。CVS から取らなくても ブラウズしてちまちま取ってくれば OK 。ちなみに、00/10/11 は WinAVR 固有なので、Linux では必要ない。
おまけ: WinAVR (gcc-4.1.2) の at90usb82/162 を avr4/avr5 → avr3 に変更するパッチ。 ○ 99-gcc-4.1.2-usb162.patch
おわりに これで、WinAVR ベースの gcc-4.1.2 と 独自拡張の gcc-3.4.6 で USB910 TypeA (attiny861) , at90usb162 が動くようになった。 3.4.6 のほうを avr-gcc にしてメインに使うつもりだが、4.1.2 も avr-gcc4 で使えるようにしている。avr-libc-1.4.7/binutils-2.18 は共通でよいようだ。 普通は、4.1.2 の方がコードが小さくなるし、特に ATtiny で MOVW 命令を使ってくれるので高速なはずだ。でも、コードによってサイズが大きくなる場合がある。USB910 TypeB (ATtiny44) は、4.1.2 ではサイズがオーバしてビルドできない。というわけで両方のバージョンを使える環境が欲しかったのだ。 ちなみに、CVS から取ってきた WinAVR ベースの 4.2.2 はまだダメ。新しいチップに対応する必要があるなら、4.2.2へのパッチと上記を参考にして 4.1.2 に追加していくほうが良いと思う。
パッチを見ていると、ATtiny43U とか 知らないチップ名がいくつか見える。ひょっとしたら、新しい WinAVR が出る前に使いたくなるかも...
----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: AVR Studio4 SP2 と新デバイス STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 12/20/2007 19:30:46 ----- BODY: ATtiny43Uが気になって.. 調べてたら AVR Studio4 SP2 が 12月に出ているのを知ったので早速インストールしてみた。 で、Program Files/Atmel/AVR Tools/Partdescriptionfiles を見てみたら ... ATtiny43U.xml とか ATtiny48.xml があった。よくよく見ると avr-libc-1.4.7の include/avr にもかなりの数の新デバイスが定義されている。 ATtiny43U:
xml の PINアサインを見てみると ATtiny43U は ATtiny461 とほぼ同じ。 avr-libc のヘッダの _vect を比べてみると、番号がずれていて数が減っている。INT1 も削られているし、PCINT も 2個→ 1個になっている。TIMER0_CAPT もないし、TIMER1_COMPD もない。それ以外には、 ADC の定義が減っている。 ATtiny461 の機能を削減した廉価版らしい。
ATtiny48:
ATtiny28 の機能拡張版というより、ATmega48 の機能縮小版のような感じ。 SPI,TWI,ADC はあるのだが、USART がない。TIMER2 がない。あと PCINT3 もなくなっている。 Tinyシリーズだから当然 乗算命令もないはずだ。
微妙に機能削減したチップが出るのは、オリジナルの ATtiny26系 、ATmega8系 の2つの系統に人気があるということだろう。 ただ、電子工作でそういうチップを使いたいとは思わない。 ...というわけでこれらのチップへの興味はなくなってしまった。 ついでなので書いておくと、ATmega48/88/168 シリーズに加えて ATmega48P/88P/168P/328P シリーズというのが出ている。avr-libc のヘッダを比較したら BODS/BODSE というのがMCUCR に追加されているだけのようだ。機能が増えたというより、328P があるというのがメリットか。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: libusb と HID STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 12/20/2007 21:25:52 ----- BODY: Windows 流にいえば COM ポート (Linux なら tty )で通信できる CDC は便利ではある。でも、AVRの コードが大きくなったり、約束ごとを決めないと、その装置がどんな装置か判別できないというデメリットもある。また、汎用インターフェイスなので遅い .. かも知れない。 USB ライターでいうと、AVR-DoperUSBasp あと USBtinyはみな libusb や (HID インターフェイス)でアクセスするので、デバイスの種類は指定しても、(COMポートの番号など)デバイスそのものを指定しなくとも使える。 こういう ことができるのが、USBのメリットだが、CDC を使いつつ、どんな装置か判別することはできないだろうか? というわけで、まずは、AVR-Doper や USBtiny そして USBasp がどんな風に使うのか調べてみた。これらは avrdude でサポートされている。avrdude のコードを見ればだいたいのことは分かる。 libusb の open/close 接続されているすべてのデバイスをスキャンして、VENDOR_ID と PRODUCT_ID が一致するものを選ぶのが普通のやり方らしい。 CLASS とかで判断する方法もあるらしいが、汎用デバイスを作るわけではないので、知る必要もないだろう。
  usb_init();
  usb_find_busses();
  usb_find_devices();
  for(bus=usb_get_busses(); bus; bus=bus->next){
      for(dev=bus->devices; dev; dev=dev->next){
          if(dev->descriptor.idVendor == VENDOR_ID 
             && dev->descriptor.idProduct == PRODUCT_ID){
              handle = usb_open(dev);
        break;
          }
      }
  }
open したあとさらにオマジナイが結構必要。列挙すると、
 usb_set_configration(handle,...);
 usb_claim_interface(handle,...);
    -- 失敗したとき usb_detach_kernel_driver_np() などで
    ドライバを解放する。
close もそう単純ではない。
 usb_release_interface(handle,...);
 usb_reaet(usb_handle);
 usb_close(usb_handle);
usb_release_interface() はともかく、usb_reset() までしなければならないのか? なぜそうするかよく分からない。 libusb での制御方法 コントロールエンドポイント に対して、ベンダー依存のリクエストを usb_control_msg() で送って制御する方法がある。これは、USBtiny や USBasp のやりかた。ファームウェアが簡単なのがメリット。 そして、コントロールエンドポイント に対してusb_control_msg() を使って制御するのは同じだが、HID クラスを定義し、HID の GET_REPORT / SET_REPORT で制御する方法がある。これは、AVR-Doper が使っているやりかた。この範囲で使うならば、WIN32API を使っても制御できるのがメリットだが、HID の定義が面倒そう。 さらに、usb_bulk_read()/usb_bulk_write() を使って バルクエンドポイントに対して送受信することで制御する方法もある。avrdude の jtagmkII(含 AVRDRAGON) や stk500v2 の制御をみると .. COM ポート以外に、libusb を使って制御する方法を提供している。 ちなみに、usb_control_msg() は、ほとんど SETUP パケットを自分で組み立てるイメージ。GET_DESCRIPTOR とかを直接 CALL したりできるかわりに、SETUP の通信について知識が必要。 WIN32API での制御方法 AVR-Doper での open の方法は次のようになっている。
  HidD_GetHidGuid();
  SetupDiGetClassDevs();
  for(i=0;; i++) {
      SetupDiEnumDeviceInterfaces();
      SetupDiGetDeviceInterfaceDetail();
      CreateFile();
      HidD_GetAttributes();
      if (deviceAttributes.VenderID == VENDOR_ID
           && deviceAttributes.ProductID == PRODUCT_ID) {
             break;
      }
  }
関数の機能も名前も違うが、libusb の open の仕方と良く似ている。 デバイスとの送受信は、HidD_SetFeature()/HidD_GetFeature() を使用する。libusb 版では、usb_control_msg()をつかって同じ機能を実現している。 さらに説明しておくと、AVR-Doper は HidD_SetFeature()/HidD_GetFeature() を 使って COM ポートのような ストリーム(というか擬似シリアルデバイス?)を実装している。その上で 上位の STK500V2 プロトコルが流れるようだ。 そういう処理をするのも面倒そうだが、HID でベンダー依存の情報を流すためには、デスクリプタの定義が必要でそれも面倒そうだ。AVR-Doper では、定義が 60バイトぐらいある。 CDC を使いつつ、どんな装置か判別できるか? すくなくとも、Linux ではできないようだ。/dev/ttyACMXX というデバイスと libusb で得られる情報のマッピングができない。 WIN32API だと、API は知らないが、分かるような気がする。 しかし、libusb とは関係ない API だと思う。 Linux で出来ない以上 WIN32API で出来てもあまり嬉しくはない。今度は逆を考えてみる。 libusb を使って、CDC のように使えるか? まず、AVRCDC や USB162 のドライバのデスクリプタだけを ベンダークラスに 変更したファームウェアを作って、普通に使えるか確認してみた。多少怪しいところがあるが、usb_bulk_read()/usb_bulk_write() でちゃんと送受信できた。 usb_detach_kernel_driver_np() を使ってドライバを解放すると、 (変更しない)AVRCDC や USB162 そのものでも送受信できる。 しかし... usb_bulk_read()/usb_bulk_write()を使った制御は、遅かった。カーネルドライバだと、複数の要求を submit して非同期に処理することができたが、libusb だと同期型になるので遅い。 性能は、2.4 オリジナル CDC ドライバ並かそれ以下 ... 処理の内容を考えてみれば当然かも知れない。 CDC のようには使えるが、非同期での処理が出来ない。スレッドを使えば read と write を非同期でできるのかも知れないのだが、複数の read , 複数の write 要求を同時に出すことは難しいのではないかと思える。 結論 性能を求めるなら、専用のドライバを用意するのが一番だろう。普通そこまでやれないので、チューニングした CDC ドライバを使うのが次善だと思う。USB ならではの便利な機能はあきらめるしかない。 しかし、性能が必要なければ、CDC ベースのファームウェアのデスクリプタだけ変えて、ベンダークラスにすることで、装置の判別や その他付加機能を簡単に付けることができる。 USBasp 流に、バルクエンドポイントをなくしてしまって、usb_control_msg()だけで制御するのも簡単で良いかも知れない。 ただ、HID を汎用に使うのは、すごく面倒。本来の目的どおりボタンを作ったり、キーボード・マウスを作るのでなければ、無理して HID を使う必要はないと思う。 (補足)この記事の最初の版は、自分でも何が書いてあるかわからないぐらいひどかったので、書き直しました。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: USB910A rev2 の構想 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: USB910A DATE: 12/26/2007 19:44:43 ----- BODY: 最初に USB910A をつくってから、ADC の特性を調べたりして、実際に使ってきて、だいぶ知識が増えた。使って来て不満な点もいくつか出ている。そろそろ 改良した rev2 を作ろうと思う。 1) 基板レイアウト これが最初のレイアウトなのだが、まずケースのフタが付けられない。ターゲット基板と接続する使い方を想定したので、フタが付けられなくても良いといえば良いのだが、保管したり、持ち運ぶときのために、フタがあったほうが良い。rev2 では、コネクタを縦方向につけようと思う。 次に、接続用に ピンフレームを使っている。これはテスト用のボード側で安いピンヘッダーを使うことを考えたのでそうしたのだが、ISP コネクタ(自分配列)を別に付けることになってしまった。 rev2 では、ピンヘッダーを使い、ISPコネクタ と共用することにする。(出力と RESET は、スライドスイッチで切り替える) そして、ピンヘッダーを ブレッドボードEIC-801に指せるようにする。そのためには、部品が ブレッドボードと干渉しないようにする必要がある。具体的には、USB コネクタや ATtiny861 を片側に寄せてピンヘッダー側には(抵抗とか)背の低い部品しか置かない。 ブレットボードには、部品面を下にして挿す。EIC-801 で干渉しないことだけ確認してレイアウトを決める。EIC-801 より幅があるブレッドボードには挿せなくともやむを得ないと割り切る。現物を持っていないし、第一これ以上デッドスペースを増やすのは無理だと思う。 2)電源周り USB910Aはもともと簡易テスターとして使えることを主目的として作った。が、相対精度はともかく絶対精度が悪く使うたびにキャリブレーションしたりして使い勝手がわるい。そのうえ、ノイズが結構のっている。 たとえば、これ ↓ バッテリーの放電特性を調べたときのものだが、グラフにしてみると、全体の形は、ちゃんと曲線になるが、こまかく見るとギザギザである。 拡大したのが↓ ぶれの幅が 50mVぐらいあるようだ。10K と 1.5K で分圧しているので、USB910A 自体のぶれは 6-7 mV 。 これをどうにかしたい。 まず 5V は切り捨てる。そして 3.3V 用に 精度の良いレギュレータを使うことにする。デジキーでしか入手できないかも知れないが MCP1700-3302 Eは、精度 0.4 % 250mA でしかも 25個 980円とかなり安い。rev2ではこれを使おうと思う。データシートを見ていると温度特性も良いようだ。 その上で、AVCC には、LC フィルタを入れる。インダクタは、いつもの LAL02NA (47uH)を使い、コンデンサは10uF を使うつもり。 AREF には、選別した同じ抵抗値の抵抗 2 個で分圧した 1/2 AVCC (1.65V) にしようと思う。同じ抵抗値を選ぶだけなら、あまり信頼できないテスターでもなんとかなるはず。
同じ抵抗値のものを選別する場合 5-6本から選別すればよいだろう。場合によっては 10本必要かも知れない。注意点は抵抗を手で持たないこと。温度変化で抵抗値が変わる。 ちなみに、テスターは、秋月で売っている P-16がお勧め。絶対精度はわからないが、再現性が良いので、自分の基準測定器にしている。 これで、MCP1700-3302E の電圧を測定したら、3.305V だった。何度計っても同じ値。AREF の電圧は、1.653V になった。
(回路図掲載予定) これに伴いピン配置が変わるし、内蔵基準電圧も使えなくなる。ファームウェアソフトも変更しないといけない。 3) 入出力ピンの定義 アナログ入力に 33KΩを付けただけにしていた。これだと入力にしか使えない。それは良いとしても入力専用ならコンデンサを付けるなどノイズ対策をすべきだろう。 クロックが 12MHz なので、ADC クロックは、1/64 の 187.5 kHz にしている。連続してADCを動かす場合は、13 クロックかかるので、14.4 ksps ということになる。 1 / 2 -- 7.2 kHz 以上の周波数が入力されないように 33KΩの本体側に 0.01 uF を入れたらよいのではないか? これだと cutoff 周波数は 0.5 kHzぐらいになる。 ファームウェアの整備 rev2 を作るのにあわせて、AVR-CDC のバージョンをあげようと思う。いったんバージョンアップしたのだが、Linux でうまく動かないので面倒になって元に戻してしまった経緯がある。だいぶ USB について勉強したので、今度は大丈夫だろう。 そうした上で、AVR-CDC にちょっとした改造を入れようと思う。COM デバイスを open すると、Linux でも Windows でも SET_CONTROL_LINE_STATE が 来る。そのときにデバイスを初期化しないと、正常に通信できない場合が出てくる。この処理ができるように改造したい。 あと USB910 ではなくなってしまうが、libusb のみ使うファームウェアも作ってみたい。 ホスト側ソフトの整備 いままでは、ちょっと作って使っていたが、使い方が決まっているものは、ホスト側のプログラムを整備しておこうと思う。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: シリアルROM AT45DB081D STATUS: Draft ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 12/28/2007 15:28:47 ----- BODY: AVR 単体で ADCをキャプチャーするのに良いデバイスはないか探していたのだが、良さそうなデバイス -- AT45DB081D をデジキーで見つけたので紹介。 インターフェイスは SPI で 8-soic パッケージがあるので、秋月の変換基板で DIP としても使える。 2MB と 容量が大きすぎるぐらいあるが、結構安価 (217 円)。書き換えも 10万回できる。 キャプチャーするのに良いと思ったのは、256B の ページWrite が比較的早い(2ms Typ/4ms Max) だけでなく、バッファを 2組持っているためだ。 バッファを 2 つ持っていると、ページWrite している間も書き込みができるので、AVR 側にバッファを持たずにすむし書き込み時間も隠蔽されてしまう。ページWriteの時間だけが、書き込み性能を規定する。 4ms あたり 256B 書けることが保証されているのであれば、8bit ならば、64k sps でデータを書き込みしてもデータ落ちがないということである。AVR の上限 77 k sps にかなり近い。10 bit だと、15 k sps でしか取れないから、2バイトづつ書いても十分間に合う。 ちなみに、AT45DB081B というデバイスもあるが、ページWriteが遅い。AT45DB041D は容量だけ違うので良いのだが、すぐ買えないかも知れない。AT45DB021D は、バッファを 1つしかもっておらずキャプチャーに向いていない。AT45DB161D も 281 円と安く良い。ページサイズが 512B で ページWrite時間が 3ms Typ/6ms Max なので、若干帯域が高い。 上記は、Write する場合。Erase には時間がかかるのであらかじめ Erase しておくのを前提にしている。Erase and Programming だと、Typ 14ms/Max 35ms になる。この場合の上限は、7.3KB/sec ほど。 Write と違って Read は制限がほとんどない。バッファに読み出す時間は 0.2 ms でしかも 2つあるから無視できそうだ。SPI クロックの上限は 66Mhz で 純粋に AVR 側の SPI 性能で決まる。たとえば ATmega88 とか AT90USB162 とかは、SPI を持っていて、さらに USART も SPI として使える。上限は 1/2 CPU CLOCK なので、CPU CLOCK が16MHz だとすれば、8MHz 。連続で読み出す場合 1MB/sec 弱で読み込めるはずだ。 USB910A rev2 で使えないか? USB は、なにもしていなくても 1ms 毎に通信が行われる。通信している間(最悪 2000クロックぐらい)は 割り込み禁止で動くので、応答時間に制限ができる。そのため、5ksps ぐらいが上限になってしまう。 実は問題はそれだけではない。ノイズが載ってしまうのだ。USB910A reb2 の構想で書いたように前よりはノイズに気を使っているのだが、まだまだのようだ。レギュレータ自体に問題があるのか、USB のような動作をさせていること自体に問題があるのか、それとも ADC 兼用のピンで USB通信をしていることに問題があるのか -- 原因は分かっていない。 原因が分かって解決可能なれば、使えることは使える。でも 5ksps ならあまり面白くない。 というわけで無理というのが現在の結論。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: USB910A rev2 の 差動入力ADC 機能の評価 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: USB910A DATE: 01/07/2008 22:43:41 ----- BODY: USB910A rev2 の構想の続き USB910A rev2 を作ってみた。ノイズ対策をしたつもりだったので、微小電圧を測定してみた。 33 mV を測定してみる 3.3V の VCC を 10KΩと 100Ωで分圧し 33mV にして 220 uF ほどのコンデンサで安定化しておく。 これを 差動入力の機能で測定するとどうなるか? これがその結果 AIN1/AIN2 , AIN5/AIN6 と名前を付けた 2組の 差動入力で、どのような値になるか見たもの。BIN は、両極動作。0 のところの線は、通常モードで、逆電圧を測定したときの値。 ± 50mV しか測定できないのだが、ノイズがすごい。 拡大したのが、これ 34 mV 弱が中央値のように見えるが、± 3mV ぐらいぶれている。3 回測定して、真ん中の値を選ぶようにしているのだが、それぐらいでは全然だめらしい。 データシートを良く見たら、ADC と共用のピンを出力にする場合は、ADC の測定中は ON/OFF するなと書いてある。なるほどその通りだろう。しかし、ATtiny861 は ADC のピン数が多く どれかを USB の信号線に割り当てなければならない。USB は 1ms 毎にフレームが来るので ON/OFF しないこともできない。 困ってしまったのだが、64 回!測定して平均を取ってみたら次のようになった。 なんか良いかんじだ。拡大してみると ... こんなふうになった。値が 2 組に分かれているのがわかる。上が 通常モード、下が BIN モード。PIN によらず 1mV 弱の差があるようだ。ノイズは ± 0.5mV にだいたい入るようになった。 64回も測定するのにどれぐらい時間がかかるか計算してみる。ADC クロックは 12MHz/64 = 187kHz 。1回に 13 クロックかかるのを 64回行っているので、225 Hz 。テスター機能と割り切れば使えないことはないだろう。 0V を測定してみる では、0V を測定したらどうなるのか。一般にオペアンプによる差動入力は 同相入力の問題があって、0V 付近や VCC 付近は最も厳しい条件になる。ほんとうに rail-to-rail でないと正しい測定値は得られない。
参考:電子回路の豆知識
なんだか幅がある。拡大すると .. 明らかに 2 つに分かれる。BIN モードでは全部 - 0.5mV ぐらい。通常モードでは、(逆電圧でも) + 0.5mV ぐらいになった。 これでも結構すばらしいのではないか。自分でオペアンプを使って組んでもこういうふうにはなかなかできない...と思う。 ちなみに、VCC 付近も 大丈夫なはず。( 電流計機能として確認) 0V を測定してみる 2 最小のレンジでは、微妙にオフセットがあることがわかった。他のレンジではどうなるのだろう? サポートしているレンジ全部調べてみた。 レンジが大きいほどオフセットの差が大きい。最大 3300mV の場合、その差は、40mV ほどになった。でも、レンジが 66 倍違うから精度に見合った誤差ということになる。 そして、PIN に関係なく、通常モードと BIN モードに差があるのは、どのレンジでも同じ。 こういう傾向があるとわかれば、多少精度を上げられるかも知れない。 33 mV を測定してみる 2 ついでなので、33mV がどうなるかも調べてみた。 ちょっと予想と違う。3300mV と 1650mV のレンジの特性をどのように解釈したらよいのだろう。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: このブログの著作権について STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 01/08/2008 00:11:09 ----- BODY: 著作権について少し考えることがあったので記しておこうと思う。 このブログの著作権は、すzが持っている。しかし、私がたとえば事故で急に死んでしまったら、どうなってしまうのだろう? おそらく、比較的すみやかに このブログは自動的に閉鎖される。そして私が誰かなのかを、さらには私の遺族が誰なのかをつきとめてかつ、許諾を得ないと二度とこのブログは見ることができなくなる。死後 70年(でたらめだ)無名・変名なので、公表後 50年もの権利があるから、ログを取っていた人がいたとしても不特定多数の人に見せることはできないだろう。 別に死ななくても、このブログが閉鎖されてしまう理由はいくつもありそうだ。 ほとんどの人にとってつまらない内容かも知れないが、せっかく書いたものなので、有用だと思う人が一人でもいる限り公開できたらと思う。 というわけで、宣言だけはしておく。
もし、このブログの内容がインターネットのどこにも見られない状態になったら、誰でも良いから、私に代わってこのブログの内容を公開してかまわない。公開を妨げる権利は放棄する。ただし、このブログの内容(文章)に限る。 文章以外に、プログラムもあるが、それは GPL として扱って欲しい。
公開してくれる人がいるかどうか分からないが、宣言しておかないと消えてしまうのは確実なので記した。 こういうことを考えた理由も書いておこうと思う。 こんなもの(このブログ)でも著作物であり、著作権というありがたい権利が与えられる。しかし、他の財物とは違って、著作権は、文化の発展を目的としている。 誰一人として欲しないなら別だが、自分の都合だけで消滅させて良いのか?それは、著作権の目的にそぐわないだろう。権利だけもらって義務を果たさないように思えてきたのだ。 デジタルデータは、コピーするのは簡単にできる。しかし、メディア(ここの URL自体もメディアかも知れない)に縛られてしまうといとも簡単に消滅する。(少なくとも今の技術レベルでは)コピーされ続けることによってのみ残りうる。そういう性質がある。(と私は思う) そういうことを考え出すと、これを書かずにはいられなくなってしまった ... というのが本意なわけだ。 おわりに このブログはあくまでも、趣味の電子工作のブログです。この記事については、必要性があったから書いたまでで、著作権について議論することは本意ではありません。 申し訳ありませんが、この記事についての議論はここではご遠慮ください。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- COMMENT: AUTHOR: kuma_hati EMAIL: IP: 61.27.121.174 URL: DATE: 02/28/2008 12:07:15 > ログを取っていた人がいたとしても不特定多数の人に見せることはできないだろう。  google のキャッシュが見せてくれます (^^;  は冗談半分にして、フリーのブログにおいて置けば相当長いこと読み継がれますぜ。実例を知ってます。今なら google が一番長そうかと。 ----- COMMENT: AUTHOR: すz EMAIL: IP: unknown URL: DATE: 02/28/2008 18:46:51 情報ありがとうございます。 実は昔痛い目にあって、フリーのサイトをプライマリーにすることは絶対にしないと決めたのです。利用するとしたらミラーしかあり得ない。 で、google blogger ちょっと使ってみたのですが、ミラーにするのもちょっと難しそうな感じ。 ぶっちゃけ、どうやってPCにセーブするかもわかりません。ここだと 記事投稿のカテゴリに、インポート・エクスポートがあって、なにもわからなくてもセーブだけはとりあえずできるようになっています。 ミラーにするのにもうひとつ問題があります。ここのコンテンツは文章と画像だけでは成り立たなくて、プログラムもミラーできないと意味ないのです。 どうせ外部サーバを利用しなければならないのなら、外部サーバにミラー置いた方がむしろ楽だと思えてきました。 ----- -------- AUTHOR: すz TITLE: 『もう俺は限界かもしれない』を読んで STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 01/10/2008 21:50:06 ----- BODY: 遅らばせながら、『ブラック会社に勤めてるんだが、もう俺は限界かもしれない』を知り読んだ。 深く感情移入できたし、いろいろ考えさせる内容であったので紹介しておく。ググれば数多くログが見つかるだろうからリンクはしない。 実話認定 2ch に投稿されたものだが、実話をベースにしていることを私は信じる。創作かも知れないと疑わずにすなおに読んでほしい。 藤田さんの言動を通じて浮かび上がるキャラを書き手本人が理解していない。そのことが読み取れるし、実際本人が雑談スレでそう書いている。これが、決定的な理由。 感想 この話あまりにリアルだ。書き手本人が意識しないことまでにじみ出てきている。だからこそ、読み手ひとりひとりが、さまざまな感想を持つことだろう。 このブログの真のテーマと関係しそうな感想までありそうに思えるので、いくつか自分の思いを書いてみようと思う。 プログラミングについて デスマや人間関係について凄惨な現状が描かれているが、プログラミング自体については、まったくネガティブな表現が見当たらない。 そもそもの動機が、タイトルから想像できるように現状から逃げ出したいという思いを吐き出したいというものだろう。それでも(はじめのやりとりから推察して)違う職業につきたいとは考えていないように見える。 この話を読んで PG あるいは SE を目指すのはやめようと思う人がいるかも知れない。でも次のことも考えて欲しい。 プログラミングという行為は楽しいのだ。そして、この話で出てくるプログラミングがすべてではない。 AVR に限った話題しか扱わないつもりでこのブログを始めても、MinGW/MSYS や gcc の改造、さらには Linux のドライバの改造まで出てきてしまう。そして、プログラミングの世界はまだまだ広い。 プログラミングあるいはデバッグするという行為は、効率よく論理的思考を身に付ける手段でもある。論理的思考といってもレベルがある。説明できないが、自分があるレベルについて理解できても、それが頂点ではない。それ以上のレベルがあり得るのだといういうことを、考えて欲しい。
すこし解説しようと思う。でもこれが、分からないからといってこれ以上説明を求めないで欲しい。 まず、プログラムというのは、だれでも理解できる非常に簡単な論理の組み合わせである。だれでも理解可能であるはずなのに、理解しがたいのは複雑だからだ。 プログラムを理解するというのは、あちこち省略された論理を読み解くのに似ている。省略された論理というのはサブルーチンのことだ。 あちこち省略された論理など論理ではない。理解できるわけがないと思う人もいるだろう。 でも、そういうことを当たり前のように出来る人もいるわけだ。論理的思考が出来ると思っている人でもこれが出来ないならば、レベルの差がある。 生活の場で感情論としか思えないものに、正論をぶつけて紛糾する...そういう場面はありがちだ。正論をぶつける側は、相手が論理思考ができないと思うかも知れない。でも、感情論側にも省略された論理があるかも知れない。レベルが違う人は当たり前のようにそれを見つけることができる(かも知れない)。
藤田さんについて 多くの人が、藤田さんがリーダにならない。そして、恋人がいた会社に行ってしまう理由が分からないと書いている。 こう考えたらどうだろう。 藤田さんは、挫折から立ち直り切っていない。新たな人生の目標を見つけ出せていないのである。上原さんや雇ってくれた社長を見捨てることはできないから職場に縛られていたが、問題がクリアになれば新たな人生の目標を模索したいのだ。そのために恋人がいた会社に行くというのは、自然な発想のように思える。 そして、人生の目標を喪失したままの人物は理想の人物ではない。藤田さんを理想の人物として描きたいなら、新たな人生の目標を模索に出ることは必然といえよう。
...ということを書いた本人が意識していないようなのだ。これ(意識していないように見せること)が表現の一手段というのはありうべかざることだ。実話であって理解せず観察だけによってこういうことを読者に伝えたとしても、驚くべきセンスである。
日本人は弱いのか? 藤田さんであれマ男であれ、脱却したとはいえ NEET 時代があったのだから、よく言えば繊細な、悪く言えば弱い人物として描かれている。木村くんが自分の意見を押し通すことに驚く場面さえある。それゆえにリアルティを感じるし、NEET であるような人の共感もえられるのかも知れない。 正直もっと強くなって欲しい。たとえば司馬遼太郎が描く戦国時代や幕末の日本人は信じがたいほどアクティブだ。繊細なだけが日本人の特質ではない。 おわりに ついに感想文まで書いてしまった。これや前の記事は、例外である。この手のものは、もう書かないつもり。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: microSDカードの書き込み耐性について STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: microSD関係 DATE: 02/26/2008 00:40:58 ----- BODY: microSD や (miniSD , SD) カードの書き込み耐性は、一般に 10万回〜数十万回ということになっているらしい。 本当にそれぐらいしか書き込みできないのか?限界を超えるとどうなるのか?ずっと気になっていた。最近大容量の microSD が安くなって来ているので、使い道がなくなった 64MB の miniSD カードで試してみることにした。 テストの方法 Windows では、どのように書き込むのか調べようがないので、Linux を使うことにする。Linux では、O_DIRECT フラグをつけて open すると、キャッシュを使わないで read/write するようになる。これを使って、確実に書き換えるようにした。 その上で、指定したファイルの指定したオフセット(デフォルト 0)を 毎回違う内容で書き換え、書いたデータが同じかどうかチェックすることにした。 テストの結果 結果は、なんと! 515万回の書き換えができた。最終的には、 write でエラーになった。 考察 この miniSD カードは、(なんらかの)不良ブロックマネージメント機能をもっていたに違いない。そうでなければ、カード全体が死んでしまうことはないはずだし、なにより 500 万回もの書き換えに耐えることはないはずだ。 さて、500 万回の書き換え耐性というのは、十分なのか?というと微妙なところ。人がオペレーションしてファイルを置いたり消したりするには十分すぎる耐性だが、Linux のルートファイルシステムを作ったりするには不安がある。 おわりに たった一例だが、どういうものなのか少しは判った気がする。ついでなので、最新の microSD カードも試してみようと思う。ずいぶん安くなったし、1つ壊してもこれからの安心が買えると思えば安いものだと思うことにする。 ターゲットは、今最も安い上海問屋オリジナルの 2G の microSD カード。 追記:現在テスト中
今、上海問屋オリジナル 2G microSD のテストをしている。 だいたい 10万回書き換えるのに 30分のペース。今 270万回の書き換えが出来ている。 どこまで行けるのかは、想像がつかない。不良ブロックマネージメント機能が多くの代替ブロックを管理していれば、500万回よりはるかに多くの書き換えが出来ても不思議はない。 一応、満足が行く耐性を 3000万回と考えていて、テストの上限も 3000万回としている。上限に達するまで、トータル 150時間もかかる計算だからテストが終了するまで数日かかる場合もあり得る。
- なぜ 3000 万回? - 仮に 30秒に1回必ず書き込まれると仮定します。そうしたら 1500万分(28.5年)持つということになります。FLASH のデータ保持期間は 10年〜数十年らしいので、これぐらいもてば安心かなぁということです。 - なぜ 30秒に1回? - Linux で通常のファイルシステムの場合、どこかが更新されたら SUPERBLOCKが更新されます。デフォルトでは SUPERBLOCK の更新間隔が 30秒に1回なのです。SUPERBLOCK 以外でも DISKキャッシュが書き出される頻度があって、これも 30秒に1回ぐらい。ガンカン書き込むようなことをしなければ、(ながい目でみて)最多で 30秒に1回と考えてよいと思います。 - もちろん使い方によっては、更新頻度がもっと高いところが出てくるかも知れません。O_DIRECT とか O_SYNC を付けて open すればこのテストのように短期間で ダメにできます。
上海問屋のユーザレビューについて フォーマットに失敗するだとか、使えない、あるいはデータが化けるというレポートがいくつか見られた。 本当に初期不良だった可能性もあるのだが、単なる接触不良である可能性の方が高いと思う。というか実際に接触不良を経験した。 新品のPhoto Fast の メモリースティック PRO Duo アダプタを介して使ったのだが、フォーマットに失敗したりした。そして、抜き指しを何回か繰り返しているうちにちゃんと使えるようになった。 SD や miniSD ではそんなことは経験していない。microSD ほど小さくなれば、端子の面積も小さくなるし危険性が高まるのだろう。 特に変換アダプタを使う場合は接触不良に注意! ちなみに、安物だから品質が悪いとは思っていない。こんな小さく薄いものを作れるメーカは限られているに違いない。どこか一流メーカの OEM のはずだと思っている。
追記:現在テスト中 - その2 現在 トータルで 690万回まで OK まだ継続中なのだが、ちょっと疑問が出てきた。 SD は、FAT16 など特別なフォーマット向けに最適化されているという事実。 コメントにあったように、ELM のページには、内部的には 512B ではなく 2KB でアクセスしていたりすることが書かれている。 ひょっとして、2,4,8..N KBのバッファを持っていて、それに満たないデータを何回買いても 実際にはバッファに書き込まれるだけではないか? そういうおそれがあったので、一回に書き込むデータ量を 8KB にしてみたのだが ... それで十分だったのだろうか? ターゲットの microSD にもともとされていたフォーマットは FAT16 だったのか FAT32 だったのか実はわからなくなっている。
少なくとも、それとは違う 2G のカードで FAT16 のものがあったことは覚えている。これも FAT16 だったのかも知れない。
さて、FAT16 の場合、アロケーションサイズ(クラスタサイズ)は、32KB にもなる。実際のFLASH への書き込みは、32KB 全部書き込まれて初めて発生するのかも知れない。 ただし、ぜんぜん違う場所への書き込みが発生すれば、カレントのバッファを書き出し始めるはず。(そうでないと仕様を満たせない) そして、おそらく、高速化のためにバッファを複数持っているはず。複数といっても普通は 2 。3 以上になると、一般のキャッシュ制御と変わらなくなる。内部 FW が複雑になりすぎるうえに、メリットがないはずで 3 以上というのは考えにくい。 このテストでルートディレクトリ・エントリが壊れるほど書き換えたことで、実際に書き換えたエリアと、ルートディレクトリ・エントリの 2 ヵ所は書き換えることが判っている。 だから本当に書き換えているのだと思うのだが、ひょっとしたらテストプログラムが書き換えたはずの回数と実際に書き換えた回数が違うかも知れない可能性が若干ある。 さらに実は、もうひとつ懸念がある。このテストは、VMware Player を使った仮想 OS (Vine-4.2) で行っているのだ。ゲストOS が DISK に書き込むのは間違いないと思っている。ソースコードを見て確かめることさえできるから、本当に怪しくなったら確かめても良い。 それは良いのだが、VMware Player あるいは、ホスト OS 側がキャッシングしてしまう可能性がある。 Flash のアクセスランプが点滅しているし、秒間 60回ぐらいしか書き換えできていないから、大丈夫のはずだが、確信にまでは至らない。 そういうわけで、このテスト継続していくが、実際の書き換え回数と違うかも知れないことを覚えておいてほしい。
おまけ - Windows XP の設定について 以前は、Flash メモリなどを取り外したときに、「安全な取り外し」の作業が必要だったことを覚えて( or 知って)いるだろうか。そして、今はそのメニューが出ないことを。 この機能の切り替えは、コントロールパネル→管理ツール→コンピュータの管理で出てくるパネルの上で、ディスクの管理→ディスク1などのリムーバブルディスクの装置自体(ボリュームではなく左)のプロパティのポリシーで切り替えられるようになっている。 デフォルトは「クイック削除のために最適化する」でキャッシュを使わない。「パフォーマンスのために最適化する」を選ぶとキャッシュを使うようになり、書き込みの回数を減らすことができる。 Flash メモリを使うときは、これを選んだほうが良いのだが、「安全な取り外し」の作業をする必要が出てきて、ちょっと面倒。 キャッシュを使わないではなくて、キャッシュの寿命を 1秒とか コントロールできたほうが嬉しかった。
追記:ほんとうに Flash を書き換えているのか? まず、Linux 内部で Flash を書き換えたかどうか検証してみた。 まず、使っている OS は vine-4.2 である。サーバ用OSとは違って システム負荷を調べるようなツールは充実していない。とりあえず、RHEL4 の sysstat のソースRPM をとって来て rpmbuild を使ってビルドしてインストールした。 次に /etc/init.d/sysstat start を動かして数時間放置。 そして、sar -d を使って DISK毎の I/O 状況を調べてみると次のようになった。(抜粋)
                 DEV       tps      rd_sec/s   wr_sec/s
21時40分00秒    dev8-0    107.08    856.45    856.46
21時50分00秒    dev8-0    108.04    864.09    864.15
22時00分00秒    dev8-0    105.17    841.15    841.18
22時10分00秒    dev8-0    108.83    870.39    870.41
22時20分00秒    dev8-0    109.10    872.61    872.62
22時30分00秒    dev8-0    109.13    872.85    872.88
22時40分00秒    dev8-0    105.96    847.47    847.52
dev8-0 というのは、major 8 minor 0 というデバイスの意味で、/dev/sda のこと。この環境だと USB mass storage である テスト中の microSD を指す。 wr_sec/s は、1秒間あたりの Write セクタ数(512B単位)。rd_sec/s は読み込んだセクタ数 。tps は1秒間あたりの I/O 回数(read writeの合計)。 この情報で、平均 I/O サイズは 8KB ぐらいとわかる。全部がテストプログラムでの read/write だとすれば、10 万回の write + read をするのに 15.4 分で済んでいるはずだ。 ところが、プログラムのログは、次のように 10万回あたり 30.5 分かかっていることを示している。
02/27 21:58:56 :05800000 times -- OK
02/27 22:29:31 :05900000 times -- OK
どういうことかというと、テストでの write+read の組に対して余分な 8KB の read と write が発生しているということ。そして、この余分な read と write は ルートディレクトリ・エントリに対しての I/O ということになる。 なぜルートディレクトリ・エントリに対して I/O が必要かというと、更新時間を記録するためである。
- ただしこれは、O_DIRECT を指定したときだけの動作、普通はキャッシングするから read はしないし、更新時間も 30秒に 1回とかの頻度になる。 - O_DIRECT を指定したからといって、ルートディレクトリ・エントリまでキャッシングしないというのはなぜなのか? -- ちょっとわからない。
こういうように Linux 側でどういう I/O をしたかは分析できる。 Windows でも 管理ツール→パフォーマンス→システムモニタで調べることができる。+のアイコンでカウンタを追加する。追加する項目は、PhysicalDISK の DISK Write Bytes/sec 。対象とするインスタンスは(リムーバブルディスクは選択できないので)Total を選択する。別に C: もあるので、これも追加する。 で、みてみると、C: と Total が同じであることがわかる。どういうことかというと、Windows では 物理DISK として管理していないということ。もっとハードウェアに近いレイヤ(デバイスそのものか デバイスを仮想化したもの)で VMware Player に接続されている。こういう状況なら Windows でのキャッシングはないといえそうだ。
- Windows の中がどうなっているかは判るわけもないが、一般に OS での DISK のキャッシングは、物理DISK にたいして行われる。 - 論理DISK (パーティショニング後の仮想化されたディスク(のはず))を対象にするかも知れない。 - でもデバイスに対してのキャッシングはあり得ない。物理DISKというレイヤの意味がなくなる。
最後に残るのは、VMware Player でキャッシングしているかどうか。デバイスそのものを扱っているのならば、やろうと思ってもまずは、無理そうだ。
- VMware Player は、USB host コントローラを ゲストOS に見せている。 - Windows から USB host コントローラへのアクセス権利をもらって(奪って) そのまま ゲスト OS に見せているのだと思う。 - ただ、あくまで推測。USB mass storage のプロトコルとかもっと上位レイアのやりとりを使って 仮想 USB host コントローラに見えるようにしているかも知れない。 - ただそういう場合でも自分でキャッシングしたら問題が出る場合がある。-- 装置を切り離したときに、書いていないデータがキャッシュに残ってしまうかも知れない。
ここまで調べて、テストの結果は信用して良さそうという結論になる。 追記:エラー発生! 1000万回書き込めた後、データの不一致を検出。 不一致になったときのデータパターン
    00: 54 e8 7c 00 da da da da da da da da da da da da
    01: da da da da da da da da da da da da da da da da
    02: da da da da da da da da da da da da da da da da
    03: da da da da da da da da da da da da da da da da
          あと全部 da
先頭 4 バイトは書き込み回数。そして、残りの da というのは、書き込み回数 の 下位1バイト。 1 バイト目と 5バイト目以降の値は同じにならなければならない。 エラーが起きたときのログから、1バイト目(先頭)が 0xda であるべきなのが、0x54 になったということだ。
このデータ調べればわかるが、8138714 回を指している。実は 2 回目。1回目は、USB が disconnect になって、テストが中断されてしまった。そのときの、190万回を足している。
ただ、壊れ方が不自然。先頭の1バイトだけが壊れるというのは、いかにもソフトのバグのような感じだ。また、普通のカードは、ECC でエラー検出しているらしい。このカードも不良セクタマネージメント機能を持っているようだから(1000万回も書けたなら絶対数回は代替しているはず)データが化けてしまったら read error になるはずなのだ。 Linux あるいは VMware Player のなんらかのバグで、書き込む前にデータが化けてしまったと判断。データを正しいものに変更し、再実行することにした。 追記:2回目のエラー発生! 1740万回書き込めた後、データの不一致を検出。 不一致になったときのデータパターン
PAGE: 28 (7168)

    00: ab 7a ba ba ba ba ba ba ba ba ba ba ba ba ba ba      
    01: ba ba ba ba ba ba ba ba ba ba ba ba ba ba ba ba      
    02: ba ba ba ba ba ba ba ba ba ba ba ba ba ba ba ba      
    03: ba ba ba ba ba ba ba ba ba ba ba ba ba ba ba ba      
2回似ているエラーになった以上、1回目の判断は怪しいということにしてあらためて考察してみよう。 512 B 単位の先頭の 1〜2 バイトが壊れたというのが共通するパターン。そして、保存されたデータ自体が壊れていて、read エラーにはならない。 なんだか、書き込みのデータ転送で microSD がデータを誤って受け取ったような感じがする。転送しようとした直後は、タイミングが厳しいとかなんらかのカード固有の理由があるのかも知れない。たしか CRC 付きの転送だったはずなので、ちゃんと調べれば、CRC 値が同じになるかどうかで判断できそうだ。 でも、転送で CRC をすり抜けるパターンでたまたまエラーが起きた ... というのもどうかという気がする。すり抜けなかったエラーは実は多数起きていてそれは、dmesg で確認できるメッセージとして表示されないだけかも知れない。そういうことはカーネルのソースコードを調べればわかるはず。 まぁ、ぜんぜん外していて、まったく違う理由かも知れない。理由を追うのは面倒だから事実だけに注目してみる。 この microSD 限定の話になるが、どうも 書き込みはいくらでも出来るように見える。ただ、書き込みでエラーが起きなくても正しいデータが記録されているとは限らない。 この点はハードディスクと違う。ハードディスクは、もっと信頼できる。そして、OS は (ハードディスクと同じ処理が基本なので)普通、正しく書けたかどうかデータを確認することまではしない。 確実にデータを保存したいケース(確率は低いようなので、本当に大事なデータの場合)は、いったん PC から切り離して、再接続し、MD5 とかチェックサムをとって確認する作業をした方が良いかも知れない。
上記のような壊れ方をした場合の考察 上記のようなパターンで壊れた場合、データが入っているところ(データブロック)が壊れたから上記のようになったわけだが、他の場所が壊れた場合どういう風にみえるのかについてもうすこし説明しておこう。(あくまで 512B のうち先頭の 1〜2 バイトが壊れたというケース限定、他の壊れ方まで説明するのは難しい) FAT が壊れた場合) たまたま FAT が上のように壊れると、更新したファイルとぜんぜん違うファイルのデータが壊れることになる。C でいうとポインタで一方向リンクを作っていたときにポインタの1つに変な値が入ったようなもの。こわれたリンクから先がめちゃめちゃになる。 OS がなにをしているかわからないのだが、FAT は 2 組あるので、chkdsk とかで復旧できるかも。(自信なし) BPB (SUPERBLOCK相当)が壊れた場合) FAT ファイルシステム覚え書きを参考にすると、先頭には、3 バイトの jmpOpeCode という部分があり、それが壊れることになる。ここに正しいデータが入っていないとおそらく、ファイルシステムが認識されない。普通の方法では復旧できないだろう。 ただ、ここだけが壊れたのが確実なら、正しい データにすればよいので復旧が完全に不可能というわけではない。 ディレクトリエントリが壊れた場合) こういうケースでは、更新したファイルがあるディレクトリで、ファイル名が化ける結果になりそうだ。ダメージとしては小さい。
追記:3回目以降のエラー 2 回目でもうやめようと思ったのだが、それからしつこくやるとどうなるか興味があったのでやってみた。 3 回目は、2回目のエラーから 78万回で write エラーが起きた。4 回目はそれから 20万回で write エラー。エラーが起きたところは、前のデータのままになっていた。 いつまでも書けるのかと思ったが違うようだ。2 回目のエラーのときには既に限界になっていたようだ。 限界を超えると write エラーになり、しかも前のデータが残っているのというのは、たちの良い壊れ方だ。ただし、1 回目/2回目のようなことがあると write エラーで限界だとわかったときには、すでにいくつかのファイルがおかしくなっているということでもある。
ちなみに、4回目のエラーの後、別のファイルに対してテストを実行してみたところ、25 万回でエラーになった。要するに 代替ブロックを消費しつくした後は、代替しないで write エラーになる。記録する FLash 自体の書き込み耐性はやはり、10 万回〜数十万回の ようだ。1 回 write エラーになった後、もう書けないわけではなく、ある確率で write エラーになる。そしてその確率は(おそらく)だんだん高くなっていくように思える。
おわりにその2 題名が microSD の 書き込み耐性で、64M miniSD はプロローグみたいなもの。それで終わるのは気がひけたので、ここまで追記してしまった。 それはともかく、他の microSD はどうなのか? なんて興味も出てきてしまった。金銭的にダメージがあるので、あんまりやるつもりはない。でも壊れ方のパターンを知りたいので、もう1つだけやってみようかと思う。 ターゲットは、キングストンの microSD 2G 。東芝の chip を使っているらしい。あと microSD 自体に JAPAN の文字がはいっている。テストをするマシンも玄箱/HG(自分改造版) の Linux に変更予定。 なお、このレポートは新しく記事にするので、追記はここで終わりです。 microSDカードの書き込み耐性(2)に続く。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- COMMENT: AUTHOR: AkSd EMAIL: IP: unknown URL: DATE: 02/26/2008 12:47:07 興味深い試験ですね。 単純に考えると、セルの損耗とともにカードの空き容量が減ると思いますが、それは記録していないのでしょうか? SDCなどで始めからFAT16でフォーマットされているものがありますが、ファイルシステムのエントリやセルのアライメントを考慮してFAT16に最適化されていると言う記事を読んだことがあります。 その為、FAT32やNTFSで強引にフォーマットするとアクセスが遅くなったり寿命が短くなったりするそうな。 FAT情報が書き込まれるメモリブロック最先頭は特別なセルになっていて、書き換え速度(や耐性?)が高くなっているそうです。 検証してみると面白いかもしれませんね。 http://elm-chan.org/docs/mmc/mmc.html ----- COMMENT: AUTHOR: すz EMAIL: IP: unknown URL: DATE: 02/26/2008 13:35:02 不良ブロックマネージメント機能とかを搭載している場合、代替ブロックは OS から見えないところに確保されているはずです。そうでないと、OS が使ってしまうかも知れない。(これは、ハードディスクも同じ。) だから OS からみえる容量は変わりません。 先頭ブロックは特別というのは(少なくともテストで使った miniSD では)事実のようですね。カード全体が死んでしまっても FDISK は成功しています。ただ、FAT 領域まではカバーしていないようです。 あと、ここで調べた結果は、あくまで実際に調べたカードの特性で、一般化できるものではないと思います。microSD だとあまりに小さいので、実装のバリエーションは少なさそうですが、CF とか USB メモリは、大きいのでいろんな実装があり得て、それぞれ特性が違うのかも知れません。 ----- COMMENT: AUTHOR: 名無し EMAIL: IP: 58.188.39.137 URL: DATE: 03/22/2008 04:58:52 細かく読んでませんが、 SDカードはOSやファイルシステムレベルではなく、一段下のSDカード内部のファームウェアレベルで、各ブロックを満遍なく使う仕組みが働いているはずです。 ファイルシステムが同じところに上書きした、と思っていても実際にはそのブロックはイレースされ、違うブロックに書き込まれます。それはOSレベルからも見えない動作です。そうやって全体を均一に使うために全体の書き込み回数が増えます。不良ブロックマネジメントみたいなのはないと思います ----- COMMENT: AUTHOR: くろぼし EMAIL: IP: 59.86.141.201 URL: DATE: 03/23/2008 09:58:35 こんにちは。 面白い事をされてますね。前の方も書かれてますが、Flashメモリはセルをまんべんなく使う機構があります。 例えば10^5回書き換えられる1GBのフラッシュメモリがあれば、概算でその製品の生涯トータルで1GB * (10 ^ 5) Byte だけ書き換えられる事になります。これはあくまで概算で、実際には、ホットスポット(一点への重点的な書き込み)を避けるため、「ブロックを移動する」などの処理を行っていますので、これより更に少ないはずです。これで気がつかれたと思いますが、実は容量が多いければ多い程、製品の寿命が長くなります。ご参考までに。 ----- PING: TITLE: ここまでやるか!?microSDカードの書き込み耐性を徹底研究!! URL: http://necomoba.blog62.fc2.com/blog-entry-57.html IP: 66.160.206.193 BLOG NAME: ねこもば。β版 - へっぽこ実験ニュースサイト DATE: 03/26/2008 21:38:02 すzのAVR研究: microSDカードの書き込み耐性について [useWillcom]  よく研究されています。興味深いですね。とりあえずケータイで普通に使う分に... ----- -------- AUTHOR: すz TITLE: 私がAVRを選んだ理由 STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 02/26/2008 02:44:08 ----- BODY: いますぐPICをやめてAVRに移行すべき10の理由に触発された。このブログを作った理由にも関係するので、私がAVRを選んだ理由を書いてみようと思う。 私がAVRを選んだ理由は、こういったことだが、考えてみれば既に過去の話で今も選び続けている理由ではない。 今AVRを選び続けている理由というのも書いてみよう。 さて、今AVRを選んでいるわけだが、ブログのタイトルから判るように AVR only である。なぜ他のチップを(少なくとも当面は)選ばないのか? その理由も書いておこう。 追記 ゆきの研究室 - つれづれ日記で知ったのだが、もうひとつ AVR しか選ばない理由が増えた。 それは、XMEGA シリーズが発表されたこと。 3.6V までしか動作しなくなったけれども、32MHz まで高クロック化され、ADC が 12bit (2Msps) まで高機能化された。さらに 12 bit DAC (1Msps)まで付き、DMA までできるようになった。AES/DES エンジンというのも嬉しい場合があるかも知れない。 たぶん実際に使うデバイスは、ATxmega16/32/64/128A4 シリーズ。TQFP44 なら、アイテムラボの変換基板も使えるし、0.8mm ピッチで半田付けも楽。 gcc,binutils,avr-libc,avrdue の対応。そして実際に入手可能になるのを待たなければ使えないが、相当に魅力的だ。DMA も持っているから、へたな 32 bit より早いかも知れない。RAM が 最大 8KB しかないことだけが不満か。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- COMMENT: AUTHOR: jujurou EMAIL: IP: 192.51.44.15 URL: DATE: 02/26/2008 08:29:59 最近、秋月で自作では扱いやすいDIP型で、容量の大きいAVR(ATMEGA164P, ATMEGA644P, ATMEGA88)も扱われ、安価で色々な事が試せる環境が整ってきましたね。 ----- COMMENT: AUTHOR: すz EMAIL: IP: unknown URL: DATE: 02/26/2008 14:27:12 ATmega88 250円というのはびっくりですね。入手しやすくなった記念に なにか作ってみたいです。 ----- -------- AUTHOR: すz TITLE: 秋月取り扱いパーツだけを使って作る何か STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 02/26/2008 19:40:37 ----- BODY: 秋月で ATmega164p, ATmega644p, ATmega88 が低価格で購入できるようになった記念にこれらのどれかと、秋月で入手できるパーツを使ったなにかを作ってみたい。(いまのところあくまで願望) で、考えていたのだが、SD カードを USB Floppy にするアダプタなんてのはどうだろう。USB の UFI という仕様を満足すれば良いはず。 動機その1
実は数週間前 、Windows XP マシンがおかしくなってクリアインストールする羽目に陥った。インストールした後、必要なアプリケーションをインストールしたりさらにアップデートしたりする必要があったのだが、非常に苦痛だった。もうクリアインストールだけは絶対したくない。...というわけで、はじめて Windows XP 付属のもバックアップを使ってみたのだが、なんとフロッピーが必要だった。PC 自体も古いのでドライブは付いているのだが、メディアがない。私はフロッピー自体あまり信用していないので、たとえメディアがあったとしてもあまりうれしくない。メディア全体をファイルにして、バックアップすることになる。 そういうことが簡単にできる装置がほしいと思った。
動機その2
これも Windows マシンがおかしくなったことが発端なのだが... VMware Player に目をつけた。仮想マシンならバックアップは非常に楽だ。ホスト OS には、あまりアプリケーションを入れずにすむし、セカンド Linux マシンにもなる。qemu を使って disk image を作ることで、VMware Player に OS をインストールできることもググってわかった。 VMware Player で扱えるストレージは、 disk image 以外は、DISK 以外の実際の装置のみ、具体的には、CD と USB ストレージ。Vine-4.2 をインストールしてみたのだが、実際の CD を用意する必要があった。 仮想マシンのインストールをするのに、実際の CD を用意するのは、なんだか馬鹿馬鹿しい。といって AVR とかで 仮想CD を作るのは性能的に無理がある -- AT90USB162 を使ったとしても、 1倍速CD ぐらいが限界のように思える。でも、network インストールできる OS なら、仮想 Floppy でも十分だ。やったことがないのでわからないが、ひょっとしたら、Windows の バックアップを仮想マシンにリストアできるかも知れない。
どんなものにしようか とりあえず動機付けはできた。あれば便利に違いない。 さて、どんなものにしよう。まず、SD カードについて考えてみる。今はビット単価が落ちすぎて、1000円以下で買える最大の容量が 1GB になってしまった。不要になった SD でも 128MB になった。(64MB はテストで壊してしまったし)。できれば SD に書き込んだ FD イメージを 1 枚の FD として扱えて、メディア切り替えができるものが、望ましい。 ファイル名は固定にして、空のFD を定義する場合も FD のサイズのファイルを用意することにする。こうすることで、ファイル生成の機能が必要なくなる。ルートディレクトリエントリから、shortname でファイルを検索し、ファイルサイズを取得して、メディアのサイズとする。そして、FAT を手繰って 1FD分のマップを作る。あとはマップにしたがって I/O コマンドを実行する。...こんな処理で良いはずだ。
マップを作ると簡単に書いてしまったが、ATmega88 では無理かも知れない。どうせフロッピーだし、無理なら、いちいちFATを手繰っても良いかも知れない。
問題はサポートできる FDの数。1枚ではチョットもったいない。複数ならオペレーションのためのインジケータとボタンが必要だ。数枚なら、LED で 2進数表示というのもアリだが... ピンがずいぶん余るはずなので、2桁の 7セグと、セレクト用の UP/DOWN ボタンを付けるということでどうだろう。...ということは サポートできるFD数は、最大 99。実際にこんなに使うとは思えないのだが、Windows 95 の時代は、本当に数十枚のFloppy を使っていたし、オーバスペックとまでは言えないかも知れない。 あとは、メディア切り替えを OS に知らせるためのオペレーションが必要。専用のボタンにするか、あるいは UP/DOWN ボタンを操作し終わった 5秒後とかでも良いかも知れない。どちらにするかは、ピンの数と、操作性と、レイアウトデザインで決めることにする。 さて、(メモリと余力があれば)もうひとつ付けたい機能がある。それは、FDD の シーク音。ここまでやれば、この装置が実際に役に立つのかどうかなどどうでも良くなるに違いない。 主要部品 シーク音機能がなければ、たぶん ATmega88 で実装できるはず。 SDカードスロットも水晶も 2桁 7seg も全部秋月で購入可能なはず。 ちなみに水晶は、最新版の usbdev を使えば 12MHz/16MHz のどちらも OK。 基板は C 基板。うまくレイアウトすれば 1枚に入るかも知れない。 おわりに まぁ、いまのところ妄想です。シーク音機能はどう作るか想像できていないけど、メインの機能は、まじめに mass-storage を調べれば作れそうなレベルだと思います。 追記:設計メモ ほんとうに作る気になったら、カテゴリを作ってあらためて書くつもりだが、まだ作る気が起きていない。とりあえず設計メモとして追記していこうと思う。 付けるパーツと pinの数の確認 もう ATmega88-20PU(250円) で作ろうと思っている。これで作れなければ、作らない。 さて、ATmega88 で作った場合、どういうパーツを選択するか。使用する pin の数にも気を付けなければならないので、pin数を確認しながら決めていく。 ATmega88 は、28 pin そのうち ~RESET , VCC, AVCC, AREF, GND x2 の 6 pin は(普通)信号線には使えない。だから pin の数は 22 からスタートということになる。 SDカードスロット(150円/220円) まぁこれは必須だ。
OLIMIX SAM7-P256の回路図
を参考にすると、信号線は、4 pin 必要ということになる。SCK/MISO/MOSI/~SS の 4 pin を割り当てて、ISP にも使う。-- まあこれは常識的な割り当てだろう。残り 18 。 USB 用ピンの割りあて INT0/PD2 とそのとなり INT1/PD3 -- これも必須だ。水晶も必要だから 4 pin 。残り 14。 水晶は、表面実装タイプ クリスタル 16MHz (5個入り 200円)にしようと思う。12 MHz でないのは、usbdev が他の周波数に対応した記念に使ってみようと思ったから。12MHz でも OK なようにはしておく。ちなみに、表面実装タイプだが、いっても PIN を引き起こせば 普通に使える。台座が付いている分だけ手配線するのは楽。 USB は、3.3V で動かす。レギュレータは、TA48M033F( 3.3V 500mA,コンデンサ付き 100円) 。SD カードは多少消費電流が多いそうなので、コネクタにには、電流が取れる USB B コネクタ(50円)を選択する。ひょっとしたら、A タイプ(50円)を使って 延長ケーブルを使うほうが使いやすいかも知れない。 表示装置は、手配線が楽な、3桁 7seg (200円)を選択することにする。ドットを使わないことにして、3 + 7 = 10 pin を使う。残り 4 。 表示は、1 つ1つ点灯するようにする。VF 1.7V として 最大 20mA とすると 80Ω。電流制限抵抗は、コモン側を使い 75 Ω x 3 ということにしよう。 残りは 4 しかない。まずはボタン。とりあえず 2 個で信号線も 2 本とする。もし 3 個にするとしても 2 本でなんとかすることにする。ちなみに通販だと、タクトスイッチ 100個セット 700円しか選択枝がない。一応通販でも売っているし、店頭なら1個単位で買えるから、”秋月取り扱いパーツだけ”というのを外していないとしよう。 残り 2 。これは機能拡張用(一応サウンド用のつもり)。何を残すべきかが難しい。シリアル RX/TX を残すこともできるし、2 つの PWM を残すこともできる。あるいは、ADC+I2C(TWI) を残すこともできる。-- もう少し設計が進むまで保留ということで。 ちなみに、LED をダイナミック点灯させると、電源にかなりのノイズが載る。ADC を使うのも PWM を使うのも精度を出すのは、結構厳しいと思う。 その他のパーツについて 基板は、両面ガラス・ユニバーサル基板 72x47mm(1枚 100円・10枚 900円) を選択する予定。SD カードスロットを上面に付けたいというだけの理由。 あとは、ケースそれに、配線材とコンデンサ・抵抗・インダクタ、それに ICソケット・ピンヘッダ。基本的にこういうものまではケアしないが...どうしよう。 できるだけ秋月取り扱いパーツを紹介するが、無理な面もある。 まずケース。 ケースに入れられるように作る場合は テイシン電機 TB-55Bから検討する。ひょっとしたら基板を削ってもパーツの配置の問題で入らないかも知れないし決定ではない。これに入らないなら、すなおにレイアウトするつもり。一応スペーサを勧めておこう。 コンデンサ・抵抗は秋月のものだけで良いのだが、SD用 インダクタは無理かも。一応 マイクロインダクタ 47uH を付けてみて、動けば OK ということにしよう。 他の目的に使う 仮想FD として使えることを第一に考えるけれども、他の目的に使えても良いかも知れない。SD カードも付くし ブートローダも使ってみたいし。-- ただ、プログラム本体も 6KB 以内という条件になってしまう。無理なら諦めるつもりだが、少しばかり検討だけはしておこう。 まずは Writer 機能ということになりそう。拡張用信号線は 2 つしかない。... のだが ボタンをさわらないことにすれば 4 本。SD カード用の信号線を使うことは考えたくないので、この 4 本を使えるように少し考えておこう。 それ以外? 7 seg 3桁ながら表示装置とボタンが付いていて USB も付いていれば意外にも有用なものが作れるかも。3桁ロックつきUSBメモリとか? PCの画面ロックとか? 秒表示 ラーメンタイマとか?。まぁ本体で作れるものは、拡張用信号線は関係ない。 2 本しかないが、ADC が使えるのはメリットかも知れない。 7seg をやめて液晶ディスプレーにする うーん。入れ替えて使える機能を考え出すとこういうことをしたくなる。あくまでおまけと考えたほうが良さそうだ。まぁ、基板を起こすぐらい気合が入ったなら、7seg と 超小型LCDキャラクタディスプレイモジュールのどちらを使うか選べるようにしても良いかも知れない。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: 電子工作と FLASHメモリ STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 02/27/2008 21:28:02 ----- BODY: 電子工作で大容量のデータを扱いたい場合のひとつの選択枝は、SD/MMC カードを使うことだ。 いまは、ビット単価がすさまじく下がっているので、実際に使うのは microSD が良いと思う。microSD のほうが一般に消費電力が少ないらしい。実際に調べたわけではないが、突入電流も少ないのではないだろうか。 SD のスロットでよいなら、秋月でも取り扱っている。-- (150円の安い方は)あまりよい品ではないらしい。220 円の ヒロセ製の方が安心。 microSD 専用にしたいなら、コネクタもデジキーで入手できる。DM3AT-SF-PEJとかDM3B-DSF-PEJとか。microSD は、1.1mm ピッチだから手半田でもなんとかなるかも知れない。
西川部品でも DM3A-SF-PEJを扱っている(315円)。-- ゆきの研究室つれづれ日記より 秋月でも DM3AT-SF-PEJを扱いだした。200円。 ちなみに MINI-SD 用スロット(DM2A-SFW-PEJ-S)も。200円。
さて、そんなに大容量である必要がなく、PCからの読み書きも必要ない場合はどうだろう。 残念ながら、あまり選択枝はない。特に ADC からキャプチャーするなど、高速かつ定期的にデータを書き込みたい場合は、ダブルバッファが必要でさらに選択枝が少なくなる。 以前さがして、そういう目的に合いそうなデバイスを1つ見つけたので紹介しようと思う。 それは、AT45DB081D -- デジキーで 213円。 インターフェイスは SPI で 8-soic パッケージがあるので、秋月の変換基板で DIP としても使える。 1MB だから GBクラス の microSD の 1/1000 以下だが、目的によっては大きすぎる場合もあるはず。書き換えも 10万回できる。 書き込みに向いていると思ったのは、256B の ページWrite が比較的早い(2ms Typ/4ms Max) だけでなく、バッファを 2組持っているためだ。 バッファを 2 つ持っていると、ページWrite している間も書き込みができるので、AVR 側にバッファを持たずにすむし書き込み時間も隠蔽されてしまう。ページWriteの時間だけが、書き込み性能を規定する。 4ms あたり 256B 書けることが保証されているのであれば、8bit ならば、64k sps でデータを書き込みしてもデータ落ちがないということである。AVR のADC の 上限 77 k sps にかなり近い。10 bit だと、15 k sps でしか取れないから、2バイトづつ書いても十分間に合う。
ちなみに、AT45DB081B というデバイスもあるが、ページWriteが遅い。AT45DB041D は容量だけ違うので良いのだが、すぐ買えないかも知れない。AT45DB021D は、バッファを 1つしかもっておらずキャプチャーに向いていない。 AT45DB161D も 276 円と安く良い。ページサイズが 512B で ページWrite時間が 3ms Typ/6ms Max なので、若干帯域が高い。
上記は、Write だけをする場合。Erase には時間がかかるのであらかじめ Erase しておくのを前提にしている。Erase and Programming だと、Typ 14ms/Max 35ms になる。この場合の上限は、7.3KB/sec ほど。 Write と違って Read は制限がほとんどない。バッファに読み出す時間は 0.2 ms でしかも 2つあるから無視できそうだ。SPI クロックの上限は 66Mhz で 純粋に AVR 側の SPI 性能で決まる。たとえば ATmega88 とか AT90USB162 とかは、SPI を持っていて、さらに USART も SPI として使える。上限は 1/2 CPU CLOCK なので、CPU CLOCK が16MHz だとすれば、8MHz 。連続で読み出す場合 1MB/sec 弱で読み込めるはずだ。 まぁ、書き込みが高速といってもこの程度だし入手性も問題がある。1MB ほどしか必要なくても、いっそのこと microSD にしてしまうのも良いのではないかと思う。 SD/MMC カードを使う場合、FAT をサポートするのが望ましい。1MB しか必要ないのに 1GB 全体を占有するのは気がひける。 でも AVR などコード領域が少なく FAT をサポートしきれない場合はどうしたらよいのだろう。 案1)あらかじめ用意した固定名のファイルの中だけを使う。 FAT16のみを使用して、アロケーションサイズも 32KB 固定にすることを前提にしてみる。
- こういうことは、Linux では簡単にできる。mkfs.msdos のパラメータを設定するだけだ。 - Windows XP だと 2GB(弱)なら FAT を選択するだけで自動的に 32KB になる→ 参考 : FAT および NTFS のデフォルトのクダスタサイズ - 1GB だと 16KB になるだけで、残念ながら普通の方法では無理。 面倒だが、コントロールパネル→ コンピュータの管理→DISKの管理→領域選択→プロパティで FAT とアロケーションユニットサイズ を選択することで FAT16で32KB に設定可能。 - 4GB の microSD は存在しない。microSDHC になる。
こういうことを前提にできるなら、1MB でも 32個 64B の変換マップを作れば良いので なんとかなるのではないだろうか? ちなみに、microSD の 1GB と 2GB のみを対象とした理由
- メモリカードの販売価格の推移を見ていると 1000円を大幅に切るまで安くなったものは、やがて市場から消えていく運命にある。 - 1GB の価格はすでに 600円台。たぶんやがて消える。 - 2GB は SD 規格の最大容量だから、結構しぶとく残るのではないか? (ただし、どこまでも安くなるとは思えない。500円〜1000円のどこかで安定するような気がする。)  - そうだとして microSD は miniSD/SD に変換できるから、2G 以下の miniSD/SDもやがて消えていくのではないか?  - そういうわけで、今からものを作るのであれば、2GB のみを対象にすれば良さそう。(1GB はおまけ)
案2) パーティションの隙間を使う。 案1を実装するだけのコード領域がないから FAT を無視して連続した領域を使いたいという場合でも 先頭から使うのだけはやめたほうが良い。 先頭の 512B さえあければパーティションをずらして作ることで、他の領域を他の目的に使えるからだ。
- これも Linux なら実に簡単だ、fdisk するときにパーティションの先頭をデフォルトから変更するだけ。 - Windows ではどうしたらよいのだろう? 商用ソフトなら、いくつか存在するのだろう。しかし、これだけのために商用ソフトを進めるわけにはいかない。 - FIPS かつては定番ツールだったらしい。今使えるのかどうか不明。 → (MD5) 0e69615d799a6dc7309cbc07a4539426 fips20.zip ソース付きなので、いろいろできるかも。
さて、どれだけずらせばよいのだろう? 一応 16セクタ(先頭から 16x 512B) ずらすことをお勧めする。
なぜか? たいした理由ではないのだが、あるシステムと同じだから。-- あるシステムって何? 誰でも知っているものだけど秘密です。
----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: microSDカードの書き込み耐性(2) STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: microSD関係 DATE: 03/07/2008 17:35:50 ----- BODY: microSD (や SD/miniSD)は、いったいどれぐらい書き換えられるものなのだろう? 実際に調べてみることにした。
誤解のないように説明しておくと、知りたいのは局所的に書き込み回数が多い場合どうなるのかということ。書き込み回数が多い場所はどうしてもできる。そこが 10万回〜数十万回でダメになるのかどうか? もっと書き込めるならいったいどこまで書き込みできるのか? このことについて調べている。 また、ダメになった後はどうなるのか?というのも知りたいのであわせて調べている。
前記事では、こういう動機で 準備として 不要になった 64MB miniSD でテストを行い、次に 最初のテストとして 上海問屋オリジナル 2GB microSD のテストをした。 結果だけ簡単にまとめておくと 書き込み内容が化ける件については書き込み耐性とは関係なさそう、でもイヤな問題なので別途考察することにしよう。 2つ目のターゲットは、キングストン 2GB miroSD。カードにJAPAN の文字がある。キングストンは東芝製のチップを使っているらしい。 そう、書き込み内容が化ける問題が、こいつでも起きてしまったのだ。 起きたのは 510 万回書き換えた後。化けたパターンは、
PAGE: 8 (2048)
00: 68 1f 63 63 63 63 63 63 63 63 63 63 63 63 63 63
01: 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63 63
2回目は、1710万回書き換えた後。化けたパターンは、
PAGE: 4 (1024)
00: 1d 78 94 94 94 94 94 94 94 94 94 94 94 94 94 94 
01: 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 94 
3回目は、2420万回目。パターンも同じような感じ。 (1回目だと)全部 0x63 であるべきところが、0x68,0x1f になっている。 512 バイト単位で、先頭の 1〜2バイトが化けるというのがこれまで起きた4回の共通パターン 今回のテスト環境は、玄箱/HG にインストールした Linux(PPC)。 OS が Linux であるということと、USB のカードアダプタが同じというのが共通点。 前記事では、Linux や Vmware を疑ったが 、少なくとも Vmware は関係ない。Linux も PPC (Big-Endian)になったので大分違うとはいえる。Linux の ファイルシステム(vfat)のバグという可能性が残るが、随分使われているものだから、たぶん違うだろう。 今疑っているのは、カードアダプタ。microSD カードの中身がたまたま同じところの製品で特性が似ていたという可能性はあるが、microSD を疑うのは保留。このテストが終わったら複数のカードアダプタでテストしてみることにする。幸い 書き込み耐性の評価に使ったカードでも 完全に壊れたわけではないので、使わなかった領域を使ってテストできる。テスト用のプログラムも広い領域を使うようなものにすることにする。
とりあえずプログラム作成→flashtest2.c ちょっと変更して、データを書く位置を ずらしていくようにした。 ずらすサイズ (個数)を 1000 にすれば、10万回しか書けなくても 全部で1億回の転送ができる。 それは良いのだが、vfat だと ディレクトリエントリが何度も書き換えられるので都合が悪い。ext3 で使ってみることにする。 sar -d で確認。
                DEV       tps     rd_sec/s  wr_sec/s
20時50分01秒    dev8-0    412.34   1647.75   1652.56
21時00分01秒    dev8-0    414.59   1656.76   1661.53
21時10分01秒    dev8-0    415.52   1660.48   1665.27
秒間 103 回の write + read が出来ている計算で、100000回なら 970 秒 15 分ぐらいで済むはずだ。で実際も 15分弱で終わっていて、プログラムでの read / write しか出ていないことを確認。 これで、3000万回ぐらいやってみて、無問題なら結構安心。 最初に使ったアダプタが悪いか、疲労してきた microSD の特性か と思うことができる。 → 3000万回の転送は無問題だった。 一応、 最初に使ったアダプタで同じことをやるつもり。それで無問題だったら、疲労してきた microSD の特性だと思うことにする。 → あまりに遅いので、300 万回でキブアップ。
USB アダプタによってこんなに性能が違うとは思ってみなかった。信頼性もかなり違うかもしれない。 どういう違いがあるのか。/proc/bus/usb/device の情報を書いておく。
最初に使っていた USB アダプタ (microSD 専用)
T:  Bus=02 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=12  MxCh= 0
D:  Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
P:  Vendor=058f ProdID=6335 Rev= 1.02
S:  Manufacturer=Generic
S:  Product=Mass Storage Device
S:  SerialNumber=058F011111B1
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=250mA
I:  If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage
E:  Ad=01(O) Atr=02(Bulk) MxPS=  64 Ivl=0ms
E:  Ad=82(I) Atr=02(Bulk) MxPS=  64 Ivl=0ms

2番目に使った USB アダプタ (microSD/SDHC 専用)
T:  Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  3 Spd=480 MxCh= 0
D:  Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
P:  Vendor=14cd ProdID=6700 Rev= 2.01
S:  Manufacturer=SDMMC M121
S:  Product=USB 2.0  SD/MMC READER 
S:  SerialNumber=845340272046
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA
I:  If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage
E:  Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
2番目に使った USB アダプタは、 おそらく、このページにある fujitek のもの(380円)と同じ(ブランドは違う)。ちなみに、480円のへんな形状のUSB/SD変換アダプタを買ってみたのだが、同じチップを使っていた。
最初に使ったものは、MxPS(パケットサイズ)= 64 だったりして、性能的にあまりよくないものだということはわかった。 普通の USB A タイプコネクタで、本体が 結構厚い。コネクタメーカの microSDコネクタを使っていて、物理的な信頼性は高いかんじで、お気に入りだったが、性能や信頼性に問題があるとなると使いたくなくなってしまった。 2番目に使ったものがお勧めかというと、わからない。あまりに小さいので、少々使いづらい。また、あまりに薄いと接触不良がおきやすかったりするかも知れない。ついでに書いておくと、対応は、8GB までらしい。 さて、キングストン 2GB microSDは、なかなか壊れない。もうやめたいが、壊れた後どうなるのか興味があるので、もう少しがんばってみようかと思う。ひょっとして実際Flashへの書き込みはもっと少なくて壊れないとか想定外の理由があるかも知れないが、高速だし、なかなか良い製品だと思う。 それとは別に実はもう1つ microSD のテストを始めている。ターゲットは、A-DATA 。A-DATA の は、不良ブロックの代替だけではなく、損耗平均化アルゴリズム (wear leveling algorithms) に対応していることが書かれている。それだけでなく、FW を更新できるなんて一般ユーザには関係なさそうなことまで書かれている。ひょっとして特性も違うのかも知れないなんて思ってしまったものだから調べないわけにはいかなくなった。ちなみに、壊すことを前提に購入したので、安い1GB にした。 キングストン 2GB microSDが、なかなか壊れないので、microSD 自体でキャッシングされているのではないか?という疑念がわいた。 プログラムを若干変更。→ flashtest3.c その上で、ファイルに対して 8KB x 1 の書き換えを行っていたのを 8KB x 5 に変更。8KB を10万回書く時間は 5分から 30分になった。
その後何回か試したところ、30分は 1回のみ。疑念は気のせいということに。
次に別の疑念がわいた。SDMMC M121は、まだ1回も write error を出していない。内部でリトライしているかも知れない。ダメになった上海問屋オリジナルを使ってどうなるか見てみることにした。 → 280万回書き換えてエラーなし。その後 第三のアダプタに変更したが、計 400万回書き換えてエラーなし。 最初のアダプタで write error が出だしたのがうそのようだ。 100MB のファイルを書く時間を見てみるとかなり遅くなっているようだし、疲労しているとは思うのだが... どうもいままでのテストの方法が甘かったようだ。 書き込むサイズを大きくしていって、時間がどれぐらいかかるか 調べてみた。以下は、1000回 write+read する時間(単位 秒)。
       上海 2G  キングストン 2G    A-DATA 1G
  8KB     7            7               7
 16KB    12          100              11
 32KB    19          100              21
 48KB    91          100              30 
 64KB   138          100              41
 96KB    --          100              60
128KB    --          200              95  
上海 2Gは、48KB になると急に遅くなる。ルートディレクトリエントリの 8KB と ファイルへの write の 2 ヵ所しか書き換えていないため、2 個のバッファが WB(Write Back) キャッシュとして作用するのではないか? 消去ブロックサイズは 32KB ですなおな設計になっているような感じだ。すくなくとも今までのテスト write 回数 = Flash 書き換えになっていない。 キングストン 2G は、16KB から遅くなる。その後サイズを大きくしていっても時間は同じ。8KB以下のサイズでは WB キャッシュを持っていたりしそう。サイズを変えても 96 KB まで時間が同じということは、消去ブロックサイズがこのあたりなのだろう。 A-DATA 1G は、リニアに時間がかかるだけ。これまたよくわからない。128KB より多い量の WB キャッシュを持っていると考えるべきなのかも知れない。 とにかく、いままでのテストはダメだったようだ。上海 2G と キングストン 2Gは、48KB で write するようにすれば 内部の Flash が書き換わりそうだから、サイズを変えてテスト継続することはできる。ただ、テスト方法をもっと練ってやりなおしたほうが良さそうだ。 この記事の更新はここで終わりにしようと思う。次はリベンジということで、新たに記事を起こす予定。 おわりに 最後に、なぜ microSD に対して書き込み耐性のテストに踏み切ったのは何故かについて書いておこうと思う。 もちろん、常々興味があった。そして十分安くなったから。というのは背景にある。ここで書くのはそれ以外の理由。 なぜ microSDなのか これから、大容量のものは別にして、2GB までのものは、microSD に収束していくだろう。今調べるなら、他のメディアを調べる意味はなく、microSD を調べるべきである。 もちろんこういう要素が大きいのだが、私の中では、もっと重要な理由がある。 それは、”CF や USB メモリ、SD/miniSD と比べて、製造の難易度が高く 実装のバリエーションが少ないだろう” ということ。少数の一流メーカしか製造できないなら、特性も似たりよったりになってくるのではないか?→ すなわち、結構特性を一般化できるはず→調査したデータが意味を持ってくる。
補足: microSD のサイズは、11mm x 15 mm x 1.0 mm 。東芝 が 2007年 03月28日に発表した 56nmプロセス 16G bit NAND型フラッシュメモリTC58NVG4D1DTG00は、12mm x 20 mm × 1.2 mm -- LSI より小さく薄いのだ。今は 8GB のものまであるが、いったいどこに入っていて、ちゃんと強度を保てているのか?不思議なぐらい。 ISSCC 2008レポートを見ると 16G bits(2G bytes)でチップ面積が 120平方 mm とか書いてある。microSD のサイズ (端子込みで 165 平方 mm) とさして変わらない。2GB ですら どういう風にチップが入っているのかあまり想像できない? まして 8GB は? -- もちろん 積層されている以外にないのだが ... 1mm の薄さにそれが入っていて、一般の人が扱えるだけの強度があるというのがとても不思議。 実装のバリエーションが少ないというのは、ほんとうらしい。 → microSDの性能についてを参照
このようなことを考えたから microSD をターゲットに調査をしている。値段の関係で microSD しか調べられないが、一般的に microSDHC も調べた特性より高耐性になるだろうという予想はできる。 これから一般化してくるであろう SSD も 調べた特性より高耐性なものに収束していくだろうと思う。ただ過渡期において変なもの・雑な設計のものが出てくる可能性はある。 USB メモリはどうなるか、さっぱりわからない。それは実装があまりに多様だからだ。書き込み耐性の面でダメダメな実装も多いかもしれない。Flash のチップ内部で 不良ブロック制御を行っているものがあるが、そういうものが一般化されないと、書き込み耐性について一般化してコメントできるような気がしない。 なぜ興味を持ったのか 普通に Windosやデジカメで使った場合、安心できるか?書き込み回数が多い場所が 10万回〜数十万回でダメになるなら、あまり安心できない。もうすこし多くないと困る。 たとえば、1日に100枚の写真を撮るとすると、100日で最悪 10万回の書き換えが起きるところ(たぶんディレクトリエントリ)が出てくるかも知れない。そう考えると 10万回というのは多いとは言えない。 また、書き込み耐性を超えたらどうなってしまうのか? これも問題だ。データが壊れるとすれば、撮った写真がダメになってしまうのか? こういうことが一般的に知りたい理由だろう。私もそういう観点で知りたいが、もっと別の理由がある。 ひとつは、電子工作的な観点。大容量のメモリ(RAM)を AVR とかにつなぐのは 配線の数が多くなるので、物理的に無理だったり、面倒だったりする。シリアルベースの Flash メモリをつなぐのは簡単だが、繰り返し書き換えられるのかどうか? たとえば、ログを全体にわたってサイクリックに書き込むとする。10万回書き換えられて、1GB あるならば、通算で 100TB ものデータを書くことはできる。1MB/sec で書き込み続けても 3年以上持つ。 それは良いのだが、どこまで書いたかという情報をどこか固定の場所に書くとすると、そこだけ異常に書き換え回数が増えることになる。1000万回のオーダで書き換えられることを知っていれば、結構安心してこういう設計ができることになるわけだ。 実はもっと別の理由もある。それは、SSD に対する理想のファイルシステムはどういうものかを考えるということ。 簡単に言えば上のような制御をやってくれるファイルシステムということになる。ファイルシステムでは、zfs のように copy-on-write という概念がある。書き換えたデータを同じところには保存せず常に新しい領域を確保してそこに書く。ハードディスクだとランダムアクセスが遅いから、連続した領域に書くというのは性能を上げるために重要な技術なのだが、SSD の場合それは関係ない。しかし、領域全体を使い書き込み回数を平均化してくれるわけで、 copy-on-write という技術は SSD に対して別の理由で有利なわけだ。 それは良いのだが、最新のデータを示すポインタが必要で普通 SUPERBLOCK といわれるところに格納する。そこだけ極端に書き込み回数が増える。 書き込み耐性がいったいどれぐらいあるのかということが、ポイントになってくるのだ。あまりに低いと ハードディスク用の設計では不十分で SSD 専用の仕組みが必要になる。結論としてはこれぐらいあればまぁ、普通に使えそう。 相当に専門的な興味だと思われるかも知れない。でもそうではない。もう SSD というのはかなり身近になってきている。Flash に変わる不揮発性メモリも話題になっているが、当面は Flash だろう。Flash ベースの SSD をどうやって使えばよいのかということを考えるのは、普通に使う立場でも有用なはずだ。
microSDの性能についてで示したように、microSD (一般の MLC Flashも)は、4KB とか小さいサイズの Write が相当遅い。OS をインストールするような場合、書き込み耐性よりこっちの方がネックになりそうだ。そういう意味でも、連続した領域に書く copy-on-write ファイルシステムが望まれる。
----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- COMMENT: AUTHOR: P EMAIL: IP: 119.72.17.127 URL: DATE: 03/21/2008 08:21:22 テストお疲れ様でした。 この記事を読んだ感想ですが、 最近のメモリカード、2GB miniSDが1000円切ったり、16GB SDカードが6千円と、値崩れして容量の陳腐化が激しいわけですが、 技術は格段に進化してて、信頼性をあげるためにメーカーがいろいろ工夫をしているんだなぁ。ということです。 ----- COMMENT: AUTHOR: とおり EMAIL: IP: 210.147.83.69 URL: DATE: 03/22/2008 23:43:22 お疲れ様です。 DVD-Rも容量単価が劇的に下がったメディアの一つですが、近年は品質の低下が目立ちます。 こういった点も懸念されます。 ----- COMMENT: AUTHOR: MASA.H EMAIL: IP: 220.219.70.230 URL: http://d.hatena.ne.jp/MasaHero/ DATE: 03/23/2008 03:16:59 貴重な実験、お疲れ様です。 思ったのですが、ファイルシステムがFATなら、書き換えの集中する先頭部分だけはフラッシュメモリでなく不揮発性SRAM等を用いてやれば実環境下に置ける平均寿命は大幅に向上するのでは? FATに限らずともどのファイルシステムにも実デート比較すると非常に小さな領域しか占めないインデックス部が有り、大抵読み書きはそこに集中するのでそこだけもっと書き換え耐性の強いものに置き換えてやればいいのでは? 既に誰かが思いついてそうなものですが、なぜそういったものが出ていないのでしょうね。やっぱり不揮発性SRAMが高いからなのか。 ----- COMMENT: AUTHOR: EMAIL: IP: 211.133.15.146 URL: DATE: 03/25/2008 17:16:37 今の Flash メモリにはデバイス(chip)内部に、物理的な書き込みブロックが集中しないような仕組みが入っていますので、外から論理的に書き込みブロックが集中するように指定しても、実際にはそうはならないはずです。 ----- COMMENT: AUTHOR: とおりすがり EMAIL: IP: 219.2.136.51 URL: DATE: 03/25/2008 17:27:12 貴重な実験を公開していただいてどうもありがとうございました。 フラッシュに対する疑念は、非専門的で漠然としたものですが、私も持っておりました。 まぁ日本のメーカーが使えると言ってるのだからそれなりなんだろうぐらいに思っておりましたが、今回の実験は参考になりました。 何より読んでて興味深く楽しかったです。 本当にありがとうございました。 ちなみにこちらのインプレスの記事から来ました。参考まで。 http://internet.watch.impress.co.jp/static/yajiuma/2008/03/25/ ----- COMMENT: AUTHOR: ほげ EMAIL: IP: 210.189.30.129 URL: DATE: 03/25/2008 19:43:40 ウェアレベリングでググってみましょう。 基本的には空き容量が多いほど書き換え可能回数は増えますので、空き容量を極力減らした状態で同じテストをしてみたらどうでしょう。 空き容量が多いほど信頼性が上がるので、大容量のカードを余裕を持って使うのがお勧めです。 ----- COMMENT: AUTHOR: EMAIL: IP: 192.51.44.17 URL: DATE: 03/25/2008 20:42:42 flashのコントローラ内に、物理的な書き込み先を分散する機能が搭載されています。 大きなサイズのflashで、小さいデータを書き換えた場合見かけの寿命は長く見えることになります。 ----- COMMENT: AUTHOR: 774 EMAIL: IP: 61.192.204.4 URL: DATE: 03/26/2008 00:52:01 上記のコメントにも散々出ていますが8KBx5の書き換えでは2GBを2000MBと仮定しても 約6200回実行しないと1回目相当の書き込みにはなりません。 何故か?と言うのはMicrosoftが面白い資料を出してるので目を通しておくと良いでしょう。 http://download.microsoft.com/download/a/f/d/afdfd50d-6eb9-425e-84e1-b4085a80e34e/WNS-T432_WH07.pptx ----- PING: TITLE: USBメモリは壊れる URL: http://catcat.boo.jp/blog2/archives/2008/02/05/110842.php IP: 202.222.30.137 BLOG NAME: Kyan's BLOG III DATE: 03/27/2008 15:30:40 USBメモリの書き換え限界寿命が来ると何が起きるのか、実際に寿命が来たケースをレポート - GIGAZINE 非常に興味深い。 この記事の場合USBメモリが壊れたのは事実でもそれが書き換え限界によるものかどうかは推定のようですが,USBメモリなどのフラッシ... ----- -------- AUTHOR: すz TITLE: microSDカードの書き込み耐性(3) STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: microSD関係 DATE: 03/26/2008 02:12:35 ----- BODY: 前記事のmicroSDカードの書き込み耐性についてmicroSDカードの書き込み耐性(2)で、microSD が壊れるまで書き込みを続けようとしてきた。 だが、まだ壊すことができていない。 いくつかのコメントにあったが、損耗平均化アルゴリズム (wear leveling algorithms) で、書き込み先を分散することで、メモリ全体に書き込みが分散されるから、この程度の書き込みでは壊れないのだろうか? そうであれば良いのだが、私は、メモリ全体に渡って書き込みを分散することはないと考えている。 その機能を作るとすると、MMU のようにマップが必要になる。2GB の メモリ全体をカバーするとすれば、65536 個のエントリが必要になる。それぞれのエントリには、マップ先を示す 16bit のエリアと 書き込み回数を記録する 24bit ぐらいのエリアが必要だろう。 合計で、384KB が必要で、更新頻度が高いから、RAM である必要がある。そして、その RAM は不揮発性であるか、カードの電源が OFF になってから FLASH に書き戻すとかする機能を持っている必要がある。 そこまでの RAM 容量と機能を持っているのはあまり考えにくい。そういう機能ではなく、書き込み頻度の高いところを見つけて、そこの書き込み回数を記録して、ある程度の回数になれば、壊れるまえに代替ブロックに置き換えるのではないだろうか?
別の見方もある。もし完全に平均化できる機能であれば、FLASH メモリの書き込み耐性の問題はクリアしているといえるのだ。もっと大々的に宣伝されているはず。そうでないから不完全な機能だと思えるわけだ。 PC 用 ハードディスクの エラーレートを知っているだろうか?たとえば、HGST Deskstar E7K500のデータシートには、1/10^14 だと書いてある。同じ土俵の数字ではないだろうが、10万ブロック x 10万回だと 1/10^10 。ハードディスクに遠くおよばないが、容量が 1/1000 だとして、容量あたりという考え方をすれば、ハードディスクの 1/10 程度にまでなってくる。
ちなみに、損耗平均化アルゴリズム (wear leveling algorithms)があることを スペックに明記しているのは、A-DATA だけ。他はハードディスクと同じような不良ブロックマネージメント機能だと思う。 ちなみに、代替ブロックは、OS から見えないところに専用のエリアがあるはずだ。どれぐらいの容量があるかはわからないが、たぶんメモリ全体の1〜5%程度だと思う。(自信なし)
追記:↑の考察はそうとうに甘かったようだ。入れ替える方法ならば、メモリ全体を使える。詳しくは↓を参照のこと。
どういうテストをすれば壊れるのか? キングストンなどは 5000万回も書いても壊れなかった。どんどん代替プロックが置き換えられているとも考えられるが、Write Back キャッシュになっていて、書き込んだ回数 != Flash に書かれた回数という可能性もある。 いろいろ考えたのだが、書き込んだら確実に Flash に書かれるように 1回の書き込みサイズを 1MB にすることにした。1MB ものキャッシュを持っているとは思えないので、大丈夫だろう。 それは良いのだが、1MB もの領域を書き込んで、確認のために読み込むとなると、相当時間がかかる。だいたい 1万回書き込むのに 1時間前後。100 万回でも 4 日のオーダになる。 ここまできたら意地である。何日かかろうともやってみようと思う。 このプログラムで、まずは、300万回書き込んでみることにする。 ターゲットは、いままで使ってきた 上海問屋オリジナル 2GB 、キングストン 2GB 、A-DATA 1GB 。 6 日やってこの状況だ。300 万回まで一週間以上かかる。300万回をクリアしたとしても、まだまだ続ける予定。 結果は、このページの追記に記載する。 おまけ 実はコメントを見て驚いたことがある。 多くの人が、書き込みを平均化するのに、空きエリアから代替するブロックを取ってくると考えているようなのだ。 結論から言うとそのようなことは不可能だ。 空きエリアは、OS のファイルシステムが管理する。そして、その情報を、DISK に書き込まずキャッシュするのが普通なのだ。 たとえ、microSD 側が、FAT ファイルシステムの構造を知ることができても情報が最新である保証がない限り、どこが空いているか確実に知ることはできない。つまり、最新の情報は OS しかもっていないから、どこが空いているか正確にはわからないのだ。 もし、使用しているエリアを使ってしまえばデータが化けてしまうわけで、そのような仕組みを入れることは不可能なのである。 ウェアレベリング機能 コメントで教えてもらったウェアレベリングをググってみた。 ウィキペディア の NAND型フラッシュメモリがわかりやすいと思う。 実際の例として、業界初のメモリ管理機能内蔵フラッシュメモリがヒットした。 東芝も LBA-NANDというウェアレベリングをサポートしたチップを出している。 たとえば、ある一定の書換回数に至ると、自動的に書換え回数の少ない領域とデータとアドレスを入れ替えるというもの(特許になっていていくつか方式がある)らしい。 なるほど、入れ替えるならば、空きエリアなどファイルシステムが管理する情報に依存せず実現できる。 入れ替える単位は、たぶん ブロックサイズなのだろう。ブロックサイズが何KB かわからないが、4K ページ x 64 とすると、256 KB 。2GB なら、8000 個ぐらいある計算。8000 個を順番に使うのなら、20万回でエラーになるとしても、1MB を 4億回書かないと寿命に至らない。300 万回程度の書き込みでは何もおこらないだろう。
フラッシュメモリは何日で壊れる? ウェアレベリングの仕組みというページを見つけた。ここでは、SanDisk の CF の仕組みを解説しているのだが、OS が空きエリアを CF に通知しないとウェアレベリングに使うプール(Erase Pool)が増えない。非対応の OS だと 3% の代替ブロックが使えるに過ぎない。ウェアレベリングにもいろいろあるようだ。 空きエリアが多いほど... と考えている人は、ひょっとして SanDisk の CF の仕組みを想定しているのかも知れない。 普通に使う範囲ならば、空きエリアは関係なく、一度も使ったことのないエリアということになる。 パーティションきりなおして、小さくしておけば耐性があがるかも。 といっても、各社ウェアレベリングは特許にしているだろうから、方式はマチマチになると思う。一般化してしまうのは無理がありそう。日立の入れ替えるという方法がもっとも良いと思うが、日立の特許で他のメーカは使え(and/or わ)ないのかも。
あまり深く考えてなかったのだが、普通の不良ブロックマネージメント機能で、5% の代替エリアを持っていると仮定しても、2000万回書き換えられる計算。前のテストで、Write Error を起こしたことがある上海 2GB なら何らかのエラーになる可能性はあるが、300 万回ではなにも起きないかも。一応 300万回 x 2 の合計 600万回やってみてなにもなければ、テストをやめることにしよう。 やはり意地である。理想的なウェアレベリング機能でなければ、壊すことは可能そうだ。ただ 300万回では話にならなさそうだ。クリアしてしまったら、再検討してトライしてみることにする。 おまけ2 上海問屋オリジナル 1G/2G は、A-DATA my Super 1G/2G の OEM らしいことがわかった。 裏面に浮き出ているパターンみたいなのがそっくりだったので、デバイスのサイズを見てみたら、まったく同じだった。
1G  994816 KB
2G 1993728 KB
3種類調べていたつもりが、ほぼ2種類(一応 1G/2G の違いがある)だったとは、ちょっとショック。 おまけ3:手持ちの microSD の性能
                       write      read      size  
A-DATA 1G             4.67       15.29    994816 (3886 x 256)
A-DATA 2G             7.96       15.29   1993728 (7788 x 256)
キングストン 2G       7.35       15.51   1966080 (7680 x 256)
Silicon Power 2G      3.91        9.21   1985024 (7754 x 256)

※ 上海問屋 1G は、A-DATA 1G と同じ性能 (2G は未測定 )

size の単位 KB 
read/write の 単位  MB/sec ( 1024x1024 /sec )

テスト内容
    write  100MB のファイルを write 
       - キャッシュを(ほぼ)書き出すまで
    read   100MB のファイルを read
       - いったん umount し DISK から読み出す
テスト環境 玄箱/HG Linux(自分改造版)
    USB アダプタ SDMMC M121 (14cd/6700) 
ファイルシステム FAT16  
  - クラスタサイズ 1G -> 16K / 2G -> 32K
microSDの性能についてに続く
追記 1MB では、秒間 3 回ぐらいしか書けない。これではラチがあかないので、もう少しなんとかしたい。 秒間 3回でも 1MB なので、3MB/sec で Write + Read していたことになる。転送性能から見てこれぐらいが精一杯。 一応 4K ページ・256K ブロックの Flash だと仮定しよう。 おなじ 1MB の領域を使うとしても、256 K バイトおきに、先頭の 数キロバイトのみ書き込みしていっても同じ効果になりそうだ。 中断して、新プログラムに変更することにする。 これだと、上海/A-DATA は、一日で 250 万回ぐらいになりそうだ。とりあえず 1000万回を上限にテストをスタート。
まだはじめたばかりに近いのに、どんどん遅くなっている。ひょっとして、エラーが頻発していたりするのだろうか? ようやく 1/2 の 500万回まできた。性能は安定しているようだ。 しかし、なにも起こらない。最後まで行ってしまう予感。
キングストンは遅い。こういう書き方をされるのは苦手なようだ。 追記 ここに来て、上海/A-DATA (1G/2G, Super) は、SLC であるということを知った。そして、キングストン 2G (日本製)も。 SLC は MLC と比べて書き込み耐性が 1桁違うらしい。なかなか壊れないのもそれが理由かも知れない。 ちなみに 8GB は確実に MLC 。4GB もたぶん MLC 。SLC だけを調べてなにかわかったとしても 4G/8G の特性まで一般化できない。 4GB のテストは、4GB が1500 円を切るようなことがあればやってみることにして、今は 2GB 。SanDisk 2GB bulk は、A-DATA とも キングストンとも特性が違うようなので、(このテストが終わったら)試してみようと思う。 それはともかく、あまりになにも起きないので、上海 2G に対して、最初に使った USB アダプタに切り替えてみようと思う。 USB アダプタ SDMMC M121 (14cd/6700) について 少しばかりコレについて説明しておこうと思う。 14cd/6700 は、USB のベンダID/プロダクトID。SDMMC M121というのは、USBからみえるベンダ名。相当変であるが、USB アダプタのチップがそう言ってくるわけで、とりあえずこれを名前にしている。
ちなみに、このベンダには、14cd/6600 というのがあって、それは、ベンダ名: Super Top プロダクト名:USB 2.0 IDE DEVICE を返すらしい。しかし、Super Top というベンダの Home Page は見つけられていない。
実際の製品としては、FUJITEK microSD超小型カードリーダー。それ以外の FUJITEK アダプタにもこのチップが使われている。また、GREEN HOUSE GH-CRMR1-S*Aシリーズも同じもの。なんと 0.82g の軽さ -- microSD を装着しても 1.22g 。 このアダプタ、これだけのテストでエラーを出していないし、小型なので気に入っている。ただいくつか不満な点もある。 ひとつは、最大性能があまり高くない(らしい)こと。Photo Fast とか 150x (22.5MB/sec)らしいが、read で16MB/sec ぐらいまでしか出ていない。たぶん 最大クロックが十分ではないのだろう。実用上はぜんぜん問題ないが、性能テストするには不十分なのだ。 もうひとつは SDのイレーズ機能がないらしいこと。パナソニックの SDformatter には、イレーズするという機能がある。しかし、この USB アダプタだと "デバイスにイレーズ機能がありません" と言われてしまう。ひょっとして、A-DATA などイレーズすることで、ウェアレベリング機能に対して空きエリアをリセットできるのではないかという気がしていて、イレーズをやってみたいのだが、それが出来ない。まぁイレーズ機能があるアダプタなど パナソニック純正以外にあるのかどうかも判らないのだが、少々残念。
電子工作ネタ 一般のUSB アダプタでは完全に初期化できないなら、イレーズコマンドを発行して SDカードを初期化し、フォーマットする。そういう装置を作るのもいいかも知れない。
A-DATA 1G 1000万回達成 なにもおこらず 1000万回達成してしまった。キングストンは遅く その時点で、329万回まで。A-DATA 2G はエラーが出るアダプタで、やはりというか754 万回にエラーが出た。 ちなみに、1MB 相当ということにしたので、4ヵ所書いて 1回 にしている。トータルでは 4000万回書いたのだが、なにも起きなかった。 これで終わりにしたいところだが、テストしたカードは実用目的には使えないし、マシンも遊んでいるので当面続けようと思う。 実は HUB を買ってきた。テストを 1台に集約して、ずっとテストし続けられるように。カードも SanDisk 2G を追加。テスト方法も少々変更する予定。1MB (4ヵ所) から 10MB (40ヶ所)に広げてみる。 地味な話題なので、経過報告は、ここに追記していく。 SanDisk 2G が 72万回でデータエラー! なんと 72万回で 書き込んだはずのデータと一致しないというエラー! で、ファイルを読み込んでチェックしてみたが、正しい。こういうのは想定外だ。何度かおきるだろうから、再実行して様子見。 キングストン 2G が 180 万回で リードエラー! お、あらためてファイルを読み出してみると、やはりリードエラー。 dmesg では複数のセクターでエラーが記録されている。
セクタ# (256KB 単位)
2131672    4163 -- テストでのエラー
2120888    4142 -- ↓ ファイル読み出しでのエラー
2120896    4142
2120896    4142
2121400    4143
2121408    4143
microSD (というか NAND Flash)は、一般に ECC を持っている。→ ググる だから、書き込んだデータが化けてしまったとき正しいデータでなかったらエラーになる。 このテストでエラーになったということは、書き込んだ直後はエラーでなかったものが、2 秒後には化けてしまったということ。 そして、複数の場所で リードエラーがおきたということは、テストで気が付かなかっただけで、ほかのところも疲労しているということ。
ちょっと気になったので、テスト中のほかの microSD も確認してみたが、リードエラーが起きたのは、これだけだった。
ALL 0 のデータを書き込んでみたら書けたので、再度テストしてみたが、途中で止めて ファイルを読み出してみるとやはりリードエラー。代替もできない状態で 劣化したブロックを使っているようだ。 では、疲労していないはずのほかのファイルに対してテストするとどうなるのか? 代替ブロックはもうないはずで、メモリ自体の耐久性がわかるはず。 ところで、書き込み直後は OK でも 2秒後には read error になるケースが出てきた。このテストでは、ほかにもそういうところが出てきている末期的状況になるまで気が付かない。それでは困るので少々工夫しようと思う。 4万回毎に どこまで進んだか表示するようにしているが、このときに デフォルト 1分間の sleep を入れる。こうすることで、その間データを保持できないところがあれば発覚するようにした。 プログラム→ flashtest5.c 本来は、もっと長期間持たなければダメとしたいところだが、それではテストにならない。かなり劣化が進まないと確認できないことに注意。 SanDisk 2G が 通算168万回で ライトエラー! dmesg で見てみるとジャーナルの I/O でエラーになっている。 それにしても、なんかこれだけ変なエラーがおきている。データ化けもそうだが、ライトエラーなんてものが起きるのはおかしい。ひょっとして、接触不良とかではないか。 一回取り外して、抜き差しして テストを再開してみることに。 通算208万回でもライトエラー。dmesg のエラーを冷静に見ると...USB レベルのエラーが先に起きている。 原因として、HUB のこのポートだけおかしいとか、USB アダプタがおかしいとか、あるいは microSD がレスポンスを返さないから USB アダプタの動作が変になったとか。まぁいろいろ考えられる。 とりあえず、USB アダプタを変えてみる。安物だから 不良品だったのかも知れない。 A-DATA 1G が 204万回でデータエラー! SanDisk 2G で最初に起きたデータ不一致と同じ現象。これはもう Hub か、Hub を使ったことでタイミングが変わったのが原因だろう。いずれにせよ USB レベルの問題で microSD は関係なさそう。 とりあえず再開
実は、使用している Hub は AC アダプタがつけられるタイプで、AC アダプタ(5V 2A)で電源を供給したら、この現象は収まったようだ。 よくよく考えたら、ホストマシンは 玄箱/HGで ACアダプタタイプに改造したもの。5V の供給は DISK も含め 全部で 2A 。たぶん 5V の供給が不足して不安定になったのだろう。
それにしても、Hub をつけて 4 つ同時実行にしたらいろいろ起こりすぎる。データ不一致が起きても、1回ぐらいは再読み込みして続行しないと 放置して結果だけ見るようなことができない。 再度、少しばかりプログラムを変更することにしよう。 プログラム→ flashtest6.c キングストン 2G が 166 万回で リードエラー! ファイル名を変更してから 166 万回の write -- 1/40 すると、 4.2 万回。 最初の リードエラーのように あとで読み出すと複数(今回は 2ヶ所)のリードエラーが起きた。 キングストン系については、代替ブロックを使い尽くしてしまえば、書き込めても、読めないところが増えだす。 そして、読めるか読めないかは時間が立たないとわからない。 ただし、かなりの量の書き込みをしないと、代替ブロックを使い尽くすところまでは行かない。
記録を集めれば、通算何回 write したかは分かるのだが、テスト方法を何度も変更しているので、基準になるような数字にはならない。 新しいので、やってみても良いとは思っている。が、またテスト方法を再検討するようなことになると無駄になるので、他のカードがどうなるか見てから決める予定。
書き込んだ直後では本当にデータが保持できるのかどうか分からないような特性だと、どういう基準で、代替ブロックに変えるのか気になってくる。書き込み上限回数を設定しているのなら問題なさそうだが、書き込みでエラー検出のみだと、メディア全体が寿命に至らなくてもリードエラーが出てくる可能性があることになる。 読めなくなるのが、ファイルのデータなら1つのファイルが途中までしか読めないようなことになるのだが、ディレクトリエントリならそのディレクトリが全滅するかも知れない。ただし CHKDSK とかで復旧できそう。FAT なら ミラーがあるので大丈夫 --- 昔はそうだったと思うのだが、今は違うはず。アクセスしていないのに読めないファイルが出てくるんじゃないかと思う。そして、SUPERBLOCK (= BPB) なら全滅。 さて、このタイミングで他の カードが読めなかったりしないかチェックしてみた。が、大丈夫のようだ。 なかなか 上海(A-DATA) 2G は壊れない。連続書き込みという使い方では丈夫なようだ。性能も良い。ただし、製品の一つの面しか評価していないことに注意が必要。たとえば書き込んでいる最中、あるいは書き込み終わったすぐあとにカードを抜いたりするのに弱いとか弱点があるかも知れない。 A-DATA 2G が 8000万回達成! 8000 万回までやってみたが無問題。完成度が高い ウェアレベリングが実装されているのだろう。 さらにテスト中 A-DATA 2G はやめてしまったが、A-DATA 1G と SanDisk 2G は実はまだテストをやっている。 でそれぞれ既に 1億回突破。壊れるような気がしないが、まぁやれるだけやってみる。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: microSDの性能について STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: microSD関係 DATE: 04/02/2008 16:45:13 ----- BODY: microSDカードの書き込み耐性についてその2 その3)を調べて来たが、ここでは集めた各社の 1G/2G microSD の性能について書いてみることにする。 シーケンシャル I/O 100MB のファイルを 作成し 読み込む性能を調べてみた。OS は Linux(powerPC 266Mhz) 、ファイルシステムは FAT16。
typewrite (MB/sec)read (MB/sec)size (256KB単位)
A-DATA 1G =上海(オ) 1G4.6715.293886
A-DATA 2G =上海(オ)2G7.9615.297788
キングストン 2G7.3515.517680
Photo Fast 2G7.3515.907680
SanDisk 2G bulk4.439.397754
Silicon Power 2G3.919.217754
トランセンド 2G5.167.987802
前の記事で、上海問屋オリジナルは A-DATA と同じと書いたが、このデータを見ると Photo Fast 2G = キングストン 2G、SanDisk 2G bulk = Silicon Power 2G のように見える。 さて本当だろうか? Photo Fast 、キングストン 確かに、裏面を見るとまったく同じ。SanDisk bulk と Silicon Power はぜんぜん違う。 ランダム I/O read 次に、100MB のファイルを使い 100MB 分ランダムに read する時間を調べてみた。単位は秒、I/O サイズは、1M,256K,128K,32K,4K。なお、ファイルシステムは、I/O の出方を制御するために ext3 にしている。
I/O サイズ→1M256K128K32K4K
A-DATA 1G =上海(オ) 1G5.9106.1436.4247.64124.212
A-DATA 2G =上海(オ)2G6.0086.2586.6807.70924.790
キングストン 2G5.6035.8876.2227.32425.970
Photo Fast 2G5.6635.8886.2257.32825.921
SanDisk 2G bulk10.31010.57910.98712.20132.568
Silicon Power 2G10.28710.56711.04012.16832.433
トランセンド 2G12.44112.65513.02314.20533.370
性能特性がまったく同じ -- これはもう断定してよいだろう。といってもこれは私が入手した製品に限った話。時期や入手先が違うとモノが違う可能性はある。
補足:SanDisk bulk 、Silicon Powerで 裏面の形状が違う以上、まったく同じという意味ではない。中身が同じという意味。 ちなみに、ここで測定した Silicon Power 2G は、2007年10月に入手したもの。最近入手したものは、形状が違う。--- でも、よくよく見れば SanDisk bulk と同じ。サイズ・性能も 同じだった。
そんなことより、注目すべきは、I/O サイズが小さいと性能がかなり低くなるということ。DISK では当たり前だが、Flash もそうなのか? 特に 4KB が遅い。これは OS や USB アダプタのオーバヘッドなのだろうか? ランダム I/O write 最後に、100MB のファイルを使い 10MB 分ランダムに write する時間を調べてみた。I/O サイズは、read と同じ 1M,256K,128K,32K,4K。
I/O サイズ→1M256K128K32K4K
A-DATA 1G =上海(オ) 1G3.4305.6278.56213.032130.487
A-DATA 2G =上海(オ)2G3.4477.98112.80221.872245.856
キングストン 2G3.6409.09513.16432.675251.279
Photo Fast 2G3.7027.80112.22629.388222.333
SanDisk 2G bulk4.74110.77116.88152.974410.973
Silicon Power 2G5.32610.23815.50254.403401.552
トランセンド 2G6.30312.49118.04154.984411.061
read の 1/10 しか I/O していないので、同じような数字なら 1桁性能が違う。4KB は 遅い 4KB read と比べて さらに 2桁違うわけだ。 ここまで遅いとは思わなかった。microSD は、ランダム I/O の write が 超苦手である。(OS をインストールするような使い方だと) 書き込み耐性なんかよりもっと大きな弱点だと思う。 そういえば、SSD への Windows のインストールに 12時間かかったという話を見たことがある。小さなI/Oサイズでの write が多いのだろう。MLC(マルチレベルセル)Flash 一般の性質と見て良さそうだ。
SSD への Windows インストールが遅いというのは、これとかこれだった。 ちなみに、ある SSD 製品を Windows の OS 用に使うことを考えているなら、CrystalDiskMark 2.1 の Random Write 4KB 値をググると良さそう。この値が 0.1 MB/sec 以上でないと厳しいらしい。 例→ TS32GSSD25-M CrystalDiskMark 2.1 ちなみに、トランセンドのページには、TS32GSSD25S-M(MLC) と TS32GSSD25S-S(SLC)の2種類があって、OS をインストールするには、SLC の方を推奨すると書いてあった。
さて、各製品の特性を見てみると、A-DATA 1G が速いのが興味深い。シーケンシャル I/O の write は 2G の 1/2 なのに、4KB のランダムは 2倍。これはいったいどういう理由なのだろう? あと、トランセンドは、Photo Fast = SanDisk bulk と特性が似ているように思う。ひょっとしたら使っている Flash チップが同じか 同一メーカのリビジョン違いなのかも。 なお、製品の性能の絶対値はあまり気にしなくて良いと思う。半年もすればモノ自体が変わって性能もぜんぜん変わってしまっているかも知れない。ランダム I/O の write が 超苦手であることだけ覚えておけば良いだろう。 ランダム I/O に使用したプログラム→ rndtest.c おわりに この記事の目的は、microSD の性質あるいは MLC(マルチレベルセル)Flash 一般の性質をつかむことを目的としている。そして個々の製品の比較は、どれぐらいのバリエーションがあるか調べることを目的にしている。情報はすぐに陳腐化する。いま現在参考にするのはともかく、半年ぐらいたってしまえば役に立たないと思う。 また、ランダム I/O 性能もこのデータのみがすべてではなさそう。微妙な最適化がなされていて、I/O パターンが違うと性能が違う場合がある。このデータでは、A-DATA と キングストンは同じような性能に見えるが、書き込み耐性の調査では、A-DATA が速かったり キングストンが速かったりする(しかも何倍も)。 性能の話はこれで終わり。書き込み耐性については、(とにかく壊れたらどうなるか見てみたいので)まだ続く... 追記 実は microSD というものは、MLC に決まっていると思っていたのだが ... A-DATA 1G/2G (Super) の メーカWebページには、SLC 採用と書いてあるし、Photo Fast 2G (EXTREME 150X)も東芝製SLCらしい。ということはキングストン(日本製) も同じはず。 確かに書き込みは速いようだが...それでも 4K の write はこの程度。それより SLC の書き込み耐性は MLC と 1桁違うらしいので、そっちの方がメリットなのかも。 追記:microSDとCFの違い この一連の記事を書き始めるまでは、CF も microSD も似たようなものなのだろうと思っていたのだが、全然違うようだ。CF はプロあるいはセミプロのカメラマンの厳しいニーズがあって、相当に高性能な(あるいは高信頼な?)なものが出ている。A-DATA 16G speedy が 7000円弱で売られている一方、SanDisk EXTREME III 8GB が 2万円弱で売られていて(たぶん)人気を保っている。 CrystalDiskMark 2.1 の結果を拾ってきたのだがこんなかんじ。(条件はいろいろ違うので参考)
SanDisk EXTREME III 8GB:

    --------------------------------------------------
    CrystalDiskMark 2.1 (C) 2007-2008 hiyohiyo
    Crystal Dew World : http://crystalmark.info/
    <../link.cgi?http://crystalmark.info/>
    --------------------------------------------------
    Sequential Read : 32.284 MB/s
    Sequential Write : 24.065 MB/s
    Random Read 512KB : 32.196 MB/s
    Random Write 512KB : 11.053 MB/s
    Random Read 4KB : 6.476 MB/s
    Random Write 4KB : 0.151 MB/s
    Test Size : 50 MB

A-DATA 16G speedy:
    --------------------------------------------------
    CrystalDiskMark 2.1 (C) 2007-2008 hiyohiyo
    Crystal Dew World : http://crystalmark.info/
    <../link.cgi?http://crystalmark.info/>
    --------------------------------------------------

    Sequential Read : 14.871 MB/s
    Sequential Write : 7.124 MB/s
    Random Read 512KB : 14.885 MB/s
    Random Write 512KB : 1.806 MB/s
    Random Read 4KB : 7.859 MB/s
    Random Write 4KB : 0.018 MB/s

    Test Size : 50 MB
シーケンシャル性能がまったく違うが、Random Write 4KBはそれ以上に違う。カメラのニーズでこういう性能が必要とは思えないから、別のニーズ(産業用機器?)に答えるためだろう。 ちなみに、CF は 333倍速(50MB/sec)の表記のものがある。が、規格上は 888倍速(133MB/sec: UDMA6)まであるから、まだまだ持ちそうだ。→ ウィキベディア あと、同じ容量でも値段がまったく違うこともあって、ニセモノの存在が大きな問題らしい。 性能とは関係ないが、ついでなので書いておくと、microSD は、取り扱いに気をつけるべき点が多々ある。 まず接触不良。接点の面積が小さいためか接触不良が起こりやすい。それに、あまりに薄いパッケージ(1mm)に積層されたチップが入っているのだから、力を加えるとか厳禁だと思う。-- やろうとは思わないが、割ることさえ簡単にできそうだ。さらにいうと端子がむき出しだし、静電気にも気をつけなければならない。あまりそれ自体を抜き差しせずに、ケイタイや各種変換アダプタに入れたまま使うのが正しい使い方のように思う。
ウィキベディアの SDカードを見ると、SDカードやminiSDカードは、基板にLSIを載せた構造らしい。たぶんモノによって強度がマチマチだと思う。microSD はどうか? そんなには差がないんじゃないかと想像。トランセンドは、データシートを公開していてそこには、
    Bending 10N
    Torque 0.10N*m , ± 2.5 deg max 
    Drop test 1.5m free fall
それが具体的にどういうことなのかよくわからないが、一応転載。
それに比べて CF は相当取り扱いが楽そうだ。コネクタもピンで耐久性ありそうだし、しかも露出しないようになっている。厚みも 3.3mm と結構あって丈夫そうだ。 eeePC の SSD さらについで。 拾ってきたeeePC の SSD のデータ
--------------------------------------------------
CrystalDiskMark 2.1 (C) 2007-2008 hiyohiyo
Crystal Dew World : http://crystalmark.info/
--------------------------------------------------

Sequential Read : 34.195 MB/s
Sequential Write : 19.897 MB/s
Random Read 512KB : 33.885 MB/s
Random Write 512KB : 10.744 MB/s
Random Read 4KB : 7.676 MB/s
Random Write 4KB : 0.152 MB/s

Test Size : 50 MB
本体の SSD は、OS をインストールしても問題ない性能レベルのものだ。信頼性や耐久性についてはわからない。SSD のコントローラはシリコンモーション社製らしいが、詳しいことは知らない。
この記事によると、コントローラは Silicon Motion SM223。そして、SM223 は トライセンドのCF(266X)にも使われているとのこと。さらに、SSD にも SM223 が使われていることがあるらしい。 ↑のページで出てくるPHISON社を見てみると、PS8005とか SD カードコントローラが見つかった。この会社データシートまで公開している。こういうものを使っていれば、(ピーク)性能は、Flash メモリの種類と数でだいたい決まりそう。ただ、信頼性や耐久性については ファームウェアで決まるものでデータシートを見てもわからない。

性能まとめ(+追記) シーケンシャル I/O 100MB のファイルを 作成し 読み込む性能。OS は Linux(powerPC 266Mhz) 、ファイルシステムは FAT16(2Gまで)、FAT32(4G 以上)。
typewrite (MB/sec)read (MB/sec)size (256KB単位)
A-DATA 1G =上海(オ) 1G4.6715.293886
キングストン 1G (TAIWAN)4.7815.263886
A-DATA 2G =上海(オ)2G7.9615.297788
PQI 2G7.9414.307788
キングストン 2G7.3515.517680
Photo Fast 2G7.3515.907680
SanDisk 2G bulk4.439.397754
Silicon Power 2G3.919.217754
トランセンド 2G5.167.987802
KINGMAX 2G5.379.067658
A-DATA 4G14.0815.215354
SanDisk 4G11.3815.315546
ランダム I/O read 次に、100MB のファイルを使い 100MB 分ランダムに read する時間。単位は秒、I/O サイズは、1M,256K,128K,32K,4K。なお、ファイルシステムは、 ext3 にしている。
I/O サイズ→1M256K128K32K4K
A-DATA 1G =上海(オ) 1G5.9106.1436.4247.64124.212
キングストン 1G (TAIWAN)6.0486.1826.4978.63325.237
A-DATA 2G =上海(オ)2G6.0086.2586.6807.70924.790
PQI 2G6.2396.5016.7847.76725.122
キングストン 2G5.6035.8876.2227.32425.970
Photo Fast 2G5.6635.8886.2257.32825.921
SanDisk 2G bulk10.31010.57910.98712.20132.568
Silicon Power 2G10.28710.56711.04012.16832.433
トランセンド 2G12.44112.65513.02314.20533.370
KINGMAX 2G10.39510.73711.02312.35030.542
A-DATA 4G5.5675.9036.1677.20022.848
SanDisk 4G5.8226.0836.4167.66527.947
ランダム I/O write 最後に、100MB のファイルを使い 10MB 分ランダムに write する時間。I/O サイズは、read と同じ 1M,256K,128K,32K,4K。
I/O サイズ→1M256K128K32K4K
A-DATA 1G =上海(オ) 1G3.4305.6278.56213.032130.487
キングストン 1G (TAIWAN)3.4895.7168.81813.007132.447
A-DATA 2G =上海(オ)2G3.4477.98112.80221.872245.856
PQI 2G3.2588.41911.48122.750258.058
キングストン 2G3.6409.09513.16432.675251.279
Photo Fast 2G3.7027.80112.22629.388222.333
SanDisk 2G bulk4.74110.77116.88152.974410.973
Silicon Power 2G5.32610.23815.50254.403401.552
トランセンド 2G6.30312.49118.04154.984411.061
KINGMAX 2G6.55310.71616.08050.064372.829
A-DATA 4G2.7497.54211.66140.478312.626
SanDisk 4G3.2975.3309.81733.498272.333
補足 PQI , KINGMAX, A-DATA 4G, SanDisk 4G のデータ追加。これらはハブ経由で測定したので、若干低い値になっている。 データを見ると PQI = A-DATA 。裏面も同じ。KINGMAX は新たなパターン。 キングストン 1G (TAIWAN) を新たに追加。性能からみて A-DATA 1G と同じ。裏面も同じパターン。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: microSDでSSD STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: microSD関係 DATE: 04/04/2008 02:14:09 ----- BODY: ちょっと妄想。 microSD は、とても小さく薄い。Flash 専用の LSI より小さいぐらいだ。それを一般の人が携帯用に買っている。まるで、LSI 単体が大量に売られているような状況だ。 いまは 2GB だが、4GB/8GB の普及が次に続くだろう。そうなると、やがて Flash メモリの中で microSD がもっとも bit単価が低くなるのではないだろうか? さて、そうなってくると SSD を製造するのに、内部で microSD を使ったほうが安いとかいう状況になってこないだろうか。 SDカード用だが、かつて4枚挿しの SDB25SDという製品があった。今は、8枚挿しのこんなのとか、16枚の こんなのがある。 microSD を縦に挿すようなソケットがあれば、8x8 (8 並列 x 8)とかも作れてしまうのではないか。64 個もばらばらに挿すのは信頼性に不安があるというならば、8枚とか板に貼り付けて かつての SIM みたいにしても良いかも知れない。 2GB の microSD でも 64 個なら、128GB 。8GB なら 512GB だ。数年で 32GB も出てくるだろうから 2TB なんてのも無理な話ではない。 microSD を使ってうれしいのは、Flash の使いまわしができることだ。優秀なコントローラが出ればそれに乗り換えることができる。段階的に増設できればさらにうれしいかも知れない。 そういう製品が出てきてほしいと祈りつつ妄想を書いてみた。
追記: GIGAZINE の情報、 PhotoFast から CR-9000という製品が出るらしい。SD カード 6枚挿し RAID0 が出来て 12980円らしい。 CrystalDiskMark の性能も公開されている。シーケンシャル I/O の性能は高いが、4KB Randam Write 性能は、0.063 といまひとつ。-- OS用Disk に使えないことはないと思うが、不満が出るかも知れない。 あと、SDHC (4GB 〜) 専用で、1枚から使用できるらしい。発売日は 6/28 。 それにしても、こういう製品が安価に出てくるのだから、microSD版(+より多くのカード)もいずれ出てくるかも知れない。
余談だが、こういうコントローラを個人で作ることは、おそらく可能だ。FPGA 使って 、IDE インターフェイスにまでできれば、IDE-SATAブリッジで SATA に変換することができる。信号線もそんなにたくさん必要ないから、FPGA も 表面実装品でいけそうだ。ちなみに、i-RAMも FPGA spartan3 XC3S1000 を使って IDE インターフェイスまでを実装している。SATA は ブリッジ。トランゼントの SSD も SATA はブリッジを使っている。(製品ページのデータシート参照)
追記:8並列 x8 とか書いたが、高速な SD Bus は、CLK を除く信号線(5 つ)は 1:1 で接続しなければならないらしい。電子工作レベルだと、TQFP144 か PQFP208 あたりが限界で、全部で 150 pin ぐらいしか信号線を使えないから、8-16 個を扱うのが精一杯かも。 追記:microSDの構造について そんな情報はほとんどないのだが、ATP 製品に関するものが若干あったので紹介。 普通の SD でも、ウェハーの裏側を削って 0.2 mm までに薄くするなんて書いてある。1mm 厚の microSD で 4 層なら 0.2mm でも全然厚いから 0.1mm とかにするのかも。 追記:CF で SSD メディアロジックAX25CF-Sが、engadjet本家 で紹介されている。リンク先を見ると 200ドルぐらい。 性能については、ここで紹介されている
センチュリー シリコンディスクビルダーCF RAID SATA SDB25CFS/ R5 として日本でも発売された。なぜか Amazon が安く17,622 円
これと、CF を組み合わせて、性能優先とか信頼性優先で SSD を組むのが今は良いように思う。32GB の (まともな)SSD は 5万円ぐらい。16GB のCFはピンキリで 7000円〜 30000円ぐらい。15000円の 16GB CF x2 でまともと言える SSD になるならば、おなじぐらいの価格性能比といえる。それなら、自由度が高い分 こちらのほうが良いのではないか。 microSD で SSD の話に戻る。 体積あたりの容量というものを考えてみると microSD の方が CF より大きい。bit単価も microSD の方が安くなっていくと思う。microSD を多数載せられるものがあれば、もっと良いのではないかと思ったのが、この記事を書いた動機だったりする。 最初は、垂直にさせるコネクタがあれば、沢山載せるのは楽勝とか思ったのだが、背が高くなってしまう。少々甘かったかも知れない。が、工夫しだいで沢山載せることは(物理的には)可能だと思う。
SSD とファイルシステム 今は、OS をインストールするような場合、SLC でないと話にならない状況らしい。前記事で書いたように、(microSD や) MLC の SSD は、ランダム Write 性能が極端に悪いのだ。 この問題は、ファイルシステムが、ランダム Write をしないように進化すれば解決する。そういうファイルシステム(コピーオンライト(COW) ファイルシステム)は現時点で存在するし、Linux では問題にならなくなるのは時間の問題だと思う。Windows でどうなるのか知らないが、やがてはそういう風になっていくのだろう。 そうなってしまえば、SLC にこだわる必要もなくなり、MLC の大容量という利点を享受できるようになる。 なにが言いたいかというと、MLC ベースのパラレル化で、シーケンシャル write を追求していくのが正しい方向だということ。SLC でなければダメだというのは、あくまで過渡期の話。いつまでも SLC が良いわけではないということを覚えておいてほしい。
補足:COWファイルシステムについて ファイルシステムで、copy-on-write というのは、データを書き換えたときに、データを上書きするのではなく、新しいブロックを割り当ててそこに書く技術。データの場所を示す管理情報や空きブロックの情報も書き換わるわけだが、それらも上書きしないで新しいところに書く。そうすることで、ランダム Write をシーケンシャル Write にしてしまうのだ。前のデータを壊さないから スナップショットを作れるが、むしろ ランダム Write をしないことで性能を向上させるのが本来の目的。
ランダム Write が遅い SSD と Windows を組み合わせて使うには これは単なる案。制限もあるし Linux の知識も必要だろう。 考え方は単純だ。シーケンシャル write が出ないように Linux を工夫してインストールし、その上で VM を使って Windows を動かす。 (たぶん)OS自体の起動を早くしたいという目的には向いていないだろうし、レスポンスが悪かったり、増設したデバイスが使えないとかいう問題が出るかも知れない。シーケンシャル write が出ないようにするにはどういう工夫が必要かも具体的にはわからないのだが... やってみれば案外簡単なのかも知れない。 実は、4G〜8G ぐらいの microSD に OS をインストールして、VMwarePlayer か VirtualBox で、どこでも myマシン環境を作ってみたいと思っている。Winows を動かしたいのではなく、Windows で Linux を動かしたいのだが。逆のパターンでもうまく動くのかも知れない。ちゃんと調べていないのだが、VMwarePlayer の仮想DISKファイル自体になんか工夫があったような気がするし、そもそも何もしなくても実用に耐えるかも知れない。ダメだとしても Linux 側で工夫の余地がいろいろある。 もし、ランダム Write が遅い SSD を買ってしまって途方に暮れているのなら試してみる価値はあるかも知れない。 microSD 上で Linuxを動かしてみる WindowsXP 上の VMware Player の仮想環境で Vine-4.2 を動かしてみた。 まず、仮想ディスクを USB アダプタ経由の microSD に置くには工夫が必要。
仮想ディスクのサイズは 3.5GB (使用率 67%) 、仮想ディスクファイル自体は、2.6 GB。本来 FAT32 は、4GB まで OKのはずなのだが、これだと ファイルが大きすぎると言われ VMware が起動できない。リムーバブルメディアのNTFSフォーマットについてを参考に NTFS にすれば OK。
起動時間の比較
仮想ディスクの場所起動時間(秒)シャットダウン時間(秒)
C:ドライブ7318
NAS(玄箱/HG)7522
microSD(キャッシュON)9763
microSD(キャッシュOFF)9754
※ キャッシュON :ポリシーをパフォーマンスのために最適化
使った microSDは、A-DATA turbo 4GB 。CrystalDiskMark はこの程度
--------------------------------------------------
CrystalDiskMark 2.1 (C) 2007-2008 hiyohiyo
      Crystal Dew World : http://crystalmark.info/
--------------------------------------------------

   Sequential Read :   19.503 MB/s
  Sequential Write :    9.836 MB/s
 Random Read 512KB :   19.397 MB/s
Random Write 512KB :    2.014 MB/s
   Random Read 4KB :    6.087 MB/s
  Random Write 4KB :    0.024 MB/s

         Test Size : 100 MB
ちょっと使っただけだが、microsSD は、少々もたつく感がある。でも、あまり気にならない。 そして、キャッシュON/OFF であまり性能が変わらない。たぶん、Windows版 VMware は、(Windows のキャッシュを使わないようにして) DISK にちゃんと書き込むような I/O をしているのだと思う。 キャッシュONの操作は、NTFS をフォーマットするときだけ必要で、使うときは必要なさそうだ。 この程度でもまともに動くのは、ゲストOS の Linux が、たちの良い I/O をしてくれている and/or VMware がなにか最適化してくれている為だと思う。どちらが効果があるのかはわからない。 さて、microSD より NAS(玄箱/HG)に置いたほうが速い。その理由は、次の値で説明できると思う。
-------------------------------------------------
CrystalDiskMark 2.1 (C) 2007-2008 hiyohiyo
      Crystal Dew World : http://crystalmark.info/
--------------------------------------------------

   Sequential Read :   10.031 MB/s
  Sequential Write :    8.809 MB/s
 Random Read 512KB :   10.411 MB/s
Random Write 512KB :    9.126 MB/s
   Random Read 4KB :    4.200 MB/s
  Random Write 4KB :    2.418 MB/s

         Test Size : 100 MB
Random Write 4KB がやたら速いのだ。C:ドライブでも 0.6 ぐらいなのに、その 4倍も速い。アプリで キャッシュを使わないようにしても、NAS 側の キャッシュまで制御できないのが理由。 あくまで予想だが、Windows を Linux 上のゲストOSとしてインストールする場合も、こういう関係になるはず。Windows がタコなI/O を出しても Linux が キャッシュを持っていてうまくやってくれると思う。 おまけの情報 -- 仮想ディスクを置いた microsSD は Windows が管理しているから、Linux からは 直接は見えない。でも別の USB DISK は Linux からみえて mount できた。さすが歴史あるVMだ、期待どおりに動いてくれる。 追記: microSD に WindowsXP をゲストOSとしてインストールしてみる Transcend TS32GSSD25-M (MLC版)は ランダム Write がきわめて遅い SSD で、OS 用の DISK に使うには向いていない(とメーカ自身認めている)。あえて Windows XP をインストールすると 12時間以上かかり、立ち上げも 20分とか30分とかかかるらしい。CrystalDiskMark の結果は以下のような値で、microSD (A-DATA turbo 4GB )より若干劣るほどのレベル。
Transcend TS32GSSD25-M
--------------------------------------------------
CrystalDiskMark 2.1 (C) 2007-2008 hiyohiyo
Crystal Dew World : http://crystalmark.info/
--------------------------------------------------
Sequential Read :   20.955 MB/s
Sequential Write :    7.321 MB/s
Random Read 512KB :   20.961 MB/s
Random Write 512KB :    1.678 MB/s
Random Read 4KB :    5.468 MB/s
Random Write 4KB :    0.014 MB/s
では、VMware Player の仮想DISK を microSD (A-DATA turbo 4GB)に置いて、WindowsXP を インストールするといったいどれぐらいの時間になるのか実験してみた。
仮想ディスクの場所インストール時間(分)1回目立ち上げ時間(分)
C:ドライブ501.5
microSD801.5
ホストOS は WindowsXP 。上の予想はホストOS が Linux なら速いというものだった。が、ホストOSがWindowsで、WriteBack キャッシュを効かさない場合でも若干遅いレベルに収まっている。 TS32GSSD25-Mが 12時間もかかるのならば、7時間ぐらいかかりそうなものだ。にもかかわらず、1時間20分で済んでいるのは VMware の仮想 DISK ファイルの仕組みが関係していることになる。 ウィキベディアの コピーオンライトを見てみると、”BochsやQEMUといった仮想マシンの仮想ディスク装置で使われている。”という記載がある。VMware Player の仮想 DISK も スナップショット機能を持っている。そして ”スナップショット機能を備える論理ボリュームマネージャやファイルシステムの多くがその実現にCOWを用いている”という記載どおりに COW を持っていると思われる。 ウィキベディアには書いてないが、COW は ランダム Write をシーケンシャルにするという側面がある。(前のデータを上書きしないならば、新しい領域に書くということだ。ならば、ちらばった領域への Write が一ヶ所にまとまる傾向にあるはずだ。)
qemu のソースコードには、block-qcow.c 、block-qcow2.c 、block-vmdk.c などがある。これらが仮想ディスクファイルの管理をしているようだ。あまりサイズが大きくないので、ちょっと調べてみようと思う。ちなみに、qcow については The QCOW Image Formatというドキュメントもあるようだ。興味があるのは vmdk だが、どう違うとか参考になるかも。
追記: WindowsXP を Flash 向けに高速化するには(考察) たとえば eeePC を 軽量化して高速化する方法として nLite というものがあるらしい(ググる)。ここでは、そういう方法ではなく、ランダムWrite の遅い DISK 自体を高速化するにはどうしたら良いか考察してみよう。 仮想マシンの方が高速になる(はずの)ケースを紹介したが、それは仮想ディスクの仕組みによるものだ。仮想マシンそのものは関係ない。WindowsXPで動く仮想ディスクソフトがあって、それがCOW機能(and/or スナップショット機能)を持っていれば、良いわけだ。 ちょっと探してみたのだが、残念ながらそれそのものは見つからなかった。しかし、TrueCryptという暗号化ソフトがあることを知った。 これには、リムーバブルディスクだけでなく、システムディスク(or システムパーティション)を暗号化する機能がある。もし、COW機能があれば、暗号化のオーバヘッドがあっても ランダムWrite が高速化されるのではないか ... ちょっと microSD(A-DATA turbo 4GB)を暗号化してベンチマークしてみた。
--------------------------------------------------
CrystalDiskMark 2.1 (C) 2007-2008 hiyohiyo
      Crystal Dew World : http://crystalmark.info/
--------------------------------------------------

   Sequential Read :   13.938 MB/s
  Sequential Write :    6.270 MB/s
 Random Read 512KB :   13.587 MB/s
Random Write 512KB :    2.813 MB/s
   Random Read 4KB :    3.750 MB/s
  Random Write 4KB :    0.038 MB/s

         Test Size : 100 MB
シーケンシャル系が遅くなっている代わり、Random Write 4KB が速くなっている。ただ、期待するような性能レンジにはなっていない。おそらく Write が非同期になったために、高速化したのだろう。 さて、TrueCrypt はソースが公開されているらしい。そして、qemu には、qcow2 というスナップショットが取れる COW 仮想ディスク機能がある。この2つをマージすると求めるものが作れるのかも知れない。
注意: この記事だけを見て商業ソフト(シェアウェア含む)を作ってみようと思いつく人が出るかも知れないので、警告。 GPL のソースを元にプロプライエタリなソフトを作ることはできないことは言うまでもない。...として COW にはさまざまな特許があるはず。特許をクリアしないで、商業ソフトを作るのは結構リスクがある。 もちろん オープンソースでもやばいのだが、オープンソースは(IBM など)正式に免責されたり、あるいは見て見ぬふりをされる傾向にあり、商業ソフトとは少々扱いが違う。なによりソースコードしか配布しない(= あとはすべて使う人の責任)という最後の逃げ道があるのだ。
----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- PING: TITLE: 結局、買い換えるのが安い URL: http://www.sside.net/2008/04/post_373.html IP: 116.94.147.226 BLOG NAME: sside.net DATE: 04/12/2008 21:16:09 ジャーナリングFSのメリットは兎も角、COWは知らなかった。そんなメリットがあるのか・・・。ディスク埋まった時はどんな挙動になるんだろうか。 さておき、SSDについて考察してみる。 すzのAVR研究: microSDでSSD ATAに変換して読み書きを分散するコントローラが、FPGAだろうとASICだろうとモバイル用途以外には関係ないと思うので置きつつ、順当な未来予想図としてはSSDの出始めた今、microSDやSDを大量に接続してSSDを形成するアダプタやコントローラはもう必要ないと思う。 恐らく(micro)SD自体は既にコントローラとメモリがオンチップ統合、譲ってもモジュール化か積層済みだと思うんですが(分解写真をGoogle様に問い合わせても見つからなかったので)、それらを大量に接続しても、コントローラが大量に配置され、冗長どころか無駄に消費電力を上げ、速度を下げるだけでしょう。 次に問題になるのがインターフェース(以下IF)。SD自体がそんなに大層なIFを持ってないですし、今後高速化するだろうフラッシュメモリにSDの物理層ではスペックがプアすぎるかと。仰るとおりコネクタも多す... ----- -------- AUTHOR: すz TITLE: XMEGAの日本語データシート STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 04/11/2008 02:45:12 ----- BODY: XMEGAの日本語データシートが、3/31 に出ていたことをいまさらながら知った。 Atmel の XMEGAのページからたどれるオリジナルの ATxmega A Manual Preliminary の忠実な翻訳なわけだが、正直日本語版でないと読む気がしない。 英語じゃなく日本語というのも大きな理由だが、理由はそれだけではない。表や図がカラーになっていたり、見やすいよう枠を入れたり、配置を変えたりしてあって読みやすいのだ。 ちなみに、WinAVR での対応は次のバージョンだそうだ。でも、チップがいついくらで入手できるかは不明。 先に発表された AVR32 の ワンチップ AT32UC3Bシリーズはデジキーに登録された。128KB の AT32UC3B1128が 1069円で、リードタイムが7/13。ATxmega128A4が、これより早く入手できることはないだろうし、これより高いこともないだろう。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: SDHCの仕様について STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: microSD関係 DATE: 04/11/2008 15:45:49 ----- BODY: SDHC が 32GB までしか対応していないという話が気になっていたので、Physical Layer Simplified Specification (v2.00)をちょっと見てみた。 Block Write/Read コマンドの Start Address は、
n * 512 bytes  (n: Integer)
という風に指定する。だから 物理レイヤでは、2G x 512 = 1TB までアクセス可能。 32GB が限界というのは SD として 32GB までの論理フォーマットしか決めていないというだけだと思う。 あと転送速度についてもチェックしてみた。
Default mode:  0 - 25 MHz,  上限 12.5 MB/sec
High-Speed mode:  0 - 50 MHz, 上限 25 MB/sec
という記載がある。すでに 150X (22.5 MB/sec)を売り文句にしている製品があるから、こちらのほうも仕様拡張が必要(に違いない)。 なのだが、CSD Register に TRAN_SPEED というのがあって、カードの上限転送速度を定義できるようになっている。 この定義、8.0 x 100M bits/sec (200 MHz, 100 MB/sec)まで決められている。( といっても決めていないだけで、その 10000倍までは定義可能そう。) ただ、今の電気的仕様のまま x4 の 200MHz は無理そう。
補足:メモリの規格が目安になると思う。
     電圧       バスクロック
   SDRAM  3.3V       133 MHz
   DDR    2.5/2.6V   266 MHz
   DDR2   1.8V       533 MHz
   DDR3   1.5V       800 Mhz  
...なのだが、
High Voltage SD Memory Card :
    Operating voltage range: 2.7-3.6 V
Dual Voltage SD Memory Card :
    Oerating voltage range: Low Voltage Range (T.B.D)
という記載もある。これをどうするかについて相当もめそうな気がする。
なんかいろいろ見ていると、NAND FLASH の電源はすでに 2電源になっていて、1.7〜1.95V, 2.6〜3.3V ぐらいが多いみたいだ。--- ということは、DDR2 相当 1.8V で、x4 の 200MHz あたりが妥当?
おまけ: CMD42 - Lock Unlock Function SDカードには、パスワードでカードをロックする機能が定義されている。 オプション機能で、全部のカードでサポートされているわけではないのだが、ロックしたら、アンロックしないと データにアクセスできなくなる。もしパスワードを紛失したら、カードを消去(Force Erase)しなければならないらしい。 一般のUSB アダプタでこの機能をサポートしているとは思えないから、電子工作ネタになるかも。 さらにおまけ、... CMD42 でググると各社の仕様書がヒット。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- -------- AUTHOR: すz TITLE: microSD の壊れ方(キングストン編) STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: microSD関係 DATE: 04/16/2008 05:13:15 ----- BODY: ついにキングストン 2GB (JAPAN)が書き込み限界に達した! ほぼ 1ヶ月の期間をかけて断続的に書き込んできた。書き込みの方法を試行錯誤しているので何回で壊れたと明確に言えないところがある。それは後でまとめるとして、どういう風になってしまったのかについてまず書こうと思う。
注意:たぶん壊れ方は、使っているチップによって違う。最初にテストした miniSD(64MB) と実際違う。ここで書くのはあくまで、キングストン 2GB microSD (JAPAN)についてということに注意してほしい。 ちなみに、2GB (TAIWAN)は、たぶん A-DATA と同じ。
キングストン 2GB の壊れ方 USB アダプタで使うかぎりいくらでも書ける。(USBアダプタでリトライしている?)そして、しばらく時間が立った後 リードエラー。
ちなみに、テストプログラムで 発覚するのが、2秒持たなかったとき。そういう状態にまでなった後、チェックしてみると複数のブロックでリードエラーがおきる状態になっていた。
ウィキペディア NAND型フラッシュにあるように不良ブロックができたわけだが、代替ブロックをすでに使い果たした後は、その不良ブロックを無理やり使い続けているんではないかと思う。 代替ブロックがない以上、このようになるのはやむを得ないとは思えるのだが、書き込んだ直後に不良ブロックの検出をやっても必ずしも発見できるとは限らないのでは? と思ってしまう。 もしそうだとすると、たとえウェアレベリングをやっていたとしても書き込み不良が起きる可能性はわずかに存在するのではないか?
余談: 実をいうとハードディスクも書いたデータが読めるとは限らない。RAID5 にしていても、ハードディスクが壊れた後、再構築でリードエラーが発覚して、データを復元できなかったという話はある。 だから、RAID5 だから安心とは言えない。定期的にディスクを読み出して、見つけた不良ブロックをつぶしていくような仕組みと併用してはじめて(それなりに)安心できる。 microSD だとメディアだから複数枚で RAID5 とかミラーリングは現実的ではない。ほんとうに大事なデータを保存するのに、カード内部でミラーリングしてくれる製品も(普通の製品とは別に)あれば嬉しいような気がしてきた。 さらなる余談: 買ってきたHDDはエージングしようというページを発見。microSD/SD カードもちょっとぐらいは、やっておいたほうが良いかも。問題のあるブロックが脱落してしまえば、しばらくは故障率が低いままで安定する ... ということになるんではないかと思う。たとえば 2GB の全体を 100回 write して チェックのため read するとして、write+read が 3MB/sec なら 18時間もかかる。メーカでこんなにテストしていないだろうから、意味はありそうな気がする。
FAT で使う場合どういう現象になるか? ファイルシステムはファイルのデータ以外にファイルを管理するためのデータ(メタデータ)も持っている。→ FAT ファイルシステム覚え書き。 FAT の場合だと、ファイルのデータに加えて、BPB (いわゆるSUPERBLOCK)、FAT、ディレクトリ・エントリの 3種類のメタデータを考察すればよい。 基本的にリードエラーが起きてくれるほうが良いと思う。エラーにならずデータが化けたりすれば、気が付かなくて後で泣きを見ることになるかも知れない。ちなみに、データが化けるという現象は、microSD と違うレイヤ (USB アダプタとか HUB とか?)で起きる可能性がある。原因がはっきりしないので、ここでは詳しく書かないが、テストでそういうことも起きている。 こうなるまで、どれだけ書き込んだか もう TEST1 は忘れたほうが良いと思う。他のテストに比べ速すぎる。カード固有の最適化にうまくはまって FLASH をほとんど書き換えていないと考えることにする。 つぎに 消去ブロックのサイズを 256KB と仮定すると、TEST2〜TEST4 で、合計 2120万 ブロック書き換えた計算。これで 代替ブロック + 40ブロックをつぶしてしまったと考え、さらに、代替ブロックが、全体(7680 ブロック)の 3% の 230 ブロックあると 考えてみる。そうすると、1ブロックあたり 7.8 万回の計算。 まぁ妥当な結果ではないかと思う。ちなみに、キングストンは代替ブロック方式で、ウェアレベリングではないと思う。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- COMMENT: AUTHOR: とーたく EMAIL: IP: 219.97.41.243 URL: DATE: 05/06/2008 14:23:48 >問題のあるブロックが脱落してしまえば、しばらくは故障率が低いままで安定する ... ということになるんではないかと思う。 考えていらっしゃることはまったく正しいです。半導体はハズレにできてしまったものはかなり壊れやすく、それ以外のものは桁がちがう寿命があります。なので負荷をかけて壊れなかったものの寿命は相応に保証できるものなのです。 しかし、慣らしをすると良いのでは?というのは現時点ではあまり意味があることではないでしょう。というのも、半導体のこのような特性はもう完全に常識で、出荷前の試験時にバーンイン(burn-in)という高温加速試験をして壊れるやつは最初に壊して選別する、というのが古くから当たり前だからです。このようなことが当たり前に行われているのは全数検査が鉄則の半導体ならではだと思います。 時間がかかって(=コストがかかる)大変なので現在のやっすいロジックを含むすべての半導体でされているかどうかはわかりませんが、少なくともフラッシュメモリの製造工程にはバーンインがまだ残っています。 だからユーザ側で(しかも常温で長々と)する必要はないと思います。 将来どこかの半導体メーカでメモリという高信頼性が要求されるデバイスからバーンインを端折るというアホウが出現したらやらざるを得ないかもしれませんね。 ただこれはチップレベルの話で、micorSDなどへのアセンブル後の話ではありません。アセンブル工程でのストレスで耐性が下がる...なんてな事があるのならばユーザサイドでの負荷試験にも意味があるかとは思いますが、ほとんど半導体チップそのままの単純極まりないmicroSDでそれがいるような気はあまりしないですね。 (それでも初期不良はあるわけですが。) HDDはどうなんでしょう。今どんな検査体制なんでしょうね。 ----- COMMENT: AUTHOR: すz EMAIL: IP: unknown URL: DATE: 05/09/2008 19:22:27 解説ありがとうございます。バーンインがされているのなら、自分でエージングまでする必要はなさそうですね。 HDDについてですが、I/O データやバッファローの交換用DISK でさえエージングしていることを売りにしているようなので、エージングは効果がある(= メーカの検査では不十分)ように思います。 ----- -------- AUTHOR: すz TITLE: 不正アクセスって? STATUS: Publish ALLOW COMMENTS: 1 CONVERT BREAKS: 1 ALLOW PINGS: 3 PRIMARY CATEGORY: CATEGORY: 日記 DATE: 05/12/2008 04:47:33 ----- BODY: ずいぶん前になるが、不正アクセスをしたとして、office氏が有罪になった事件があった。office氏がした行為がなぜ不正アクセスに該当するのか? 正直いってかなりの違和感を感じた。 なにがおかしいと思えたのか、不正アクセス禁止法の条文をひもといて説明してみようと思う。 第三条には、何人も、不正アクセス行為をしてはならない。 と書いてある。なぜなのかは、第一条に書いてあり、不正アクセス行為の定義は、第二条と第三条でなされている。 大幅に要約すれば、不正アクセス行為とは、 (不正な方法で)アクセス制御機能により制限されている特定利用をし得る状態にさせる行為 で、アクセス制御機能とは (あるしくみで)特定利用の制限の全部又は一部を解除するものをいう。 ということで、第三条の一、二、三で、不正な方法とは何という定義づけがされている。 さて、個人情報を読むという特定利用がアクセス制御機能により制限されているのであれば、office氏の行為はアクセス制御機能になんらかの働きかけをしたはずである。そうでなければ特定利用は制限されていないということになる。 第三条の二に、制限を免れることができる情報(識別符号であるものを除く。)又は指令を入力するという働きかけは不正であると書いてあってそれに該当したことになったらしいのだが、そうであるとすると、CGI のパラメータをいじる以外の行為をしていないわけだから、CGI のパラメータ自体でアクセス制御がなされていることになる。 それは変じゃないか?と条文をざっと見ただけで思ったのだ。 当時の議論では、こういう主張はなかった。裁判での議論も微妙に違う。 なぜに?と思ったのだが、どうも アクセス制御機能になんらかの働きかけをしなければ特定利用の制限の全部又は一部を解除できるはずはない という考えが普通の人には自然ではないらしい。 上のようなことはどこにも書いていないではないかと思う人がいるかも知れない。しかし...である。それを認めないとどこかに矛盾が生じて、相当におかしい結論でも出せてしまうのだ。
別の理解のしかたも紹介しておこうと思う。 何人も、不正アクセス行為をしてはならない... その行為は悪である。 法律で行為そのものを禁止するのだから、誰にでもすみやかに理解できる概念があるはずである。 さて、実社会でアクセスを制限する機能をもったものはなにか? それは鍵である。鍵にたとえるとすみやかに理解できるはず。 第三条の一は合鍵を作って勝手に鍵を開けてならないということで、第三条の二はピッキングあるいは鍵を壊してはならないということだ。 ひょっとしたら裁判官の目には、office 氏の行為がピッキングに写ったのかも知れない。しかし...である。いったいどういう鍵をピッキングしたのか? 鍵とまでいえるものがあったのか?そうでなければ、ピッキングのような行為でもピッキングではない。それを明らかにする必要があったと思う。
おわりに また、電子工作とは関係ないことを書いてしまった。が、このような考え方があるということを紹介したかった。 こういう主張を見たことはないので、かなりユニークなものだと思う。ひょっとしたら、こういう考え方は、プログラミングを読むあるいはデバックする手法を応用した結果なのかも知れない。 できれば、主張の是非だけではなく、発想について深く考えてみてほしい。 ----- EXTENDED BODY: ----- EXCERPT: ----- KEYWORDS: ----- --------