wingetってコマンド知ってました?。perlをインストールしてみます。
なんと、
windowsでLinuxみたいにパッケージ管理が出来るコマンドでっす。
びっくりしちゃいました。
ちなみに以下の写真はインドの女優のJennifer Wingetさんです。

関係ないですけど。この殺風景なブログに初登場の女性ですね。
geminiに聞いてみたら
「winget(Windows Package Manager)は、
2020年5月20日に開催されたMicrosoft Build 2020でプレビュー版が発表されました。
その後、2021年5月26日にバージョン1.0が正式リリースされました。」
by Gemini
という事ですね。
ここ10年ほどWindowsの開発から離れてたからね。
知らなかったよ。
ごめんね知らなくて。
そのまま起動してみると
winget
実行結果
使用できるコマンドは次のとおりです:
install 指定されたパッケージをインストール
show パッケージに関する情報を表示します
source パッケージのソースの管理
search アプリの基本情報を見つけて表示
list インストール済みパッケージを表示する
upgrade 利用可能なアップグレードの表示と実行
uninstall 指定されたパッケージをアンインストール
hash インストーラー ファイルをハッシュするヘルパー
validate マニフェスト ファイルを検証
settings 設定を開くか、管理者設定を設定する
features 試験的な機能の状態を表示
export インストールされているパッケージのリストをエクスポート
import ファイル中のすべてのパッケージをインストール
pin パッケージ ピンの管理
configure システムを適切な状態に構成します
download 指定されたパッケージからインストーラをダウンロードする
一通りyumとかaptとかrpmとかdpkgとかと同じ様なコマンドありますね。
という訳で、
知ってしまった以上は試さないと。そしてブログに足跡を残さないとね。
で、考えた結果、今のところインストールしていないWindowsにperlを
インストールしてみる。
perlのIDを検索
winget search perl
実行結果
ソースの検索中にエラーが発生しました;結果は含まれません: msstore
名前 ID バージョン 一致 ソース
---------------------------------------------------------------------------------------
Strawberry Perl StrawberryPerl.StrawberryPerl 5.42.0.1 Command: perl winget
MAMP & MAMP PRO MAMP.MAMP 5.0.5 Tag: perl winget
EditPlus ES-Computing.EditPlus 6.0.632.0 Tag: perl winget
XAMPP 8.2 ApacheFriends.Xampp.8.2 8.2.12-0 Tag: perl winget
XAMPP 8.1 ApacheFriends.Xampp.8.1 8.1.25-0 Tag: perl winget
Sharperlight 5.4 PhilightPtyLtd.Sharperlight 5.4.60 winget
Paperlib FutureScholars.Paperlib 3.1.10 winget
Microsoft Hyperlapse Pro Microsoft.HyperlapsePro 1.6.116 winget
PerlPrimer OwenMarshall.PerlPrimer 1.1.21 winget
Teambition Alibaba.Teambition 2.0.3 Tag: paperless winget
一番上のやつですね。
IDが「StrawberryPerl.StrawberryPerl」
インストール実施。
winget install StrawberryPerl.StrawberryPerl
実行結果
ソースの検索中に失敗しました: msstore
コマンドの実行中に予期しないエラーが発生しました:
0x8a15005e : The server certificate did not match any of the expected values.
作業ソースの中以下のパッケージが見つかりました。
続行するには、'--source' オプションを使用していずれかのパッケージを指定してください。
名前 ID ソース
----------------------------------------------------
Strawberry Perl StrawberryPerl.StrawberryPerl winget
うーん。msstoreしか検索しないっぽいですね。
一番右に出ているwingetの所が--sourceで指定する部分か?
ここらへんの指定が判りにくすぎてやばい。
もう一回。sourceにwingetを指定して実行
※途中 いつもインストール中に出るUAC制御の画面になってたりするので注意!!
winget install StrawberryPerl.StrawberryPerl --source=winget
実行結果
見つかりました Strawberry Perl [StrawberryPerl.StrawberryPerl] バージョン 5.42.0.1
このアプリケーションは所有者からライセンス供与されます。
Microsoft はサードパーティのパッケージに対して責任を負わず、ライセンスも付与しません。
ダウンロード中 https://github.com/StrawberryPerl/Perl-Dist-Strawberry/releases/download/SP_54201_6 4bit/strawberry-perl-5.42.0.1-64bit.msi
██████████████████████████████ 198 MB / 198 MB
インストーラーハッシュが正常に検証されました
パッケージのインストールを開始しています...
インストールが完了しました
インストールできたっぽい。
実行
perl
実行結果
'perl' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
うーん、どこにインストールしたん?
いろいろ探して・・・途中で、ひらめいて
cmdプロンプトもう一個起動して
実行
perl
実行結果に何も表示されず。何も起きてないように見えるが、
コマンドに入って何も出てない状態になるので、
ctrl+Cで抜ける。
どうやら
インストールしてたcmdプロンプトはpathの設定が自動では入らないですね。
ま、そういうもんか?
インストール自体は成功してました。
バージョン表示
perl -v
実行結果
This is perl 5, version 42, subversion 0 (v5.42.0) built for MSWin32-x64-multi-thread
Copyright 1987-2025, Larry Wall
略
プログラムを書いて
print "Hello, miha!¥n";
hello.plで保存
perlで実行
perl hello.pl
実行結果
Hello, miha!
成功成功
perlでメール送信 sendmail
センサーシステムが停止している場合に
メールで知らせてくれると良いよなーと思っておりましたが、
なかなか腰が重くて今までなんにもしていなかったんですけど。
止まったまま1週間とかデータが上がってこないまま気づかない
なーんて事が発生したりして。
流石に対策することにしました。
データベースを検索して最終更新時刻が1時間以上経過したら
次のバッチ処理でメールを送る事にしました。
言語はperl。
まず
DBには更新日付が入っていて、
文字列の12桁で年月日時分秒が記録されています。
形式は
YYYYMMDDhhmmで、YYYYが年、MMが月、DDが日、hhが時、mmが分
これに合わせて60分前の文字列を作成
#現在時刻から各種変数を作り出す、時間単位、日付単位、最終更新時刻
my ($sec, $min, $hour, $mday, $mon, $year) = (localtime(time-(60*60)))[0..5]; #60分前
my $last_update=sprintf("%d%02d%02d%02d%02d", $year + 1900, $mon + 1, $mday, $hour, $min);
DB検索は
select sensor_id, sensor_name, last_update, batch_flag
from sensor
where last_update < '$last_update' and batch_flag=1 order by display_order;
最終更新時刻が60分より前でしかも、batch_flagが1。
ちなみにbatch_flagは処理する場合は1処理しない場合は0を入れておいて、
そもそも、センサーが接続されていない場合は0を入れておけばOK。
でないと毎回止まってますよーってメールが来ちゃうので。嘘つき狼みたいになってしまうのでめんどい。
そしてメール送信します。
今回はメール送信に的を絞って以下になります。
sendmailにパイプでつなげて、
open(MAIL, "| $sendmail -t ")
次々と必要な文字列を送信
print MAIL "X-Mailer: x-mail V1.00¥n";
print MAIL "Errors-To: $mailfrom¥n";
print MAIL "Return-Path: $mailfrom¥n";
print MAIL "From:$mailfrom¥n";
print MAIL "To: $mailto¥n";
print MAIL "Subject:$subject¥n";
print MAIL $message;
そしてパイプクローズ
close(MAIL);
半角の英数字送る場合は上記でOKなんですけどね。
日本語を送りたい場合はJISに変換して送らないといけません。
メールタイトルは
$subject=Encode::encode('MIME-Header-ISO_2022_JP', $subject);
メール本文は
$message=Encode::encode('iso-2022-jp', $message);
詳しくはソース参照。
https://drive.google.com/file/d/1glL2HAaCKFOGp20MMY4g31Z1JHouaOBN/view?usp=sharing
そしてそして、大問題
自分の環境が古いせいなんですけど。
老舗のsakuraのレンタルサーバなんですが、
perlがv5.14.4でmysqlが5.7なんです。
ちなみに最新はPerl5.43.0、mysql8.4ですね。
sakuraさんが悪いわけじゃなくて、自分が古いまま使いたいってだけです。
たぶん、そのせいで
日本語が素直に扱えない問題が発生してしまいました。
事象としては
SELECT で取得してきた日本語。
そのままprintしてあげる分には、表示されるし、
htmlとして出力しても大丈夫なんですけど。
他の文字と合体
$GATTAI = "停止中".$row[1]
とすると、文字化けになります。
色々ヤッてみて駄目だったので調べると。
https://adiary.adiary.jp/0367
何やら、UTF8フラグなるものがあり。普通のUTF8とは扱いが異なる模様です。
結局、自分専用機能なので、日本語じゃなくても良くて、
センサーのIDが判れば良いってことにして今回妥協しました。
sakuraさんからも、新しいサーバーに移行しても良いんですよー
って無料の案内が来てますので、こういう事がたくさん起きるようであれば
移行したほうが良いかもしれません。
ESP32のWROVERピッチ変換基盤
こちら
https://akizukidenshi.com/catalog/g/g116186/
前に買ったときはWROVER-Bが
https://akizukidenshi.com/catalog/g/g113689/
既にはんだ付けしてある版だったんですが、
今は基盤だけ売ってるみたいですね。
それはそれで、
16MのWROVERを使いたい人もいると思うので、良いと思います。
以下は写真です。

