2016年1月31日日曜日

コンソールプログラムで表現を豊かに

CygwinをはじめとするUnixらいくな環境ではコンソールプログラムの文字色や背景色をプログラムで1文字ごとに設定することができる。ということで色の一覧。



1行毎に背景色を、1列毎に文字色を設定している。色は黒、赤、緑、黄、黄緑、青、マゼンタ、シアン、デフォルトがある(でもシアンってどう見ても白だよね)。



この表現がどういうふうに使えるかというと、例えばビットのON/OFFで情報が入ってくるとして、それを文字だけではなく色として表現することができる。上の画像では青がON、赤がOFFで、現在選択しているデータを緑で表している。hjklキーで選択を移動することができ、スペースキーなどで反転することもできる。
この表現は基本的にUnixライク環境専用だが、Windowsでも使うことは可能。また、C#のConsoleでも同様の表示が可能。C#だとシリアルポートが簡単に使えるので、ちょっとした電子機器のステータス表現に使うと便利かもしれない。

2016年1月10日日曜日

STM32F1のGPIO

STM32F1のGPIOマッピング。STM32F103VE向け。STM32F103CBでも使えるはず。

一部のペリフェラルに対するピン。

ハイフンはリマップが存在しない、スラッシュはピン割当が存在しない事を表す。
リファレンスマニュアルによるとSPI3にもリマップが存在するようだが、103VEのPDFには書かれていなかったのでここでも表記していない。

ピンに対するペリフェラル。


STM32F1のGPIOは結構ペリフェラル割り当てられてる気がするけど、表で見ると意外とスカスカ。


STBee F4も発売されたことだし、僕も本格的にF4に移行したいかなと思いつつ、まだSTBeeで足りてるのでわざわざ移行する気力が。もっとも、F4のほうが容量多くて早いのに数百円安いので、64ピンで足りるならF4使ったほうが良いかもしれないけど。

2016年1月9日土曜日

STM32F1のUSARTを割り込みで送信

USARTの送信をポーリングで行う場合、115.2kbaudで32文字送った場合、2.8msec程度かかる。わずかといえばわずかだが、この時間はほとんど無駄にループさせているため、CPUのリソースが浪費されている。一旦データをバッファにコピーし、送信処理を終了してから、割り込みなどを利用してデータを送ればこの時間を200usec未満にすることができる。

1) 変数を用意する

#define USART1_TX_Buff_Size (128)
uint8_t USART1_TX_Buff[USART1_TX_Buff_Size];
uint16_t USART1_TX_Buff_SetCounter = 0;
volatile uint16_t USART1_TX_Buff_GetCounter = 0; // 割り込みで更新するのでvolatileをつける 

USART1_TX_Buff_Sizeでバッファサイズを設定する。その後USART1_TX_Buffでバッファを用意し、SetCounterとGetCounterを用意する。Setは挿入位置、Getは取り出し位置を記録する。GetCounterは割り込みの中で変更されるため、コンパイラの最適化によってwhileによる監視等が削除される場合がある。そのためGetにはvolatileをつけて最適化を回避する。

2) 下位関数を用意する

uint16_t USART1_TX_Buff_SetCounter_Inc(void) {
    uint16_t counter = USART1_TX_Buff_SetCounter;

    counter++;

    if (counter == USART1_TX_Buff_Size) {
        counter = 0;
    }

    return(counter);
}

uint16_t USART1_TX_Buff_GetCounter_Inc(void) {
    uint16_t counter = USART1_TX_Buff_GetCounter;

    counter++;

    if (counter == USART1_TX_Buff_Size) {
        counter = 0;
    }

    return(counter);
}

SetCounter_IncとGetCounter_Incはその名の通りSetとGetをインクリメントする。ただし関数内では変数に反映せず、戻り値として値を返すので関数を呼び出したところで責任をもって変数に反映する必要がある。

3) 割り込みを有効にする

    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    USART_ITConfig(USART1, USART_IT_TC, ENABLE);

USARTを初期化する際にNVICも初期化する。USART自体の初期化は前回のエントリを参照。

4) 割り込みハンドラを用意する

