PR

超音波距離センサーHC-SR04をRaspberry Pi Picoで使う|仕組み・配線・精度検証

ハードウェア制御 / 電子工作

HC-SR04 × Raspberry Pi Pico

  1. はじめに
  2. 超音波距離センサー(HC-SR04)とは|非接触で距離を測れる仕組みと原理
    1. 音を出して跳ね返りが戻る時間を測る(ソナーの原理)
    2. Trig(送信の合図)と Echo(反射の受信)の2本の信号線
    3. 距離の計算式と音速の温度補正(v = 331.5 + 0.6 × 気温)
    4. 検出範囲 2〜500cm・指向角 約15°という仕様の意味
  3. 今回使うセンサー(Winova 2cm-500cm)と HC-SR04 の互換性
    1. ピン配列も使い方も HC-SR04 と同じ
    2. HC-SR04 / HC-SR04+ / 互換品の違い
    3. 2個セットの片方が初期不良だった話 — 予備があると安心
  4. この記事で使う部品(Raspberry Pi Pico・HC-SR04・OLED ほか)
  5. Arduino ではなく Raspberry Pi Pico + MicroPython で動かす(配線の注意点)
    1. Arduino の作例は多いが、配線の考え方は同じ
    2. 【重要】Echo の 5V を Pico の GPIO に直結しない — 抵抗2本で分圧する
    3. Trig は 3.3V 直結で OK・VCC は VBUS(5V)から取る
    4. 配線一覧
  6. 配線図と MicroPython の最小コード(使い方の基本)
    1. time_pulse_us() で Echo のパルス幅を測る
    2. パルス幅から距離(cm)へ変換する
    3. 反射が返らないときの落とし穴 — 「約58ms」というダミー値
    4. 測れないときの切り分け手順
  7. 測定値がばらつく・ちらつく問題への対策
    1. 数十回に数回混ざる「飛び値」を中央値で無視する
    2. 測定と測定の間隔を 60ms 以上あける理由
    3. 気温を使った音速補正で誤差を減らす
  8. 実際に測って精度を検証してみた
    1. 精度検証用のロガー(test003)
    2. メジャー実測 vs センサー値(10cm〜300cm)
    3. 誤差が大きくなる条件(斜めの面・柔らかい面・至近距離)
    4. カタログの 500cm は実用でどこまで届くか
    5. この個体で分かったこと(記事の結論)
  9. 距離を OLED(SSD1306)にリアルタイム表示する
    1. i2c.scan() で 0x3C を確認する
    2. 標準フォントを拡大して大きく表示する
    3. ちらつき対策 — 変化したときだけ描き直す
    4. main.py 全文
  10. 応用アイデア(駐車アシスト・障害物検知・液面レベル計)
    1. 使ったブザーは「アクティブ・アクティブハイ」だった
    2. 起動時に勝手に「ピー」と鳴る問題
    3. この記事のコードをまとめてダウンロード
  11. よくある質問(FAQ)
  12. まとめ
  13. シリーズ記事一覧
スポンサーリンク

はじめに

こんにちは。ニンジンです🥕

「超音波距離センサー」を1つ買ってみました。Winova というメーカーの、検出範囲 2cm〜500cm・5V駆動のモジュールです。形は定番の「HC-SR04」とまったく同じで、目玉のような送受信部が2つ並んだ、あのセンサーです。

超音波距離センサーは、対象に触れずに距離を測れる部品です。身近なところだと、車のバックソナー(障害物に近づくとピピピと鳴るあれ)、自動ドアやトイレの人感、タンクの液面レベル計などに使われています。工作でも「壁までの距離を測って止まるロボット」「箱に手を近づけると光る」といった仕掛けが手軽に作れます。1個あたり数百円と安いのも魅力です。

この記事では、この HC-SR04(互換品)を Raspberry Pi Pico + MicroPython で動かします。ネットで「HC-SR04 使い方」を調べると Arduino の作例ばかりが出てきますが、Pico(MicroPython)での実装解説は意外と少なく、しかも Pico で使うときは Arduino にはなかった「配線の落とし穴」があります。そこを実機で確かめながら、次のことを一通りやります。

  • 超音波で距離が測れる仕組み・原理
  • Pico で安全に使うための配線(Echo の分圧が必須)
  • 値がばらつくときのフィルタと気温補正
  • メジャーと突き合わせた精度検証(どこまで信じていい数字か)
  • OLED表示、障害物アラートへの応用

途中、2個セットの片方が初期不良だった話や、起動時にブザーが勝手に鳴った話など、実際にハマった箇所も挟んでいきます。

まずは完成形です。距離を OLED に数値と横バーで表示するプログラム(main.py)を動かしたところです。

▲ 対象との距離が OLED に数値+横バーグラフでリアルタイム表示される様子

なお、Raspberry Pi Pico への MicroPython の書き込みや Thonny のセットアップ、OLED(SSD1306)のライブラリ導入は過去記事で解説しているので、未経験の方はそちらを先にご覧ください。この記事では再掲しません。

🔧 事前準備|MICROPYTHON ラズパイPico WとDHT11で温湿度を測定する方法|配線図とMicroPythonコード Pico への MicroPython 書き込みと Thonny の導入手順を、実機写真つきで解説しています。 📟 事前準備|OLED Raspberry Pi Pico Wで作る熱中症警戒アラート表示器 0.96インチ OLED(SSD1306)の配線と micropython-ssd1306 ライブラリの導入を解説しています。

スポンサーリンク

超音波距離センサー(HC-SR04)とは|非接触で距離を測れる仕組みと原理

まず「なぜ音で距離が測れるのか」からです。原理はコウモリやイルカ、船のソナーとまったく同じで、音を出して、跳ね返って戻ってくるまでの時間を測るだけです。

音を出して跳ね返りが戻る時間を測る(ソナーの原理)

音は空気中を1秒間におよそ 343m 進みます(20℃のとき)。センサーから対象に向けて音を「ポン」と出し、跳ね返って戻ってくるまでに 0.001 秒(1ミリ秒)かかったとすると、音は往復で 0.343m 進んだことになります。知りたいのは片道の距離なので、これを半分にして約 17cm、と分かります。

式にするとこうです。

距離 [m] = 音速 [m/s] × Echo が HIGH だった時間 [s] ÷ 2

人間の耳では聞こえない 40kHz(キロヘルツ)の高い音=超音波を使うのは、指向性(まっすぐ飛ぶ性質)を持たせやすく、周囲の生活音と混ざらないからです。

HC-SR04 の外観
▲ HC-SR04 の外観。左右の円筒が超音波の送信部(T)と受信部(R)、中央の四角い部品が 40kHz の発振子

