Crazy Whopper

blog20100723-CrazyWhopper

本日発売のCrazy Whopper。ハバネロを抜いて世界一辛い唐辛子とされているブートジョロキアを使用した、激辛バーガーとなっております。ブートジョロキアが使われているのは濃い茶色のソースであり、挟まれている緑のピクルスはハラペーニョ。また広告Link を見るとハンバーグパティよりはるかに厚い2cmはあろうかというハラペーニョ層となってますが、実際には積み重なってはいませんでした。しかしパティの上に満遍なく敷き詰められていたには違いなく。

食べ始めは大したこと無いなと思ってたのですが、半分くらいから苦痛。Whopperの大きさも手伝って、最後の2口がなかなか進まず苦戦しました。アイスティも氷も含めて全部飲んじゃったし。

個人的にはバーガーキングの特徴であるハンバーグパティの旨みが辛さでかき消されたようで、残念。普通のWhopperの方がいいかなぁ。

[2010/8/9 追記] 再度挑戦。前回のように苦戦することもなく、アイスティもMサイズで余裕。一緒に行った会社の後輩が私のような苦戦をしていたので、辛いのは間違いなく。しかしタイや中国出張が多いためか、辛いものに耐性ある人が多いうちの会社。「日本で発売だし、一線は越えてないよなぁ」の意見が主流でした。

— posted by mu at 10:34 pm   commentComment [0]  pingTrackBack [0]

.NETで順番を守って排他制御

マルチスレッド環境で排他制御する時に、先に要求したスレッドほど先に実行させたい、ということを考える機会がありました。

.NETプログラミングで有名な排他制御方法はMonitorLinkManualResetEventLink でしょうか。C#ではMonitorクラスを便利に使えるlockステートメントもあり、私もよく使います。しかしManualResetEventは単一もしくは複数のスレッドを待たせて一気にスタートさせるものですし、Monitorは待ち状態にある複数のスレッドに対してロックを順番に与えてはくれません。後者はどういうことかというと、
  • スレッド1は既に排他ロックを取得し実行中
  • スレッド2がロックを求めて待ち状態に入った
  • スレッド2より後にスレッド3がロックを求めて待ち状態に入った
という状態でスレッド1がロックを開放した場合、次に排他ロックを取得するのは…どちらか分かりません。待ちスレッドが1個や2個では発生しにくいかもしれませんが、10や20スレッド待たせると順番通りにロックさせてくれないのが分かると思います。

最初に目をつけたのがQueueLink ジェネリッククラス。

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ではConcurrentQueueLink なんていうスレッドセーフなQueueが登場したので、使えるかもしれません。

次にInterlockedLink クラスを使うこと。Incrementメソッドを使えば確実に早くやってきたスレッドから小さい番号を割り当てることができます。しかし単に数字が分かっただけ。各スレッドに自分の順番が来るまで待たせる上手い方法が分かりません。唯一思いついたのが、もう一個Interlockedで管理される整数を用意して、処理が終わったスレッドはこの数を増やしていくこと。銀行とかにある順番待ち整理券がイメージしやすいでしょうか。前者の変数が整理券の番号で、後者が「○番のカードをお持ちの方…」としゃべる機械。自分の番号が来たスレッドは処理を開始。

ただこの方法は各スレッドが自分の順番が来たかどうかポーリングでチェックせねばならず、CPU負荷が高くなる欠点があります。負荷の低いManualResetEventなどを使いたいのですが、Interlocked.Incrementで得られた数字とManualResetEventを結び付けようとする(Dictionary<int, ManualResetEvent>とか)所でスレッドセーフにする方法が思いつかず。

現時点の答えはReaderWriterLockLink を使い、全スレッドAcquireWriterLockを呼び出すこと。とりあえず100スレッドAcquireWriterLockを呼び出して待ち状態に入るプログラムを書いてみましたが、順番通りにスレッドがロックを取得していました。こういう使い方って、保障されているのでしょうか? ちなみにReaderLockされている状態ではAcquireWriterLockは待ち状態にされますが、その後にAcquireReaderLockのスレッドが来ると待ち状態のAcquireWriterLockを平気で追い抜きます(複数同時ReaderLockを認めているから)。

[2011/8/2 追記] 最終文訂正(AcquireReaderLock→AcquireWriterLock)

— posted by mu at 09:44 pm   commentComment [0]  pingTrackBack [0]

30VでLED

blog20100721-ConstantCurrentCircuit

先日の記事Link で触れた回路設計の見直しに関連するのですが、詳しい背景は省略して要求事項を要約すると、
  1. 外部から来る電圧のOn/Offに合わせて普通のLEDを点滅させる。
  2. その電圧は10~30V。外部で使用する電源電圧なので電源を変えない限りは一定。
  3. この電圧以外にLEDが使える電力源はない。
まずこの電圧を普通のLEDに直接入れると確実に焼けてしまいます(5Vでも煙出せますよ)ので、電圧を落とさないといけない。一番簡単なのは直列に抵抗を入れることですが、電源電圧の変動幅が大きいので全電圧に対応できる抵抗値が決まらない。電源がOn/Offを繰り返すのでレギュレータやDC-DC変換回路もダメ。

