前回
以降、依頼主に回路を引渡して使ってもらい何度か(主に使い勝手の)修正、試験使用を待つ状態になったようです。
一段落ついたということで記録に残すという意味も兼ね、AVR側のプログラムと使い方を公開
することにしました。現時点PC側のプログラムを提供してませんので、お手軽には使えないと思いますが…使う目的によってプログラムは千差万別と思ってまして、簡単かつ汎用的な目的が思い浮かばない状態です。
2010/9/25
前回
以降、依頼主に回路を引渡して使ってもらい何度か(主に使い勝手の)修正、試験使用を待つ状態になったようです。
一段落ついたということで記録に残すという意味も兼ね、AVR側のプログラムと使い方を公開
することにしました。現時点PC側のプログラムを提供してませんので、お手軽には使えないと思いますが…使う目的によってプログラムは千差万別と思ってまして、簡単かつ汎用的な目的が思い浮かばない状態です。
— posted by mu at 06:26 pm
Comment [4]
TrackBack [0]
2010/8/29

この例外を検索すると多くはx64のコードからx86のDLLなどをロードしようとした(または逆)時に発生するようですが、今回そんなDLLを使った覚えはなく。
問題なく動いていたコードに書き戻してどのファイルが問題を発生させるのか調べたところ、原因はどうやらcsprojファイルに<None Include="app.config" />という行が追加されるかららしい。試しにこの行をテキストエディタで削除してプロジェクトを再読み込みすると、問題なく起動します。
しかしこれはapp.configをプロジェクトから外すという事。設定項目はsettingsとapp.configファイル両方に記録されるのですが、ビルド後の設定変更で使われるのは後者であり外すのはまずい。また設定項目を編集すると問題の行が復活するのでいちいち消さないといけないので、面倒。
Visual Studioのどこかに設定するところがあるのだろうか、それともバグ?
環境は以下のとおり[2010/8/29 追記] 32bit OSだと問題なし。ということはやっぱり64bitと32bit混在が原因なのか、むむむ…
[2010/8/29 追記] Visual Studioの設定をいじっているうちに発生しなくなってしまいました。やったことは以下の内容。
— posted by mu at 12:30 am
Comment [0]
TrackBack [0]
2010/8/17

