見出し画像

単3ニッケル水素電池1本で動くESP32のSlimeVRトラッカーをつくったという「話」 -前編-

そう、つまりこれはニッケル水素電池1本で動くSlimeVRトラッカーの作り方を解説する記事ではない

そして今現在ESP32(wroom32)でこれをやるべきでないことがわかっている
1本で動かすにはあまりにも消費電流(電力)が多いので非推奨
やるならXiao ESP32C3あたりを使うべき
完成したら続編記事を書く

↓書いた


*ところで初めてnoteの記事書いてるけどChromeでh2,h3タグ使おうとするとページがクラッシュする 何故
(ぼくが入れてる拡張に問題があるかもしれないけれどめんどくさいのでEdgeで書いてる うんちだね)
あとなんかぼくのついったー埋め込まれない なんで?

まえがき

SlimeVRって知ってるか?

ESP8266やESP32とかのArduino互換機や、果てはjoy-conやらスマホで動くトラッカーのオープンソースソフトウェア&ハードウェアプロジェクトだ

しゅごい

ちなみにベーシックな作り方はおおよそSlimeVR Docsにすべて書いてある
Building from Scratch - SlimeVR Docs
ハードウェア構成の例やら配線図やら評価やら至れり尽くせりである

あと作るに当たってはSlimeVR Docsを基軸に、あとはこの辺の記事を参考にするといいとおもう


筆者の知識レベルとこの記事について

電気的知識:ほぼない

あるでゅうぃ~の?しってるぜ!マイコン?ってやつだろ!!!
え?ESP32…?なにそれ…多分なんか…超能力的な……やつだろ!?なっ!!
って感じ
V=RIくらいは知ってる、高校生+αならぬ-αくらいの知識レベル

プログラミング的知識:ほぼない

まずは はろ~わ~るどってやつをやるんだろ!?
forとかifでなんかやるんだろ!?
ってくらい
これならそこそこ書ける!みたいな言語は無い

なのでこの記事を鵜呑みにするのはよくないし、DIYというのはすべて自己責任ということを書いておく

つまりこの記事は「話」である というわけ
この記事は作り方 ではなくマイコンを触ったことも無い人間がどういうルートを辿ってオリジナルSlimeVRトラッカー完成に至ったかという日記的な おはなし である

でもがんばれば多分普通に作れるよ
そのうち君も トラッカーを手に入れる<トラッカーを作る になる
がんばって


だからニッケル水素電池1本+ESP32で作ろうと思った

SlimeVRの公式やらではリチウムイオンバッテリーを使った作例しか無い(上記で上げたさくらさんのブログにはリン酸鉄リチウムバッテリーを使った作例もあるが)

リチウムイオンバッテリーはご存知の通り、扱いを間違えば発火するし、廃棄処理もめんどくさい、長期間放っておくだけで妊娠する、でも使い勝手が良いとかいうヤンデレヒロインみたいなやつである

きらいじゃないけどぼくは怠惰な人間なのでへやの隅に放置したり寝てる間に充電したりしたいのであんまりリチウムイオンバッテリーは使いたくなかった

なのでとりあえずはニッケル水素電池2本くらいを使ったSlimeVRトラッカーを作ってみようと思ったわけ

でもさ、やってたらさ、動いちゃったんだ1本で
じゃあさ、作るしか無いじゃん

電気的知識が無いがゆえに1本ってのが割りと無謀であることを理解しないまま
1本でも動くじゃん!軽くてええやん!で作った
作ってる途中で知識のあるひとは「まず無理だろう」と思うことに気がついた

でもトラッカーとして完成させてる人も実用的なIoT機器を作ってる人も観測範囲では見たこと無い
大したことでなくても未踏領域というのは男の子の心をくすぐるだろ?
だからだ


なぜトラッカーを作るのかということ

読者に作りたいと思ってもらうためにSlimeVRでトラッカーを自作する意味について書く

安い!!!!!!!!!!
普通に作れば今できる最高のハードウェアで組んでも2万程度で5点ならいけると思う

意外と性能がいい(らしい)!!!!!!!!
Viveトラッカーとかの光学式でないIMU式のトラッカーにはドリフトするという運命にあるらしいが市販のIMU式トラッカーで使われているIMUと同じかそれ以上の性能が期待できるらしい(らしい)(スペック上は)(しらんけど)
あとSlimeVRのドリフト補正は結構強力らしい(らしい)
それなら作るしかないじゃん?

