電池駆動のデータロガーを作ってみる(2) — RTC周りをmicroPythonで動作確認

部品一式揃ったので、まずはRTC周りの動作確認

パーツだけは載せてみた、配線はまだ終わってないけどRTC動作確認はできる状態

VScodeでのmicroPython使い方としては以下を参考

https://kousaku-prog.com/vscode-micropython/

・拡張機能(MicroPico:VScodeの拡張機能として最も一般的)をインスト、実際はインスト済みであった

・プロジェクト初期化(メニューから以下の画像の機能を選択)して、以下から持ってきたmicroPythonのサンプルプロジェクトを置いとく

% wget -P ~/pico https://files.waveshare.com/upload/5/5a/Pico-rtc-ds3231_code.zip

スクリーンショット 2025-09-12 17.06.15.png

・microPythonのファーム(2025.8.9版)をダウンロードしてきて、ディスクモードでラズピコに書き込むと接続状態になる(VScode下端のステータス表示)

スクリーンショット 2025-09-12 17.11.50.png

・VScodeのターミナルでrunをクリックすると実行される

スクリーンショット 2025-09-12 17.14.36.png

日時はPythonソースで設定されているだけ

・割り込み処理の受け側がないのでそれを追加、同時に割り込みが配線されてないからハードも修正(汚いけどR5相当をはんだブリッジした、これでGPIO3番につながる)

R5相当をジャンパーしたところ

jumper.jpg

コード(set_alarm_time())も元のコードでは割り込み待ち処理ないし、割り込み要因も適切じゃないので修正必要で、それは生成A.Iで修正、

#!/usr/bin/python
# -*- coding: utf-8 -*-
from machine import Pin, I2C
import time
import binascii

#    the first version use i2c1
#I2C_PORT = 1
#I2C_SDA = 6
#I2C_SCL = 7

#    the new version use i2c0,if it dont work,try to uncomment the line 14 and comment line 17
#    it should solder the R3 with 0R resistor if want to use alarm function,please refer to the Sch file on waveshare Pico-RTC-DS3231 wiki
#    https://www.waveshare.net/w/upload/0/08/Pico-RTC-DS3231_Sch.pdf
I2C_PORT = 0
I2C_SDA = 20
I2C_SCL = 21

ALARM_PIN = 3


class ds3231(object):
#            13:45:00 Mon 24 May 2021
#  the register value is the binary-coded decimal (BCD) format
#               sec min hour week day month year
    NowTime = b'\x00\x45\x13\x02\x24\x05\x21'
    w  = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
    address = 0x68
    start_reg = 0x00
    alarm1_reg = 0x07
    control_reg = 0x0e
    status_reg = 0x0f
    
    def __init__(self,i2c_port,i2c_scl,i2c_sda):
        self.bus = I2C(i2c_port,scl=Pin(i2c_scl),sda=Pin(i2c_sda))

    def set_time(self,new_time):
        hour = new_time[0] + new_time[1]
        minute = new_time[3] + new_time[4]
        second = new_time[6] + new_time[7]
        week = "0" + str(self.w.index(new_time.split(",",2)[1])+1)
        year = new_time.split(",",2)[2][2] + new_time.split(",",2)[2][3]
        month = new_time.split(",",2)[2][5] + new_time.split(",",2)[2][6]
        day = new_time.split(",",2)[2][8] + new_time.split(",",2)[2][9]
        now_time = binascii.unhexlify((second + " " + minute + " " + hour + " " + week + " " + day + " " + month + " " + year).replace(' ',''))
        #print(binascii.unhexlify((second + " " + minute + " " + hour + " " + week + " " + day + " " + month + " " + year).replace(' ','')))
        #print(self.NowTime)
        self.bus.writeto_mem(int(self.address),int(self.start_reg),now_time)
    
    def read_time(self):
        t = self.bus.readfrom_mem(int(self.address),int(self.start_reg),7)
        a = t[0]&0x7F  #second
        b = t[1]&0x7F  #minute
        c = t[2]&0x3F  #hour
        d = t[3]&0x07  #week
        e = t[4]&0x3F  #day
        f = t[5]&0x1F  #month
        print("20%x/%02x/%02x %02x:%02x:%02x %s" %(t[6],t[5],t[4],t[2],t[1],t[0],self.w[t[3]-1]))

    def set_alarm_time(self, alarm_time):
        self.alarm_pin = Pin(ALARM_PIN, Pin.IN, Pin.PULL_UP)
        self.alarm_pin.irq(lambda pin: print("alarm1 time is up"), Pin.IRQ_FALLING)

    # ステータスフラグクリア
        status = self.bus.readfrom_mem(self.address, self.status_reg, 1)
        self.bus.writeto_mem(self.address, self.status_reg, bytes([status[0] & 0xFE]))

    # コントロールレジスタ設定 (INTCN=1, A1IE=1)
        self.bus.writeto_mem(self.address, self.control_reg, b'\x07')

    # アラーム時刻設定
        hour = alarm_time[0] + alarm_time[1]
        minute = alarm_time[3] + alarm_time[4]
        second = alarm_time[6] + alarm_time[7]
        date = alarm_time.split(",", 2)[2][8] + alarm_time.split(",", 2)[2][9]
        now_time = binascii.unhexlify((second + minute + hour + date).replace(' ', ''))
        self.bus.writeto_mem(self.address, self.alarm1_reg, now_time)
        
