2017年8月11日金曜日

PIC32MX250F128B+HarmonyでUSBメモリーに書き込みをする

やはりUSB Hostを手軽にやりたいならばPIC32MX250F128Bです。
以前、USBメモリーにアクセスしたり、 それを一部改造してファイルシステムはFatFsで読み書きしたりして遊んでいましたが、久々にUSBメモリーを使いたくなってもう一度この時使ったPIC32MX250を取り出してきました。

当時とは環境を一新してやろうとしたところ、どうもライブラリに新しいものが出てきているようでした。

MPLAB Harmony

MPLAB HarmonyはPIC32シリーズ専用のライブラリ群(公式サイトにはフレームワークって書いてありますが)で、柔軟で抽象度の高いプログラムを書くことを目的に開発されたもののようです。Harmonyという名前からも、各機能が調和し合って完成していくような様を表しているのでしょう。

以前、PIC32MX250でUSBメモリーにアクセスしたときはMicrochip Libraries for Application(MLA)というライブラリを使っておりました。MicrochipはこれをMPLAB Harmonyで置き換えようとしているみたいで、新しいバージョンのMPLAB XやXC32でMLAを使おうとしたところ鬱陶しいほどの警告が出てきました。


というわけで、今回はMPLAB Harmonyを使ってUSBメモリーにアクセスしてみたいと思います。回路はMLAのときとほぼ同じですが、LEDの場所だけ都合によって変えました。

とその前に、今回使用した環境だけ明記しておきますね。こういうの、バージョンによって結構変わってきそうなので。
  • MPLAB X IDE v3.65
  • XC32 v1.44
  • MPLAB Harmony v1.11
まずは、HarmonyをインストールしてHarmonyのプロジェクトを作れるようにします。これはググればいろいろなサイトで出てくるのでそこまで苦労しないでしょう。


プロジェクトテンプレートが用意されているので、今までのようにサンプルプログラムから必要なソースコードをコピペしてきたリ、いちいちライブラリのincludeディレクトリに参照を追加したりという面倒な作業が必要無くなります。

そして何よりも強力なのがこの「MPLAB Harmony Configurator」です。
PICでプログラミングするうえで、初心者殺し(そして慣れれば単に面倒)だった作業の1つであるConfigurationビットの設定がGUIでできてしまいます。そして、Configurationビットだけにとどまらず、どのライブラリをインポートするか、どのような設定で使うかなどということまでここで設定できてしまうためかなり楽ちんになっています。


今回はUSB HostでMSD(Mass Storage Device)を使うので上記のような設定にします。
そして、Harmony Configuratorで最も強力なのがこのClock Diagramです。


複雑な構造のクロックのプリスケーラ、ポストスケーラ等の設定が図の上で簡単に設定できてしまいます。
今回は8MHzのセラロックを付けたので、そのように設定し、USBには48MHz、システムクロックには60MHzが供給できるように設定します。

最後に「Pin Settings」でLEDを接続したピンをデジタル出力に設定して、「Generate Code」ボタンをクリックすれば自動的にこの設定に従ったソースコードをプロジェクトに設定してくれます。
ああ、なんとゆとりな時代になったのでしょう。

ちなみに、ユーザーが編集するソースコードは[ProjectName]/Source Files/app/app.cと[ProjectName]/Header Files/app/app.hの2つだけです。
これ以外は上記のGeneratorが自動的に作ってくれるコードですので、設定を変えたらせっかく自分が編集していた分も消え去ってしまいます。

おっと、最後に1つ注意事項。
ヒープ領域を設定します。
これを設定しないと、謎の実行時エラー(USB_HOST_EVENT_DEVICE_UNSUPPORTED)に悩まされることになります。これはMLAの時もハマりポイントでした。適当に2000bytesくらいをヒープ領域に割り当てておけばよいでしょう。



さて、肝心のapp.cとapp.hですが、これはデモプログラムの移植がとっつきやすいでしょう。
Harmonyのインストールフォルダ(C:\microchip\harmony\v1_11\apps\usb\host\msd_basic\firmware\src)の中にあるapp.cとapp.hを今作ったプログラムのapp.cとapp.hにコピペします。

コンパイルするとLED関係の関数呼び出し(マイコンボード用?)がエラーになりますが、必須ではないのでコメントアウトしてやれば良いでしょう。