基盤の裏にはピンのラベルが書いてあるんですけど
表から見ると何だかわかんない状態になるので。
ピンがわかるように裏から取った写真を左右に貼り付けたものです。
この写真をみながらいつも作業します。
回路です。

上手く行く時は上手く行く。
上手く行かない時は全然うまく行かない。
ちょっと触ると、
「Brownout detector was triggered」とか
出てしまうんです。今回は大丈夫なカナー
ブレッドボードで組んでるので接触が悪いせいだなー。
今回はうまく行った。
もしかしたら手持ちのコンデンサーが
容量抜けしているやつが結構有るのかもしれない。
今回はなんというか、何度も作っている回路だけど、
ちゃんと回路図にしていなかったので記憶の継承的なメモでした。
スーパーキャパシタ 電気二重層コンデンサ
今回試験したのは5F/5.4V
https://akizukidenshi.com/catalog/g/g104247/
・静電容量:5F
・定格電圧:5.4V
・等価直列抵抗(ESR):200mΩ
・サイクル数:500000cycle

5.0Vに充電します。
充電時は急速ですね。
2A以上を目視確認。
後半は数十mAまで落ちます。
10秒~20秒ぐらい充電。
これの放電をEmoWat'sで様子を見ていきます。
https://miha.jugem.cc/?eid=388
放電。
5.0V最初
消費側にLEDを接続すると、11mA消費します。
4.0Vまで放電。
12分経過、7.7mA 電圧が減った分電流も減ります。
累積 1.8mAh 8.0mWh
3.0Vまで放電。
31分経過、3.8mA
累積 3.7mAh 14.6mWh
2.0Vまで放電。
94分経過、0.3mA
累積 5.3mAh 18.8mWh
その後1.91Vで0mAを記録。132分経過(94分から132分迄の間は見てない。ランチタイム)
LEDの動作電圧に達しなくなって電流ゼロって状態ですね。
その時点で累積ワット数が18.8mWhだったので、
ほとんど流れてないですね。
5F(5ファラド)のやつでこんな感じですね。
計算の時間
5.3mAh 18.8mWh
仮にRTC-8564NBのバックアップ用に使う場合、
消費電流が330nAですから、
=5.3mA ÷ 0.33μA
=5.3mA / 0.00033mA
=16060時間
=669日
ですね。
電源逆接続での保護回路2 リセッタブルヒューズ版
前に電源の逆接続の回路を試験してみました。
電源逆接続での保護回路
https://miha.jugem.cc/?eid=408
ヒューズが切れて最終的に回路を守ったんですが、
今回はリセッタブルヒューズを使ってやってみました。
リセッタブルヒューズの場合は逆接続を解消すれば、
元に戻ってまた接続状態に戻るので、
何度でも試験できます。
課題が残ってました。
うちの安定化電源は10Aしか出せないので、
そこまでの試験としていました。
10Aよりもっと上の電流の試験が出来ていませんでした。
今回はリン酸鉄の12V10AHバッテリーを使って試験していきます。
バッテリーの最大パワーの電流が流れますからね。
10Aどころではありません。
回路

使用したパーツ
ダイオード SBM1045VSS
https://akizukidenshi.com/catalog/g/g106168/
・DC耐圧:45V
・ピーク耐圧:45V
・平均順電流:10A
・ピーク順電流:200A
・順電圧:0.44V
200Aまで流れても一瞬なら大丈夫
リセッタブルヒューズ MF-RX065
・定格電圧:72V
・定格電流:0.65A
・トリップ電流:1.3A
・遮断電流:40A
1.3A以上流れると、抵抗値が増大して電流を制限してくれる。
逆接続時の動きについて。
逆電圧がかかると、
ダイオードに無限に電流が流れ始めて、
その後ろの回路には電気行きません。
ただし、ダイオードの順方向電圧0.44Vあるので、
0.44Vは後ろの3端子レギュレーターに逆電圧がかかる。
それで壊れるようであればアウト。
ダイオードは一瞬であれば200Aまで耐えられます。
その一瞬はデータシートによると
https://akizukidenshi.com/goodsaffix/sbm1045vss.pdf
「Peak Forward Surge Current : 8.3ms Single Half Sine-Wave
Superimposed On Rated Load (JEDEC method)」
翻訳
ピーク順方向サージ電流:8.3ms 単発半正弦波
定格負荷に重畳(JEDEC方式)
8ミリ秒未満なら200Aまで大丈夫と解釈。
その一瞬の間にリセッタブルヒューズが電流遮断してくれればOKなんですね。
リセッタブルヒューズのデータシートによると
https://akizukidenshi.com/goodsaffix/mfrx72.pdf