if __name__ == '__main__':
    rtc = ds3231(I2C_PORT,I2C_SCL,I2C_SDA)
    rtc.set_time('17:18:00,Friday,2025-09-12')
    rtc.read_time()
    rtc.set_alarm_time('17:18:10,Friday,2025-09-12')
    
    try:
        while True:
            time.sleep(1)  
    except KeyboardInterrupt:
        print("terminated")

割り込み処理が実行できました、

 

<今の回路図>

前回から手直し、特にRTC周りをオプションの回路図から書き写し

 

microPythonではdeepsleepとかちゃんと動かないらしいので、microPythonはプロトタイピングで本番はpico-sdkになるかな

 

admin

電池駆動のデータロガーを作ってみる(1)

ラズピコで低消費電力、概ね電池駆動(単三3本)で数ヶ月稼働、のデータロガーを作ってみる

<考慮点>

① 消費電力の観点からはラジピコはWi-Fi無しの素のモデルで、なおかつ相対的に低消費電力になるラズピコ2を使う

電源はVSYSから供給(単三アルカリ電池3直)する、内部のDC-DCで1.8V~5.5V程度の電圧変動範囲が受付可能、ただしDC-DCの効率最適化のような考慮は必要そう

② Wi-Fiなどの通信は使わずにSDスロットのカードにログを取る、但し待機電力大きいから電源のオンオフは制御必要

シンプルにP-chのFETスイッチで電源をオン・オフする

③ 時計機能が必要だからRTC機能を外付けする

https://www.switch-science.com/products/7335?_pos=41&_sid=61626aafc&_ss=r

④ 開発環境はVScodeでmicroPythonを使う、簡便で速度も不要だし

microPythonのファームウェアは現時点で(v1.26.0)が最新

machine.deepsleep処理はは実質ハードリセットと同じだから、再開時は初期化処理が必要

https://docs.micropython.org/en/latest/library/machine.html

<回路図>

部品は発注した、

 

admin

 

Cursorを使ってみる

生成AIでコード補完を行えるツールはいくつかありますが、オールインワンになっているのがCursorだろうと思う

UIがVScodeそのままだからエディタそのものに慣れる必要もないから使う障壁が低い、さらにはプラグイン機能もVScode用のがそのまま使えるし

Cursorにはいくつかのライセンス方式ありますが、個人で使うならばHobbyでもそこそこ使えそうだからHobby版をインストしてみた、他にはPro/Businessがあります、ここでLLMにはGemini 2.5 Flashを選択しています、無料と引き換えの情報提供はビジネスじゃないから良いかな

無料のHobby版と有料のエントリーのPro版との差異は、

https://zenn.dev/umi_mori/books/ai-code-editor-cursor/viewer/price

を参照してください

最初の一歩はHello world!的なもので、新規ファイルを作成するとプロンプトが出てくるので「golangで簡単なwebサーバーのコード作成」、そのあとで「違うディレクトリでレスポンス変えて」といって作成されたコードは以下のコード

ただしGoのプロジェクトを作成したわけではないから、main.goが作成されただけ

次に既存のコード(ラズピコのpico-sdk + CMSIS dsp)を開いて、関数の解説をさせると、

コード全体のリファクタリングしてというと、

こんな感じ、

Hobby版での制限は、たまにコード書くならなんとか使えるかなというレベルですかね、仕事で使う人は間違いなくPro以上の選択になります

この領域の進歩は日進月歩だから、このレベルの機能はそれほど遠くなく無償化されるように落ちてくるように思う

 

admin

 

ソーラーバッテリーで車の鉛バッテリーを充電する

前回の記事から、部品を入手して工事完了までの手順

① 室内の温度測定

パワコンの動作温度保証範囲はMax 60℃なので、真夏の車の中の温度測定、もちろん直射日光の当たらない後部座席の足元