ちなみにですが、今回はRB13にLEDを付けましたので、アクセスランプとして書き込み中に点灯するように改造しておきます。
case APP_STATE_WRITE_TO_FILE:

    // Try writing to the file
    
    PLIB_PORTS_PinSet(PORTS_ID_0, PORT_CHANNEL_B, PORTS_BIT_POS_13);
    
    if (SYS_FS_FileWrite( appData.fileHandle, "Hello, world!\r\n", 15 ) == -1)
    {
        // Write was not successful. Close the file and error out.
        SYS_FS_FileClose(appData.fileHandle);
        appData.state = APP_STATE_ERROR;

    }
    else
    {
        // We are done writing. Close the file
        appData.state = APP_STATE_CLOSE_FILE;
    }

    PLIB_PORTS_PinClear(PORTS_ID_0, PORT_CHANNEL_B, PORTS_BIT_POS_13);
    
    break;
GPIOの制御はPLIB_PORTS_PinSet関数などを使います。
直接LATBなどを叩いていたらライブラリによる抽象化が台無しですからね。

余談ですが、Harmonyはファイルシステムの制御モジュールとしてFatFsを使っているようです。
ついにMicrochipに使われるようになったかFatFs。素晴らしいライブラリです。ですので、MLAのときにあったタイムスタンプが書きこまれないトラブルも回避されています。


さて、前回はUSBメモリーへの書き込みをやっただけで満足して終わりでしたが、今回はちゃんとアプリケーションを作るぞー!

2017年5月29日月曜日

パナソニックの照明を制御する

我が家の建物にはパナソニック製の照明が備え付けられています。
そして、入居してしばらくは気づかなかったのですが、どうもこの照明、リモコンに対応しているようです。部屋にはリモコンが備え付けられていませんでした。

型番をググって説明書を見ると、リモコンはHK9487MMというものらしいです。Amazonで2500円程度…。高いな…。

さて、説明書やリモコンの画像を見ると、どうも下記のボタンがあるようです。
  • 点灯(普段)
  • 全灯
  • 常夜灯
  • 消灯
  • 白い色(調色ボタン)
  • 暖かい色(調色ボタン)
  • 明るい(明暗ボタン)
  • 暗い(明暗ボタン)
  • おやすみ30(30分タイマー)
  • チャンネル選択(1,2,3)
  • チャンネル確定
ほうほう、壁のボタンだと全灯→暗め→常夜灯しか切り替えられませんが、こんなにいろいろな機能があるようです。

手元にリモコンがあれば、赤外線フォトトランジスタとかを使ってコードを解析すればいいのですが、無いのでどうしようもありません。

赤外線通信の方式

どうもググるところによると、この手の赤外線通信はおおよそ3種類あるそうです。NECフォーマット、SONYフォーマット、家電協フォーマットがその3種類ですが、パナソニック製照明はどうも家電協フォーマットのようです。

赤外線リモコンの通信フォーマット

細かいプロトコルはこのページに詳しく書いてあります。
T=425usとして、赤外線LEDを38kHzで点滅させている状態(duty比1:2)をON、消灯させている状態をOFFとすると、0はONを1T、OFFを1Tで1はONを1T、OFFを3Tで表現するようです。

ここでハマったことは、最後のビットを送信し終わった後にONを1Tだけ送ってストップビットとすることです。このストップビットを送らないと、最後のビットでOFFが1T続いたのか3T続いたのかがわからないので、最後のビットを読むことができません。結果、デコードエラーとなり受け付けてくれません。

送信データの内容

さて、具体的にどんな信号を送ればいいかと言うと、このサイトに書いてありました。

iRemo2 リモコン・データベース

例えば、CH1の全灯コマンドは

0x344A9034A4

です。
上記のフォーマットに当てはめてみると、「0x344A」がパナソニックのカスタマーコードのようです。その次の「9」が、この16bit値を4bitずつ区切ってXORを取ったパリティです。
次は、「0x034」が命令コード本体で、最後の「A4」は、カスタマーコードのパリティを含んだ「0x9034」の16bit値を8bitずつ区切ってXORを取ったパリティのようです。

すなわち、パナソニック照明に何かしらのコマンドを送るのにキーとなるのはたったの12bit分です。
しかも、上記のページにはコマンドがある程度書いてあります。

さて、その肝になる12bit分をリストに書いてみるとこうなります。

0000 0101 0100 CH1 明るく
0000 0100 1100 CH2 明るく
0000 0101 1100 CH3 明るく
0000 1011 0100 CH1 点灯(普段)
0000 1010 1100 CH2 点灯(普段)
0000 1011 1100 CH3 点灯(普段)
0000 1101 0100 CH1 暗く
0000 1100 1100 CH2 暗く
0000 1101 1100 CH3 暗く
0000 1111 0100 CH1 消灯
0000 1110 1100 CH2 消灯
0000 1111 1100 CH3 消灯
0000 0111 0100 CH1 常夜灯
0000 0110 1100 CH2 常夜灯
0000 0111 1100 CH3 常夜灯
0000 0011 0100 CH1 全灯
0000 0010 1100 CH2 全灯
0000 0011 1100 CH3 全灯