Trig(送信の合図)と Echo(反射の受信)の2本の信号線

HC-SR04 には信号線が2本あります。役割は完全に分かれています。

ピン向き役割
Trigマイコン → センサーここを 10マイクロ秒だけ HIGH にすると、センサーが超音波を8発送信する
Echoセンサー → マイコン送信した瞬間から反射音を受け取るまでの時間だけ HIGH になる

つまりプログラムがやることは「Trig を一瞬 HIGH にする」→「Echo が HIGH だった時間をストップウォッチで測る」の2つだけです。MicroPython には Echo のようなパルスの幅を測る専用関数 time_pulse_us() があるので、実装はとても短くなります(後述)。

距離の計算式と音速の温度補正(v = 331.5 + 0.6 × 気温)

音速は温度で変わります。気温が高いほど空気の分子が活発に動くので、音は速く伝わります。実用上は次の1次式で十分です。

音速 v [m/s] = 331.5 + 0.6 × 気温 [℃]

  0℃  → 331.5 m/s
 15℃  → 340.5 m/s
 25℃  → 346.5 m/s

0℃と25℃では音速が約 4.5% 違います。距離 3m を測るなら 13cm の差です。「20℃固定」で計算しているコードが多いですが、後半の精度検証で見るように、実際の室温を入れるだけで誤差がはっきり減ります。

検出範囲 2〜500cm・指向角 約15°という仕様の意味

今回の Winova のスペックは「2cm〜500cm」「指向角 15°」となっています。ここは額面通りには受け取らないほうがいいです。

  • 下限 2cm: 近すぎると、送信した音がまだ鳴り終わらないうちに反射が戻ってきてしまい、受信回路が切り替わりません。実測でも 3cm は誤差が大きく出ました。
  • 上限 500cm: 理想的な条件(大きく平らで固い壁に真正面)での値です。実用は 2〜3m と考えたほうが無難でした。
  • 指向角 15°: センサーの正面 ±15° くらいの範囲の反射しか拾いません。裏を返すと、対象の面がその角度以上に傾いていると、音は明後日の方向へ反射して戻ってきません。

HC-SR04 は電源(VCC)5V、GND、Trig、Echo の4ピン構成です。この形と仕様が事実上の業界標準になっていて、各社から互換品が出ています。


スポンサーリンク

今回使うセンサー(Winova 2cm-500cm)と HC-SR04 の互換性

ピン配列も使い方も HC-SR04 と同じ

購入した Winova のモジュールは、基板のシルク印字・ピンの並び(VCC / Trig / Echo / GND)・動作(Trig 10µs → Echo パルス)すべてオリジナルの HC-SR04 と同じでした。ネット上の HC-SR04 の情報や作例は、配線もコードもそのまま流用できます。

基板を真上から見たピン配列
▲ 基板を真上から。ピンは左から VCC / Trig / Echo / GND の4本

HC-SR04 / HC-SR04+ / 互換品の違い

売られているものには何種類かあります。

種類電源Pico で使うとき
HC-SR04(無印・オリジナル/互換品)5VEcho が 5V で出るので分圧が必要
HC-SR04+ / HC-SR04P3.3〜5VEcho も電源電圧に追従。3.3V 給電なら分圧不要のものがある
RCWL-1601 など3.3〜5V同上。Pico と相性が良い

今回の Winova は無印相当(5V専用)なので、後述の通り Echo を分圧して使いました。「Pico や ESP32 で分圧なしに使いたい」なら、購入時に「+」や「3.3V対応」と明記されたものを選ぶと配線が1つ楽になります。

2個セットの片方が初期不良だった話 — 予備があると安心

今回のセンサーは2個セットでした。「1個は実験用、1個は完成品用に」くらいの気持ちだったのですが、結果的にこのセット構成に助けられました。

最初に配線した個体が、給電も配線もトリガも問題ないのに、反射音をただの一度も受信できませんでした。Echo は毎回「反射なし」を示す約 58ミリ秒(≒1000cm相当)を返すだけ。テスターで VCC に 5V が来ていることも、Trig のパルスが出ていることも確認しました。切り分けの結果、送信側のトランスデューサ(音を出す円筒)の不良と判断し、もう片方に差し替えたところ一発で動きました。

安い互換品にはこうした個体差・初期不良がそれなりの確率であります。2個セット以上を買っておくと、いざというとき原因の切り分け(センサーを替えて再現するか)ができて安心です。 次のセクションで、実際にやった切り分け手順も紹介します。

HC-SR04 互換センサーの2個セット
▲ 今回の2個セット。見た目はまったく同じだが、片方は反射を1回も受信できない初期不良だった

スポンサーリンク

この記事で使う部品(Raspberry Pi Pico・HC-SR04・OLED ほか)

今回の工作で使った部品です。センサー本体以外は、これまでの Pico 記事で使ってきたものと同じで、電子工作の定番パーツです。

winova 超音波距離センサーモジュール(2cm-500cm・5V対応・2個セット)
必須

HC-SR04 互換。2個入りなので、初期不良を引いても切り分け・交換ができる

winova 超音波距離センサーモジュール(2cm-500cm・5V対応・2個セット)

この記事で距離測定に使うセンサー。オリジナルの HC-SR04 とピン配列・使い方が同じで、5V 駆動。2個セットは「実験用+本番用」だけでなく、動かないときの原因切り分けにも効きます。

HC-SR04互換2個セット5V駆動
ヘッダー ハンダ付け済み Raspberry Pi Pico 2WH
必須

ピンヘッダー実装済みで、届いたその日からブレッドボードに挿せる

ヘッダー ハンダ付け済み Raspberry Pi Pico 2WH

今回のマイコン。無線付き(W)・ピンヘッダー実装済み(H)モデル。MicroPython が動けば初代 Pico / Pico W でも同じ配線・同じコードで動きます。

無線+ヘッダー実装済みMicroPython
0.96インチ OLED ディスプレイ(SSD1306・I2C)
OLED表示で使用

I2C の2本+電源だけで、距離をその場に数字で出せる

0.96インチ OLED ディスプレイ(SSD1306・I2C)

「距離を OLED に表示する」章で使用。micropython-ssd1306 ライブラリで制御する定番モジュールで、temp-alert001・servo-moter002 でも使ったものと同じです。

I2C接続SSD1306
ブレッドボード 400穴
必須

はんだ付けなしで回路を組み替えられる基本の作業台

ブレッドボード 400穴

分圧抵抗・センサー・OLED をまとめて挿すのに使用。400穴サイズで今回の回路は十分収まります。