青マークした所
1.3Aでリセッタブルヒューズが反応した場合20秒ぐらいでトリップします。
1.3Aなら、このダイオードはビクともしません。
逆接続しない場合はダイオードには電流は流れずに、
3端子レギュレーター側に流れて
通常動作を行います1.3Aを超えることが無いように
設計する必要があります。
オレンジマークした所
もっと電流が入ってきた場合(逆接続した場合)、
グラフの存在する所の最大の40Aで見ると、
3ミリ秒でトリップします。
上記ダイオードの限界は8ミリ秒未満で問題ありません。
40A以上は、リセッタブルヒューズの遮断電流が40Aなので、電気が切れます。
バッテリの性能の最大値がどのぐらいか?わからないんですけど、
理論上は電線の抵抗が0Ωで無限に電流が流れます。
そして、リセッタブルヒューズが1.3A以上は制限がかかって
抵抗が上がって100mAぐらいしか流れなくなります。
現実の回路では電線とか、コネクタ等も0.1Ω~0.2Ωぐらい抵抗があります。
リセッタブルヒューズも通常時0.27Ωですので、
抵抗が0Ωという事はなく、
0.1+0.1+0.27=0.4Ωぐらいですね。計算すると12Vなら30Aが最大になります。
バッテリ内部の抵抗もありますしね。
実際、トリップ中のダイオードの準電圧を測定すると0.22Vでした。
トリップまでどの様に変化するのか見たいんですが、やはりうちの機材では無理ですね。
今回はココまでです。
バッテリーで試験できたし、
ヒューズを使わない方式に出来たので自分的には満足です。
3端子レギュレーターの比較2
良いのを見つけました。
https://akizukidenshi.com/catalog/g/g100432/

これの良い点は電圧降下が少ない点です。
安定化電源からNJU7223F33の入力に3.2Vを加えて
ESP32に電力を供給。
micropython起動、
センサーからのデータ取得
ファイルの読み書き
WIFIのAPモードでWEBサービスを開く
ルーターへのWIFI接続
サーバーへのセータ送信
を試したところ問題なく動作。この時NJU7223F33の出力は3.2Vを測定。
電圧降下ほぼ無いね。
なので、電池駆動の場合に最後までちゃんと動く事が期待できます。
3端子レギュレーターの比較
https://miha.jugem.cc/?eid=412
の続きの記事になります。
前回の記事では
6μAの世界では全体的に成績が悪い。
という結果と、
6μの世界ではBP5293-xxが一番効率がいいと言いました。
それと、
150mAではM78ARxxシリーズが抜群に良かった。
バランスは
BP5293-xxが良いかなーって感じでまとめましたが、
良いの見つけましたよ。
従来の3端子レギュレーターも6μ勝負だったら行けそうだったので、
追加レポートになります。
結果
6μA
NJU7223F33→3.3V
入力12V、0.05mA 0.6mW 効率3.6%
150mAは
NJU7223F33→3.3V
入力12V、150mA 1.8W 効率27.5%
150mAの方は従来の3端子レギュレーターのままの数字ですね。
6μAは効率3%まで上がりました。
前回6μのチャンピオンがBP5293-33で、
BP5293-33→3.3V
入力12V、0.3mA 3.6mW 効率0.6%
比較してかなり上がってますね。
商品自体は前々からありますけどね。
なお、上に書きましたのと関連しますけど
スイッチングレギュレーターのBP5293-xxは7ボルト以上にならないと動作しません。
7Vから3.3Vとなると、電圧差が2倍以上となります。
それに比較してNJU7223F33は3.2VでもESP32を動かしてくれるあたり
意外と馬鹿にできないメリットです。
OLDテクノロジーもまだまだ行けそうです。
ESP32のULP動作時の消費電流の確認
ULPというのはUltraLowPowerの事です。
ULPの記事として以下書いてきました。
MicropythonからのULP呼び出し と GPIOの入出力、ADC
https://miha.jugem.cc/?eid=409
I2C通信(BMP180)mycropython版
https://miha.jugem.cc/?eid=413
今回は仕様書通り本当に消費電力低いのか?
というテストをしてみたいと思います。
ただ、
素人測定ですし、
機材がアナログメーターだったりしますので、
マイクロレベルの正確性には欠けると思ってください。
悪しからず。
実際deepsleep時のESP32の実行時の消費電流は
仕様書上では6μAとなってますが、
私の手元の機材では4μAとなってたりします。
それらを念頭に、参考にしてもらえればと思います。

ESP32の本体CPU
標準 電源ON 40mA
ESP32のULP+BMP180電力調査
以下はdeepsleep時。BMP180は標準モード
パターン1 BMP180接続しない。GPIO14を確認後HALT 4μA
パターン2 BMP180接続。GPIO14を確認後HALT 18μA
(0.5秒に一回測定だとこの値で安定アナログメーター読み)
パターン3 BMP180接続。BMP180連続アクセス 840μA ※2
パターン4 BMP180接続。BMP180に10秒に1回アクセス 10μA ※1
(bmp180へのアクセス無し時)
※1 google先生によるとBMP180が標準モードで5μA
ESP32がdeepsleepで6μAなので、合計11μAですね。
ま、1μAずれてますが素人機材なので・・・許す。
※2 測定時はそれなりにBMP180で電気使いますね。
BMP180の仕様書によると650μAってなってますね。
実測840μAとの差はI2Cによるものと思います。
ESP32のULP+スイッチ
以下はdeepsleep時
スイッチをプルダウン時は常時80μA消費
スイッチをプルアップに変更すると、4μA
プルダウンだと電気食うって聞いたことありますが結構な違いですね。
省エネ設計ではプルアップと覚えておきましょう。
ESP32のULP+LED電力調査
以下はdeepsleep時
パターン1 GPIO14だけLED点灯 点灯時6mA 消灯時4μA
パターン2 上記パターン1にLEDに抵抗2000Ωを追加 点灯時1mA 消灯時4μA
(LEDの光り方は抵抗によってぼんやりになる)
パターン3 使えるGPIO全部をULPに接続&全部出力モードに設定。消灯時29mA ※3
(ULPからGPIOを使えるように設定するだけで電力消費大。)
※3 GPIO出力モードにするだけでLED点灯しなくても電気食います。
基本的にはULP接続せずに使用して
必要な時だけ接続するようにする様な使い方が良いみたいです。
ESP32のULPでI2C通信(BMP180)mycropython版
ESP32のULPで実行する記事
https://miha.jugem.cc/?eid=409 で、
ESP32のULP紹介、GPIO入力、GPIO出力、ADC入力をやってみた。
これにI2Cが使えるようになると便利だなーと思い。挑戦し成功した記事です。
I2Cのセンサーとして選んだのが
BMP180という温度と気圧が取得できるセンサーだ。
https://amzn.to/4ljLPU1
3つ入ってて649yenって事は一つ220円ぐらいですね。