さて、ここまで見ると(わざとらしく色分けしていますが)見えてきます。
最初の4bit、最後の3bitはよくわかりませんが、5~7bit目は点灯内容を表すコード、8,9bit目はチャンネルに対応しています。

ここまでの話はMSBからデータを送信しているとの仮定ですが、LSBから送信していたとするとチャンネルのbitがそのままチャンネル番号に対応していると言えそうですが、まあ細かいことなのであまり気にしないことにしましょう。MSBから送っていると考えたほうがわかりやすいですし。

他の送信コード

最初にリモコンの外見等から見た機能の中で、上記のコードに含まれていないものがあります。
  • 白く
  • 黄色く
  • おやすみ30(30分タイマー)
  • チャンネル確定
といったところでしょうか。
最初は上記の青色部分が「000」と「100」の2通りが無いので、これが「白く」と「黄色く」に対応するのかなと思いましたが、どうも違うようです。

とりあえず、チャンネルの位置を8,9bit目として他の部分で10bit分。これを総当たりすれば1024通りです。「白く」「黄色く」の調色ボタンは1回押しただけでは変化がわかりにくいので、20回くらい連打するべきでしょう。
20回の連打に3秒かければ、だいたい1時間くらいで総当たりが終わります。その間にゴロゴロしながらアニメでも見ていればいいでしょうと思いながらやってみました。

そうすると、一部のコードが見つかりましたが全部は見つかりませんでした。
うーん、こうなったら12bit総当たりだ!それでも4時間くらいですしまあ何とかなるでしょう。

というわけで洗いだしたコードが下記の通りになります。

1100 110‬‬1 0001 CH1 黄色
1100 1011 0001 CH2 黄色
1100 1111 0001 CH3 黄色
1100 100‬0 1001 CH1 黄色く
1100 1010 1001 CH2 黄色く
1100 100‬1 1001 CH3 黄色く
1100 010‬1 0001 CH1 白
1100 0011 0001 CH2 白
1100 0111 0001 CH3 白
1100 0000 1001 CH1 白く
1100 0010 1001 CH2 白く
1100 000‬1 1001 CH3 白く
1100 1000 0101 CH1 タイマー
1100 0101 0101 CH2 タイマー
1100 110‬0 1101 CH3 タイマー
1100 010‬1 1011 CH1 チャンネル変更
1100 110‬‬1 1011 CH2 チャンネル変更
1100 001‬‬‬1 1011 CH3 チャンネル変更

リモコンにはない、「(最も)黄色にする」「(最も)白にする」 というコマンドもオマケで見つかりました。
ですが、これを見てもどこがチャンネルと言うべきか、どこが点灯内容と言うべきかいまいちよくわからないコードです。色関係のコマンドでは少し共通性はありますが、タイマーやチャンネル変更を合わせたコマンドを見てもいまいち規則性はわかりませんでした。
誰か解読できた人がいたら教えてください。

実装(ダイジェスト)

さて、これをESP8266に実装し、基板を作成して箱に収めるとこんな感じになります。



ESP8266なのでWi-Fiで操作できます。
ウェブブラウザでも操作できますが、せっかくなのでスマホアプリも作ってみました。
まあこの辺の製作話はまた今度、気が向いたらにしましょう。

ではでは。

2017年4月23日日曜日

10万PV突破

初めての投稿から3年弱、皆様に支えられてつい最近10万PVを突破いたしました。
ありがとうございます。
趣味でやっているプログラミング関係のことを中心にしたブログですので、かなり不定期の更新になっています。下手したら更新が数か月開くこともザラでした。

ですが、最近はだいたい1日当たり100~200PVほどいただいているようです。1か月にしてだいたい4500PV程度。更新頻度が低く、しかも自分の備忘録としての側面が強いブログにしてはかなりPVが大きなほうだと思います。

参考までに、ここ1か月のPVランキングを示すと

1位WPFのScrollViewerやScrollBarのスクロール位置を同期させる2015/01/16339PV
2位ポケモン「サファイア」の時計を復活させる2016/01/22308PV
3位プロキシ設定とレジストリ2015/11/09231PV
4位WPFでタスクトレイ常駐型アプリを作る2015/11/12195PV
5位非同期処理とAggregateException2014/10/15167PV

