月別アーカイブ: 2024年4月

C++勉強メモ

やりそうなエラー

stringリテラルの設定もれ

string型のリテラルはincludeとnamespace設定がいる

忘れた場合のエラーメッセージは

vscode

ユーザー定義のリテラル演算子が見つかりませんC/C++(2486)

gcc

chap3.cpp:4:18: error: unable to find string literal operator ‘operator""s’ with ‘const char [6]’, ‘long unsigned int’ arguments
4 | std::cout << "hoge\n"s;
| ^~~~~~~~~
make: *** [Makefile:6: chap3.o] Error 1

補足

C++11でリテラル演算子をユーザー定義できるようになったとのこと。自分で定義するなら

ただし、自作する場合はアンスコ(_)で始めろと。

試しに自作したら

上でも動いた

Found orphan containers

docker-composeを新たに作成して実行したところ以下のワーニングが出た。

WARNING: Found orphan containers (proxy_letsencrypt-nginx-proxy-companion_1, nginx-proxy) for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up.

こちらにあるように他のdocker-composeとの名前重複が原因。

]新しいdocker-composeだとドキュメントによると以下のようにname要素(top level element)が存在し名前重複を避けられるそう。ただ、一時期バグがあって使えない時期もある模様。

対応していないと思われる私の環境では以下のエラー

ERROR: The Compose file './docker-compose.yml' is invalid because:
Invalid top-level property "name". Valid top-level sections for this Compose file are: version, services, networks, volumes, secrets, configs, and extensions starting with "x-".

現在の環境は長く使わない予定なので他の暫定対処を選択する。

環境変数にCOMPOSE_PROJECT_NAMEを指定しても同じ効果があるそうなので。docker-compose.ymlと同じディレクトリに.envを以下内容で作成。

COMPOSE_PROJECT_NAME=momoyama_shop

そしてdocker-compose buildをすると以下のように指定したcompose_project_nameを持つイメージが作成された。

Building front
Step 1/2 : FROM nginx
---> 92b11f67642b
Step 2/2 : RUN echo 'server_tokens off;\n' > /etc/nginx/conf.d/my_default.conf
---> Using cache
---> 597e7dfaab23

Successfully built 597e7dfaab23
Successfully tagged momoyama_shop_front:latest

自宅用通知マシン作成(5)

前回の続き

スタックチャンがしゃべれるようになったので、次は外部からしゃべる指令を出す端末のバージョンアップ。呼び出しは予約確認のための自宅用通知マシンと兼用。

エッジ検出処理&疑似的な並列処理はこちらに大体まとめた感じ。

メインのループ(Arduinoのloop関数)は並行処理するループ(yoyakuCheckLoop,yobidashiCheckLoop)をそれぞれ呼び出しyobidashiCheckLoopの中でボタンが押されている判定をして押されていたらネットワーク越しにスタックチャンがしゃべるURLをたたいてしゃべらせる。

最初はPOSTで叩こうとしたけどPOSTの引数違うぞみたいなエラーメッセージが出たのでとりいそぎGETメソッド(5秒も調べていない)

メインのループの中でyobidashiCheckLoopを呼び出し。下に張った中のyobidashiCheckLoopでやっていることはこちらに大体まとめた感じ。で、execYobidashi(開発環境ならexecDevYobidashi)で、httpsのリクエストを投げているだけ。セキュリティ的なものはつけていないのでそのまま叩ける。

一応全体

続けてネットワーク回り

ESP8266でエッジ検出処理

やりたいこと

ボタンを押したときにそれを検出して処理をしたい。ループの中とかで検出処理をごにょごにょやるのはつらいのでボタン検知の割り込み処理を試す。LOWからHIGHになったとき(立ち上がりエッジ:RISING)や逆にHIGHからLOW(立ち下がりエッジ:FALLING)になった時を検出するやつ。

概要

void ICACHE_RAM_ATTR shopYobidashiCallback() {
  Serial.println("working");
}
void setup() {
  pinMode(INPUT_PIN, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(INPUT_PIN), shopYobidashiCallback, FALLING);
}

割り込みが効くGPIOでattachInterruptを呼び出し。GPIOがどれかはちゃんと確認していない。(データシート参照)とりあえず、12は効いて1-15が効くと思う。

呼び出し元

attachInterrupt(割り込み番号,コールバック関数名,検出エッジ)の引数。

割り込み番号はdigitalPinToInterrupt(ピン番号)で取得できる。

コールバック関数名はそのまま関数名