BME280より安いかなーと思いましたのでULPで温度と気圧を取得してみました。
今回もmycropythonでやります。
今回の元にしたプログラム
https://github.com/tomtor/ulp-i2c
ESP-IDEでコンパイルできます。
ULPでI2Cプログラムをしたいがために、
ESP-IDEも入れてしまった。
それで、ESP-IDEのクセを掴むのに結構かかってしまった。
こちら、ULPでセンサーの値を取得後、
前の値と比較してしきい値を超えた場合に本体復帰して表示するサンプルですが
mycropythonにするに当たり、ボタンで復帰する様に変更しております。
プログラムの仕様
mycropython上のULPプログラムをアセンブルして
メモリ上へロード、ULPプログラムをを起動する。
0.5秒単位でULPプログラムが起動して
センサーから値を持ってきてメモリ上に配置
ESP本体はdeepsleepする。ULPは動き続ける
ボタンが押されたら本体復帰しpython側で
メモリ上の値を取得して
温度と気圧を計算して出力する。(uart->comポート)
センサーからデータ取得する瞬間LEDを光らせる
表示例
ULP-BME180-R2
略
Temperature= 31.07753
Pressure= 1002.685
run
deepsleep(3600sec)
接続
ESP32 BME-180
GPIO32 scl (物理プルアップ)
GPIO33 sda (物理プルアップ)
3V VIN
GND GND
GPIO14 SW (物理プルアップ)
GPIO2 LED
プログラム
こちらからダウンロードできます。
https://drive.google.com/file/d/1UnT5i8G1GwxzGrEtb9N8IAs8-kNProBp/view?usp=sharing
#
# BME180のULP制御
#
# 0.5秒単位でセンサーから取得し
# GPIO14押下で本体復帰して最新の温度、気圧を表示する
#
# ULP I2C BME-180
# scl = GPIO32 物理プルアップ
# sda = GPIO33 物理プルアップ
# 復帰ボタン:GPIO14 プルアップ
# LED:GPIO2
#
#
VERSION_STR="ULP-BME180-R2"
import sys
import esp32
from esp32 import ULP
import time
import machine
from machine import Pin
from machine import mem32
import math
from esp32_ulp import src_to_binary
def end():
while True:
pass
time.sleep(1)
print(VERSION_STR)
def k(n) :
ret = ""
for i in range(n):
ret = ret + " "
return ret
#
#マクロ処理用
#
def src_to_preprocessor(input) :
output = ""
input_sp = input.split("¥n")
for line in input_sp:
#print("line=", line)
kuhaku=len(line)-len(line.lstrip())
#print("kuhaku=", kuhaku)
line = line.strip()
sp = line.split(" ")
#print("sp[0]=", sp[0])
if sp[0]=="psr" :
output = output + k(kuhaku)
output = output + "#psr "+sp[1]+"¥r¥n"+k(kuhaku)
output = output + "move r1, "+sp[1]+"¥r¥n"+k(kuhaku)
output = output + "st r1,r3,0"+"¥r¥n"+k(kuhaku)
output = output + "sub r3,r3,1"+"¥r¥n"
elif sp[0]=="ret" :
output = output + k(kuhaku)
output = output + "#ret¥r¥n"+k(kuhaku)
output = output + "add r3,r3,1¥r¥n"+k(kuhaku)
output = output + "ld r1,r3,0¥r¥n"+k(kuhaku)
output = output + "jump r1¥r¥n"
elif sp[0]=="push" :
output = output + k(kuhaku)
output = output + "#push "+sp[1]+"¥r¥n"+k(kuhaku)
output = output + "st "+sp[1]+",r3,0"+"¥r¥n"+k(kuhaku)
output = output + "sub r3,r3,1"+"¥r¥n"
elif sp[0]=="pop" :
output = output + k(kuhaku)
output = output + "#pop "+sp[1]+"¥r¥n"+k(kuhaku)
output = output + "add r3,r3,1"+"¥r¥n"+k(kuhaku)
output = output + "ld "+sp[1]+",r3,0"+"¥r¥n"
elif sp[0]=="I2C_delay" :
output = output + k(kuhaku)
output = output + "#I2C_delay"+"¥r¥n"+k(kuhaku)
output = output + "wait 10"+"¥r¥n"
elif sp[0]=="read_SCL" :
output = output + k(kuhaku)
output = output + "#read_SCL"+"¥r¥n"+k(kuhaku)
output = output + "READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S + 9, 1)"+"¥r¥n" #RTC_GPIO_9 == GPIO_32
elif sp[0]=="read_SDA" :
output = output + k(kuhaku)
output = output + "#read_SDA"+"¥r¥n"+k(kuhaku)
output = output + "READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S + 8, 1)"+"¥r¥n" #RTC_GPIO_8 == GPIO_33
elif sp[0]=="set_SCL" :
output = output + k(kuhaku)
output = output + "#set_SCL"+"¥r¥n"+k(kuhaku)
output = output + "WRITE_RTC_REG(RTC_GPIO_ENABLE_W1TC_REG, RTC_GPIO_ENABLE_W1TC_S + 9, 1, 1)"+"¥r¥n"
elif sp[0]=="clear_SCL" :
output = output + k(kuhaku)
output = output + "#clear_SCL"+"¥r¥n"+k(kuhaku)
output = output + "WRITE_RTC_REG(RTC_GPIO_ENABLE_W1TS_REG, RTC_GPIO_ENABLE_W1TS_S + 9, 1, 1)"+"¥r¥n"
elif sp[0]=="set_SDA" :
output = output + k(kuhaku)
output = output + "#set_SDA"+"¥r¥n"+k(kuhaku)
output = output + "WRITE_RTC_REG(RTC_GPIO_ENABLE_W1TC_REG, RTC_GPIO_ENABLE_W1TC_S + 8, 1, 1)"+"¥r¥n"
elif sp[0]=="clear_SDA" :
output = output + k(kuhaku)
output = output + "#clear_SDA"+"¥r¥n"+k(kuhaku)
output = output + "WRITE_RTC_REG(RTC_GPIO_ENABLE_W1TS_REG, RTC_GPIO_ENABLE_W1TS_S + 8, 1, 1)"+"¥r¥n"
else :
output = output + k(kuhaku)
output = output + line
output = output + "¥r¥n"
return output
#ULP実行ファイルのメモリ上にロードされるアドレスと実行開始アドレス
load_addr, entry_addr = 0, 40 * 4
ULP_MEM_BASE = 0x50000000
#16ビットデータマスク
ULP_DATA_MASK = 0xffff
#ULPプログラム
source = """¥
#define DR_REG_RTCIO_BASE 0x3ff48400
#define RTC_GPIO_ENABLE_W1TS_REG (DR_REG_RTCIO_BASE + 0x10)
#define RTC_GPIO_ENABLE_W1TS_S 14
#define RTC_GPIO_ENABLE_W1TC_REG (DR_REG_RTCIO_BASE + 0x14)
#define RTC_GPIO_ENABLE_W1TC_S 14
#define RTC_GPIO_IN_REG (DR_REG_RTCIO_BASE + 0x24)
#define RTC_GPIO_IN_NEXT_S 14
#define RTC_GPIO_OUT_REG (DR_REG_RTCIO_BASE + 0x0)
#define RTC_GPIO_OUT_DATA_S 14
#define RTC_GPIO_ENABLE_REG (DR_REG_RTCIO_BASE + 0xc)
#define RTC_GPIO_ENABLE_S 14
#define RTC_CNTL_STATE0_REG 0x3FF48018
#define RTC_CNTL_ULP_CP_SLP_TIMER_EN (BIT(24))
#define RTC_CNTL_LOW_POWER_ST_REG 0x3FF480C0
#define RTC_CNTL_RDY_FOR_WAKEUP (BIT(19))
#GPIO32------------------------------------------
#{RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32P_MUX_SEL_M, RTC_IO_X32P_FUN_SEL_S, RTC_IO_X32P_FUN_IE_M, RTC_IO_X32P_RUE_M, RTC_IO_X32P_RDE_M, RTC_IO_X32P_SLP_SEL_M, RTC_IO_X32P_SLP_IE_M, RTC_CNTL_X32P_HOLD_FORCE_M, 9}, //32
#define RTC_IO_XTAL_32K_PAD_REG (DR_REG_RTCIO_BASE + 0x8c)
#define RTC_IO_X32P_MUX_SEL_M (BIT(17))
#define RTC_IO_X32P_FUN_IE_M (BIT(5))
.set gpio32, 9
#GPIO33------------------------------------------
#{RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32N_MUX_SEL_M, RTC_IO_X32N_FUN_SEL_S, RTC_IO_X32N_FUN_IE_M, RTC_IO_X32N_RUE_M, RTC_IO_X32N_RDE_M, RTC_IO_X32N_SLP_SEL_M, RTC_IO_X32N_SLP_IE_M, RTC_CNTL_X32N_HOLD_FORCE_M, 8}, //33
#define RTC_IO_XTAL_32K_PAD_REG (DR_REG_RTCIO_BASE + 0x8c)
#define RTC_IO_X32N_MUX_SEL_M (BIT(18))
#define RTC_IO_X32N_FUN_IE_M (BIT(11))
.set gpio33, 8
#GPIO14------------------------------------------
#define RTC_IO_TOUCH_PAD6_REG (DR_REG_RTCIO_BASE + 0xac)
#define RTC_IO_TOUCH_PAD6_MUX_SEL_M (BIT(19))
#define RTC_IO_TOUCH_PAD6_FUN_IE_M (BIT(13))
.set gpio14, 16 # gpio14
#GPIO2------------------------------------------
#{RTC_IO_TOUCH_PAD2_REG, RTC_IO_TOUCH_PAD2_MUX_SEL_M, RTC_IO_TOUCH_PAD2_FUN_SEL_S, RTC_IO_TOUCH_PAD2_FUN_IE_M, RTC_IO_TOUCH_PAD2_RUE_M, RTC_IO_TOUCH_PAD2_RDE_M, RTC_IO_TOUCH_PAD2_SLP_SEL_M, RTC_IO_TOUCH_PAD2_SLP_IE_M, RTC_CNTL_TOUCH_PAD2_HOLD_FORCE_M, 12}, //2
#define RTC_IO_TOUCH_PAD2_REG (DR_REG_RTCIO_BASE + 0x9c)
#define RTC_IO_TOUCH_PAD2_MUX_SEL_M (BIT(19))
#define RTC_IO_TOUCH_PAD2_FUN_IE_M (BIT(13))
.set gpio2, 12
#16 * 4 = 64
status: .long 0
temp: .long 0
pressure: .long 0
pressure2: .long 0
ac1: .long 0
ac2: .long 0
ac3: .long 0
ac4: .long 0
ac5: .long 0
ac6: .long 0
b1: .long 0
b2: .long 0
mb: .long 0
mc: .long 0
md: .long 0
counter: .long 0
#20 * 4 = 80byte
stack:
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
stackEnd:
#1 * 4 = 4
.long 0
#3 * 4 = 12
prev_temp: .long 0
prev_pressure: .long 0
prev_pressure2: .long 0
entry:
move r3,stackEnd
# GPIO32 input mode
WRITE_RTC_REG(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32P_MUX_SEL_M, 1, 1)
WRITE_RTC_REG(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32P_FUN_IE_M, 1, 1)
# GPIO33 input mode
WRITE_RTC_REG(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32N_MUX_SEL_M, 1, 1)
WRITE_RTC_REG(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32N_FUN_IE_M, 1, 1)
# GPIO14 input mode
WRITE_RTC_REG(RTC_IO_TOUCH_PAD6_REG, RTC_IO_TOUCH_PAD6_MUX_SEL_M, 1, 1)
WRITE_RTC_REG(RTC_IO_TOUCH_PAD6_REG, RTC_IO_TOUCH_PAD6_FUN_IE_M, 1, 1)
#gpio2 output mode
WRITE_RTC_REG(RTC_IO_TOUCH_PAD2_REG, RTC_IO_TOUCH_PAD2_MUX_SEL_M, 1, 1);
WRITE_RTC_REG(RTC_GPIO_ENABLE_REG, RTC_GPIO_ENABLE_S + gpio2, 1, 1)
//DEBUG
move r1, status
move r0, 100
st r0, r1, 0
wait 65535
//
// Read the BMP-180 every 4 timer cycles:
#move r1,counter
#ld r0,r1,0
#add r0,r0,1
#st r0,r1,0 // increment counter
#and r0,r0,0x3
#jumpr waitNext,1,ge
// GPIO2 LED ON
WRITE_RTC_REG(RTC_GPIO_OUT_REG, RTC_GPIO_OUT_DATA_S + gpio2, 1, 1)
psr l00010
jump readBMP
l00010:
// GPIO2 LED OFF
WRITE_RTC_REG(RTC_GPIO_OUT_REG, RTC_GPIO_OUT_DATA_S + gpio2, 1, 0)
/* wake up after significant change */
// move r1,pressure
// ld r0,r1,0
// move r1,prev_pressure
// ld r2,r1,0
// sub r0,r0,r2
// psr l00020
// jump abs
//l00020:
// jumpr testTemp,6,lt
// jump wakeUp
//
//testTemp:
// move r1,temp
// ld r0,r1,0
// move r1,prev_temp
// ld r2,r1,0
// sub r0,r0,r2
// psr l00030
// jump abs
//l00030:
// jumpr waitNext,10,lt
#GPIO14-----------------------------------------------
# GPIOからr0に読む
READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S + gpio14, 1)
#押されてたら0
jumpr wakeUp, 0, eq
jump waitNext
wakeUp:
//jump waitNext #DEBUG
/* save new pressure and temp */
move r1,pressure
ld r0,r1,0
move r1,prev_pressure
st r0,r1,0
move r1,temp
ld r0,r1,0
move r1,prev_temp
st r0,r1,0
#
#ここにwakeしても良いか?確認する処理が抜けている
#
/* Wake up the SoC, end program */
wake
/* Stop the wakeup timer so it does not restart ULP */
WRITE_RTC_FIELD(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN, 0)
waitNext:
halt
// Compute abs value of R0
#abs:
# and r1,r0,0x8000
# jump noNegate,eq
# move r1,0
# sub r0,r1,r0
#noNegate:
# ret
////////////
//i2c-bme180.S
////////////
#define BMP180_ADDR 0x77
#define BMP180_REG_CONTROL 0xF4
#define BMP180_REG_RESULT 0xF6
#define BMP180_REG_RESULT2 0xF8
#define BMP180_COMMAND_TEMPERATURE 0x2E
#define BMP180_COMMAND_PRESSURE0 0x34
#define BMP180_COMMAND_PRESSURE1 0x74
#define BMP180_COMMAND_PRESSURE2 0xB4
#define BMP180_COMMAND_PRESSURE3 0xF4
readBMP:
move r1,ac1
ld r0,r1,0
jumpr initBMP,1,lt
didInit:
move r1,BMP180_ADDR
push r1
move r1,BMP180_REG_CONTROL
push r1
move r1,BMP180_COMMAND_TEMPERATURE
push r1
psr l0r010
jump write8
l0r010:
add r3,r3,3 // remove 3 arguments from stack
move r0,r2 // test for error in r2
jumpr fail,1,ge
// Wait 5ms for sensor computation
move r2,5
psr l0r020
jump waitMs
l0r020:
// Read 16 bit result
move r1,BMP180_ADDR
push r1
move r1,BMP180_REG_RESULT
push r1
psr l0r030
jump read16
l0r030:
add r3,r3,2 // remove call parameters from stack
move r1,r0 // save result
move r0,r2 // test for error
jumpr fail,1,ge
move r2,temp // store result
st r1,r2,0
// Read raw pressure
move r1,BMP180_ADDR
push r1
move r1,BMP180_REG_CONTROL
push r1
move r1,BMP180_COMMAND_PRESSURE1
push r1
psr l0r040
jump write8
l0r040:
add r3,r3,3 // remove 3 arguments from stack
move r0,r2 // test for error in r2
jumpr fail,1,ge
// Wait 8 ms for sensor computation
move r2,8
psr l0r050
jump waitMs
l0r050:
move r1,BMP180_ADDR
push r1
move r1,BMP180_REG_RESULT
push r1
psr l0r060
jump read16
l0r060:
add r3,r3,2 // remove call parameters from stack
move r1,r0 // save result
move r0,r2 // test for error
jumpr fail,1,ge
move r2,pressure // store result
st r1,r2,0
move r1,BMP180_ADDR
push r1
move r1,BMP180_REG_RESULT2
push r1
psr l0r070
jump read8
l0r070:
add r3,r3,2 // remove call parameters from stack
move r1,r0 // save result
move r0,r2 // test for error
jumpr fail,1,ge
move r2,pressure2 // store result
st r1,r2,0
ret
fail:
move r1,temp
move r0,0 // 0 signals error
st r0,r1,0
ret
#define BMP085_CAL_AC1 0xAA
#define BMP085_CAL_AC2 0xAC
#define BMP085_CAL_AC3 0xAE
#define BMP085_CAL_AC4 0xB0
#define BMP085_CAL_AC5 0xB2
#define BMP085_CAL_AC6 0xB4
#define BMP085_CAL_B1 0xB6
#define BMP085_CAL_B2 0xB8
#define BMP085_CAL_MB 0xBA
#define BMP085_CAL_MC 0xBC
#define BMP085_CAL_MD 0xBE
#define BMP085_END 0xC0
// Read calibration data
initBMP:
move r1,ac1
push r1
move r1,BMP180_ADDR
push r1
move r1,BMP085_CAL_AC1
push r1
read_cal:
psr l0i010
jump read16
l0i010:
or r2,r2,0 // test error
jump readok,eq
jump fail
readok:
ld r1,r3,12
st r0,r1,0
add r1,r1,1
st r1,r3,12 // next cal parameter address
ld r0,r3,4
add r0,r0,2 // next register
st r0,r3,4
jumpr read_cal,BMP085_END,lt
add r3,r3,3
jump didInit
// Wait for r2 milliseconds
waitMs:
wait 8000
sub r2,r2,1
jump doneWaitMs,eq
jump waitMs
doneWaitMs:
ret
////////////
//i2c-util.S
////////////
write_intro:
psr l00230
jump i2c_start_cond
l00230:
ld r2,r3,20 // Address
lsh r2,r2,1
psr l00240
jump i2c_write_byte
l00240:
jumpr popfail,1,ge
ld r2,r3,16 // Register
psr l00250
jump i2c_write_byte
l00250:
jumpr popfail,1,ge
ret
write8:
psr l00260
jump write_intro
l00260:
write_b:
ld r2,r3,8 // data byte
psr l00270
jump i2c_write_byte
l00270:
jumpr fail_util,1,ge
psr l00280
jump i2c_stop_cond
l00280:
move r2,0 // Ok
ret
write16:
psr l00290
jump write_intro
l00290:
ld r2,r3,8 // data byte 1
rsh r2,r2,8
psr l00300
jump i2c_write_byte
l00300:
jumpr fail_util,1,ge
jump write_b
read_intro:
psr l00310
jump i2c_start_cond
l00310:
ld r2,r3,16 // Address
lsh r2,r2,1
psr l00320
jump i2c_write_byte
l00320:
jumpr popfail,1,ge
ld r2,r3,12 // Register
psr l00330
jump i2c_write_byte
l00330:
jumpr popfail,1,ge
psr l00340
jump i2c_start_cond
l00340:
ld r2,r3,16
lsh r2,r2,1
or r2,r2,1 // Address Read
psr l00350
jump i2c_write_byte
l00350:
jumpr popfail,1,ge
ret
popfail:
pop r1 // pop caller return address
move r2,1
ret
read8:
psr l00360
jump read_intro
l00360:
move r2,1 // last byte
psr l00370
jump i2c_read_byte
l00370:
push r0
psr l00380
jump i2c_stop_cond
l00380:
pop r0
move r2,0 // OK
ret
fail_util:
move r2,1
ret
read16:
psr l00390
jump read_intro
l00390:
move r2,0
psr l00400
jump i2c_read_byte
l00400:
push r0
move r2,1 // last byte
psr l00410
jump i2c_read_byte
l00410:
push r0
psr l00420
jump i2c_stop_cond
l00420:
pop r0
pop r2 // first byte
lsh r2,r2,8
or r2,r2,r0
move r0,r2
move r2,0 // OK
ret
////////////
//i2c.S
////////////
i2c_started:
.long 0
i2c_didInit:
.long 0
i2c_start_cond:
move r1,i2c_didInit
ld r0,r1,0
jumpr i2cs_didInit,1,ge
move r0,1
st r0,r1,0
// set GPIO to pull low when activated
WRITE_RTC_REG(RTC_GPIO_OUT_REG, RTC_GPIO_OUT_DATA_S + 9, 1, 0)
WRITE_RTC_REG(RTC_GPIO_OUT_REG, RTC_GPIO_OUT_DATA_S + 8, 1, 0)
i2cs_didInit:
move r2,i2c_started
ld r0,r2,0
jumpr not_started,1,lt
// if started, do a restart condition
// set SDA to 1
set_SDA
I2C_delay
set_SCL
clock_stretch: // TODO: Add timeout?
read_SCL
jumpr clock_stretch,1,lt
// Repeated start setup time, minimum 4.7us
I2C_delay
not_started:
// if (read_SDA() == 0) {
// arbitration_lost();
// }
// SCL is high, set SDA from 1 to 0.
clear_SDA
I2C_delay
clear_SCL
move r0,1
st r0,r2,0
ret
i2c_stop_cond:
// set SDA to 0
clear_SDA
I2C_delay
set_SCL
clock_stretch_stop:
read_SCL
jumpr clock_stretch_stop,1,lt
// Stop bit setup time, minimum 4us
I2C_delay
// SCL is high, set SDA from 0 to 1
set_SDA
I2C_delay
// if (read_SDA() == 0) {
// arbitration_lost();
// }
move r2,i2c_started
move r0,0
st r0,r2,0
ret
// Write a bit to I2C bus
i2c_write_bit:
jumpr bit0,1,lt
set_SDA
jump bit1
bit0:
clear_SDA
bit1:
// SDA change propagation delay
I2C_delay
// Set SCL high to indicate a new valid SDA value is available
set_SCL
// Wait for SDA value to be read by slave, minimum of 4us for standard mode
I2C_delay
clock_stretch_write:
read_SCL
jumpr clock_stretch_write,1,lt
// SCL is high, now data is valid
// If SDA is high, check that nobody else is driving SDA
// if (bit && (read_SDA() == 0)) {
// arbitration_lost();
// }
// Clear the SCL to low in preparation for next change
clear_SCL
ret
// Read a bit from I2C bus
i2c_read_bit:
// Let the slave drive data
set_SDA
// Wait for SDA value to be written by slave, minimum of 4us for standard mode
I2C_delay
// Set SCL high to indicate a new valid SDA value is available
set_SCL
clock_stretch_read:
read_SCL
jumpr clock_stretch_read,1,lt
// Wait for SDA value to be written by slave, minimum of 4us for standard mode
I2C_delay
// SCL is high, read out bit
read_SDA
// Set SCL low in preparation for next operation
clear_SCL
ret // bit in r0
// Write a byte to I2C bus. Return 0 if ack by the slave.
i2c_write_byte:
stage_rst
next_bit:
and r0,r2,0x80
psr l00430
jump i2c_write_bit
l00430:
lsh r2,r2,1
stage_inc 1
jumps next_bit,8,lt
psr l00440
jump i2c_read_bit
l00440:
ret // nack
// Read a byte from I2C bus
i2c_read_byte:
push r2
move r2,0
stage_rst
next_bit_read:
psr l00450
jump i2c_read_bit
l00450:
lsh r2,r2,1
or r2,r2,r0
stage_inc 1
jumps next_bit_read,8,lt
pop r0
psr l00460
jump i2c_write_bit
l00460:
move r0,r2
ret
"""
#
#BME180から16bitで値を取得する時に負の数字の場合
#ちゃんと受け取れないので変換uint16→int16
#
def conv_int16(uint16) :
if uint16 > 32767 :
int16 = (-1)*(65536 - uint16)
else :
int16=uint16
return int16
#
#BME180からデータを取得必要な計算を実施し表示する
#
def display() :
#データ取得
status = mem32[ULP_MEM_BASE + load_addr + 0] & ULP_DATA_MASK
ulp_temp = mem32[ULP_MEM_BASE + load_addr + 4] & ULP_DATA_MASK
ulp_pressure = mem32[ULP_MEM_BASE + load_addr + 8] & ULP_DATA_MASK
ulp_pressure2 = mem32[ULP_MEM_BASE + load_addr + 12] & ULP_DATA_MASK
ac1 = mem32[ULP_MEM_BASE + load_addr + 16] & ULP_DATA_MASK
ac2 = mem32[ULP_MEM_BASE + load_addr + 20] & ULP_DATA_MASK
ac3 = mem32[ULP_MEM_BASE + load_addr + 24] & ULP_DATA_MASK
ac4 = mem32[ULP_MEM_BASE + load_addr + 28] & ULP_DATA_MASK
ac5 = mem32[ULP_MEM_BASE + load_addr + 32] & ULP_DATA_MASK
ac6 = mem32[ULP_MEM_BASE + load_addr + 36] & ULP_DATA_MASK
b1 = mem32[ULP_MEM_BASE + load_addr + 40] & ULP_DATA_MASK
b2 = mem32[ULP_MEM_BASE + load_addr + 44] & ULP_DATA_MASK
mb = mem32[ULP_MEM_BASE + load_addr + 48] & ULP_DATA_MASK
mc = mem32[ULP_MEM_BASE + load_addr + 52] & ULP_DATA_MASK
md = mem32[ULP_MEM_BASE + load_addr + 56] & ULP_DATA_MASK
counter = mem32[ULP_MEM_BASE + load_addr + 60] & ULP_DATA_MASK
ac1 = conv_int16(ac1)
ac2 = conv_int16(ac2)
ac3 = conv_int16(ac3)
b1 = conv_int16(b1)
b2 = conv_int16(b2)
mb = conv_int16(mb)
mc = conv_int16(mc)
md = conv_int16(md)
#print("status=", status)
#print("ulp_temp=", ulp_temp)
#print("ulp_pressure=", ulp_pressure)
#print("ulp_pressure2=", ulp_pressure2)
#print("ac1=", ac1)
#print("ac2=", ac2)
#print("ac3=", ac3)
#print("ac4=", ac4)
#print("ac5=", ac5)
#print("ac6=", ac6)
#print("b1=", b1)
#print("b2=", b2)
#print("mb=", mb)
#print("mc=", mc)
#print("md=", md)
#print("counter=", counter)
oversampling= 1
UP= ((((ulp_pressure) << 8) | (ulp_pressure2)) >> (8-oversampling))
#print("UP=", UP)
X1 = (ulp_temp - ac6) * (ac5) >> 15
#print("X1=", X1)
X2 = (mc << 11) / (X1+md)
#print("X2=", X2)
B5 = X1 + X2
#print("B5=", B5)
temp = (B5+8) / 16.0
#print("temp=", temp)
temp = temp / 10
print("Temperature=", temp)
B6 = B5 - 4000
#print("B6=", B6)
X1 = (b2 * ( int(B6 * B6)>>12 )) >> 11
#print("X1=", X1)
X2 = int(ac2 * B6) >> 11
#print("X2=", X2)
X3 = X1 + X2
#print("X3=", X3)
B3 = (((ac1*4 + X3) << oversampling) + 2) / 4
#print("B3=", B3)
X1 = int(ac3 * B6) >> 13
#print("X1=", X1)
X2 = int(b1 * (int(B6 * B6) >> 12)) >> 16
#print("X2=", X2)
X3 = int((X1 + X2) + 2) >> 2
#print("X3=", X3)
B4 = int(ac4 * (X3 + 32768)) >> 15
#print("B4=", B4)
B7 = (UP - B3) * ( 50000 >> oversampling )
#print("B7=", B7)
if (B7 < 0x80000000) :
p = (B7 * 2) / B4
#print("point 1")
else :
p = (B7 / B4) * 2
#print("point 2")
#print("p=", p)
X1 = (int(p) >> 8) * (int(p) >> 8)
#print("X1=", X1)
X1 = int(X1 * 3038) >> 16
#print("X1=", X1)
X2 = int(-7357 * p) >> 16
#print("X2=", X2)
p = p + (int(X1 + X2 + 3791)>>4)
#print("p=", p)
pressure = p
altitude_meters= 3
print("Pressure=", (pressure / math.pow(1.0-altitude_meters/44330, 5.255))/100.0);
###########
#MAIN
###########
#DEBUG
# print("ac1=", conv_int16(7493))
# print("ac2=", conv_int16(64488))
# print("ac3=", conv_int16(50901))
# print("ac4=", conv_int16(32931))
# print("ac5=", conv_int16(25567))
# print("ac6=", conv_int16(19438))
# end()
machine.Pin(2, machine.Pin.OUT) #LED
pin_scl = machine.Pin(32, machine.Pin.IN, machine.Pin.PULL_UP)
pin_sda = machine.Pin(33, machine.Pin.IN, machine.Pin.PULL_UP)
#ULP
ulp = ULP()
#ULP停止(前のdeepsleep中に動いていたプログラムを停止)
ulp.set_wakeup_period(0, -1)
print("machine.reset_cause() -->", machine.reset_cause())
print("machine.wake_reason() -->", machine.wake_reason())
if machine.wake_reason() != 6 :
print("prep start")
prep = src_to_preprocessor(source)
#print("prep=", prep)
print("src_to_binary start")
binary = src_to_binary(prep)
print("src_to_binary done")
ulp.load_binary(load_addr, binary)
else :
display()
#ULP
ulp.set_wakeup_period(0, 500000) # use timer0, wakeup after 500000usec (0.5s)
print("run")
ulp.run(entry_addr)
#ULP割り込みON
esp32.wake_on_ulp(True)
#
print("deepsleep(3600sec)")
machine.deepsleep(3600*1000)
#以下はDEBUG deepsleepを外すと走る
old = 0
while True:
#new = mem32[ULP_MEM_BASE + load_addr] & ULP_DATA_MASK # current state
#if old != new :
# print(new)
# old=new
#if new==888 :
# display()
# time.sleep(10)
# print()
time.sleep(3)
display()
3端子レギュレーターの比較
3端子レギュレーターの比較2もあります。
https://miha.jugem.cc/?eid=419
先日、3端子レギュレーターを注文しようと秋月のページを見てましたが、
前は見かけなかった(自分が避けてただけ?)
スイッチングタイプの3端子レギュレーターを発見。
ROHM社BP5293-33
特徴としては
3端子レギュレータと比較して電源効率が良く、放熱処理が不要
となってます。
スイッチングってその場で発振して交流を発生させてトランス的なもので降圧して
お届けするのかと思ってましたが違うんですねー。
スイッチング方式恐るべし。
自分の頭の中が昔のACアダプター
(中にトランスが入っててダイオードで整流するってやつ)
だったので、今こうなってるのかーって感動しました。
動機としては
例えば、ESP32のULPを使って6μAで動作させたとしても、
入力する電力(3.3V)を生成する時に物凄く電力消費してたら
やだなーって思いますよね。
とはいえ、レギュレーターを使わないと部品点数も増えますしね。
それなら少し高いROHMのを使っても良いかなと思ったりしますよね。
入手したものを比較していきます。
比較対象は以下となります。
他のメーカーのも見たかったけど、全部買うわけにもいかず。
普通の3端子レギュレーター
BA033CC0T(3.3V-低損失)
https://akizukidenshi.com/catalog/g/g113675/
7805A(5V)
https://akizukidenshi.com/catalog/g/g108678/
ROHM
BP5293-33(3.3V)
https://akizukidenshi.com/catalog/g/g111187/
BP5293-50(5V)
https://akizukidenshi.com/catalog/g/g111188/
MINMAX
M78AR033-0.5(3.3V)
https://akizukidenshi.com/catalog/g/g107178/
M78AR05-0.5(5V)
https://akizukidenshi.com/catalog/g/g107179/
どれもピン配置は一緒で入力電圧は30Vまで対応しています。
測定項目は効率になります。
上記で書いた6μAと上は150mAまで測定したいと思います。
負荷は普通の抵抗で良いと思ったんだけど。
5Vで150mA流すとすると、33Ω
電力は0.75W って事は・・・普通の1/8Wの抵抗だと燃えますね。
5Vで6μAは83KΩ
電力は0.03mW=30μW こっちは燃えないね。
3.3Vで150mAは22Ω
3.3Vで6μAは550KΩ
150mAはちょうどよく出来ないので
5VはLEDを14個
3.3VはLEDをを30個
どれも秋月で手に入る抵抗内蔵型です。
ありあわせですが。