はんだ付け不要
ELEGOO 120pcs 多色デュポンワイヤー
必須

オス-オス/オス-メス/メス-メスが一通り入って使い回しが利く

ELEGOO 120pcs 多色デュポンワイヤー

Pico とブレッドボード、センサー、OLED をつなぐジャンパー線。色数が多いと配線の追いかけが楽になります。

3種コネクタ入り
Freenove Pico 1/2 W・H・WH 用 ブレイクアウトボード
応用

全ピンがネジ端子+GPIO番号のシルク印字で、配線ミスがぐっと減る

Freenove Pico 1/2 W・H・WH 用 ブレイクアウトボード

Pico を載せると、全 GPIO が番号入りのネジ/ソケット端子で出てくる拡張ボード。今回のように分圧抵抗・OLED・ブザーと配線数が増えるときに重宝します(この記事の写真もこれを使用)。

配線ミス防止ネジ端子
GOODCHI 金属皮膜抵抗器 抵抗セット(10Ω〜1MΩ・30種×20本・600個)
必須

Echo の分圧に使う 1.0kΩ・2.2kΩ も、その他の値もこれ1箱でまかなえる

GOODCHI 金属皮膜抵抗器 抵抗セット(10Ω〜1MΩ・30種×20本・600個)

次章の Echo 分圧に 1.0kΩ と 2.2kΩ を1本ずつ使います。手持ちの抵抗が無ければ、こういう詰め合わせが1つあると電子工作全般で困りません。1.8kΩ+3.3kΩ など近い比でも代用できます。

30種類1% 金属皮膜ケース付き
LIKENNY 電子ブザー(連続音・DC3-24V・圧電・2個入)
応用

電圧をかけるだけで鳴る「連続音」タイプ。PWM 不要でコードが簡単

LIKENNY 電子ブザー(連続音・DC3-24V・圧電・2個入)

「障害物アラート」の章を作る場合に使用。電圧 HIGH で鳴る連続音(アクティブ)タイプなら Pin.high() だけで鳴らせます。DC3〜24V 品ですが Pico の 3.3V でも鳴ります(音量は控えめ)。

連続音(アクティブ)PWM不要2個入
USBケーブルは手持ちのものでOK:Pico 2WH は micro USB です。ただしデータ通信対応のケーブルを使ってください。充電専用ケーブルだと PC が Pico を認識しません。

※リンクはアフィリエイトを含みます。価格・在庫・同梱内容は変わることがあるので、購入前に各商品ページをご確認ください。


スポンサーリンク

Arduino ではなく Raspberry Pi Pico + MicroPython で動かす(配線の注意点)

ここがこの記事のいちばん大事なところです。

Arduino の作例は多いが、配線の考え方は同じ

HC-SR04 の作例は Arduino UNO のものが大量にあります。UNO は 5V マイコンなので、Echo の 5V 信号をそのまま digital ピンに入れて pulseIn() で測る、というのが定番です。

Raspberry Pi Pico は 3.3V マイコンです(今回の実機は Pico 2 W ですが、初代 Pico / Pico W でも配線・コードは同じです)。中身のチップ(初代=RP2040、Pico 2=RP2350)の GPIO は 5V 入力に対応しておらず、絶対最大定格は 3.6V 前後です。ここに HC-SR04 の Echo(5V)を直結すると、チップにダメージを与える可能性があります。

Trig と Echo で扱いが違うので、分けて考えます。

【重要】Echo の 5V を Pico の GPIO に直結しない — 抵抗2本で分圧する

Echo はセンサーから出てくる信号で、HIGH のとき電源電圧(5V)近くまで上がります。これを Pico が安全に読める電圧まで下げます。いちばん簡単なのが抵抗2本の分圧です。

今回は手元にあった 1.0kΩ と 2.2kΩ を使いました。

HC-SR04 Echo ──[ 1.0kΩ ]──┬── GP2(Pico)
                          │
                       [ 2.2kΩ ]
                          │
                         GND

分圧ノードの電圧 ≒ 5V × 2.2 /(1.0 + 2.2)≒ 3.4V

3.4V は RP2040 / RP2350 の絶対最大定格 3.6V の範囲内で、かつ Pico が HIGH と判定するには十分な電圧です。実測でも問題なく測定できました。

  • もっと 3.3V ぴったりに寄せたいなら 1.8kΩ + 3.3kΩ などでも構いません(ノード ≒ 3.24V)。
  • 抵抗を触りたくなければ、市販の「ロジックレベル変換モジュール」を Echo の間に挟む方法もあります。
やりがちな失敗:分圧抵抗の向きを逆に付ける。Echo につながる側が直列(1.0kΩ)、GND につながる側が分圧(2.2kΩ)です。逆に付けるとノード電圧が約 1.56V にしかならず、Pico が HIGH と認識せず「まったく反射が返ってこない」ように見えます。

Trig は 3.3V 直結で OK・VCC は VBUS(5V)から取る

  • Trig: Pico から出す信号です。Pico の 3.3V を HC-SR04 に入れることになりますが、HC-SR04 側は 3.3V でも「HIGH」と認識してくれたので、今回は直結で動きました(動かない個体に当たったら、Trig にもレベル変換かトランジスタ1石が必要です)。
  • VCC: センサーの動作電源は 5V が必要です。Pico の「3V3(OUT)」から取ると、送信する超音波が弱く、近くの物しか測れない・まったく測れないといった症状が出ます。Pico を USB 給電しているなら、USB の 5V がそのまま出ている VBUS(物理40番) から取ります。
VCC を Pico の VBUS 端子へ
▲ VCC は Pico の VBUS 端子、GND は GND 端子へ。今回は Freenove のブレイクアウトボード経由

配線一覧

接続元接続先(Pico)物理ピン備考
HC-SR04 VCCVBUS(5V)403V3 だと送信が弱くて測れない
HC-SR04 TrigGP353.3V 直結で動作
HC-SR04 Echo1.0kΩ 直列 → 分圧ノード → GP24Echo は 5V で出る
分圧ノード2.2kΩ → GNDノード ≒ 3.4V
HC-SR04 GNDGND38
ブレッドボード上の配線と分圧抵抗
▲ ブレッドボード上の配線。中央に Echo 分圧用の抵抗2本(1.0kΩ・2.2kΩ)が入っている
配線全体
▲ 全体。Pico 2 W(Freenove ブレイクアウト)+ブレッドボード+スチール定規

スポンサーリンク

配線図と MicroPython の最小コード(使い方の基本)

配線ができたら、まず「1回測って距離を print する」だけの最小コードで動作確認します。