たのしい!!!!!!!!!
今はドキュメントや作例がかなり充実してるので作るたのしさというものに割りとフォーカスできる環境にあるとおもう


Day1-モジュールと部品探しの旅-

まずトラッカーを作るには以下が最低限必要らしい

  • マイコン(ESP8266 or ESP32)

  • トラッカーモジュール(IMU)

  • 電源5V or 3.3Vを供給するナニカ

    • 今回はニッケル水素電池を利用するので

      • 低電圧昇圧DCDCコンバータ

      • 電池

      • 電池ケース

はぇ~

上記を今回はとりあえず5個くらいずつ用意するとして設計を始めた

マイコン選定

いやESP8266やらESP32系モジュールって200種類あんねん!!!
になる ここが一番意味わからん状態になったかも
実際200種類以上ありそう

ちなみに今もわからん

ふ~~ん調べたところD1miniESP32?っていうマイコンがどうやら入手性もよく、wifiの技適も通ってるらし~~~
さいきょうじゃん!(何も理解してない)

この選択がのちにぼくの運命とトラッカーの設計に歪をもたらす

ちなみにリチウムイオンバッテリーで作るならなんの問題も無いと思う

使っている(いた)ESP32モジュール 403円!安いねぇ~~~
↓実際に買ったアリエクショップのリンク(別にここから買う必要性は無いよく調べて買うこと)

これの色:D1miniESP32ってやつ
色ってなんだよってなるし、なにがD1miniESP32なのかよくわからない
おそらくMH-ET LIVE MiniKitってやつのコピーモデルUSB-C版だと思う

↓いい感じのドキュメント↓

https://doc.riot-os.org/group__boards__esp32__mh-et-live-minikit.html
https://macsbug.wordpress.com/2017/07/10/esp32-minikit/


IMU選定

GY-BNO08Xってのが性能最強でいいらし~~~
安く作りたいならBMI160とかもあるらしい
詳しくはググって ぼくはよく知らない

↓GY-BNO08Xアリエクリンク


こんなん

今1,786円らしい、ほんのちょっぴりぼくが買ったときより安くなってる
でもモジュールとしては高いねぇ~
こんな親指よりちいせぇのが2000円でいいのかよ…と感じるかも

ちなみにBOSCH?CEVA?hillclrest?(もう意味わからん)のBNO080?BNO085?(は?)ってが載ってるらしい なんもわからんがまあ動くのでOK
BNO080_085_Datasheet-3196201.pdf (mouser.jp)


電源モジュール選定

一番の問題である
とりあえず今のところ最強そうなやつを使ってる

↓スヨヨヨヨヨベリーリナックスへのリンク、これまでと違ってちゃんとしたとこ
https://strawberry-linux.com/catalog/items?code=61201

https://strawberry-linux.com/catalog/items?code=61201