5Vは0.75W
3.3Vは0.495W
6μAもちょうど良くないので
5Vは100KΩで5μA 25μW
3.3Vは500KΩで6.6μA 21.78μW
入力電圧は屋外でIoT設置でよく有るパターンとして車のバッテリーを想定して
12Vとします。
さて、12Vから降圧する時どの程度電気が捨てられてしまうのでしょうか?

150mA
BA033CC0T→3.3V
入力12V、150mA 1.8W 効率27.5%
結構熱くなる。
BP5293-33→3.3V
入力12V、45mA 0.54W 効率91.6%
ほんのり温かい。
M78AR033-0.5→3.3V
入力12V、42mA 0.50W 効率99%
時間が経つとすこーし温まる。
7805A→5.0V150mA
入力12V、150mA 1.8W 効率41.6%
結構熱くなる。
BP5293-50→5.0V150mA
入力12V、68mA 0.816W 効率91.9%
ほんのり温かい。
M78AR05-0.5→150mA
入力12V、60mA 0.72W 効率104.1% 100%超えてる。
時間が経つとすこーし温まる。
どっか測定がおかしい。まー素人測定なので誤差です。
6μA
BA033CC0T→3.3V
入力12V、2mA 24mW 効率0.09%
BP5293-33→3.3V
入力12V、0.3mA 3.6mW 効率0.6%
M78AR033-0.5→3.3V
入力12V、3mA 36mW 効率0.06%
7805A→5.0V
入力12V、4mA 48mW 効率0.05%
BP5293-50→5.0V
入力12V、0.32mA 3.84mW 効率0.6%
M78AR05-0.5
入力12V、4mA 48mW 効率0.05%
まとめて呼称したいので
従来の3端子レギュレーター(BA033CC0T、7805A)を①
ROHM(BP5293-33、BP5293-50)を②
MINMAX(M78AR033、M78AR05)を③
とすると。
150mAの場合の効率
③>②>①
6μAの効率
②>③>①
MINMAXは値段が高いんですが、150mAの結果は最高です。
6μAでは3mAと4mAと従来の3端子レギュレーターと変わらないかむしろ悪くなります。
6μの効率は0.09%と0.06%ですね。必要な電力の1000倍以上を降圧の為に捨ててます。
とは言ってもROHMも0.6%なので、そんなに変わらんと言われればその通りです。
ROHMは150mAで効率90%を超えており、6μAでも他よりも良い。
価格もそれなりなので、バランスが良いと言えます。
それでも捨ててる電力は結構もったいない。
とはいえ、従来型に比較すれば6分の1です。
あえて言えば、常時150mA流しておく場合はMINMAX、
deepsleepで長時間休憩、しかもバッテリーで動かしたい場合はROHMでしょうか?
全体的に6μAでの性能が残念で、
スイッチングタイプ期待したほどではないなーというのが今回の感想です。
しかし、従来型だと2mA常時消費が0.3mAまで低減できるのは有り難い。
3端子レギュレーターの比較2もあります。
https://miha.jugem.cc/?eid=419
OFFになると光る「ほたるスイッチ」
自分は真っ暗にして寝たいです。
ですので、全部の電気を切って寝るんです。
そうすると、目覚めた時は真っ暗です。
夏場は4時ぐらいから明るくなってしまうので
カーテンは遮光性を最高にしてます。
窓からの光の漏れを防ぐ目的で
段ボールに防災シート(https://www.amazon.co.jp/dp/B0DDKKDH9H)を
貼り付けて、窓全体を塞ぎます。
なので、やっぱり目が覚めると真っ暗です。
そんな時に電気のスイッチがそこに有るのにわからないって事が発生します。
寝相が悪いので、寝たときと起きたときでは自分の角度や位置が変わってます。
振動で光る犬にくっつけるやつとか(https://www.amazon.co.jp/dp/B0CKLGXCG1)も試しましたが
振動を与えないと光らないので、やっぱり探すのに時間がかかり駄目でした。
寝るのに不便でないぐらいぼんやり光ってほしいんですけど。
電気ついている時は消えててほしいんですけど。
という願いを叶えるために「ほたるスイッチ」を作ってみました。
回路

スイッチがOFFの時は上のLEDに電気が供給されて、
下のLED電球の内部回路を通過して電気が流れる。
実は上と下のLEDが直列で接続されるんだけど、
下のLED電球は電力が足りなくて光りません。
スイッチがONの時は上のLEDに電気が供給されず消灯。
下のLED電球には通常通り100Vがかかって光るって言うわけです。
写真

暗くてウチのスマホではこんぐらい