void USART1_IRQHandler(void)
{
    if (USART_GetITStatus(USART1, USART_IT_TC))
    {
        if (USART1_TX_Buff_SetCounter == USART1_TX_Buff_GetCounter) {
            USART_ITConfig(USART1, USART_IT_TC, DISABLE);
        } else {
            USART_SendData(USART1, USART1_TX_Buff[USART1_TX_Buff_GetCounter]);

            USART1_TX_Buff_GetCounter = USART1_TX_Buff_GetCounter_Inc();

            USART_ClearITPendingBit(USART1, USART_IT_TC);
        }
    }
}

内部処理としてはSetとGetの差が0なら割り込みを停止し、割り込み自体はクリアせずに終了する。データが存在する場合はUSART_SendDataで送信を行い、Getをインクリメントする。その後割り込みをクリアして終了する。

5) 送信用の関数を用意する

void USART1_putc(unsigned char ch) {
    uint16_t inc;
    
    do {
        inc = USART1_TX_Buff_SetCounter_Inc();
    } while (inc == USART1_TX_Buff_GetCounter);

    USART1_TX_Buff[USART1_TX_Buff_SetCounter] = ch;

    USART1_TX_Buff_SetCounter = inc;

    USART_ITConfig(USART1, USART_IT_TC, ENABLE);
}

putcの中ではバッファへのコピーのみを行う。ただし未送信のデータを破壊しないようにdo whileで待機する。その後にバッファへコピーを行い、SetCounterを更新する。最後に割り込みを有効にする。


割り込みはデータの流れが面倒になるのと、ソフトウェアもそれなりに複雑になる。毎度のことだがほんとうに必要かどうかを考えてから実装しよう。

STM32F1のUSARTをDMAで受信

USARTを受信するにはポーリングでは不都合。とりあえずタイマ割り込みを使うのが手っ取り早いが、タイマ割り込みではデータが来るたびに割り込み処理を行う必要がある。DMAを使うとソフトウェアではほとんど処理する必要が無いため、気分的に早くなってる気がする。

1) 変数を用意する

#define USART1_RX_Buff_Size (256)
uint8_t USART1_RX_Buff[USART1_RX_Buff_Size];
uint16_t USART1_Rx_Buff_GetCounter = USART1_RX_Buff_Size;

今回はバッファサイズを256としたが、USART1_RX_Buff_SizeをGCCのオプションで設定すればmakefileとかで変更することもできると思う。バッファサイズを小さくし過ぎると取りこぼすデータが発生するかもしれない。上限は数十kbyteあたりだが、実用上は数百バイトもあれば十分だろう。

2) USARTその他を初期化する

void USART1_Init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    DMA_InitTypeDef DMA_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOA, &GPIO_InitStructure);


    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_Init(USART1, &USART_InitStructure);


    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART1->DR);
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)(USART1_RX_Buff);
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    DMA_InitStructure.DMA_BufferSize = sizeof(USART1_RX_Buff) / sizeof(USART1_RX_Buff[0]);
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

    DMA_DeInit(DMA1_Channel5);
    DMA_Init(DMA1_Channel5, &DMA_InitStructure);
    DMA_Cmd(DMA1_Channel5, ENABLE);

    USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);


    USART_Cmd(USART1, ENABLE);
}

まずGPIOとUSARTを初期化する。これはポーリングでの受信や割り込みでの受信と全く同じ。TXのPin9はAF_PP、RXのPin10はPullUpで初期化する。
ペリフェラルを初期化したらDMAの初期化を行う。DMAの初期化も特に変なところはないが、ModeをCircularに設定する。優先度はMediumとしたが、例えばSPIを最大速度でVeryHighにした場合はUSARTを取りこぼすかもしれない。USARTは非同期で送信されるため、可能なかぎり優先度を上げておくほうがいい。
それと大事なことだが、DMAを初期化する前にDMAのクロックを有効にしておく必要がある(RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);)。

3) 受信関数

int USART1_getc(void) {
    int counter = DMA_GetCurrDataCounter(DMA1_Channel5);

    if (counter == USART1_Rx_Buff_GetCounter) {
        return(-1);
    }

    uint8_t ch = USART1_RX_Buff[USART1_RX_Buff_Size - USART1_Rx_Buff_GetCounter--];

    if (USART1_Rx_Buff_GetCounter == 0) {
        USART1_Rx_Buff_GetCounter = USART1_RX_Buff_Size;
    }

    return(ch);
}