1枚990円!?こんな小指の先みたいな(ry

ちゃんとしたとこはちゃんとしたデータシートとか説明書があっていいね
↓マニュアルとデータシート

https://strawberry-linux.com/pub/tps61201-manual.pdf

https://strawberry-linux.com/pub/tps61200.pdf


電池

FDKのが安くていいんじゃない?中身ほぼエネループだし

↓アマゾンリンク(あふぃじゃない)

電池保ちは期待できないだろうなと思ってぼくはばかなので24本買った
ばかである

ちなみにイチケンさんの検証では東芝IMPLUSとかアマゾンベーシック(大)が実容量的にも値段的にもいいらしい(耐久性については未検証)
中国製に負けちゃだめだろ!!!頑張れFDK!潰れるな!

ちなみに出力電流(内部抵抗値)ではFDKはいい感じみたいなのでまあヨシ


電池ホルダー

逆電圧印加防止(ホルダーの+側が凹んでて導通しないやつ)のものがいいと思う
適当に買ったけどこれが意外といいと思う
凹んでててもほんとに導通しないかどうかは怪しいので逆電圧印加には気をつけよう 低電圧回路かつぼくはめんどくさがりなのでこれ以上の逆電圧対策をするつもりは無い

↓アリエクリンク

みえないけどちゃんと+は凹んでる(ほんとに導通しないかどうかはまた別問題だが)


Day2 -アリエクからはるばる届く部品を待つ-

届かない

春節直前で頼んだのが悪かったのか最初に選んだセラーからではトラッカーモジュールが届かなかった
上記で紹介したセラーからはちゃんと届いた(しかも爆速1週間で)

じゃあESP32モジュールと戯れよう①

幸いESP32モジュールは届いていた
だが、そもそもマイコンを触ったことがなかったのでマイコンの開発環境の立ち上げとLチカ(LEDをチカチカさせて実際にコードが動いたことを楽しむ変態の遊び、プログラミングで言うHelloWorldみたいなもん)をやった

じゃあとりあえずSlimeVRをインストールしよう
は???
って思うかもしれないけどこれが一番速いと思います
とりあえずで入れる理由はESP32とシリアル通信するためのドライバがSlimeVRインストール時に入るから

ちなみにインストールするときに注意が必要でUSBドライバなんてよくわからんから全部入れたれwと全部入れると競合するらしい
買ったモジュールの商品説明とかモジュールに載ってる通信ICの印刷をめっちゃ頑張って読んで正しいのを入れよう

めっちゃがんばったときの図、右上の正方形のがUSB通信ICでCH9102Fと書いてある


VS Codeとその拡張機能からPlatformIOを入れよう

VS Codeは普通に入れる
PlatformIOは左側の上から4番目の四角がスタックされてるみたいなアイコンから検索して入れる、下の画像だと①って更新かなんかの通知が来てるアイコン

これ

実際にLチカするコードを書こう
まずPIO Homeタブから+New Projectする
するとProject Wizardが立ち上がるのでBoardから自分の使っているモジュールを選ぶ
今回はMH-ET LIVE MiniKitのコピーモデル?のためMH-ET LIVE MiniKitにした

するとそのモジュールに最適化されるようになんかいろいろ勝手に設定してくれるらしい
プロジェクトのplatform.iniってやつを見るとおそらくなんかライブラリみたいなのがあってこのファイルで呼び出して定義してるんだろうな(あへ)みたいなのがわかる

; PlatformIO Project Configuration File
;
;   Build options: build flags, source filter
;   Upload options: custom upload port, speed and extra flags
;   Library options: dependencies, extra library storages
;   Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

[env:mhetesp32minikit]
platform = espressif32
board = mhetesp32minikit
framework = arduino

んでmain.cppを見るとこんな感じのが書いてある

#include <Arduino.h>

// put function declarations here:
int myFunction(int, int);

void setup() {
  // put your setup code here, to run once:
  int result = myFunction(2, 3);
}

void loop() {
  // put your main code here, to run repeatedly:
}

// put function definitions here:
int myFunction(int x, int y) {
  return x + y;
}

setup()とloop()があってまあUnityで言うStart()とUpdate()みたいなもんかぁ#includeはなんかライブラリみたいなのを宣言してて所謂おまじないってやつかぁとなんとなく雰囲気を理解する
なんとなく理解したら#include以下をコメントアウトとか消すとかする

んでESP32 Lチカとか検索する
ESP32でLチカ制御 - みるしるてくる (mirushirutechru.com)
するとサンプルコードが出る
はぁんsetup()の中で弄くるpinを定義してloop()の中でピンの制御をするわけね
が、LEDもブレッドボードもねぇじゃんとなる
おばか!このモジュールにはLED2つ載ってるんだから多分片方は制御できるだろ!
じゃあこれを光らせよう

LEDが何pinに繋がっているか調べる

GPIO2ということがわかる
書いてみる

#include <Arduino.h>

void setup() {
  pinMode(2, OUTPUT);
}

void loop() {
  digitalWrite(2, HIGH);
  delay(1000);
  digitalWrite(2, LOW);
  delay(1000);

  digitalWrite(2, HIGH);
  delay(500);
  digitalWrite(2, LOW);
  delay(500);
}

ビルドする

左側下の✔がビルド、→がアップロード(書き込み)

ドキドキしながらesp32モジュールをUSBに刺して→マークから書き込む

https://twitter.com/mmtg03/status/1761766405475848220?s=20

光る
うれしい


Day3 -届かない-

まだ届かない

じゃあもうプレ的に設計しちゃおう!

部品レイアウトをこねこね考える
おじさんなのでパワポで作っちゃう
自分で書いてちょっと悲しくなる

こねこねしてるときが一番たのしい

こんなんとか
こんなんとか

え?二本使ってんじゃん!しかも電源モジュールなんかよくわからんの使ってんじゃん!ってなるかもしれない
このころはまだ常識があったので二本で動かそうと考えてた
ちなみにこのころ使おうと思っていた電源モジュールはこれ

↓アリエクリンク

↓tps63020モジュールのスヨヨヨヨヨベリーリナックスで売ってるバージョン

https://strawberry-linux.com/catalog/items?code=12085

電池二本ならこれかな~と思っていた
2V時で1000mAくらい出せる
トラッカーモジュールと同じセラーで頼んだため、この電源モジュールは結局届いていないので実際には検証してない
多分いけると思う
たぶん

Day4 -まだまだトラッカーモジュールは届かない-

じゃあESP32モジュールと戯れよう②

ESP32はwifiを積んでいるのが特徴
ならwifiを使ったコードも書いてみよう
なにを書くかって?
L チ カ ❤

ESP32 wifi Lチカ とかでググるとSimpleWiFiServerというサンプルコードがあることがわかる
これを元にLEDピンを今回のボードに合わせて書き直す そんだけ

#include <Arduino.h>
#include <WiFi.h>

const char SSID[] = "じぶんのいえのwifiのSSID";
const char PASSWORD[] = "そのパスワード";

WiFiServer server(80);

void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
  

    delay(1000);

    // We start by connecting to a WiFi network

    Serial.println();
    Serial.println();
    Serial.print("Connecting to ");
    Serial.println(SSID);

    WiFi.begin(SSID, PASSWORD);

    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }

    Serial.println("");
    Serial.println("WiFi connected.");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
    
    server.begin();

}
 