てな具合です。

ScrollViewerの記事はここのところずーっと首位です。これがヒットするとは思っていませんでしたが、実はそれなりに需要があった記事なんですかね。
2位のポケモンのソフトのRTCをいじる記事は、最近PVをどんどん上げています。たぶん、近いうちにScrollViewerの記事を抜くのではないかなと思います(週単位でランキングを作るとすでに抜かれています)。記事を書いた当時はまだ任天堂はGBAソフトの電池の交換をやってくれていましたが、今はもうそのサービスは終了したそうなので、復活させるなら否が応でも自分でどうにかしなきゃいけないという背景もあるのかもしれません。
プロキシの記事は、自分がネットにソフトを初めて公開した件にかかわる話ですので、PVを伸ばしてくれていることはとても嬉しいです。

てな具合で、今後もぼちぼち自分のペースでブログを書いていこうと思います。
今後ともよろしくお願いいたします。

2017年4月22日土曜日

Visual Studio 2017でXamarin.Forms入門

「申し訳ないがJavaはNG」

この言葉を座右の銘に置く私としては、常にAndroidアプリ開発は戦いです。
AndroidはJava開発が最も基本で、C#で開発するにはXamarinなどの環境が必要です。

Xamarinは昔は有料だったうえ、ドキュメンテーションも少なく非常にとっつきにくいものでした。しかし、Visual Studio 2015にはオプションでXamarinをインストールできるようになり、ついに2016年にはMicrosoftに買収され、Visual Studio 2017ではモバイル開発の中核に置かれるようになりました。

というわけで、私もXamarin初心者ですが、VS2017もインストールしたことだし本格的にいじってみようと思います。

Visual Studio 2017のインストール時にXamarin関係のオプションを選択してインストールすると、プロジェクトテンプレートにXamarin.Formsが現れます。
そうするとテンプレートの選択が出てきます。
空のアプリを選択してOKを押します。
そして、プロジェクトをビルドして実行すると…
見事にエミュレーター上でAndroidアプリが動きました。

しかし、このプロジェクトテンプレートには問題が1つあります。
上の画像にも書きましたが、最初のページに相当する「MainPage.xaml」がどのプロジェクトにも含まれていません。
そのため、Visual Studioがコードの依存関係等を理解できずに、IntelliSenseがほとんど働きません。編集しているとコードのいたるところに参照が解決できずに波線が引かれます。とても鬱陶しいです。

この解決には苦労しましたが、とりあえず次のようにやるとできるようです。

まずは、ソリューションにXamarin.Forms用のPCL(Portable Class Library)を追加します。
次は各プラットフォームのプロジェクトでこのプロジェクトへの参照を追加します。
さっき追加したプロジェクトに適当なMainPage.xamlを作ります。
このテンプレートには、XAMLだけでなくコードビハインドにも余計なコードが書いてあるので注意してください。コードビハインドで架空のViewModelクラス(ContentPageViewModel)をインスタンス化しようとしてくるのでコンパイルエラーが出ます。
public partial class App : Application
{
    public App ()
    {
        InitializeComponent();

        //MainPage = new XamarinFormsTest.MainPage();
        MainPage = new XamarinFormsTest.PCL.Views.MainPage();
    }

    protected override void OnStart ()
    {
        // Handle when your app starts
    }

    protected override void OnSleep ()
    {
        // Handle when your app sleeps
    }

    protected override void OnResume ()
    {
        // Handle when your app resumes
    }
}
最後はApp.xamlのコードビハインドでMainPageのインスタンスを自分が追加してやったPCLのほうへ書き換えてやればおkです。もとあったMainPage.xamlはいらないので削除してしまってもよいでしょう。
これでMainPageをPCL上に移動することに成功しました。

PCL上にUIを置けるということは、Nugetなどを活用して適当なライブラリを入れることもできるということですので、例えばXamarin.Formsに対応しているMVVMライブラリ「Prism」を入れてみましょう。
そうすれば、ほとんどWPFと変わらずにXAML+C#でAndroidアプリを開発することができます。
このアプリでは、スライダーを 動かすとそれに追従して上に表示されている数字が変わります。「ADJUST TO 50」ボタンを押すと数字とスライダーが50の位置に移動します。
XAML+C#のデータバインディングのデモをするにはこれくらいやれば十分でしょう。

例えばコントロールの配置が「HorizontalOptions」「VerticalOptions」とかいう名前のプロパティだったりと、若干WPFと違うところもありますが、まあこれくらいならフィーリングでわかるレベルでしょう。
あとはXAMLデザイナーでリアルタイムに配置の絵が表示される機能は内容ですが、この程度ならば個人的にはまあギリギリ許容できます。