この関数ではDMAを確認し、データがない場合は-1を返す。データが有る場合は最初に受信したデータを返す。この関数はバッファからデータを読む機能しかない。1行を受信したい場合は上位の関数で改行文字を検出したりする必要がある。



今回はUSARTの受信をDMAで行った。割り込みを使う場合と比べてちょっとくらい早くなった気がする。
USARTの受信はそんなに大変じゃないけど、送信は結構面倒。ただ送信をバッファリングできれば数msecとか数十msec単位で高速化できたりするので試してみる価値はある。

STM32F1のDMA

STM32F1のDMA接続一覧。ソースはRM0008のRev11日本語版。書き間違えてたらごめんなさい。





1枚目がDMAに対するペリフェラルの関係、2枚目がペリフェラルに対するDMAの関係。

例えばデータロガーを作る場合、SDカードを接続するSPI1とセンサを接続するSPIはDMA使用で、コンソールに使用するUARTもDMAを使用したい、という場合、SPI1,SPI2を使用し、UARTは4を使用することになると思う。
まずSPIだが、とりあえずSDカードはSPI1に固定しておいたほうが良い。これはSPI1では36MHzまで、それ以外では18MHzまでという制限があるため、なるべく早く通信したいSDカードはSPI1に接続する。センサはSTMの場合10MHzまでの場合が多いので、SPI2の9MHzでも十分という判断。
次にUART4を使用する理由だが、USART2のDMAは1_6と1_7が割り当てられている。しかし1_6,1_7にはI2C1も割り当てられており、I2CをDMA化したい場合に困ることになる。一方UART4なら他にはADC3とタイマしか割り当てられていないため、競合する可能性は低いと判断した。またUART4のピンにはリマップでUSART3を割り当てることが可能であり、UART4で足りない場合はUSART3を使用することが可能となる(もちろんDMAはSPI1と競合するため割り込みでしか送受信できないが)。

その他のDMAソースはADCとDAC、それからTIMしかなく、ADCはDMA1_1を割り当てることが可能、ただしDAC2は競合がTIMのみだが、DAC1はUART4_RXと競合しているため、DACを2ch使う場合は選択する必要がある。もっとも、DACを使いたい場合も大半はDMAソースにTIMを使うと思うけど。

定期的にデータを送りたい場合(GPIOでパルスを出したりDACでアナログ波を出したり)はタイマに同期してDMAを蹴ることになると思うが、タイマに割り当てられたDMAは結構数があるとはいえ、他のペリフェラルを目一杯使っているとかなり厳しいことになりそう。
ただしADCの場合はADCのトリガをTIMに接続し、DMAのトリガはADCに接続するため、DMAとTIMの接続は不要。


プログラムは実際に動作するハードウェアに合わせて作ることになると思うが、とりあえず上記のようなSPI1/SPI2/I2C1/UART4あたりをDMA化するライブラリを作っておけば互いに競合せずに後々便利かもしれない。ただしSTBee Miniに使用されているSTM32F103xCにはUART4は搭載されていない。STBee Miniを使う場合はSPI2のDMAを使用せずにUSART1を使うか、I2C1のDMAを使用せずにUSART2を使用することになるはず。
結局大抵の組み合わせのドライバを作っておけば便利だよ!ってなっちゃうんだなぁ。。。

今回はUARTは1本のみの想定だが、缶サットの場合は 1)テレメ 2)GPS 3)JPEGカメラ のように複数のUARTを使用することになると思う。そういう場合はまたいろいろ考える必要がある。
例えばJPEGカメラやGPSはコンスタントにデータが流れ込んでくるために受信はDMA化しておくと都合がいい。しかしGPSに送信する必要はあまり無く、JPEGカメラでもせいぜい数十バイトを送れば十分なので、送信はDMA化する必要はない。対してテレメの場合、受信はあまり多くないだろうが、送信はある程度のデータ量になるのでDMA化しておくと良いかもしれない。

まぁ行き当たりばったりで作るとろくな事にならないので、最初にどんな機能がほしいかを考え、それを作るためにどういう配置をすればいいかというのをしっかりと検証しておくと言いと思う。