int value = 0;

void loop(){
 WiFiClient client = server.available();   // listen for incoming clients

  if (client) {                             // if you get a client,
    Serial.println("New Client.");           // print a message out the serial port
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected()) {            // loop while the client's connected
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        Serial.write(c);                    // print it out the serial monitor
        if (c == '\n') {                    // if the byte is a newline character

          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println();

            // the content of the HTTP response follows the header:
            client.print("Click <a href=\"/H\">here</a> to turn the LED_BUILTIN on.<br>");
            client.print("Click <a href=\"/L\">here</a> to turn the LED_BUILTIN off.<br>");

            // The HTTP response ends with another blank line:
            client.println();
            // break out of the while loop:
            break;
          } else {    // if you got a newline, then clear currentLine:
            currentLine = "";
          }
        } else if (c != '\r') {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        }

        // Check to see if the client request was "GET /H" or "GET /L":
        if (currentLine.endsWith("GET /H")) {
          digitalWrite(LED_BUILTIN, HIGH);               // GET /H turns the LED on
        }
        if (currentLine.endsWith("GET /L")) {
          digitalWrite(LED_BUILTIN, LOW);                // GET /L turns the LED off
        }
      }
    }
    // close the connection:
    client.stop();
    Serial.println("Client Disconnected.");
  }
}

ちなみに調べたらオンボードのLEDのpinはLED_BUILTINという変数にエイリアスされてることがわかったのでそれに変えてる
そらただ2とか書いてあってもそのpinが何をするpinなのかわからんもんね
自分でコードを書く時はpinの値をわかりやすい変数に入れて使うといいんだなぁ~ということを理解する

http周りを眺めてよくわからんなぁと思いながらビルドと書き込みをする

https://x.com/mmtg03/status/1764974886982988010?s=20

動く はぇ~

Day5 -狂う-

トラッカーモジュールとDCDCコンバータモジュールが届かなすぎてついに狂う

ストロベリーリナックスで気になっていたDCDCコンバータモジュールを注文してしまう
Day1で書いたDCDCコンバータである

トラッカーモジュールが届かないイライラをぶつけるためにDCDCコンバータのデータシートを読む

https://strawberry-linux.com/pub/tps61200.pdf

つよそ~
2Vで900mAくらい出るしぃ~いろいろ機能ついてるぅ~
ん?1Vでも…300mAくらい出る…
ESP32のwifi使用時の消費電流をインターネッツでしらべてみよう

どうやらwifiの起動時に1A近くまでスパイクするらしい(デカすぎ)(ふざけるな)