これくらいWPFの開発にそっくりだと、普段からWPFで開発している身としてはとてもありがたいですね。

というわけで、いろいろといじってみようと思います。はい。

2017年4月18日火曜日

最強のWPF MVVMインフラ「Livet」をVS2017で使う

世の中的にはWindows開発と言えばUWPとかなのかもしれませんが、まだまだレガシーなWindowsデスクトップアプリが滅びる様子はありませんよね。
そのレガシーな中でも最も近代的なプラットフォームと言えばやはりWPFで、WPFでアプリケーションを作るのならばやはりLivetは欠かせません。

Livet - ProjectHome

しかし、LivetはVS2015対応としてリリースされたver.1.3を最後に更新されておりません。
作者自身もVS2015対応版がLivet 1.xの最終リリースとする旨の発言をしており、今後はLivet2を開発すると言っています。

ugaya40/Livet2 - GitHub

しかし、現時点でLivet2のLastest commitは2015年8月。Livetの最大の武器ともいえるプロジェクトテンプレート付きのインストーラはおろか、正式リリースさえされていない状態です。このような状況ではVS2017対応は絶望的です。

そうすると、何とかして自力でLivetをVS2017にインストールしなければなりません。

さて、VS2013とVS2015がリリースされた直後も、自力でLivetのプロジェクトテンプレートを組み込んでいた漢たちはいました。

最強のWPF MVVMインフラ「Livet」をVS2013で使う
最強のWPF MVVMインフラ「Livet」をVS2015で使う

Livet自体もこの時からほとんど進んでいませんし、こちらのページで紹介されているバッチファイルをちょっと改造すればいけるでしょう。

の前に、コードスニペットを改良しておきます。
本来、その改良はVS2015対応でやるべきでした。

VS2015と同時にリリースされたC#6でnameof演算子が導入されています。この、INotifyPropertyChangedインターフェースの実装に使ってくださいと言わんばかりの機能を通知プロパティのスニペットに使わない理由は無いでしょう。
ちなみに、.NET4.5からはCallerMemberName属性を使うことで自動的に呼び出し元のプロパティ名を引数としてメソッドに引き渡す機能があるので、通知プロパティの実装にそれを使う人も多いようです(Livetももちろんそれに対応しています)。しかし、「書いてもいないものが勝手に生成される」という気持ち悪さから私はこの言語機能を使いたくないので、nameofを使ったコードを書くことにしています。

というわけで、GitHubからダウンロードしたLivet-master\Installer\Files\Snippets内のLivetProperty_NET45_CSharp.snippetは削除して、LivetProperty_NET40_CSharp.snippetをnameof演算子に書き換えておきましょう(VBも必要があればやっておくといいと思います)。
<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2008/CodeSnippet">
  <CodeSnippet Format="1.0.0">
    <Header>
      <Title>Livet プロパティ</Title>
      <Shortcut>lprop</Shortcut>
      <Author>Livet Project</Author>
      <Description>プロパティを作成します</Description>
      <SnippetTypes>
        <SnippetType>Expansion</SnippetType>
      </SnippetTypes>
    </Header>
    <Snippet>
      <Imports>
        <Import>
          <Namespace>Livet</Namespace>
        </Import>
      </Imports>
      <Declarations>
        <Literal>
          <ID>type</ID>
          <ToolTip>プロパティの型</ToolTip>
          <Default>string</Default>
        </Literal>
        <Literal>
          <ID>name</ID>
          <ToolTip>プロパティ名</ToolTip>
          <Default>MyProperty</Default>
        </Literal>
      </Declarations>
      <Code Language="csharp">
<![CDATA[
#region $name$変更通知プロパティ
private $type$ _$name$;

public $type$ $name$
{
get
{ return _$name$; }
set
{ $end$
if(_$name$ == value)
return; 
_$name$ = value; 
RaisePropertyChanged(nameof($name$));
}
}
#endregion
]]>
      </Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>
最後に、上記のVS2015版のサイトのbatファイルの「2015」を「2017」に置換してから実行してやればOKです。
@echo off
cd %~d0%~p0

@echo on
echo copy snippets
xcopy /I /Y .\Files\Snippets\*_CSharp.* "%UserProfile%\Documents\Visual Studio 2017\Code Snippets\Visual C#\My Code Snippets\Livet"
xcopy /I /Y .\Files\Snippets\*_VB.* "%UserProfile%\Documents\Visual Studio 2017\Code Snippets\Visual Basic\My Code Snippets\Livet"

