工作と競馬2

電子工作、プログラミング、木工といった工作の記録記事、競馬に関する考察記事を掲載するブログ

ESP32-WROVER-B/E(モジュール単体)へのプログラム書き込み失敗に対処する

概要

ESP32-WROVER-B/Eへのプログラム書き込みがうまくいかなかったため、原因を見つけて対処した。



背景と目的

以前、ESP32-WROVER-Eの開発ボードを使ってカメラを動かすことができた。そこで、次はESP32-WROVERの単体を使ってカメラを動かす回路を作ろうとしていたのだが、いつも通りプログラム書き込み用のシリアル通信ラインを接続して書き込もうとしたところ、うまくいかなかった。そこで、原因を探り書き込めるように対処する。



詳細

1. 環境/使用アイテム


2. 状況整理

まず、書き込みに関与するEN端子、IO0端子については、ダウンロードモード(ESP-WROVERの仕様書でいうところのBooting Mode=Download Boot)に入れるように正しく配線されている。シリアルについては、今までESP-WROOM-32のモジュール単体でうまくいっていた方法と同様、USBシリアル変換アダプターの端子と直結している。

この状態で、書き込みを行おうとするとArduino IDE上では以下のような表示になって書き込みができない。つまり、シリアルがうまく通信できていないらしい。

esptool.py v3.0-dev
Serial port COM5
Connecting........_____....._____....._____....._____....._____....._____....._____

A fatal error occurred: Failed to connect to ESP32: Invalid head of packet (0x00)
A fatal error occurred: Failed to connect to ESP32: Invalid head of packet (0x00)


3. 対処方法(いきなり結論)

ESP32-WROVER-B/EのTXD0端子に3.3Vラインへのプルアップ抵抗1kΩをつける

ことで、書き込みがうまくいく。


4. 調査メモ

3.1 調査

  • ESP32-WROVER-E開発ボード
  • ESP-WROOM-32モジュール
  • ESP32-WROVER-B/Eモジュール単体

の間で、シリアル通信ライン上の信号に違いがないかオシロスコープで、TXD0、RXD0端子を観測した。(ESP32-WROVER-Eについても調べたが、Bと同様だったのでBのみ載せる)

  • 赤: TXD0端子
  • 青: RXD0端子
  • TXD0がLOWに落ちたところでキャプチャ(t=0)

3.2.1 ESP32-WROVER-E開発ボード

TXD0、RXD0とも通常3.3Vで、書き込み中に信号に応じてLOWに落ちる動き。

f:id:dekuo-03:20210418144945p:plain

3.2.2 ESP-WROOM-32モジュール単体

手持ちのESP-WROOM-32モジュール単体でも、ESP32-WROVER-E開発ボードと同様。(書き込んだプログラムが異なるので波形は違う)

f:id:dekuo-03:20210418144954p:plain

3.2.3 ESP32-WROVER-Bモジュール単体

TXD0の電圧が1.2V程度となっており、明らかに低い。(※トリガレベルより低くて引っかからないので波形が描けていない)ここで、

  • TXD0はUSBシリアル変換アダプターのRX端子を繋がなければ、HIGH。内部でプルアップされている様子。
  • TXD0の接続相手であるUSBシリアル変換アダプターのRX端子は、TXD0を繋がない状態ではLOW。

だから、TXD0がUSBシリアルのRX端子を引っ張り上げ切れていないようだ。

f:id:dekuo-03:20210418145728p:plain

3.2 TXD0を無理やりプルアップしてみる

TXD0と3.3Vとの間に、1kΩのプルアップ抵抗を入れてみたところ、完全にHIGHになり切れていないが、電圧は少し上がった。この状態で、書き込みをやってみたところ、うまくいった。また、書き込んだプログラムのシリアル出力は、ArduinoIDEのシリアルモニターで見ることができるので通信はできてはいる。つまり、抵抗の付加は効果があったといえる。 とはいうものの、RXのラインがHIGH/LOWでしっかり振れているとは全く言えない状態なので、この方法だと不安ではある。他に方法がないか、後々探ってみたい。

f:id:dekuo-03:20210418150151p:plain

なお、さらに低抵抗(200Ωくらい)を入れてはみたが、電圧としてはあまり変わらないので1kΩでよさそう。



まとめと今後の課題

ESP32-WROVER-B/E(モジュール単体)へのプログラム書き込み失敗に対処し、書き込みできるようになった。ただ、波形が開発ボードとは明らかに違うので、本当はもっと違うやり方があると思う。


Pythonのjsonschemaを試しに使う

Pythonのjsonschemaパッケージを使ってみた。