しかし定常的な消費電流は最大200~300mA程度なので起動さえ乗り切れば動く可能性が示唆される…

どうやって乗り切るか、それはコンデンサを積むことで解決できる場合がある
コンデンサは電荷を貯めるのでDCDCが足りてない消費電流のスパイクをコンデンサが肩代わりするかんじ

いけるいけるいける!!!

力こそパワー

https://x.com/mmtg03/status/1765325834708254940?s=20


二度と逆らうな…

DCDCコンバータの出力側に6600uF(は???)を積むことでとりあえずwifiLチカの起動を確認出来た
やた~~~(あへ)
使ってるコンデンサ
UCM0J222MNL1GS Nichicon | コンデンサ | DigiKey
これが一番入手性最悪だし高すぎかも
別にパナとかケミコンとかでもいいと思う
EMZR6R3ARA222MJA0G Chemi-Con | コンデンサ | DigiKey
EEE-FT0J222AP Panasonic Electronic Components | Capacitors | DigiKey
高い
タンタルコンでもいいかもね
でもタンタルコンは故障モードがショートだからきをつけてね
つまり壊したら燃えるよ

急にIQを上げる

静電容量を減らしてみると4400uFで1Vくらいまで起動ができた
ちなみに2880uFでは1.2V時で起動できなくなった
上のデータシートのMAX OUTPUT CURRENTを見ると1V時で280mA程度吐き出せる
3.3V,4400uFで吐き出せる電荷の量は14,520uCだが、オシロスコープで電流を測定し任意の電流値を上回っている部分の積分値が何クーロンかを求めれば必要なコンデンサの容量が求められる…かな?

IQを上げたり下げたりする

いやぼくおしろもってないし
そも2880uFで1.2V時起動できないんだから測らなくても4400uFでよくね?

コンデンサの静電容量は構造上体積が小さいほど体積あたりの静電容量も小さくなる

実際に2200uFは10x10のサイズで得られるが680uFは6.5x7.7なので実装面積から考えて積むなら2200uF二個だろうということで今のところ4400uFが最適ということになる(なれ)

Day6 -流石にトラッカーモジュール届かなさすぎでは???-

セラーへの連絡と でぃすぱいと

アリエクは一定の期間発送されないと返金処理に移る
この期間は消費者側が伸ばすこともできる
前日くらいにセラーへ連絡した
伸ばすか?どうする?って
そうするとすぐ発送された
まあなんなんと思いながらまた待つことに

・・・一週間後、荷物がロストした

昔ってアリエクの返金処理って「紛争を開始する」(Open Dispute)って書いてあるボタンを押して始める感じだったけど今は「返金&返品」みたいなやつからやる
「紛争を開始する」が好きだったからちょっとかなしい
そういうわけででぃすぱいとした
一瞬で返金処理された やさしいせかい

別のセラーで注文しその間にpcb設計

おそらく単3ニッケル水素電池1本で動くだろうという実験結果が得られた(?)のでその構成でpcb設計に入った
pcb設計や注文と聞くと難しいし高そうと思うかもしれないけれど最近(?)ではかなり安い
5枚で5ドルとかだよ
JLCPCBってまにふぁくちゃーとeasy EDAってCADを組み合わせると簡単に注文できる
どちらも同じとこが運営してるので連携が強力
easy EDA
EasyEDA - Online PCB design & circuit simulator
JLC PCB
PCB Prototype & PCB Fabrication Manufacturer - JLCPCB
わかんね~~~うんちうんちうんちぃ!!!
っていいながらまずは回路図を書く
書こうと思ったらまずモジュールが無いやんってなるはず
libraryのuser contributedで探したり

ESP32 minikitとかで調べる(正しいとは限らないからちゃんと確かめること)

ピンアサインを調べて頑張って回路図記号とフットプリントを書く

回路図記号は要る分だけのピンにして


フットプリントも要る分だけにしちゃうとかもあり


とりあえずで作ったアートワークはこんな感じ


うんちアートワーク なにこれ

うんちなので参考にしないでね
DCDCはENでON/OFFしたほうがいいと思うしBNOはADDをGNDに繋がないとだめだよ

Day7 -ついにトラッカーモジュールが届く-

うおおおおおおおおおおおおおおおおおおおおおおおお!!!!!!!!!!!!!!!