echo project templates
call :copy_project_template_csharp Livet_WPF4.0_CSharp
call :copy_project_template_csharp Livet_WPF4.5_CSharp

call :copy_project_template_vb Livet_WPF4.0_VB
call :copy_project_template_vb Livet_WPF4.5_VB

echo item templates
call :copy_item_template_csharp LivetInteractionMessageAction_CSharp
call :copy_item_template_csharp LivetMessage_CSharp
call :copy_item_template_csharp LivetModel_CSharp
call :copy_item_template_csharp LivetViewModel_CSharp
call :copy_item_template_csharp LivetWindow_CSharp

call :copy_item_template_vb LivetInteractionMessageAction_VB
call :copy_item_template_vb LivetMessage_VB
call :copy_item_template_vb LivetModel_VB
call :copy_item_template_vb LivetViewModel_VB
call :copy_item_template_vb LivetWindow_VB

echo simple install completed!!!
pause

:copy_project_template_csharp
xcopy /I /E /Y .\Files\Templates\%1 "%UserProfile%\Documents\Visual Studio 2017\Templates\ProjectTemplates\Visual C#\%1"
exit /b

:copy_project_template_vb
xcopy /I /E /Y .\Files\Templates\%1 "%UserProfile%\Documents\Visual Studio 2017\Templates\ProjectTemplates\Visual Basic\%1"
exit /b

:copy_item_template_csharp
xcopy /I /E /Y .\Files\Templates\%1 "%UserProfile%\Documents\Visual Studio 2017\Templates\ItemTemplates\Visual C#\%1"
exit /b

:copy_item_template_vb
xcopy /I /E /Y .\Files\Templates\%1 "%UserProfile%\Documents\Visual Studio 2017\Templates\ItemTemplates\Visual Basic\%1"
exit /b
これで見事VS2017に追加されました。めでたしめでたし。


2017年3月6日月曜日

aitendoのリチウムポリマー電池を使ってみる

お久しぶりです。

最近、ふと思い立ってリチウムポリマー電池を買ってみることにしました。
リチウムポリマー電池とは、 リチウムイオン電池の一種です。電池の電解質にポリマー高分子を使っているため、リチウムイオン電池に比べて比較的安全なようです。

リチウムイオン電池の最大の魅力と言えば、そのエネルギー密度です。ニッケル水素電池などと比べると、非常に小型軽量で高容量の電池が作れるため、最近のパソコン、スマートフォン等の持ち運び性が重要な電子機器の電池はたいていリチウムイオン電池ですよね。

しかし、リチウムイオン電池はそのエネルギー密度の大きさや電解液が可燃性などの理由から、ニッケル水素電池などに比べてかなり危険です。よく燃えます。最近ではSamsung Galaxy Note 7のバッテリー発火事故は記憶に新しいですし、そのちょっと前にはボーイング787のバッテリー発火事故なんていうのもありました。



特に過充電は非常に危険で、上記の動画のように勢いよく火を噴きます。

過充電による発火メカニズムなどの詳しいことは省きますが、このような事故を起こさないためには充放電をしっかり管理してあげる必要があります。

というわけで、世の中にはリチウムイオン電池の充電を管理するICというのも出回っています。それを使えば、下手に自分で回路を作ったりプログラムで制御するより安全にリチウムイオン電池が扱えるでしょう。

比較的入手性の良さそうなリチウムイオン電池(リチウムポリマー電池)と充電制御モジュールは、aitendoで売っています。
上に挙げたのは300mAhの電池ですが、aitendoでは3種類(110/300/850mAh)のリチウムポリマー電池を売っているようです。

ちなみに、実際に買ってみて驚いたのですが、この電池思っていた以上にコンパクトでした。すげえ。


さて、肝心の充電制御モジュール「CHR4056-MCU1A」ですが、aitendoのサイトには具体的なことが「TP4056使用」としか書いてなくて、「過電流出力保護チップ搭載」と言うもののその具体的な型番も書いていなければ、モジュールの回路図も使い方も書いていません。さすがaitendoクオリティとでも言うところでしょうか…。せっかくですので、買ってみて回路図を起こしてみました。



たぶんこんな感じです。コンデンサの容量はわかりませんが、容量が重要なコンデンサはあまりなさそうです。