今回の結線図
▲ 今回の結線図(HC-SR04 + OLED + ブザー。この章では HC-SR04 部分だけ使う。図は Pico W で描いているが Pico 2 W もピン配置は同じ)
信号線の接続
▲ 信号線の接続。Trig=GP3 / Echo(分圧後)=GP2 / OLED SDA=GP0 / SCL=GP1

MicroPython の書き込みや Thonny の使い方が初めての方は、先にこちらをご覧ください。

🔧 事前準備|MICROPYTHON ラズパイPico WとDHT11で温湿度を測定する方法|配線図とMicroPythonコード Pico への MicroPython 書き込みと Thonny の導入手順を、実機写真つきで解説しています。

この記事で使うコード(test001〜test004・main.py・切り分け用スクリプト)は、まとめてダウンロードできます。

📦 この記事のコード一式をダウンロード(ZIP・test001〜test004 / main.py ほか)

time_pulse_us() で Echo のパルス幅を測る

machine.time_pulse_us(pin, level, timeout_us) は、「指定ピンが level(今回は 1=HIGH)である時間をマイクロ秒で返す」関数です。HC-SR04 の Echo を測るためにあるような関数で、これを使うと測定部分が数行で書けます。

パルス幅から距離(cm)へ変換する

test001 の全文です。

"""
ultrasonic-distance-sensor001 test001: HC-SR04 で距離を1回測る最小コード
"""
from machine import Pin, time_pulse_us
import time

trig = Pin(3, Pin.OUT)
echo = Pin(2, Pin.IN)

# 20℃ のときの音速 [m/s]。気温で変わる(test002 で補正する)
SOUND_SPEED = 343.2
# この距離を超えたら「測れなかった」とみなす(センサーの実用上限)
MAX_RANGE_CM = 500


def measure_cm(timeout_us=60000):
    """1回だけ測って距離[cm]を返す。範囲外 / 反射なしなら None"""
    # Trig を最低 2us LOW にしてからパルスを出す
    trig.low()
    time.sleep_us(2)
    trig.high()
    time.sleep_us(10)
    trig.low()

    # Echo が HIGH になっている時間(us)を測る
    dur = time_pulse_us(echo, 1, timeout_us)
    if dur < 0:
        return None

    # dur[us] -> [s] にして音速[m/s]を掛け、cm に直して往復ぶんを半分にする
    distance_cm = (dur / 1_000_000) * SOUND_SPEED * 100 / 2
    if distance_cm > MAX_RANGE_CM:
        return None
    return distance_cm


while True:
    d = measure_cm()
    if d is None:
        print("測定できませんでした(範囲外 / 反射なし)")
    else:
        print("距離: {:.1f} cm".format(d))
    time.sleep(0.5)

対応ファイル: ultrasonic-distance-sensor001-test001.py

test001.py 実行中のシェル
▲ test001.py 実行中のシェル。対象を動かすと距離が変わる
▲ 手を近づけたり離したりすると数値が追従する

反射が返らないときの落とし穴 — 「約58ms」というダミー値

HC-SR04 でいちばんハマりやすいのがここです。

time_pulse_us() は、指定した timeout_us の間ずっと Echo が HIGH にならなければ、負の値(-2 など)を返します。それなら if dur < 0 で弾けそうに見えます。

ところが このモジュールは、反射音を受け取れなかったとき Echo を約 58ミリ秒(距離に直すと約1000cm)HIGH にしてから LOW に戻します。 これは正の値なので dur < 0 はすり抜けます。何も対策しないと「1000cm」というありえない距離がしれっと混ざります。

対策は、MAX_RANGE_CM(実用上限=500cm)を超えた値を None にすることです。上のコードの if distance_cm > MAX_RANGE_CM: return None がそれです。ここを入れておかないと、次の章のフィルタも意味をなしません。

測れないときの切り分け手順

「配線したのに測れない」ときは、time_pulse_us を使わず自分で Echo を監視するデバッグ用スクリプトで、どこで詰まっているか切り分けます。今回、前述の初期不良を特定したときにやった順番です。

  1. Echo のアイドル電位: 測定していないとき Echo は LOW のはず。echo.value() を1000回読んで全部 0 か確認する。0 でない回が多ければ、Echo の配線か分圧抵抗の向きを疑う
  2. 自前でパルス幅を測る: Trig を出した後、echo.value() が 1 になるのを待ち、0 に戻るまでの時間を time.ticks_us() で測る。ここで一度も HIGH にならなければ、Trig が弱い(3.3V)か分圧しすぎ
  3. time_pulse_us の生の戻り値: -2 ばかり=一度も HIGH にならない、-1=HIGH のまま戻らない、正の値=そのパルス幅
  4. テスターで VCC を実測: センサーの VCC に本当に 5V 来ているか。VBUS の電圧も見る

今回の初期不良品は「1・2・3 すべて正常なのに、パルス幅が毎回 約58800µs(反射なしのタイムアウト値)で一定」でした。センサーの正面で手や本を前後に動かしても数値がまったく変わらない=送信または受信ができていない、という結論です。別個体に替えて解決しました。

Thonny のインタプリタ選択ミス:ModuleNotFoundError: No module named 'machine' が出たら、Thonny の右下のインタプリタが「Local Python 3」になっています。「MicroPython (Raspberry Pi Pico)」を選び直してください。

スポンサーリンク

測定値がばらつく・ちらつく問題への対策

test001 をしばらく動かすと、対象を固定していても値がチラチラ変わり、ときどき大きく外れた数字が出ることに気づきます。実用に使うにはひと手間必要です。

数十回に数回混ざる「飛び値」を中央値で無視する

面にきちんと正対させていても、数十回に数回は「反射なし(≒1000cm、コード上は None)」や、実際より大きく外れた値が混ざります。超音波が一度あらぬ方向に反射して、遠回りして戻ってきたケースなどです。

ここで平均を取ると、1回の大外れに全体が引きずられます。中央値(ソートして真ん中の値) なら、飛び値はきれいに無視できます。5回測って3番目の値を採用する、という単純な処理です。

測定と測定の間隔を 60ms 以上あける理由

立て続けに測ると、前回出した超音波の反射(残響)がまだ空気中や周囲に残っていて、それを拾って誤測定します。HC-SR04 のデータシートでも測定周期は 60ms 以上が推奨されています。連続測定するときは各測定の間に time.sleep_ms(60) を入れます。

気温を使った音速補正で誤差を減らす

test001 では音速を 343.2 m/s(20℃相当)で固定していました。ここを実際の室温で計算し直します。