どりゃぁあぁぁぁぁぁぁっぁ!!!

https://twitter.com/mmtg03/status/1766750360725753875?s=20

解説

まずSlimeVR-Tracker-ESPをVScodeにgitクローンしよう
VScodeを新しいウインドウで開いてclone git repositoryからhttps://github.com/SlimeVR/SlimeVR-Tracker-ESP.git
を入力して好きなとこにクローンする
githubのリンクはこれ↓

そしたら「うわぁなんかいっぱいでてきたなぁ」になるのでとりあえずplatforomio.iniを書き換えよう
ぼくは一番下のとこに以下をコピペしてる

[env:mhetesp32minikit]
platform = espressif32
board = mhetesp32minikit
framework = arduino
board_build.f_flash = 40000000L //省電力になるかなと思っての悪あがきなのでなくても良い

そしたらdefines.hを書き換えよう

#define IMU IMU_BNO085
#define SECOND_IMU IMU
#define BOARD BOARD_CUSTOM
#define IMU_ROTATION DEG_90
#define SECOND_IMU_ROTATION DEG_90

#define PRIMARY_IMU_OPTIONAL false
#define SECONDARY_IMU_OPTIONAL true

#define MAX_IMU_COUNT 1

#ifndef IMU_DESC_LIST
#define IMU_DESC_LIST \
    IMU_DESC_ENTRY(IMU,        PRIMARY_IMU_ADDRESS_ONE,   IMU_ROTATION,        PIN_IMU_SCL, PIN_IMU_SDA, PRIMARY_IMU_OPTIONAL,   PIN_IMU_INT) 

#endif


#define PIN_IMU_SCL 26
#define PIN_IMU_SDA 18
#define PIN_IMU_INT 19
#define PIN_IMU_INT_2 255
#define PIN_BATTERY_LEVEL 36

#define LED_INVERTED false
#define LED_PIN LED_BUILTIN

#define BATTERY_MONITOR BAT_EXTERNAL
#define BATTERY_SHIELD_RESISTANCE 0

//voltage x101
#define BATTERY_SHIELD_R1 1
#define BATTERY_SHIELD_R2 100

こんな感じで書いてみた
IMUは今回BNO085なので#define IMU IMU_BNO085
IMUの向きはこの時点では適当でいいんだけど#define IMU_ROTATION DEG_90にしといた
↓参照

https://docs.slimevr.dev/firmware/configuring-project.html


SCL,SDA,INTは好きなpinを指定すればいいと思う
PIN_BATTERY_LEVELについてはアナログ入力(ADC)があるpinじゃないとだめ

https://api.riot-os.org/group__boards__esp32__mh-et-live-minikit.html

silmeVRにはバッテリー残量を検知するためのシステムがついてる
1から書くのはまだだるかったので既存のシステムを使ってとりあえずのバッテリー検知を実装した

これ↑はこんな感じ↓で本来は実装されることになってるらしい

https://docs.slimevr.dev/diy/tracker-schematics.html

180kΩ抵抗を入れて電圧を下げてADCのpinに読ませるみたいな感じらしい
この構成の場合は値を180にするらしいが今回はニッケル水素電池を使っているので電圧が低く、下げる必要はないため0にしている
#define BATTERY_SHIELD_RESISTANCE 0
ついでに分圧して読ませる場合の変数も用意されてて↓みたいな感じでコメントが書いてある

// BAT_EXTERNAL definition override
// D1 Mini boards with ESP8266 have internal resistors. For these boards you only have to adjust BATTERY_SHIELD_RESISTANCE.
// For other boards you can now adjust the other resistor values.
// The diagram looks like this:
//   (Battery)--- [BATTERY_SHIELD_RESISTANCE] ---(INPUT_BOARD)---  [BATTERY_SHIELD_R2] ---(ESP32_INPUT)--- [BATTERY_SHIELD_R1] --- (GND)
// #define BATTERY_SHIELD_RESISTANCE 180 //130k BatteryShield, 180k SlimeVR or fill in external resistor value in kOhm
// #define BATTERY_SHIELD_R1 100 // Board voltage divider resistor Ain to GND in kOhm
// #define BATTERY_SHIELD_R2 220 // Board voltage divider resistor Ain to INPUT_BOARD in kOhm
デフォルトだとこんな感じで想定されてる