検出エッジはLOW/CHANGING/RISING/FALLINGが選べる模様。LOWはLOWの時常に。実際に試したのはFALLINGのみ。(参照 ESPでなくArduinoのドキュメントなので少し違うかもしれない)

コールバック

ドキュメントはこちら

コールバックには関数をRAM上に配置する指定のIRAM_ATTRまたはICACHE_RAM_ATTR(多分こっちはDupricated)がいる。

つけ忘れると下みたいなメッセージが出て再起動するはず。

ISR not in IRAM!

User exception (panic/abort/assert)
--------------- CUT HERE FOR EXCEPTION DECODER ---------------

Abort called

>>>stack>>>

ctx: cont

RAMにない=Flashにあるとそっちの書き込みとかぶってだめよという事らしい。

その他制限として

  • delay() or yield()を読んだり内部で使うものを使用できない
  • 1ms以上かかる処理をすると不安定orクラッシュ引き起こす。よって、時間かかる処理は他でして極力そのためのフラグ操作など推奨。フラグはvolatileつける(参照
  • ヒープ操作は不具合起こしえる。malloc最小限にしてreallocとfreeは使うなと。stringやvectorも要注意。詳細はドキュメント。
  • C++のnewやdeleteも

あとは、ドキュメントに書いてないけどコールバックの宣言は使う前に。

チャタリング対策

立ち上がり、立ち上がりを検出したいが変化した時に押しているのか押していないのか中間の状態を経由するのでその際に何度もコールバック関数が呼ばれてしまう。(参照

今ブレッドボードでやっているけどイメージは下。

0件だよ
0
working
working
working
working
working
working
working
working

呼ばれたときの処理で出力される”working”が一回であってほしいが何度も出力される。

参照先に色々な対策があるが、ソフトウェアで対策できれば楽。今回の使用用途としては押されたときにあるURLをたたければよい。また、即時に何度も呼ばれなくてもよい。なので、エッジ検出後一定期間その状態が続いていれば処理を実行するとすればよい。

  1. ボタン押す
  2. 最初の立ち上がり/立下りを検出後最初数100msはチャタリングしているかもしれないので読み飛ばす
  3. その後、100ms間隔で数回状態が継続していたら押されていると判断する

みたいな感じで今回は大丈夫。

ソフトウェア的にやらないなら積分回路組んだり、ラッチ回路組んだり、いいスイッチ使ったりとあるが要件厳しくなければソフトで切り抜けた方が大体良い気がする。(というかそういう要件に収めたい)

で、ループからボタン検知と状況確認の並行処理しようとしたらESP8266はスレッドなかった。並行処理するためにFreeRTOSいれる。FreeRTOSを使おうと思ったら「ESP8266などいまさら開発する暇ないんじゃ!」とのお言葉。ESP32-C3なら使えるらしい。

ループ切り替えながらやる。2つの処理があるけど、時間はざっくりでよい。

下のイメージになった。

コールバック(shopYobidashiCallback)はフラグの設定のみ

メインのループ(Arduinoのloop関数)は並行処理するループ(yoyakuCheckLoop,yobidashiCheckLoop)をそれぞれ呼び出しのみ。

yobidashiCheckInterval 経過していなかったらスキップする処理を入れつつチェックをいれる。yobidashiCheckLoopが走っている間はもう一個の処理(yoyakuCheckLoop)は順番回ってこない。

ESP8266には基本INPUT_PULLDOWNなかった。

ESP8266(ESP-WROOM-02)で内部プルダウン使おうと思ったら怒られた。

C:\Users\kitam\git\yobidashi\client\home_yobidashi\home_yobidashi.ino:109:22: error: 'INPUT_PULLDOWN' was not declared in this scope; did you mean 'INPUT_PULLDOWN_16'?
109 | pinMode(INPUT_PIN, INPUT_PULLDOWN);
| ^~~~~~~~~~~~~~
| INPUT_PULLDOWN_16

ESP8266のGPIO1から15にはPULL_DOWN抵抗はない。INPUT/OUTPUT/INPUT_PULLUPのいずれか指定。

GPIO16だけプルダウン抵抗がある。GPIO16はディープスリープ用の特別なやつ。指定する場合はINPUT_PULLDOWN_16。

https://links2004.github.io/Arduino/dc/d6f/md_esp8266_doc_reference.html

ブレッドボードの配線的にPULL_DOWNの方が指しやすかっただけなのでおとなしくPULL_UP使う。