S21HTのバッテリー状態の遷移を記録してみた
思うところがあって、S21HTのバッテリー状態の遷移を記録してみることに・・・。
とりあえずなんか記録用のツールがないかと思ったりして探しても何もなさそう。しょうがないので、バッテリーの残量を取得するプログラムを書いてみることにしました。
WindowsMobileって、Windowsと同じ手法でバッテリーの情報を取得できるんだろうか?
まあ、とりあえず同じじゃないかって仮定して取り組むことにします。
//Copyright (C) 2008 chameleon. //EMBlogger Ver.0.0.1 using System; using System.Linq; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.IO; //Call for Win32API using System.Runtime.InteropServices; namespace EMBlogger { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void logWriter(string status) { StreamWriter writer = new StreamWriter(@"\My Documents\BTLOG.txt", true); writer.WriteLine(status + ":" + "\t" + DateTime.Now.ToString()); writer.Close(); } // Win32APIの定数の定義 private const byte AC_LINE_OFFLINE = 0x00; private const byte AC_LINE_ONLINE = 0x01; private const byte AC_LINE_BACKUP_POWER = 0x02; private const byte AC_LINE_UNKNOWN = 0xFF; private const byte BATTERY_FLAG_HIGH = 0x01; private const byte BATTERY_FLAG_LOW = 0x02; private const byte BATTERY_FLAG_CRITICAL = 0x04; private const byte BATTERY_FLAG_CHARGING = 0x08; private const byte BATTERY_FLAG_NO_BATTERY = 0x80; private const byte BATTERY_FLAG_UNKNOWN = 0xFF; private const byte BATTERY_PERCENTAGE_UNKNOWN = 0xFF; private void showBatteryStatus() { byte ACLineStatus; byte BatteryFlag; byte BatteryLifePercent; uint BatteryLifeTime; win32API api = new win32API(); api.getBatteryStatus(); ACLineStatus = api.ACLineStatus; BatteryFlag = api.BatteryFlag; BatteryLifePercent = api.BatteryLifePercent; BatteryLifeTime = api.BatteryLifeTime; // ACLineStatus switch (ACLineStatus) { case AC_LINE_OFFLINE: textBox1.Text = "Battery"; break; case AC_LINE_ONLINE: textBox1.Text = "AC"; break; case AC_LINE_BACKUP_POWER: textBox1.Text = "BackUp"; break; case AC_LINE_UNKNOWN: textBox1.Text = "Unknown"; break; default: textBox1.Text = "Undefine"; break; } //BatteryFlag switch (BatteryFlag) { case BATTERY_FLAG_HIGH: textBox2.Text = "High"; break; case BATTERY_FLAG_LOW: textBox2.Text = "Low"; break; case BATTERY_FLAG_CRITICAL: textBox2.Text = "Critical"; break; case BATTERY_FLAG_CHARGING: textBox2.Text = "Charging"; break; case BATTERY_FLAG_NO_BATTERY: textBox2.Text = "no_battery"; break; case BATTERY_FLAG_UNKNOWN: textBox2.Text = "Unknown"; break; default: textBox2.Text = "Undefine 0x" + ACLineStatus.ToString("x2"); break; } textBox3.Text = BatteryLifePercent.ToString() + "%"; progressBar1.Value = BatteryLifePercent; logWriter(BatteryLifePercent.ToString() + "%"); } private void Form1_Load(object sender, EventArgs e) { showBatteryStatus(); } private void button1_Click_1(object sender, EventArgs e) { showBatteryStatus(); } private void timer1_Tick(object sender, EventArgs e) { showBatteryStatus(); } private void menuItem1_Click(object sender, EventArgs e) { Application.Exit(); } private void Form1_KeyDown(object sender, KeyEventArgs e) { if ((e.KeyCode == System.Windows.Forms.Keys.Up)) { // Up } if ((e.KeyCode == System.Windows.Forms.Keys.Down)) { // Down } if ((e.KeyCode == System.Windows.Forms.Keys.Left)) { // Left } if ((e.KeyCode == System.Windows.Forms.Keys.Right)) { // Right } if ((e.KeyCode == System.Windows.Forms.Keys.Enter)) { // Enter } } } [StructLayout(LayoutKind.Sequential)] struct _SYSTEM_POWER_STATUS_EX2 { public byte ACLineStatus; public byte BatteryFlag; public byte BatteryLifePercent; public byte Reserved1; public uint BatteryLifeTime; public uint BatteryFullLifeTime; public byte Reserved2; public byte BackupBatteryFlag; public byte BackupBatteryLifePercent; public byte Reserved3; public uint BackupBatteryLifeTime; public uint BackupBatteryFullLifeTime; public uint BatteryVoltage; public uint BatteryCurrent; public uint BatteryAverageCurrent; public uint BatteryAverageInterval; public uint BatterymAHourConsumed; public uint BatteryTemperature; public uint BackupBatteryVoltage; public byte BatteryChemistry; } class win32API { // Win32APIのDllの定義 [DllImport("COREDLL.dll")] private extern static void GetSystemPowerStatusEx2(out _SYSTEM_POWER_STATUS_EX2 pSystemPowerStatusEx2,uint dwLen, bool fUpdate); static _SYSTEM_POWER_STATUS_EX2 SystemPowerStatusEx2; public void getBatteryStatus() { uint sizeof_SystemPowerStatusEx2; // unsafe unsafe { sizeof_SystemPowerStatusEx2 = (uint)sizeof(_SYSTEM_POWER_STATUS_EX2); } // Call Win32API GetSystemPowerStatusEx2(out SystemPowerStatusEx2, sizeof_SystemPowerStatusEx2, true); } public byte ACLineStatus { get { return SystemPowerStatusEx2.ACLineStatus; } } public byte BatteryFlag { get { return SystemPowerStatusEx2.BatteryFlag; } } public byte BatteryLifePercent { get { return SystemPowerStatusEx2.BatteryLifePercent; } } //S21HTでは有効な値を取得できない public uint BatteryLifeTime { get { return SystemPowerStatusEx2.BatteryLifeTime; } } } }
時間節約のためC#で書いたので、.Net Compact FrameWorks 3.5が必須です・・・。
WindowsMobile特有の部分もあったり、Windowsと同じAPIでも取得できる情報が限られているみたいだったりしますが、とりあえずバッテリーの残量や状態は取得できました。
上記のコードをコンパイルしたものも一応アップしておきます。
エミュレータで動作確認し、ログファイルも仮想的に生成されていることを確認して実機で実験してみました。 WM5のX51とWM6のS21HTで動作確認しました。
端末を操作しながら取得したログファイルをエクセルでグラフ化してみました。グラフの最初の下り坂は、BluetoothでPCのモデムとして使っていました。その次のしばらく平坦なところは、端末がスリープ状態になっています。さらにその後の下り坂は、S21HT単体でYouTubuを視聴していました。ほとんど途切れることなくバッテリー不足で端末がシャットダウンするまで負荷を与えています。
その後は、MyBatteryPro ExpertのUSBポート経由で充電をしています。充電しながら明示的な操作は全くしていません。(まあ使用者が寝てたわけです。)
何故か途中で充電が進捗しなくなっています。その後、やや上昇しているあたりは、専用のACアダプタに切り替えてみたあたりです。ACアダプタからの充電なら劇的に充電状況が改善するかと思ったんですが大差ないです…。
もう翌日の朝になっているので、その後、端末の電源を完全に落として充電するとすぐに満充電となりました。どうも、ログをとる自作プログラムが一定間隔(10分)ごとにテキストファイルにバッテリー状況を記録するのですが、Timerイベントで処理しているせいか、端末が頻繁にスリープ状態から解除されることで充電に時間がかかるのかな・・・まあいいや・・・とにかく、S21HTのバッテリー状態が1%刻みで取得できることがわかりました。
今回の真の目的はログをとることではなく、バッテリー状態をプログラムでどうやって取得するかってことと、プログラミング上の課題を探ることだったのでおおむね目的達成。
課題としては、やっぱりタイマーイベントを用いて常にプログラムでバッテリーを監視するというのは端末にそれなりに負荷をかけることになりそうなのでこのあたりを考え直していけばよさそう。
確かWindowsMobileにはバッテリー状態の変化を通知する機能があったはず。これならOSが通知してくれるので、それをとらえて必要な処理をすればほとんど端末に負荷をかけることはないし。
今回の実験プログラムで必要なノウハウは得たので、これから、うっかりS21HTをバッテリー切れにしてしまうことを避ける、もうちょっと実用的なプログラムを書いてみることにします。
私のDiamondでは、このグラフの示す通り、充電がいつまでも終わらずに100%に達しないと言う現象が出ています。その後にリセットすると100%表示になります。表示切替のトリガーが来ていないような感じです。
下記に同様な現象に遭遇して、初期不良交換しても直らなかったと言う人がいます。
http://bbs.kakaku.com/bbs/31105001111/SortID=8485651/
この現象を解明していただけることを期待しています。
情報ありがとうございます。
この充電状況は故障なのかなぁ・・・リンク先の情報ではメーカーが初期不良対応しているってところから考えると、それが妥当なのかもしれませんねぇ。
もっとも交換しても状況は変わっていないので、ハードの特性とも考えられますし。
自分も何回か、翌朝になっても充電が終わってないってことがありました。そのときは、BTやWifi入れっぱなしだったからかなとか思ってました。完全にシャットダウンすれば速やかに充電完了になったのを記憶しています。
ちょっと条件をいろいろ変えて充電状況のログをとってみようかとか思ってます。
追加情報です。
その後、充電がいつまでも100%に達しないという不具合が発生しなくなりました。色々調べてみると、どうもG-Lightというバックライト自動調光ソフトを入れてから起きなくなったようです。このソフトが常駐したことで、表示切替のトリガーがかかるようになったような感じです。
[...] そんなわけで、ちょっと前に、バッテリの充電状況の遷移をログにしてグラフ化してみたのですが、途中でまったく充電が進捗していないことが明らかになりました。 また、同様の状況にあるという人からコメントをいただいたり、価格.COMのクチコミにも同様の状況で初期不良対応でTouchDiamondを交換してもらったが、状況が改善しなかったという書き込みを教えてもらったりして、どうやら何らかの原因で充電が完了しない状況があると判断しました。 [...]
カーク様、ありがとうございます。
あれこれやっているんですが、まだ、本件の原因については確証はありません・・・。
G-Light試してみます。