これ普通R1とR2逆では???ってなるがまあそれはいいとして
slimeVRトラッカーはLi-Poバッテリー前提で作られていてその終止電圧が3.2Vくらいだから電池残量0%のときに上のデフォルト設定で分圧した場合ADCに入力されるのは1Vみたいな感じ
つまり逆に言うと分圧抵抗値から元の電圧に戻すために抵抗値が定義されている
ほ~ん じゃあ適当にR1とR2の値を定義して挙動を見てみようか
#define BATTERY_SHIELD_R1 1
#define BATTERY_SHIELD_R2 100


じゃあbatterymonitor.cppを見てみようか
う~ん…voltage…ある!

voltage = ((float)analogReadMilliVolts(PIN_BATTERY_LEVEL)) / 1000 * ADCMultiplier;

なるほど?mV単位で読み取った電圧を/1000してVに戻してるね
ADCMultiplierってのはおそらく前述した分圧を元の電圧に戻すための係数だろうとわかる
じゃあADCMultiplierはどこで定義されてるのさってことでADCMultiplierを選んでF12
batterymonitor.hに飛ぶ

// Wemos D1 Mini has an internal Voltage Divider with R1=100K and R2=220K > this means, 3.3V analogRead input voltage results in 1023.0
// Wemos D1 Mini with Wemos Battery Shield v1.2.0 or higher: Battery Shield with J2 closed, has an additional 130K resistor. So the resulting Voltage Divider is R1=220K+100K=320K and R2=100K > this means, 4.5V analogRead input voltage results in 1023.0
// ESP32 Boards may have not the internal Voltage Divider. Also ESP32 has a 12bit ADC (0..4095). So R1 and R2 can be changed.
// Diagramm:
//   (Battery)--- [BATTERY_SHIELD_RESISTANCE] ---(INPUT_BOARD)---  [BATTERY_SHIELD_R2] ---(ESP_INPUT)--- [BATTERY_SHIELD_R1] --- (GND)
// SlimeVR Board can handle max 5V > so analogRead of 5.0V input will result in 1023.0
#define ADCMultiplier (BATTERY_SHIELD_R1 + BATTERY_SHIELD_R2 + BATTERY_SHIELD_RESISTANCE) / BATTERY_SHIELD_R1

けいさんしきわかった!
つまり今回R1=1,R2=100にしたからADCMultiplierは101/1、つまり101倍だ!

じゃあとりあえずvoltageの値をslimeVR Serverに送る前に1/101してやりゃあええ!
ど~こだ

networkConnection.sendBatteryLevel(voltage, level);

batterymonitor.cppのここ!じゃあ…

networkConnection.sendBatteryLevel(voltage/101, level);

よし(あへ)


おっけ~


いや、おっけ~じゃないんだよね

とりあえず電圧表示はできるようになったけれど%表示がこのままではずっと100%のまま
ダサいのでちゃんと表示するように書き換えよう
%表示は~…levelってので定義されてるね

                // Estimate battery level, 3.2V is 0%, 4.17V is 100% (1.0)
                if (voltage > 3.975f)
                    level = (voltage - 2.920f) * 0.8f;
                else if (voltage > 3.678f)
                    level = (voltage - 3.300f) * 1.25f;
                else if (voltage > 3.489f)
                    level = (voltage - 3.400f) * 1.7f;
                else if (voltage > 3.360f)
                    level = (voltage - 3.300f) * 0.8f;
                else
                    level = (voltage - 3.200f) * 0.3f;

                level = (level - 0.05f) / 0.95f; // Cut off the last 5% (3.36V)

                if (level > 1)
                    level = 1;
                else if (level < 0)
                    level = 0;

ほ~ん3.2Vで0%、4.17Vで100%になるようになってるんだねぇ~(やべ…よくわかんね…)

リチウムイオンバッテリーの放電曲線はこんな感じ

https://www.murata.com/-/media/webrenewal/products/batteries/cylindrical/datasheet/us18650vtc5-product-datasheet.ashx?la=ja-jp&cvid=20220207015420000000

おそらくいい感じに時間通りに%表示が減るように係数をつけて計算してる…のか?いや、よくわかんね…
わりと線形だから5パターンも場合分けしなくてよくねぇ?と思う
よくわからない なにもわからない
じゃあニッケル水素電池は?