TP4056の周辺はTP4056でググるとよく出てくる感じの回路です。電源5Vとバッテリー陽極の間に入って充電電流をコントロールしてくれます。データシートを見ると詳しく書いてありますが、電圧が低いうちは定電流制御をし、電池の電圧が4.2Vに達すると定電圧制御をしてくれるようです。
定電流制御をする電流はR3で決まります。最大1Aで、その時の抵抗値は1.2kΩになります。私はUSBを想定して400mAの3kΩに取り換えました。

さて、問題の過電流出力保護についての回路です。
これには2つのチップが使われていますが、DW01というICのほうがその頭脳になります。FS8205AはただのFETです。
ただのFETではあるのですが、2つFETが、しかもドレイン同士がつながっているへんてこな回路になっています。ここでポイントになってくるのがこのFETに存在する寄生ダイオードです。DW01がOC端子をHigh(>Vth)、OD端子をLow(<Vth)出力すると、上記回路図の左側のFETがONになり、右側のFETはOFFとなります。しかし、寄生ダイオードを経由して2,3番ピンから6,7番ピンへの電流ならばは流すことができます(逆方向は無理)。すなわち、充電する方向のみへの電流を流すことができる状態になっていると言えます。
逆にOCをLow、ODをHighとした場合は放電する方向のみに電流を流せまし、両方Highにすれば両方向へ電流が流せます。もちろん両方Lowにすれば両方向電流を止められますよね。なかなか面白い回路です。

OCのみHighになった場合の電流方向

充電や放電を止めたり許可したりする方法はわかりました。では、どうやって電流を検出しているのでしょうか。
ヒントはCS端子にありました。
FETにはON抵抗がありますから、両方のFETがONになっていると仮定すると、CS端子は放電時にはGND+2×R_on×Iの電圧がかかります。この電圧を測ることで過電流を検出しているようで、GNDとの電位差が150mV以上を10ms、または1.35mVを300usで電流を遮断するように作ってあるそうです。
データシートを見るとFS8205AのR_onは20mΩ程度なので、およそ3.75Aの電流で過電流検知をしてくれる、といったところでしょうか。

ついでに、このICはVCCを測ることで過充電と過放電も監視してくれているようです。4.25Vで過充電検知、2.40Vで過放電検知をするようです。
なかなかに賢いICですね。

ちなみにですが、R5とC2の回路はリプル除去(ローパスフィルター)が目的のようです。負荷変動などで電池の出力電圧が変わっても、DW01に与える電源電圧の変化をできるだけ抑えるようにするために付けていると解釈できます。


なかなか素晴らしいモジュールだということがわかりました。
リチウムイオン電池をいじってみたければ、とりあえず電池とセットでこのモジュールを買うとよいでしょう。

しかし、自分の回路に組み込もうとなると、モジュールをそのまま載せたのでは見栄えが悪くなりますよね。あと重要なことなのですが、このモジュールのOUT+、B+などの端子は2.54mmピッチではありません。ピンヘッダなどを付けてユニバーサル基板やブレッドボードに取り付けようと思ってた皆さん、残念でした。

そうすると、皆さんは自前でカッチョイイ充電モジュールを作ろうと考えますよね。大丈夫です、私もそう考えます。ですが、TP4056DW01はaitendoで見つかりますが、FS8205Aはなかなか扱っている場所は無さそうです。
そんなあなたに、代替としてBR8205というFETモジュールがaitendoで売っているのでオススメしておきます。FS8205Aと同じようにFETが縦に2つつながったもので、使用目的も同じく充電制御に使うためのもののようです。R_onはFS8205に比べたらほんの少しだけ高そうですが、まあ問題になるほどではないでしょう。ピン配置やパッケージが違うことにさえ注意すれば、十分に使えそうです。


最初説明した通り、リチウムイオン電池はその容量密度は非常に魅力的であるものの、扱いを誤ると発火などの危険があり、どうしても敷居が高い電池です。

今回は、aitendoの充電制御モジュールを解剖することによって、リチウムイオン電池の充放電管理の回路やICを学びました。これをうまく使いこなせば、より電子工作ライフが充実してきそうです。

2016年10月5日水曜日

ポケモンGOのポッポマラソンに必要なアメ数を計算する。

最近ブームが去りつつあるような気もするポケモンGOですが、私はいまだに楽しく遊んでいます。
しかし、トレーナーレベルが20以降になるとレベルアップに必要な経験値が非常に大きく、なかなか伸び悩んできました。


というわけで、ポケモンGOでトレーナーレベルを上げるには、効率の良い経験値稼ぎが必要です。そこで行われる方法がポッポマラソンなわけですね。
ポッポ、ビートル、キャタピーは比較的入手性がよく、また進化に必要なアメ数がとても少ないです。進化で得られる経験値は500EXPと非常に高く、また、その経験値を入手するタイミングもコントロールできるため、しあわせタマゴで経験値を倍増させている30分間に集中して進化させ、経験値を荒稼ぎするのがいわゆる「ポッポマラソン」なわけです。