結果、気温の+10℃程度には収まりそうだ、パワコンでソーラーからの最大電力受けてバッテリー充電している時がワーストだろうけど、これは単純に温度測定しただけ

 

② パーツ

以下の部品以外にODB2コネクタはAmazonで購入

 

③ 設置場所

冬場も日光が当たる時間が長そうな場所に設置、ルーフキャリアにタイラップ止め

 

④ 接続

ODB2コネクタ経由でバッテリー直結します、コネクタからは電源しか出てなかったのでグランド線は追加、接続先はシャーシーグランドです当然

 

⑤ 車内への引き込み

バックドアのウエザーストリップの外側を一部クリップ留めで回して引き込み、雨漏りしたらその時に対策考える

 

⑥ 動作確認

全体つないで機能確認、ソーラーを太陽光受けるようにすると、パワコンの充電表示LEDが点滅(つまり充電中)

実は日陰になっても、そこそこ発電するようで充電LEDは点滅してました

真夏の太陽直下でのソーラー出力電圧(@パワコン入力)

@パワコンバッテリー出力電圧

 

運用の安定性は一年経過後の判断だね、

 

admin

 

車バッテリーのトリクル充電を考える

最近の車はバッテリー上がりを防ぐためにバッテリー端子を外すと言うのは余程の時で、なぜならECUの学習結果やナビの設定諸々が全て消えてしまうので、覚悟がないと簡単にカットオフできないので頻繁にやることではありません

乗らない時に常時100V電源から充電制御とかもありますが、設置(接続)の手間などを考えると現実的じゃない、ならば自然エネルギーでソーラーバッテリー(以下ソーラーと略記)を使った、充電制御というのがメンテフリーの解になりますが、方法は大きく二種類に大別できて、

    1. 省電力(5Watts以下)のソーラーをバッテリーに直結する
    メリットは制御簡単(逆流防止のダイオード入れるぐらい、大概のソーラーでは対応済みですが)、ただし夏場の太陽光強い時には過充電リスクはある
    2. それ以上の出力のソーラーとパワコンを使う
    メリットは① 過充電の完全防止でき、場合によってはバッテリーの充電にも使える、② 発電量に余裕あるので、日照時間短くても機能を発揮できる、デメリットは① パワコンの暗電流が小さいものを使わないと夜間などはバッテリーからの電力を消費する、目安は2mA程度でしょう、元々の車の暗電流は電装品の使用状況によりますが10mA以上はあるらしいから、② パワコンの動作温度保証範囲は概ね上限60℃ぐらいだから設置場所は直射日光の当たらない場所限定
    で検討の結果、方法2で行くことにしました

 