2016年1月6日水曜日

FatFsでBack Write

FatFsでBack Writeっぽいのを実装してみました。つまりCMD24/CMD25のデータをRAMにキャッシングしておき、DMA(と転送完了割り込み)で処理し、その間は他の処理が可能、ということです。Back Writeを使う利点は、ROMにデータを転送している間の時間を他の処理に使用することが可能という点です。



BW転送中のキャプチャです。SPIバスも表示されていますが、SPIクロックが36MHzに対してロジアナは2MHzですからデータは破壊されています。「信号が動いていれば何か転送してるかも」くらいです。もちろん2MHzでは見れない瞬間的な波形は表示されません。

一番下の黄色はメインループでGPIOをトグルしています。その上のオレンジは1msecの割り込みでGPIOをトグルしており、だいたい500Hzになっています。この1kHz割り込みはビジーチェックや転送のキックにも使用しています。

上の画像では4KiBを転送しています。オレンジの波形と比較するとおおよそ30msecで転送終了しているので、転送速度は135Kbyte/sec程度です。これはCMD25のビジーチェックが不適当なためだと思われます。適切に実装すればあと6msecくらいは早くなる気がします。それでも170kByte/sec程度ですけど。
メインループに戻ってメインループが動作しているのは8msecくらいです。転送に必要な30msecのうちの8msecが他に使えるということですから、25%くらいを別に使用可能ということになります。

以前のエントリに書いている転送速度は「f_write + f_syncの時間」です。対して今回の速度はf_mountでFATを開くところから、f_mount(null)でFATを閉じるところまでの時間です。またファイルはFA_CREATE_ALWAYSで開いているので、ファイルサイズを0に変更するための処理も必要になります。データロガーなどファイルは開きっぱなしで後ろに書き加えるだけの場合はもっと早くなると思います。

BWを使用しない場合は転送時間は33msecくらいです。BW使用時はビジーチェックが不適当だと仮定すると、BWを使用しないほうが転送時間は短いはずですが、1割ほど余計に時間がかかっています。BW使用時は30msec-8msecで22msec、BW未使用時は33msecとすると3割ほどCPUリソースを有効活用できるようです。

BWを使用した場合、大量のRAM(大半の時間はこのRAMは未使用)を消費したり、Write中にReadが発生しないように(あるいはその逆が起こらないように)するために様々な配慮が必要だったり、割り込み処理が非常に面倒だったり、とソフトウェアの面ではかなり不利になります。またプログラムも1.3Kほど増えるようです。
BWを有効に活用できるのは非常にメモリに余裕があり、ソフトウェアの開発も十分に専念して行える場合に限られるでしょう。
SDカードの書き込み速度は8KiBくらいをまとめて書く場合で、データロガーの場合はダブルバッファにして文字通り「書き込みが遅れた場合のバッファを確保する」必要があるでしょう。またBWに使用するメモリはFAT操作などもありますから実データ+数ブロック分が必要と思われます。そのためBWを十分に活用するにはRAMはバッファ領域だけでも30Kほど欲しくなります。

今回Back Writeを実装してみて、かなりいろいろな工夫が必要なことがわかりました。この工夫は直接書き込む場合には必要ありませんから、実装にはかなりのコストが必要になります。バックグラウンドで書き込もうとする場合には本当にその必要があるかを考えたほうがいいと思います。

2016年1月3日日曜日

ACMD23



マルチブロックライトでACMD23を叩くとすげー早くなる、というのを見たので試してみた。アスタリスク付きがACMD23適用、それ以外はACMD23を叩かずにCMD25を叩いている。それと0.5KiBはシングルブロック書き込みなのでACMD23は使用していない。
TR32*の4.5KiBではものすごい遅くなってるけど、何回か試したらちゃんと0.5Mbyte/secくらい出る。運が悪いと遅くなる(前エントリの現象)。
有意な変化はなさそう。コマンドの使い方が間違ってるだけかもしれないけど。

とりあえず、しばらくはACMD23無しで運用しようと思う。

STM32F1でメモリ間コピー



ちょっと思う所ありメモリ間コピーを試してみた。上から 1)memcpy関数 2)forでコピー 3)DMAでM2M 4)DMAでM2M(2本並列で動作) という感じ。
転送サイズは2KiB。

