前回少し話しましたように、古い電池で充電が不十分と思われる現象があり、その改善を検討していましたが、さらに大きな問題が埋もれており、検討し直す事態となりました。
条件を網羅してテストした積もりが、非常に御粗末な状況になっており、毎回申訳ありません。
以下は、前回に続く顛末の報告です。
9 残問題の処置
9.1 顕在問題の対処
いろいろな電池で実験を行ううちに、特に古い電池において、充電が終止電圧に達せず、すぐ終了してしまう現象が発生しました。
電圧の推移を調べると、充電開始後ほどなく、終止電圧 1.38V※ に達して充電終了し、終了後の電圧は、1.1V 程度しかありません。
この状況から、古い電池は内部抵抗が高く、充電電流による電圧降下(吸い込んでいるから、充電電圧は上昇)で、充電完了しないのに終止電圧に達していると考えました。
※ 実際は、この電圧も正確ではありませんでした(次項を参照)。
今回の終止電圧は、回路やプログラムの誤差を考慮して決めましたが、誤差を終止電圧に転嫁することは、本来適切ではありませんでした。
よって、誤差をもう少し追い込んで、終止電圧を本来の 1.4V まで引き上げることにします。
電圧検出に影響する要素として、以下が存在します。
回路面では・・・
・電圧検出用抵抗(R15 ・ R16)
・ADC の Vref( = AVcc)
プログラム面では・・・
・ADC分解能
・電圧の計算・比較
まず回路面において、マルチメータで実測して、誤差がどの位か確認します。
回路要素 | 規格値 | 実測値 | 誤差 |
R15 | 1kΩ | 998Ω | 0.2% |
R16 | 470Ω | 470Ω | 0% |
Vref(=AVcc) | 5.00V | 5.04V | 0.8% |
この実測値に合わせて、プログラムの定数値を修正します。
次にプログラム面ですが、ADCの分解能は、10ビット固定であり、変換誤差 eADC は、
eADC = (1 / 1024) × 100% = 0.1%
また、電圧の計算は、6.2.2項の通り、10ビットデータで計算していますので、
D(VBatt) = 1024 / 5V × 1.4V = 286.72
これを四捨五入して 287 と定数宣言すれば、誤差 eVbatt は、
eVbatt = 286.72 / 289 × 100% = 0.1%
プログラム面の変換誤差も追い込むに越したことはありませんが、これはADCが10ビットである限り避けられませんので、回路定数のみ反映し、終止電圧を1.4Vに修正してみます。
今度は、充電が終了しません・・・上記の誤差など論外となる問題が内在していました。
9.2 潜在問題の検討・対処
充電が終了した電池の温度がかなり高くなっています(手で触って、熱く感じる)。
当初は、これも電池の加齢が原因ではと考えましたが、比較のため、新しい電池を購入して充電したところ、1.38V で終了せず、1.47V 付近!まで充電が続く状況となりました(当然この電池も熱くなる)。
もはや電池の問題ではなく、電圧検出に重大な問題が存在するようです。
まず回路面は、前項で確認しましたので問題無い筈です。
次に、プログラム面を探って行きます。
ADCの分解能は、10ビット固定であり、以下が守られていれば、10ビット値が正しく読めています。
・ADMUXレジスタのADLARビットを操作せず、変換結果が左揃えになっていない。
・変換結果を、ADCWレジスタを使用して読んでいる。
上記は正しく設定されています。
また、変換結果の変換式は、D = 1024/Vref で計算されており、その誤差に前項計算値 0.1% を見込んでも、当然問題はありません。
続いて、検出電圧の計算を調べます。
電圧検出の計算箇所を抜粋してみます。
#define R_15 998 #define R_16 470 //(中略) uDataI = ADC_GetData(1); // get current(ADC1) uDataV = ADC_GetData(0); // get voltage(ADC0) uint16_t uDataB = (uint16_t)(1 + R_15 / R_16) * uDataV - UdataI;
R15・R16 を宣言して、6.2.2項の通り計算していますが、宣言が整数値のため、R15/R16 の計算も整数のままです。
本来なら、 R15 / R16 は 2.12 ですが、現状では少数点切捨てで 2 と計算されています。
誤差は6%に及びます。
原因は確定しましたので、少数点が正しく計算できるように、抵抗値が浮動少数点計算されるように、宣言と計算を以下の通り修正します。
#define R_15 998.0F #define R_16 470.0F //(中略) uint16_t uDataB = (uint16_t)(1.0F + R_15 / R_16) * uDataV - UdataI;
※ 998F などの表記では、AVR Studio ではコンパイルエラーとなりました。
この対策により、ようやく 1.4V で充電終了するようになりました。
9.3 お詫びと反省点
このような問題は、本来テストの初期で検出できて当然ですが、今回以下の理由で検出できませんでした。
・電圧の監視をアナログテスタの10Vレンジで行っていた。
・充電中に適切な観察をしていなかった。
電圧の検出に10mVオーダーの誤差が求められるので、精密な測定器を用いるのは当然のことで、また、データロガーなどを用いて、電圧及び時間の経過を正しく把握するのも当然のことですが、手持ちにアナログテスタしか無く、上記を怠っていたのです。
しかも、9.2項の問題を内包しながら、9.1項のように充電がすぐ終了する現象の発生は起こり得ず、実験過程に疑義すら生じています。
※ 実際に、9.1項の問題は、9.1項の時点に回路・プログラムを戻して実験しても、再現しません。
正確に、客観的かつ定量的な実験を行わなければ、品質を確保することはできません。
今後は、最低限の備えとしてマルチメータを用意し、以降の実験を行うものとし、データロガーは予算が付き次第導入することにします。
次回の予定
全く手つかずである、ケース加工や組み立てを行う予定です。