ソーラーは車の屋根にあるルーフキャリアに設置して車内に引き込み

    部品は手配したので、簡易に組み立てて思惑通り動作するかどうかを検証後に設置の手順
      admin

      qwen2.5から3.0,ついでにollamaからLMStudioに変更

      qwen3.0の方がモデルサイズが小さくとも性能は2.5の大きいモデルと同等との情報あったので3.0系を使ってみようと思ったけど、ollamaでそのまま使える3.0系のモデルがなかったから、LMStudioをインストしてみた

      デフォルトではOpenAIの大きめのモデルをロードするようになっているけど、それはSSD領域もったいないので削除

      メニュー右上のダウンロードボタンから、画像に示すメニューが開けるから、Open Downloads Directoryをクリックして不要なモデルを削除すれば良い

      今ダウンロードしたのは4Bと8Bモデル、

      4Bでもそこそこの対応力があって速度も速いから、こちらを標準で使ってみようと思う、uvはC言語で書かれてると言ってくるけどもね、それでも初期のLLMモデルに比べればかなり優秀ではある

      Roo codeからollmaは設定できるけど、LMStudioは見えない、起動はしているはずなのだけど起動してない状態だね

      ollamaを使うと、ClineもそうだけどLLMとして想定しているのはClaudeなので回答の出方はイマイチ、今の所の利用範囲でクラウドの利用料払うつもりは無いね

      P.S. 2025/8/20

      Qwen3-8Bだとuvについて正しく回答する、その後4Bに切り替えても同様だから、一見結果を共有しているように見える、ただし8Bだとメモリ管理(メモリ32GBでもコンテナも立ち上げてるから多分厳しい)でyellowマークが出てしまうけども

       

       

      admin

       

      A.Iアシストでコーディング

      最近はコード自体はほぼ生成A.Iで作成されることが多いと思うけど、ローカルでLLM動かして使えるかどうかやってみた

      ・参考サイト

      https://zenn.dev/mkj/articles/cf8536923d9cd7#discuss

      ・環境:M4 MacBook Pro 32GBメモリ、ollama、VScode + Cline

      ・モデルの選択(Alibabaのモデルが限定されらリソースではコーディング目的には一番向いているらしいから)

      % ollama pull qwen2.5-coder:7b-instruct

      コンソールから動かしてみた感じではなかなかいけてる感じ、Rustは知らないと言われるけどC言語、Python、Golangは扱える

      ・設定:ollamaを選択、

      ・動かしてみたとこ、

      ソースファイルが見つからないと言われるから設定が必要かもしれない

      ・リソース消費状況

      メモリもかなりキツいし、途中でファンも回り出すから、高負荷ではあるからAirでは32GBでもきついかもしれない

      ローカルLLMでどこまで使い物になるかやってみる

      P.S.

      結構タイムアウトするケースが多くて、いまいちollamaとの相性がよくなさそうに思える、コンソールからollama経由でモデル使う方が遥かに安定している

       

      admin

      uvめちゃ高速

      Pythonのパッケージ管理ツールですが、Rustで書かれているとのことで驚嘆するぐらい高速(10倍から100倍と言われてます)に動作、もはやpipやvenvは不要と言っても良いと思うよ

      導入については、

      https://note.com/daisukeminagawa/n/nd1e39a10873a

      にわかりやすく書かれているので、それに沿ってMacBook M4 Proでやってみた

      インストール
      % curl -LsSf https://astral.sh/uv/install.sh | sh
      
      パスを通す
      source $HOME/.local/bin/env
      
      確認(日付見ると、かなりアクティブぽい)
      % uv --version
      uv 0.8.9 (68c0bf8a2 2025-08-11)
      
      uv環境のプロジェクトディレクトリ作成して移動
      % mkdir uv_python
      
      .venvという名前の仮想環境を作成
       % uv venv
      Using CPython 3.13.3 interpreter at: /opt/homebrew/opt/python@3.13/bin/python3.13
      Creating virtual environment at: .venv
      Activate with:  % uv venv
      Using CPython 3.13.3 interpreter at: /opt/homebrew/opt/python@3.13/bin/python3.13
      Creating virtual environment at: .venv
      Activate with: source .venv/bin/activate
      
      環境のアクティベート
      % source .venv/bin/activate
      
      uv pipでパッケージインストール
      % uv pip install requests
      Resolved 5 packages in 892ms
      Prepared 5 packages in 38ms
      Installed 5 packages in 4ms
       + certifi==2025.8.3
       + charset-normalizer==3.4.3
       + idna==3.10
       + requests==2.32.4
       + urllib3==2.5.0
      
      ~~~全てのコマンドめちゃ早いよ、~~~
      
      Python実行(サンプルのGoogle.comにアクセスするだけのコード)
      % python test.py
      Hello from uv-powered project!
      Successfully fetched Google. Status code: 200
      
      仮想環境から抜ける
      % deactivate
      
      Activateしなくとも直接実行できるrunコマンドがある
      % uv run python test.py
      Hello from uv-powered project!
      Successfully fetched Google. Status code: 200

      condaPython以外のライブラリが必要なケースで使って、高速開発環境構築にはuvかな、ともかく高速でストレスなく実行できます

      コマンドの詳細は、

      https://zenn.dev/tabayashi/articles/52389e0d6c353a

      に詳しい

       

      admin

      玄関のスマートロックをタンデム運用にした

      玄関ドアが物理的に経たってきたので、リフォーム実施、交換するドアもスマートロック対応

      しかし生体認証が実質ないので、セサミをそのまま流用して並行運用することにした

      YKKとsesameでの結合度合いはサムターンキーンの状態だけなので、お互いのスマートロックシステムから見ると、手操作とほぼ変わらないので独立して動作可能できるということになります

       

      admin

       

       

      デジポテをi2cインターフェースからSPIに変更

      i2cのMCP4018はレスポンスはまともに帰ってきても機能しなかった(レスポンスは返るから実装の問題ではないと思う)から、DIP品のMCP4131に変えてみた

      MCP4131はデータ線が入出力共通なので、ドライバー側には抵抗入れてMCP4131が出力モードの時にレベルを確保できるようにしないといけない、その割には戻り値は使ってないですが

      三端子ともオープンなので、使い方の自由度はMCP4018に比べると高い、これだとちゃんと書き込み値に応じて抵抗値も変化(当たり前、それが普通)

      SPI版のデジポテ制御に変えたソースコードは、

      https://github.com/chateight/dsp/blob/main/dsp.c

      になります

       

      admin