1はそのままその通り、string.hのmemcpy関数を使用した。だいたい25usくらい。
2は32bitポインタ間で512回forコピー。67usくらい。
3はDMAでM2M。優先度はVeryHigh、チャンネルは2-5。8usくらい。
4は3とほとんど同じ、ただし2-5で優先度はLow、そして2-4のVeryHighを同時に走らせる。これはDMAが競合した状態でどうなるかを見ている。9usくらいかな。

感想:memcpy早い。どんな最適化してるんだよ。

とりあえず、DMAのM2Mを使うのが最速っぽい。条件によってはコアからは干渉が不要で、初期化の数usec以外はほっといても勝手に転送してくれたりもする。DMAの初期化を含めても2KiB程度なら10usec未満で完了するらしい。

SDカードの速度

SDカードの書き込み速度を計測しなおしてみた。



SPI接続で3種類のSDカードの速度を計測してみた。

・TS 32GB
Transcend製
32GB/クラス10/UHS-I/300xとか書いてあって早そうなパッケージ
多分これ:http://www.amazon.co.jp/dp/B00APCMME0/

TO 4GB
東芝製
4GB/クラス4
これ:http://www.amazon.co.jp/dp/B00K187GP8/

TO 8GB
東芝製
8GB/クラス10/UHS-I
これ:http://www.amazon.co.jp/dp/B00K187ILA/


SDの規格作ったグループに東芝いるんだから早いだろ、と思って東芝の2種類を買ってみたけど、意外と遅かった。これは「Transcendすげぇ!」なのか、「技術の進歩すげぇ!」なのか、判断に迷うところ(おそらく8GBや4GBはかなり古い設計)。
あと8GBは2000円程度、4GBでも1500円程度する。32GBは現在1400円で売ってるので、小容量じゃないとダメという訳の分からない理由でも無い限りは32GBのメディアで良さそう。書き込み早いし、安いし、大容量だし。

//***

念のためにロジアナで確認してみる。上がTS32で4ブロックのマルチブロックライト。下がTO8で4ブロックのマルチブロックライト。





1回しかキャプチャしてないし、誤差だろ と言われればそれまでだけど、Transcendは1ブロック目のビジーがかなり長い。対して東芝はあまり間をおかずに2ブロック目を転送している。対して転送終了後のビジーは切れてて申し訳ないけど、Transcendは1.7msecほど、東芝は1.9msecほどと、Transcendのほうが早い。しかしCSがLの時間は東芝が2.65msec、Transcendが3.37msecと、東芝のほうが2割少し早い。
現在使っているロジアナはこのシリーズではかなりメモリが大きい方だけど、それでもクロック100MHzだと12msecくらいしかキャプチャできない。SDカードへの転送はもっと時間がかかるので、全体を見渡すことができない。

//***

次にもう一つ比較。





1ブロック書き込みの時の波形。Transcendは1トランザクションが2.9msecほどで終了している。対して東芝では27msecを超えており、ロジアナのメモリには入りきらない。FATで数ブロックを書き換える場合はマルチブロックライト以外にもFATテーブルを書き換えるためのシングルブロックライトがかなりの割合を占める。そのため、シングルブロックライトに数十msecを必要としている場合、マルチブロックWが数割早い程度では回収できないほどの遅れを生じてしまう。Transcendが倍くらい早いのは、TranscendがシングルブロックWをうまくバッファリングしてるのか、東芝がシンブルブロックWが下手なのか、または双方かもしれないけど。

念のため、シングルブロックがアホな処理をやっている、という可能性を潰すために512バイトでもマルチブロックライトで書き込んでみた、ちゃんと計ったわけではないが、8KiBを書いて0.39Mbyte/secほどだった。しかしロジアナで見える範囲では数十msecのビジーが発生しているようには見えない。マルチブロックライトで1ブロックだけの場合は内部でシングルブロックと等価な処理を行っているのかもしれないが、ビジーはそんなに長くない、しかし総合的な処理はシングルブロックライトと変わらないし、というちょっと謎な挙動となった。これ以上を調べるのは手持ちの機材ではつらそうだ。

//***