今回の環境は室温 25.6℃でした。v = 331.5 + 0.6 × 25.6 ≒ 346.9 m/s です。この補正を入れたら、後述の 50cm 測定で 誤差がほぼゼロになりました。気温センサー(DHT11 など)を積んでいれば自動で、なければ手元の温度計の値を定数で渡します。

測定時の室温を温度計で確認
▲ 測定時の室温を温度計で確認(25.6℃)。この値を DEFAULT_TEMP_C に入れる

test002 の全文です。

"""
ultrasonic-distance-sensor001 test002: 測定値のばらつき対策 + 気温補正
"""
from machine import Pin, time_pulse_us
import time

trig = Pin(3, Pin.OUT)
echo = Pin(2, Pin.IN)

MEASURE_GAP_MS = 60      # 測定と測定の最小間隔
DEFAULT_TEMP_C = 25.6    # 気温センサーが無いときの仮の室温
MAX_RANGE_CM = 500       # これを超えたら「測れなかった」とみなす


def sound_speed(temp_c):
    """気温[℃]から音速[m/s]を返す"""
    return 331.5 + 0.6 * temp_c


def measure_once(temp_c, timeout_us=60000):
    """1回測って距離[cm]。範囲外 / 反射なしなら None"""
    trig.low()
    time.sleep_us(2)
    trig.high()
    time.sleep_us(10)
    trig.low()

    dur = time_pulse_us(echo, 1, timeout_us)
    if dur < 0:
        return None
    dist = (dur / 1_000_000) * sound_speed(temp_c) * 100 / 2
    if dist > MAX_RANGE_CM:
        return None
    return dist