ここまで電圧電圧と書きましたが、LED制御に重要なのは電流量で電流を決めればLEDにかける電圧が決まるというのが正しい考え方。というわけで、LEDに20mAを流す定電流回路を考えればいいことになります。もっとも簡単なのは定電流ダイオードLink という素子を使うことですが、その場合問題になるのが発熱。

(動力・音・光などを発生しない)回路に電圧をかけて電流を流すと必ずジュール熱Link が発生します。今回の場合なら30V×20mA=0.6W。どこかで必ず発生します。LEDに直接繋ぐと焦げてしまうのはこの熱がすべてLEDで発生するため(実際にはもっと大量の電流が流れもっと発熱します)。抵抗器や定電流ダイオードを直列に繋ぐと、発熱がLEDとで分担されるのでLEDが焼けずにすむわけです。

で、一般的な定電流ダイオードが許容できる発熱量は0.3Wが多いので、完全にオーバー。写真上側のように複数を並列に繋いで発熱を分担させないといけません。こんな米粒みたいな素子がよく0.3Wも耐えられるなと思ったら、リード線を伝わって基板などに放熱させることを前提としているようですね。写真の縦に取り付けてある銅版は放熱目的だったりします。

blog20100721-ConstantCurrentCircuit

別の解決としてはトランジスタを使った定電流回路Link 。発熱はトランジスタ・エミッタに接続された抵抗器・LEDで分担されます。一番発熱するのはトランジスタなのですが、トランジスタは種類が豊富、安くて発熱に強い(コレクタ損失が大きい)やつが一杯あるのが魅力。

しかし…定電流ダイオード3個と比べると、トランジスタを使った回路はユニバーサル基板上では倍の面積を取るんですよね。今回基板面積にもあまり余裕がないので、素直に定電流ダイオードでしょうか(だけど値段高い)。

[参考] 個別半導体の豆知識 (なひたふ電子情報)Link

— posted by mu at 10:39 pm   commentComment [0]  pingTrackBack [0]

PCでmsec時間測定(5) - 校正

AVR側はとりあえずできLink 、Windows側も結構出来上がってきました。センサとの接続部で回路設計の見直しが生じ、プログラムの方は待ち状態になりつつあるため、以前から気になっていた以下のことを検証することに。
正確な時間を測定しているのか
AVRを駆動するクロックをカウントして時間を測定しているので、正確さはクロックのそれに直接依存してます。ストロベリーリナックスLink のボードは16MHzクォーツですのでそれほど狂ってはいないと思いますが。
頻繁にボタン・センサをOn/Offしても正確に測定できるか
回路はOn/Offが切り替わったときだけPC側にその情報を送ります。On/Offが頻繁に起きるとUSB通信も増えるわけで、そういったCPU負荷が高い状態でも時間を正確に刻めるか。
というわけでPC側のプログラムを拡張。
  • PCの時計は信用できないので、あらかじめNTPLink でサーバに同期。
  • AVR側は10kHz(1秒間に1万回)、内部のカウンタを延々と+1し続けます。PCから命令を受けるとその時の内部カウンタをPC側に返す機能を追加。
  • PC上のWindowsプログラムは1時間ごとにAVR側に内部カウンタを報告させるコマンドを発行、1時間の間にカウンタがいくつ増加しているかを調べる。
  • 上の測定をスイッチのOn/Off無しと頻繁に繰り返す状態で行い、比較する。
On/Offの繰り返しは手元にあったPIC 12F683でM系列Link を発生させるプログラムを作成、AVR側のスイッチ入力としました。AVRのクロックが正確なら、1時間後のカウンタは3600万増えているはず。測定の結果は以下の通り。
スイッチOn/Off 1時間のカウント増加 1秒あたり
なし 35998815.95 9999.67
あり 35998770.97 9999.66

今やっているのはミリ秒単位の測定なので、1秒間1万カウント中影響が出てくるのは10の位。しかしAVR側のカウンタの狂いはその2桁下、スイッチOn/Off有無による違いは更に1桁下。

スイッチOn/Off間隔が数分にも及ぶような測定の場合はミリ秒単位に影響が出てくるのでこの結果による補正が必要になってきますが、今前提としているのは1~2秒間隔。無視しても良さそうですねぇ。

[2010/9/25 追記] 続きLink

— posted by mu at 07:11 pm   commentComment [0]  pingTrackBack [0]

今から投票行ってきます

この2週間ゲームしながら政見放送見てたりしたのですが、結局いつもと同じくあまり考えずに投票してたりします。大体この地区の候補者も知らないしorz 今回は小党乱立で、さらに分かんね。

ただひとつ思うのは
減税だってバラ撒きでしょ?
撒く方向が違うだけ。なにバラ撒き批判しておいて減税(もしくは税率維持)謳ってるんだか。公約をカタカナに言い換えたり、言葉遊びが過ぎる。

[2010/7/11 追記] 完了。初めて出口調査ってやつを経験。

— posted by mu at 03:13 pm   commentComment [0]  pingTrackBack [0]

T: Y: ALL: Online:
ThemeSwitch
  • Basic
Created in 0.0150 sec.
prev
2010.7
next
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31