ロジアナでキャプチャしながらブログ書いてるけど、最初はこんなに長く書く気はなかった。でもなんだかムキになってきてもうちょっと続く(計画性がないからこんなことになるんだ)。

//***





こちらは10MHzでサンプリングした波形。SPIクロックは36MHzなのでデータとしての正しさはあまりない。ただCSの形はおおよそわかるので、1トランザクションの長さはある程度信頼できると思う。
が、波形が見えたところでどの波形がどういう通信なのかがわからないのであまり意味が無い。一応双方とも同じデータが流れているはずで、MISO(一番下の茶色)でLowが続いているのはビジー状態だと思う。そう考えると東芝の方はビジーが長い気がする。

//**





Transcendは10MHz、東芝は5MHzで4ブロック書き込みをキャプチャ。東芝のカードは1個目のシングルブロックで85msec以上のビジーが発生しており、これがネックっぽい。というかこれはひどい。。。

//***

ところで、SDカードでは少し不思議な挙動がある。東芝の場合は何回も書いていると数割くらいの確率で書き込み速度が倍増くらいになる。Transcendの場合は、最初の数回がものすごく遅くても、何回も書いていればちゃんと速度が出るようになる。



このキャプチャは東芝8GBで16ブロック(8KiB)を書いた時のキャプチャ。この時には0.6Mbyte/secを超えている。相変わらずTranscendには劣るが、それでもかなり早くなった。

ちなみにSDカード初期化直後のキャプチャはこれ。



シングルもマルチも関係なく512バイト転送ごとに70msec前後のビジーが発生している。明らかに駄目な感じ。この時は0.021Mbyte/secくらい。21.5kByte/secである。ISDNの2.6倍くらいの速度。遅すぎ。

//***

なんか「実は電源が貧弱で安定動作していません」みたいなオチがしっくりきそうな気がしてきた。
現在はマイコンボードのLDOで3.3Vを作って、そこからちょっと引き回して470uFの電コン(これしかなかった)に突っ込んで、microSDブレークアウトボードの下で0.1uFという構成。
もうわけがわからないよ。

2016年1月1日金曜日

MT2Aを買った



NITECOREという会社のMT2Aという製品を買った。実は14年春にも買ったけど、先日紛失してしまったので買い直した。真面目に探したら出てくるような気がするけど、ピカティニーマウントも可能なので2本あっても困らないかなって。ミリヘルメットのARCレールにも搭載できるので3本あっても困らないです。

上の写真は製品パッケージ。左が14年春に買ったもの。右が15年末に買ったもの。輝度が280lmから345lmに向上している。他に大した変更はなく、防水性や耐衝撃性は変化ない。左はLEDがCREEのXP-G R5で右がXP-G2 R5という製品。LEDが新型になって輝度が向上してるらしい。

右にあるのがMT2Aで、ロスコ(ROTHCO)のヘルメットマウント(マウントリング)を装着している。これにより同メーカーのエアソフトヘルメットに装着できる。ちょっとした作業の時はエアソフトヘルメットを使ってると頭をぶつけても痛くないし、寒くないし、高輝度ライトを装着できるので便利。

今回MT2Aを買うとき、最初はMT1Aを買おうとしていた。こちらは電池が1本で若干短くなっている。輝度は半分だが、MT2AのMAXは普段使わないので。しかしMT1AとMT2Aでは値段は数百円しか違わないので、結局MT2Aを買ってしまった。手で持つときにもMT2Aのほうが慣れてるし。

このMT2Aという製品は単3電池2本で動作し、アウトドアで使うのにも必要な性能は十分揃えているので、かなりオススメできる製品。
単3電池なので寒冷地での性能に不安があるのと、ボディが金属なので超低温では素手で使えないのが欠点だけど、今のところそういう環境には遭遇していないので余り問題にはなっていない。寒いところで素手で使うわけ無いだろ、とも思うけど、この程度の重量なら口で咥えて両手で作業する、という状態もありえるので、そういう意味ではガワが金属なのはちょっと減点かも。
といっても氷点下ではNiMHなどは使用できず、この環境で使用できるのはCR123等に限られるので、極限環境で使用するならSureFireのSF123使用タイプを選択するべき。普段使いにMT2Aを、バックアップにポリマーで123を使うSureFireを、という組み合わせがいいかも。