akira.kei が 2025年03月06日10時09分47秒 に編集
コメント無し
本文の変更
[<前の記事](https://elchika.com/article/03ee4a80-3e5c-4a91-bb16-3281413cb85b/) : [次の記事>]() ## モバイルバッテリーを電子工作用電源にする モバイルバッテリーは安定した5V(USB-PDならもっと高い)を供給する大容量で優秀な電源なのだが、流れる電流が少ないと勝手にシャットダウンする。単体だとトリガーボタンを押したら30秒くらいで電源が切れてしまう。


だいたい50〜100mAくらい流しておけばシャットダウンしない(かも)とのことで、何秒かおきに100mAを一瞬だけ流して、モバイルバッテリーのシャットダウン機能を騙してやろうというのが今回の記事の概要だ。 ## 外付け回路を考える Nch MOSFETのゲートに100ms程度のパルスを与えて100mAを流す回路を以下に示す。ドレインに接続される150Ω抵抗が並列で3つ並んでいるので、合成抵抗は50Ωだ。5V負荷で50Ωなんだから100mAが流れる。0.1A@5Vだから合成抵抗には0.5Wが流れてしまう。手持ちはみんな1/4W=0.25Wなのでこれを超えられないから、150Ωを3並列にして抵抗一つ当たりに流れる電流は33mAに抑えた。これで0.17W程度が150Ω抵抗1つの瞬時消費電力である。  ## どうやるか PIC側が電流を消費すると勿体無いのでまずは源振はLFINT(31kHz)にしておく。これを512分周して約60HzをFoscとすると1命令に66msかかる。ポートを上げて下げるなら出力されるパルス幅はこれの1〜2倍だろう。 ループにはウォッチドッグタイマー(WDT)を使う。すなわち、時間が来たら強制的にリセットして最初からやり直すということだ。これによりプログラムは各種設定したらポートを上げ下げして無限ループでリセットを待つという形になる。 ## pragma_config オシレータは内臓のLFINT(31kHz)を使い、分周するのでNOSC/NDIVは書き込み可能(CSWEN=ON)にしておく。動いているかどうか分かりにくいだろうからCLKOUTも有効に、いつも無効にしているWDTは有効にしてBORも有効にしておく。パワーパワーアップタイマーを有効にするとリセット周期が想定より長くなり計算に合わなくなるため無効(PWRTE=OFF)にした。 ``` // CONFIG1 #pragma config FEXTOSC = OFF #pragma config RSTOSC = LFINT #pragma config CLKOUTEN = ON #pragma config CSWEN = ON #pragma config FCMEN = OFF // CONFIG2 #pragma config MCLRE = OFF #pragma config PWRTE = OFF #pragma config WDTE = ON #pragma config LPBOREN = ON #pragma config BOREN = ON #pragma config BORV = LOW #pragma config PPS1WAY = ON #pragma config STVREN = ON #pragma config DEBUG = OFF // CONFIG3 #pragma config WRT = OFF #pragma config LVP = OFF // CONFIG4 #pragma config CP = OFF #pragma config CPD = OFF ``` ## main.c 冒頭はいつも通りアナログ無効、ディジタルバッファ無効だ。delayを使おうとも思ったが意味なさそうなのでやめた(_XTAL_FREQ定義なし)。 ``` #include <xc.h> #include "pragma_config.h" void main(void) { ANSELA=0; TRISA=0xff; ``` オシレータ設定とPIC自体の消費電力低減のため各モジュールを無効化しておく。効果があるかどうかは確認していない。全体的なパルス周期はこのWDTPSで決まるが、この値だと4秒周期くらいなので2倍か4倍が妥当かも。 ``` // OSCCON1 = 0x49; WDTCONbits.WDTPS = 0b01100; PMD0=0xff; PMD1=0xff; PMD2=0xff; PMD3=0xff; PMD4=0xff; PMD5=0xff; ``` あとはゲートにパルスを送ってリセットを待てば良い。ラッチ操作の間に入れる_nop()でパルス幅を調整している。 ``` // TRISAbits.TRISA2=0; LATAbits.LATA2=1; _nop(); LATAbits.LATA2=0; while(1) {} } ``` ## 実際の動作は 上の設定では4s周期でパルスが出ていることが確認できる。バッテリー側の内部抵抗の影響で若干の電源電圧変動があるのが見える。オーディオ回路には使いにくそうだが、アナログのアンプなどは十分な電流が無音時にも流れるだろうからこの回路は不要だろう。ディジタルアンプは無音時には電流が流れにくいのでオートオフになるかも(それはそれでOKか?)。  パルス幅は約200msなので、nop()は抜いてもいいかもしれない。  ## 騙せないやつもいる ダイソーで買った公称10000mAhのやつは一晩動かしてもシャットダウンしなかったが、別の安いブランド不明の(!)バッテリーは約40秒くらいでシャットダウンした。このバッテリーは内部抵抗が大きいのか電圧低下も大きいので、これ以上の電流を流すのは憚られるため高頻度にすればいけるのか。実際にダイソーでも「nopはやめてパルス幅を半分にする」「頻度を半分の8secにする」を両方やるとシャットダウンしてしまう。まぁ中には容易に騙されないやつが居るということで。