前回
からほぼ1ヶ月経ちましたが、最初の2週間は依頼主からの仕様決定待ち、その後は部品購入&組み立てで結構忙しかったのです。出てきた仕様が予想とちょっと異なったため、定電流回路
は不要、代わりにレギュレータを装備することとなりました。見切り発車で部品買わなくてよかった。
写真は一通りに動作確認を終えた回路基板など。ケースの値段も馬鹿にならない&穴あけめんどくせ~と依頼主に言ったら、今回は試作なので100円ショップで売ってるような材料で良いと。というわけでタッパーに入れましたが、あまりかっこ良くないな。3個100円のタッパーは全体的に薄い作りでカッターナイフで穴を開けるには簡単な反面、割れやすかったりドリルで穴あけると材質がドリルに絡み付いてきてきれいな穴が開かない。やっぱり電子工作用のケースはそれなりに利点があるってこと。
右下で赤く光っているのは、本システムの最重要パーツであられます光センサ。数秒単位でOn/Offを繰り返すスイッチ
というのはこれのことで、このセンサの前を通り過ぎる対象を測定するわけです。
なぜ最重要かというと、センサ以外の全回路&部品(写真のAT90USB162のボード含む)を全部合わせてもこのセンサの値段の半分にも満たないためw メーカーは全然値引きに応じないとうちの会社の購買部門も愚痴をこぼす某社。依頼主によると今回も当然ほぼ定価で購入、たくさん買ったらいくらになるかと聞いてもほぼ定価と、今も変わり無いようで何よりw
[20109/25 追記] 続き
— posted by mu at 12:37 am
Comment [0]
TrackBack [0]
2010/7/22
マルチスレッド環境で排他制御する時に、先に要求したスレッドほど先に実行させたい、ということを考える機会がありました。
.NETプログラミングで有名な排他制御方法はMonitor最初に目をつけたのがQueue
ジェネリッククラス。
using System.Collections.Generic;
using System.Threading;
class FIFOLock
{
Queue<ManualResetEvent> eventQueue = new Queue<ManualResetEvent>();
public void GetLock()
{
ManualResetEvent myEvent = new ManualResetEvent(false);
lock(eventQueue)
{
eventQueue.Enqueue(myEvent);
if(myEvent.Equals(eventQueue.Peek())) return; // No thread is locking resource
}
myEvent.WaitOne();
}
public void ReleaseLock()
{
lock{eventQueue)
{
eventQueue.Dequeue(); // Remove ManualResetEvent of this thread
eventQueue.Peek().Set(); // Signal to next waiting thread
}
}
}
実際にVisualStudioに打ち込んでないので、文法間違いなどあるかもしれません。打ち込まなかったのは考えている途中で「あ、lock使ってるからダメだ、これは」と思ったから。複数のスレッドがGetLock()に飛び込んできて競合待ち状態になったときに、次にeventQueueにアクセスできるスレッドが不定なため、順番の追い越しが発生する可能性があります。eventQueueがロックされている時間は僅かで、複数のスレッドがGetLock内で競合する確率は低いとはいえ、完璧ではない。ちなみに.NET 4.0ではConcurrentQueue
なんていうスレッドセーフなQueueが登場したので、使えるかもしれません。
次にInterlocked
クラスを使うこと。Incrementメソッドを使えば確実に早くやってきたスレッドから小さい番号を割り当てることができます。しかし単に数字が分かっただけ。各スレッドに自分の順番が来るまで待たせる上手い方法が分かりません。唯一思いついたのが、もう一個Interlockedで管理される整数を用意して、処理が終わったスレッドはこの数を増やしていくこと。銀行とかにある順番待ち整理券がイメージしやすいでしょうか。前者の変数が整理券の番号で、後者が「○番のカードをお持ちの方…」としゃべる機械。自分の番号が来たスレッドは処理を開始。
ただこの方法は各スレッドが自分の順番が来たかどうかポーリングでチェックせねばならず、CPU負荷が高くなる欠点があります。負荷の低いManualResetEventなどを使いたいのですが、Interlocked.Incrementで得られた数字とManualResetEventを結び付けようとする(Dictionary<int, ManualResetEvent>とか)所でスレッドセーフにする方法が思いつかず。
現時点の答えはReaderWriterLock
を使い、全スレッドAcquireWriterLockを呼び出すこと。とりあえず100スレッドAcquireWriterLockを呼び出して待ち状態に入るプログラムを書いてみましたが、順番通りにスレッドがロックを取得していました。こういう使い方って、保障されているのでしょうか? ちなみにReaderLockされている状態ではAcquireWriterLockは待ち状態にされますが、その後にAcquireReaderLockのスレッドが来ると待ち状態のAcquireWriterLockを平気で追い抜きます(複数同時ReaderLockを認めているから)。
[2011/8/2 追記] 最終文訂正(AcquireReaderLock→AcquireWriterLock)
— posted by mu at 09:44 pm
Comment [0]
TrackBack [0]
2010/7/21

ここまで電圧電圧と書きましたが、LED制御に重要なのは電流量で電流を決めればLEDにかける電圧が決まるというのが正しい考え方。というわけで、LEDに20mAを流す定電流回路を考えればいいことになります。もっとも簡単なのは定電流ダイオード
という素子を使うことですが、その場合問題になるのが発熱。
(動力・音・光などを発生しない)回路に電圧をかけて電流を流すと必ずジュール熱
が発生します。今回の場合なら30V×20mA=0.6W。どこかで必ず発生します。LEDに直接繋ぐと焦げてしまうのはこの熱がすべてLEDで発生するため(実際にはもっと大量の電流が流れもっと発熱します)。抵抗器や定電流ダイオードを直列に繋ぐと、発熱がLEDとで分担されるのでLEDが焼けずにすむわけです。
で、一般的な定電流ダイオードが許容できる発熱量は0.3Wが多いので、完全にオーバー。写真上側のように複数を並列に繋いで発熱を分担させないといけません。こんな米粒みたいな素子がよく0.3Wも耐えられるなと思ったら、リード線を伝わって基板などに放熱させることを前提としているようですね。写真の縦に取り付けてある銅版は放熱目的だったりします。

別の解決としてはトランジスタを使った定電流回路
。発熱はトランジスタ・エミッタに接続された抵抗器・LEDで分担されます。一番発熱するのはトランジスタなのですが、トランジスタは種類が豊富、安くて発熱に強い(コレクタ損失が大きい)やつが一杯あるのが魅力。
しかし…定電流ダイオード3個と比べると、トランジスタを使った回路はユニバーサル基板上では倍の面積を取るんですよね。今回基板面積にもあまり余裕がないので、素直に定電流ダイオードでしょうか(だけど値段高い)。
[参考] 個別半導体の豆知識 (なひたふ電子情報)
— posted by mu at 10:39 pm
Comment [0]
TrackBack [0]
Comments