環境


インストール

pip install jsonschema


試用

汎用的に使える基底クラスを作ってみた。

import json
import jsonschema
import typing

class DefinedJson:

    _SCHEMA = {}

    def __init__(self):
        self._schema = self._SCHEMA

    @property
    def schema(self):
        return self._schema

    @schema.setter
    def schema(self, x: dict):
        self._schema = x

    def read_schema(self, filepath: str):
        """
        filepath: スキーマ定義ファイルパス
        """
        try:
            with open(filepath) as fo:
                self.schema = json.loads(fo)
            return True
        except:
            return False

    def validate(self, data: dict, on_invalid: (callable, typing.Any)=None):
        """
        Parameters
        --------------
        data: 検査対象
        on_invalid: 不正の場合のユーザー定義処理(func(message: str, args: any), args)
            message: エラーメッセージ
            args: ユーザー引数

        Returns
        --------------
        tf: boolean
            成否
        """
        try:
            jsonschema.validate(data, self._schema)
            return True
        except jsonschema.ValidationError as e:
            if on_invalid is not None:
                on_invalid[0](e.message, on_invalid[1])
            return False

スクリプト

サンプルのクラスを作成して、呼び出してみた。

class Sample(DefinedJson):

    _SCHEMA = {
        "required": [
            "name",
            "age"
        ],
        "type": "object",
        "properties": {
            "name": {
                "type": "string"
            },
            "age": {
                "type": "integer",
                "minimum": 0,
                "maximum": 100
                
            },
            "weight": {
                "type": "number",
                "minimum": 0
            },
            "height": {
                "type": "number",
                "minimum": 0
            },
            "country": {
                "type": "string",
                "enum": ["Japan", "America", "Others"]
            }
        }
    }

    def __init__(self):
        super().__init__()


if __name__ == "__main__":

    dj = Sample()

    data = {
        "name": "test",
        "age": 8,
        "weight": 6.7,
        "country": "China"
    }

    def on_invalid(msg, args):
        print("on_invalid", msg, args)

    print(dj.validate(data, (on_invalid, None)))

実行結果は以下。エラーを検出できている。

on_invalid 'China' is not one of ['Japan', 'America', 'Others'] None
False



まとめ

JSONスキーマの仕様を全部把握できていないが、とりあえずすぐに使う必要がありそうなものは試せた。


リモート水位センサシステム ver3(ソーラー発電対応)(2) --- ソーラーパネル部組み込みと動作確認 ---

概要

ソーラーパネルと充電回路、リチウムイオン電池をシステムに組み込み、動くことを確認した。



背景と目的

前回、ソーラーモジュールを防水施工したパネルを作成したので、今回はパネルをシステムに組み込む。



詳細

1. 構想

現行のリモート水位センサシステムに対して、

  • 乾電池を、リチウムイオン電池と充電回路に変更する
  • ソーラーモジュールの出力を充電回路に接続する
  • ソーラーモジュールは、本体を支持するフレームに取り付ける

としたい。

f:id:dekuo-03:20210404003129j:plain


2. フレームへの固定

2.1 固定金具の作成

固定にあたり、ホームセンターで売っていた金折れとアングルを使用して、以下のような金具を作成した。屋外で使用するので、耐食性を考慮してステンレス製にしたいが、高かったのでメッキ処理されたものを選んだ。

f:id:dekuo-03:20210404003456j:plain

2.2 固定

まず、フレーム上部の塩ビ管にネジ穴を空け、金具をタッピングネジで固定。

f:id:dekuo-03:20210404003429j:plain

ソーラーパネルをつけて完了。

f:id:dekuo-03:20210404003440j:plain


3. リチウムイオン電池と充電回路

3.1 充電回路の作成

以前作成したものと全く同じ材料を使って作る。

f:id:dekuo-03:20210411125527p:plain ※2021/04/11 間違いがあったので差し替えた

今回は、基板に電池も一緒に取り付けた。

f:id:dekuo-03:20210404002449j:plain

3.2 筐体への取り付け

現状は、電池ボックスが取り付けられている。

dekuo-03.hatenablog.jp

この電池ボックスを取り払って、作成した充電回路を取り付ける。これで、システムへの組み込みは完成。

f:id:dekuo-03:20210404002105j:plain


4. 動作テスト

ひとまず、充電できること、水位センサシステムが動作することを確認できた。田植えまで、約1か月あるので、屋外でしばらくテストを継続したいと思う。



まとめと今後の課題

リモート水位センサシステムのソーラー発電対応ができつつある。5月の現場導入に向けて、動作テストを進めたい。