しかし、しあわせタマゴは貴重なアイテムであるばかりか30分という制限時間まであり、なおかつ進化にはアニメーションが付きまとうため、最大限手際よく30分間ポケモンを進化させ続ける必要が出てきます。


アニメーションの時間はおおよそ25秒程度、操作をするのに必要な時間を加味して、30分間ではおおよそ60~70匹程度のポケモンを進化させられることができます。すなわち、70匹程度ポケモンが進化させられる状態にしたうえでポッポマラソンを開始させなければなりません。しかし、進化やポケモンを博士に送る(以下、『D進』と呼ぶこととする)ことでさらにアメを得られるため、それに必要なアメの数はそう簡単に暗算できるほどのものでもありません。もちろん進化させるのはポッポだけでないでしょうから、今、自分の手持ちの中で進化できるポケモンの数を管理するのは頭の中だけでできるようなものでもありません。

というわけで、ポッポマラソンに必要なアメ数を計算し、管理する必要が出てきます。

アメは、ポケモンを進化させることで1つ、ポケモンをD進させることで1つ手に入れることができます。すなわち、ポッポマラソン中にもどんどんアメが増えていくわけです。そのことを、Excelを使って管理してみましょう。


まず立式ですが、現在持っているアメの数を$c$、進化に必要なアメの数を$c_e$とします。進化させながらだと進化させた直後に1個アメが手に入りますから、実質進化に必要なアメの数は$c_e-1$個になります。というわけで、進化可能数$e$は
\[e=\left\lfloor\frac{c}{c_e-1}\right\rfloor\]
となります。$\lfloor\rfloor$は床関数ですね。与えた数字以下の最大の整数を返す関数です。


しかし、この式では不十分です。
例えば11個アメを持っていた場合、この式では進化可能数が1になってしまいます。そうです。「実質進化に必要なアメ数」と言いましたが、進化で得るアメは、その進化では使えないですね。 その分の項が入っていませんでした。
これはどう入れるかというと、「最後の進化で得るアメによる進化可能数の上昇」を差し引いてやればいいわけです。最後の進化で得るアメによる進化可能数の上昇というとややこしいかもしれませんが、すなわち$1/c_e$です。すなわち、完成した式は
\[e=\left\lfloor\frac{c}{c_e-1}-\frac{1}{c_e}\right\rfloor\]
と書くことができます。

ただ~し、この式にはまだ1つ問題があります。$c=0$のときに、$e$がマイナスになってしまうんですね。例えば$c_e=12$とすると$e=\lfloor-0.08333...\rfloor=-1$となるわけです。ですので、まあせこいですけど絶対値を取ってから床関数にでも与えれば大丈夫でしょう。床関数の中身が負になる場合はあっても、それが-1以下になることは無いですから。
\[e=\left\lfloor\left|\frac{c}{c_e-1}-\frac{1}{c_e}\right|\right\rfloor\]
ちなみに、Windowsの多くの処理系の小数型から整数型への変換やExcelのROUNDDOWN関数では0方向への丸めとなります。すなわち、正の数に対しては床関数になりますが、負の数に対しては天井関数となるわけです。なので、そのようなもので処理する場合は、このように絶対値をわざわざとる必要はありません。


さて、この式の何がいいかというと、進化直後にD進するときの式にも簡単に転用できるからです。
進化直後にそのポケモンをD進させた場合は、進化とD進で2個アメが手に入りますから、実質進化に必要なアメの数は$c_e-2$個になります。しかし、それでは進化やD進で発生したアメをそのポケモンの進化に使えてしまうことになるので、その分を差し引いておく必要があります。まあ、ついでに負の数になっちゃう問題も込々で式を立てると
\[e_{D進}=\left\lfloor\left|\frac{c}{c_e-2}-\frac{2}{c_e}\right|\right\rfloor\]
となりますね。


「進化させたり、それをD進させたりして、それで生まれるアメをまた再び進化に使う」という考えは手続き的で、このように1つの数式で進化可能数を求めることはできません。どちらかと言えばプログラムでループを回すようなイメージになってしまいます。
ですが、このような「実質的に進化に必要なアメ数」という考え方と、その考えで起こる問題に対する修正項を加えるという考え方で1つの式にすることができ、簡単にExcel等で計算できるようになりました。


あと少しで70匹になるぞ…。