def measure_cm(samples=5, temp_c=DEFAULT_TEMP_C):
    """samples 回測って中央値[cm]を返す。全部失敗したら None"""
    values = []
    for _ in range(samples):
        d = measure_once(temp_c)
        if d is not None:
            values.append(d)
        time.sleep_ms(MEASURE_GAP_MS)

    if not values:
        return None
    values.sort()
    return values[len(values) // 2]


while True:
    d = measure_cm(samples=5, temp_c=DEFAULT_TEMP_C)
    if d is None:
        print("測定できませんでした")
    else:
        print("距離(中央値): {:.1f} cm".format(d))
    time.sleep(0.3)

対応ファイル: ultrasonic-distance-sensor001-test002.py

test002.py 実行中のシェル

▲ test002.py 実行中のシェル。値の暴れが収まる

左が test002 実行中のシェルです。中央値フィルタが効いて、test001 で見られた値の暴れ(たまに混ざる 1000cm など)が収まります。

右の写真は 50cm の位置に対象を置いた測定の様子です。

50cm の位置に対象を置いた測定の様子
▲ 50cm の位置に対象を置いて確認

スポンサーリンク

実際に測って精度を検証してみた

カタログの「2〜500cm」を鵜呑みにせず、メジャーで実距離を測って対象を置き、センサーの値と突き合わせました。「この数字はどこまで信じていいのか」を知っておくと、応用のときに判断できます。

精度検証用のロガー(test003)

指定回数ぶん連続測定して、平均・中央値・最小・最大・ばらつき(標準偏差)・実距離との誤差を出すだけのスクリプトです。TRUE_DISTANCE_CM にメジャーの値、ROOM_TEMP_C に室温を入れて実行し、対象を 10 / 20 / 50 / 100 / 200 / 300cm と動かして毎回実行しました。

# test003 の集計部分(全文は配布ファイル参照)
def stats(values):
    n = len(values)
    mean = sum(values) / n
    var = sum((x - mean) ** 2 for x in values) / n
    s = sorted(values)
    return mean, s[n // 2], s[0], s[-1], var ** 0.5   # 平均, 中央値, 最小, 最大, 標準偏差

対応ファイル: ultrasonic-distance-sensor001-test003.py

実距離 50cm での集計結果
▲ 実距離 50cm での集計結果。平均の誤差 +0.0cm

メジャー実測 vs センサー値(10cm〜300cm)

室温 25.6〜26.3℃、平らで固い面(本・板)に正対、各条件 30 回連続測定した結果です。

実距離平均中央値最小〜最大ばらつき(±)平均の誤差反射なし
3cm(至近)4.2cm4.5cm3.7〜4.60.35+1.2cm(+41.5%)0/30
10cm10.8cm10.7cm10.7〜11.50.29+0.8cm(+7.9%)0/30
20cm22.6cm22.6cm22.6〜22.60.00+2.6cm(+13.1%)0/30
50cm50.0cm49.9cm49.9〜50.80.28+0.0cm(0.0%)0/30
200cm201.4cm200.1cm199.2〜209.02.83+1.4cm(+0.7%)0/30
250cm250.8cm250.7cm249.4〜254.10.87+0.8cm(+0.3%)0/30
300cm301.1cm300.6cm299.6〜304.31.23+1.1cm(+0.4%)0/30
精度検証のセットアップ
▲ スチール定規を伸ばし、対象を実距離ちょうどに置いて30回連続測定する

誤差が大きくなる条件(斜めの面・柔らかい面・至近距離)

すべて実距離 50cm で、条件だけ変えた結果です。

条件平均誤差反射なし解釈
面を45°傾ける59.7cm+9.7cm(+19.3%)0/30斜め面は正面に返らず、遠回りした反射を拾う
対象をタオル/布97.8cm+47.8cm(+95.6%)9/30繊維が超音波を吸収・散乱。実質測定不能
至近 3cm4.2cm+1.2cm(+41.5%)0/30送受信の切替が間に合わず近距離は苦手
対象を45°傾けた測定

▲ 50cm の位置に対象を 45° 傾けて置くと、平均で +10cm 近くずれる

左は 50cm の位置に対象を 45° 傾けて置いたときの様子です。平均で +10cm 近くずれました。指向角から外れた面は、音がまっすぐ返ってこないためです。

下は同じ 50cm の位置にタオルを置いたとき。値が倍近くになり、3割は「反射なし」でした。布はほぼ測れないと考えたほうがよいです。

対象をタオルにした測定
▲ 50cm の位置にタオルを置くと値が倍近くになり、3割は反射なし。布はほぼ測れない

カタログの 500cm は実用でどこまで届くか

  • 300cm は、対象の面をセンサーときっちり平行にしないと検出できませんでした。何度も位置を調整してようやく安定します。指向性がシビアです。
  • 人が横切ったのを拾えるのは体感 250cm くらいまで。
  • 500cm は今回の環境(6畳間)では条件を作れず未検証。カタログ値は理想条件の数字なので、実用は 2〜3m と見ておくのが安全です。

この個体で分かったこと(記事の結論)

精度検証のまとめ

  • 30cm〜300cm・正対・固い面なら優秀。絶対誤差は数cm、相対誤差 1% 以下(50cm で誤差ゼロ)。
  • 20cm 以下は相対誤差が大きい(+8〜13%)。距離が近いほど「約 +1cm の下駄」が効いてくる。
  • 全体に +1cm 前後の系統誤差(オフセット) がある個体。気になるなら main.pyOFFSET_CM = -1.0 で詰められる。
  • 中央値フィルタが効いている。200cm で最大 209cm(+9cm)の外れ値が出たが、中央値 200.1cm は実距離どおり。
  • 斜めの面・柔らかい面は苦手。布は測定不能。距離を測りたい対象は「固くて平ら」が前提。

スポンサーリンク

距離を OLED(SSD1306)にリアルタイム表示する

PC につながず単体で距離が見えるように、0.96インチ OLED(SSD1306、I2C接続)に数値と横バーグラフを出します。

OLED の配線(SDA / SCL / VDD / GND)と micropython-ssd1306 ライブラリの導入は過去記事で解説しているので、そちらを参照してください。

📟 事前準備|OLED Raspberry Pi Pico Wで作る熱中症警戒アラート表示器 0.96インチ OLED(SSD1306)の配線と micropython-ssd1306 ライブラリの導入を解説しています。

追加の配線はこれだけです。

OLED接続先(Pico)物理ピン
SDAGP01
SCL(基板シルクは SCK)GP12
VDD3V3(OUT)36
GNDGND38

i2c.scan() で 0x3C を確認する

まず配線が正しいか、I2C バス上に OLED が見えているかを確認します。

from machine import Pin, I2C

i2c = I2C(0, scl=Pin(1), sda=Pin(0), freq=400000)
print("I2Cデバイス検出:", i2c.scan())   # [60] (0x3C) が出れば正常

I2Cデバイス検出: [60] と出れば OK です(60 は 0x3C、SSD1306 の標準アドレス)。[] なら SDA/SCL の挿し間違い、ジャンパの半挿し、VDD/GND の未接続を疑います。

標準フォントを拡大して大きく表示する

ssd1306 ライブラリの oled.text() は 8×8 ピクセル固定で、距離の数字を出しても離れると読めません。小さな FrameBuffer に一度描いてから、点いているピクセルを scale×scale の四角として拡大コピーする text_scaled() を使います。この仕組みは前回の記事で詳しく書いたので、ここでは関数だけ載せます。

🔤 くわしい解説 サーボモータの角度をタクトスイッチで可変|OLED(SSD1306)に現在角度をリアルタイム表示 標準8×8フォントを framebuf で拡大描画する text_scaled の仕組みを、この記事で詳しく解説しています。
import framebuf

def text_scaled(fb, s, x, y, scale, color=1):
    """標準8x8フォントの文字列を scale 倍に拡大して描画する"""
    w = len(s) * 8
    tmp = framebuf.FrameBuffer(bytearray(8 * ((w + 7) // 8)), w, 8, framebuf.MONO_HLSB)
    tmp.fill(0)
    tmp.text(s, 0, 0, 1)
    for ty in range(8):
        for tx in range(w):
            if tmp.pixel(tx, ty):
                fb.fill_rect(x + tx * scale, y + ty * scale, scale, scale, color)

ちらつき対策 — 変化したときだけ描き直す

oled.show() は 128×64=1024バイトのバッファを I2C で丸ごと送るため、1回 20ms 以上かかります。毎ループ呼ぶと画面がちらつき、測定周期も伸びます。前回表示した距離と 0.5cm 以上変わったときだけ draw() を呼ぶようにして、静止時は再描画しないようにしました。

main.py 全文

test002(中央値フィルタ + 気温補正)に OLED 表示を統合した本番プログラムです。Pico 本体に main.py として保存すれば、PC も Thonny もつながず、モバイルバッテリー給電などで単体動作します。

"""
ultrasonic-distance-sensor001 main.py: HC-SR04 の距離を OLED(SSD1306)に
数値+横バーグラフでリアルタイム表示する

配線 (結線図と同じ):
- HC-SR04 VCC  -> VBUS(5V) / 物理40番
- HC-SR04 Trig -> GP3 / 物理5番
- HC-SR04 Echo -> 1.0kΩ -> 分圧ノード -> GP2 / 物理4番
                  分圧ノード -> 2.2kΩ -> GND
- HC-SR04 GND  -> GND / 物理38番
- OLED SDA -> GP0 / SCL -> GP1 / VCC -> 3V3(OUT) / GND -> GND

事前準備: Thonny の「パッケージを管理...」で micropython-ssd1306 を入れておく
"""
from machine import Pin, I2C, time_pulse_us
import framebuf
import ssd1306
import time

# ===== HC-SR04 =====
trig = Pin(3, Pin.OUT)
echo = Pin(2, Pin.IN)

MEASURE_GAP_MS = 60
DEFAULT_TEMP_C = 26.7     # 気温センサーが無いときの仮の室温
BAR_MAX_CM = 300          # 横バーが振り切れる距離
MAX_RANGE_CM = 500        # これを超えたら「測れなかった」とみなす
OFFSET_CM = 0.0           # 実測すると全体に +1cm ほど出る個体があった。
                          # メジャーと比べて詰めたいときはここに補正値(例 -1.0)を入れる
REDRAW_THRESHOLD_CM = 0.5  # この差より小さい変化では描き直さない(ちらつき対策)


def sound_speed(temp_c):
    return 331.5 + 0.6 * temp_c


def measure_once(temp_c, timeout_us=60000):
    trig.low()
    time.sleep_us(2)
    trig.high()
    time.sleep_us(10)
    trig.low()
    dur = time_pulse_us(echo, 1, timeout_us)
    if dur < 0:
        return None
    dist = (dur / 1_000_000) * sound_speed(temp_c) * 100 / 2 + OFFSET_CM
    if dist > MAX_RANGE_CM:
        return None
    return dist


def measure_cm(samples=5, temp_c=DEFAULT_TEMP_C):
    values = []
    for _ in range(samples):
        d = measure_once(temp_c)
        if d is not None:
            values.append(d)
        time.sleep_ms(MEASURE_GAP_MS)
    if not values:
        return None
    values.sort()
    return values[len(values) // 2]


# ===== OLED =====
i2c = I2C(0, scl=Pin(1), sda=Pin(0), freq=400000)
print("I2Cデバイス検出:", i2c.scan())   # [60] (0x3C) が出れば正常
oled = ssd1306.SSD1306_I2C(128, 64, i2c)


def text_scaled(fb, s, x, y, scale, color=1):
    """標準8x8フォントの文字列を scale 倍に拡大して描画する"""
    w = len(s) * 8
    tmp = framebuf.FrameBuffer(bytearray(8 * ((w + 7) // 8)), w, 8, framebuf.MONO_HLSB)
    tmp.fill(0)
    tmp.text(s, 0, 0, 1)
    for ty in range(8):
        for tx in range(w):
            if tmp.pixel(tx, ty):
                fb.fill_rect(x + tx * scale, y + ty * scale, scale, scale, color)


def draw(distance_cm):
    oled.fill(0)
    if distance_cm is None:
        text_scaled(oled, "-- cm", 8, 10, 2)
        oled.text("out of range", 16, 44, 1)
        oled.show()
        return

    # 上段: 距離の数値(2倍角)
    text_scaled(oled, "{:>3d} cm".format(int(round(distance_cm))), 4, 6, 2)
    # 下段: 0-BAR_MAX_CM の横バーグラフ
    bx, by, bw, bh = 6, 42, 116, 16
    oled.rect(bx, by, bw, bh, 1)
    ratio = min(1.0, distance_cm / BAR_MAX_CM)
    fill_w = int(ratio * (bw - 4))
    oled.fill_rect(bx + 2, by + 2, fill_w, bh - 4, 1)
    oled.show()


# ===== メイン =====
last_shown = None
draw(None)
print("準備完了")

while True:
    d = measure_cm(samples=5, temp_c=DEFAULT_TEMP_C)

    if d is None:
        if last_shown is not None:
            draw(None)
            last_shown = None
        print("距離: 範囲外")
    else:
        if last_shown is None or abs(d - last_shown) >= REDRAW_THRESHOLD_CM:
            draw(d)
            last_shown = d
        print("距離: {:.1f} cm".format(d))

    time.sleep_ms(120)

対応ファイル: main.py

main.py の設定値まわりと実行中のシェル
▲ main.py の設定値まわりと実行中のシェル。中央値を通した距離が流れ、500cm超は「範囲外」

動いている様子は冒頭の完成動画のとおりです。対象を近づける/遠ざけると、OLED の数字とバーがリアルタイムに追従します。

✓ 動作確認方法

  1. Thonny でコードを開き F5 で実行する
  2. シェルに I2Cデバイス検出: [60] が出る
  3. OLED に大きな数字で距離(cm)、下に横バーが出る
  4. 対象を近づける/遠ざけると、数字とバーが追従する
  5. 500cm を超える/反射がない状態で -- cm out of range になる

スポンサーリンク

応用アイデア(駐車アシスト・障害物検知・液面レベル計)

距離が測れて表示できると、あとは「ある距離より近づいたら何かする」だけでいろいろ作れます。

  • 駐車アシスト / バックソナー: 壁との距離に応じてブザーの間隔を変える。近いほど速く鳴らす
  • 障害物検知ロボット: 前方の距離が一定以下になったら停止・方向転換
  • 液面レベル計: タンクの上からセンサーを下向きに付け、水面までの距離で残量を推定(水面は平らなので相性が良い)
  • 自動点灯 / 人感: 一定距離内に人が入ったら LED や照明を点ける

ここでは1つめの「バックソナー風の障害物アラート」を作りました(test004)。距離に応じて LED・ブザー・OLED の警告レベルを切り替えます。

距離レベルブザー / LEDOLED 表示
50cm 以上・範囲外SAFE消灯SAFE
30〜50cmCAUTION遅い断続(600ms)CAUTION
20〜30cmWARNING速い断続(200ms)WARNING(白黒反転)
20cm 未満DANGER鳴りっぱなしDANGER(白黒反転)
アクティブブザーの配線
▲ アクティブブザーを追加。赤線=GP15、黒線=GND
▲ 対象を近づけると SAFE → CAUTION → WARNING → DANGER と切り替わり、ブザーの鳴り方が変わる

使ったブザーは「アクティブ・アクティブハイ」だった

手元のブザー(基板に「PCB120」の表記)が、電圧をかけるだけで鳴る「アクティブブザー」なのか、PWM で周波数を与えないと鳴らない「パッシブブザー」なのか分からなかったので、1状態ずつ確認しました。

# buzzer-check.py の要点
buz = Pin(15, Pin.OUT)
buz.low()          # step0: 静かなはず
buz.high()         # step1: 鳴れば「アクティブ・アクティブハイ」
time.sleep(3)
buz.low()          # step2: 止まるはず
# step3: PWM 2kHz -> アクティブなら不要、パッシブならここで初めて鳴る
  • DC HIGH で鳴りっぱなし → アクティブブザー(自励式)。今回のはこれ
  • 一瞬「プッ」と鳴るだけ → パッシブブザー(PWM が必要)
  • 見た目の目安: 裏が黒く密閉されている=アクティブ、緑の基板が見える=パッシブ。極性線(赤黒)があるものはアクティブが多い

今回の品は GP15 を HIGH にすると鳴る(アクティブハイ) で、PWM は不要でした。PWM 2kHz でも鳴りましたが、内蔵発振の共振周波数から外れるため音は弱く低くなります。

起動時に勝手に「ピー」と鳴る問題

電源を入れてからプログラムが動き出すまでの一瞬、GP15 の状態が不定になり、アクティブブザーが「ピー」と鳴ることがあります。対策はスクリプトの冒頭で必ず出力を LOW にすることです。

buzzer = Pin(15, Pin.OUT)
buzzer.low()   # 起動直後のノイズ鳴りを止める。他の初期化より先に

ハードで確実に消したい場合は、GP15 と GND の間に 10kΩ 程度の抵抗(プルダウン)を入れておくと、マイコンが制御する前は必ず LOW に落ちます。

test004 のレベル判定と OLED 反転表示の要点です。

def level_of(distance_cm):
    if distance_cm is None or distance_cm >= 50:
        return "SAFE"
    if distance_cm >= 30:
        return "CAUTION"
    if distance_cm >= 20:
        return "WARNING"
    return "DANGER"

# WARNING / DANGER は OLED を白背景に反転させて目立たせる
LEVELS = {
    "SAFE":    (None, False),   # (ブザー周期ms / None=消灯 / 0=鳴りっぱなし, 反転表示)
    "CAUTION": (600,  False),
    "WARNING": (200,  True),
    "DANGER":  (0,    True),
}

対応ファイル: ultrasonic-distance-sensor001-test004.py

test004.py 実行中のシェル
▲ test004.py 実行中のシェル。距離とレベルが流れる

この記事のコードをまとめてダウンロード

ここまでで登場した MicroPython コードを ZIP にまとめました。配線メモを書いた README.txt と、うまく測れないときの切り分け用スクリプト(debug.py / debug2.py)、ブザー判別用の buzzer-check.py も同梱しています。

📦 この記事のコード一式をダウンロード(ZIP・test001〜test004 / main.py ほか)


スポンサーリンク

よくある質問(FAQ)

Qこのセンサーの精度はどれくらいですか?

A今回の個体では、30cm〜3m の範囲で、固くて平らな面に正面から向ければ、絶対誤差は数cm・相対誤差は 1% 以下でした(50cm では誤差ゼロ)。ただし 20cm 以下は +8〜13% と誤差が大きく、対象の面が傾いていたり布などの柔らかい素材だと大きくずれる・まったく測れないこともあります。「固い平面までのざっくりした距離」を測る用途なら十分実用的です。

QRaspberry Pi Pico の 3.3V で動かせますか? 5V は必須ですか?

Aセンサーの電源(VCC)は 5V が必要です。Pico の 3V3(OUT)から取ると、送信する超音波が弱く、まともに測れません。Pico を USB 給電しているなら VBUS(5V)から取ります。一方、Echo の信号は 5V で出てくるので、そのまま Pico の GPIO に入れず、抵抗2本で 3.3V 前後に分圧します(記事本文参照)。

Q分圧せずに Echo を直結したら壊れますか?

APico の GPIO の絶対最大定格は 3.6V 前後で、そこに 5V が入る状態になります。すぐ壊れないこともありますが、メーカーの想定外の使い方で、じわじわ劣化する・ある日突然そのピンが死ぬ、というリスクがあります。抵抗2本(数円)かレベル変換モジュールを挟むだけなので、必ず対策することをおすすめします。

Q超音波距離センサーを複数個いっぺんに使えますか?

A使えます。ただし Trig / Echo のピンをセンサーごとに分け、測定のタイミングをずらします。同時に鳴らすと、隣のセンサーが出した超音波を自分の反射だと勘違いして誤測定する(混信)ためです。1個測る→少し待つ→次を測る、と順番に回します。

Q屋外や車で使えますか?

A使えますが、風が強いと反射がぶれます。また気温変化で音速が変わるので、温度補正(v = 331.5 + 0.6 × 気温)を入れておくと安定します。直射日光でセンサー本体が高温になると値が甘くなることもあります。

QArduino 用の HC-SR04 コードをそのまま Pico に使えますか?

A考え方は同じですが、そのままは動きません。Arduino の pulseIn() は MicroPython では machine.time_pulse_us() に置き換えます。また Arduino UNO は 5V マイコンなので Echo を直結できましたが、Pico は 3.3V なので Echo の分圧(またはレベル変換)が必須です。この2点を直せば、あとはほぼ同じロジックで動きます。

QHC-SR04+ / HC-SR04P との違いは?

A「+」が付くものは電源電圧が 3.3〜5V に対応していて、3.3V で給電すれば Echo も 3.3V で出るため、Pico で使うときの分圧が不要になります。今回の Winova は無印相当(5V専用)なので分圧しました。これから買うなら「+」表記のものを選ぶと配線が1つ減ります。


スポンサーリンク

まとめ

HC-SR04(互換品)を Raspberry Pi Pico + MicroPython で、距離測定から OLED 表示・障害物アラートまで一通り動かしました。

  • 仕組みは「超音波を出して跳ね返る時間を測る」だけ。距離 = 音速 × Echo パルス幅 ÷ 2、音速は 331.5 + 0.6 × 気温
  • Pico で使うときの肝は Echo の分圧。5V の Echo を抵抗2本(1.0kΩ + 2.2kΩ)で 3.4V に落として GP2 へ。Trig は 3.3V 直結、VCC は VBUS(5V)から
  • 反射がないとき約1000cm のダミー値が返るので上限で弾く。値のばらつきは中央値フィルタと 60ms 間隔で抑える
  • 精度は、30cm〜3m・正対・固い面なら誤差1%以下で優秀。20cm 以下と、斜め・柔らかい面は苦手
  • 2個セットの初期不良、起動時のブザー鳴りなど、実機ならではの小さいハマりもあった

安くて扱いやすいセンサーですが、「どういう条件で正確に測れて、どういう条件でダメか」を先に知っておくと、応用のときに悩まずに済みます。


この記事が役に立ったら、シェアしてもらえると嬉しいです🥕

Xでポスト はてブ LINE Pocket
ニンジン🥕アイコン

Follow me on X

本ブログの中の人「ニンジン🥕」はXやってます。新着記事はいち早くポストでお知らせしているので、見逃したくない方は @ninjin_py_vba をフォローしてみてください🥕

@ninjin_py_vba をフォロー

PROJECT LOG — SERIES INDEX
スポンサーリンク

シリーズ記事一覧

電子工作・自動化ツールの製作記録をシリーズごとにまとめています。気になるテーマからお読みください。


超音波距離センサーHC-SR04をRaspberry Pi Picoで使う|仕組み・配線・精度検証
.uds1-block { position: relative; overflow: hidden; border-radius: 12px; border: 1px solid #f0cba8; background: linear-g…
今週の注目ガジェット〜09/07週〜|電子工作・自作向け新製品まとめ(TickrCast/Radxa Linkr ほか)
ニンジンのガジェット通信 09/07週。ESP32-P4の自作気象モニター、極小IP-KVM「Radxa Linkr」、ESP32のDINレール型PLC、LTE開発キットなど、電子工作で使えそうな新製品5つを解説。
サーボモータの角度をタクトスイッチで可変|OLED(SSD1306)に現在角度をリアルタイム表示
Raspberry Pi Pico 2W×MG996RにタクトスイッチとOLED(SSD1306)を追加。ボタンで角度を可変しながら現在角度をリアルタイム表示するMicroPython実装を、framebufの文字拡大やサーボの遊び対策まで実機ベースで解説します。
MG996RサーボモーターをRaspberry Pi Pico 2Wで動かす:PWM制御とキャリブレーション実践
MG996RサーボモーターをRaspberry Pi Pico 2Wで動かす方法を解説。公称180度のはずが実測198度だった個体差の原因究明から、ホーンのズレ補正、タクトスイッチでの角度制御まで実機検証の様子を紹介します。
Tapo P110Mの消費電力をExcelレポート化する【年次集計・電気代試算・セキュリティ判断編】
FastAPI+openpyxlでTapo P110Mの消費電力をExcelレポート化。15秒間隔の生ログを日次集計する設計や、31円/kWhでの電気代試算、外部公開を見送った理由まで解説します。

コメント