https://docs.rs-online.com/1324/0900766b812ff4ca.pdf

ほ~ん これはエグい
DCDC後の3.3Vが300mA使うと仮定とすると1.2Vの電池からは825mA出ることになる
まあ1000mAの曲線を見ればいいかなってかんじかな
ざっくり分けて1.40V~1.27V,100~80%、1.27V~1.2V,80%~20%、1.2V~1.12V,20%~10%、1.12V~1V,10%~5%、1V~0.9V,5%~0%
みたいな感じにすればいいかな~

・・・

                if (voltage > 1.27f)
                    level = (voltage * 1.538f) - 1.154f;
                else if (voltage > 1.2f)
                    level = (voltage * 8.571f) - 10.086f;
                else if (voltage > 1.12f)
                    level = (voltage * 1.250f) - 1.300f;
                else if (voltage > 1.0f)
                    level = (voltage * 0.417f) - 0.367f;
                else
                    level = (voltage * 0.500f) - 0.450f;

                if (level > 1)
                    level = 1;
                else if (level < 0)
                    level = 0;
                networkConnection.sendBatteryLevel(voltage, level);

うるせ~~~~~~しらね~~~~~~~わかんね~~~~~~
😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭😭

学生のみんなはちゃんと数学がんばろうね
ぼくみたいなカスの汚っっっったねぇアルゴリズムを書く羽目になるぞ
っていうか元のやつってどうやって求めてるんすかね
わかんね
これは前述した放電特性曲線を線形に近似してるだけなのでおそらく1.27~1.20Vがセンシティブ過ぎて%表示がふらふらしそう キレそう

まあ…いいか…

さっき1/101したとこは直しておこう(networkConnection,~~~のとこ)
あとADCMultiplierは必要なくなったので消しておこう

                // voltage = ((float)analogReadMilliVolts(PIN_BATTERY_LEVEL)) / 1000 * ADCMultiplier; //Original
                voltage = ((float)analogReadMilliVolts(PIN_BATTERY_LEVEL) / 1000);


Day8 -pcbが届く-

特にない 実装するだけ

実装するだけ
アドヴァイスするとしたらフラックスは大事だよってことと鉛入りハンダのほうがぼくはすきだなぁってこと

Rev.1基板 かわいそう ちゃんと設計しようね

https://twitter.com/mmtg03/status/1769321291956597147?s=20

Q.どのくらいの時間動くの?

A. 静止状態で4時間くらい…ですねぇ…
あと6600uFあったほうが安定して低電圧(1.05V付近)でも動きそうですねぇ…

Day9 -Rev.2の設計-

Rev.1のうんち💩ポイントとその改善点

  • 電池の電流がスイッチを通る設計なのでスイッチの抵抗分もったいない

    • DCDCコンバーターにENピンがあるのでそれをスイッチする方式に変更

  • 蓋ほしい

    • 四隅に穴を開けて何も配線のないpcbを蓋にする

  • アートワークの配線細い

    • ベタっぽく塗ってみた

  • やっぱ6600uF要る

    • 泣きながら3つコンデンサを載せる方式に

  • 第2IMUをつなぐパットがデカすぎるし間隔が広すぎる

    • リボンケーブルをつなぐ用に変更

出来上がったものがこちらです

ちなみに真似して作らないほうがいいので今回はデータ非公開で画像だけにしときます
欲しかったらデータあげるけどこの構成はやめといたほうがいいとおもうよ
アイディアとかは好きにして

おもて
うら
ふた
かいろず
ボトムレイヤー非表示
トップレイヤー非表示
ふた

Day 10 -終わり-

は?
いやまあ申し訳ないけど終わりなんだよねこの話はこれで

完成してないじゃないかって?
そう怒らないでくれよ
まあこれを見てくれ

https://twitter.com/mmtg03/status/1770427088291647563?s=20

XiaoESP32C3っていうマイコンを買ってみたんだ
そしたらさ
コンデンサなしでも起動するんだよ
そんなんさ 消費電流が明らかに違いすぎてダメじゃん
Xiaoで作ったほうが良いじゃん電池保ちがさ…

次回

自作トラッカーって一生完成しないらしい

-Xiao ESP32C3編-へ続く…

この記事が気に入ったらサポートをしてみませんか?