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がかかって光るって言うわけです。
  
写真
  

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