0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Raspberry pi 3+ に気圧/湿度/温度センサを付けてデータ取得する

Posted at

Raspberry pi 3+ を買ったので、折角なのでセンサーも買ってみました。
BME280(気圧/湿度/温度センサ)です。
コマンドでデータ取得して、更にWebSocket経由でブラウザに表示してみます。

接続

BME280モジュール RasPIピン番号 RasPIピン機能
VCC 1 3V3 Power
GND 9 Ground
SCL 5 GPIO4(SCL)
SDA 3 GPIO3(SDA)
CSB 17 3V3 Power
SDD 13 Ground

はんだは気合で付ける。
メスメスのジャンパピンは予め用意しときましょう。

I2Cを有効にする

raspi-config をインストールします。
Ubuntu Mate でしたが、apt ですんなり入りました。

$ sudo apt install -y raspi-config

設定を開きます。

$ sudo raspi-config

以下の画面が開くので、I2Cを有効にします。
スクリーンショット 2025-05-27 011253.png

スクリーンショット 2025-05-27 011320.png

デバイス確認

再起動後に /dev/i2c-nn でデバイスが認識されています。

$ ls  /dev/i2c-*
/dev/i2c-1  /dev/i2c-2

i2cdetect コマンドでスキャンしてみます。

$ i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- 76 --   

0x76 でデバイスが見つかりました。適当なはんだでも認識するもんですね。

データ取得

データを取得してみます。巷では python が大半ですが、コマンドにしたいので Rust で書きます。
BME280のデータ取得できる Crates があるのでお世話になってみます。

ほぼ example のまま使えます。

main.rs
use linux_embedded_hal as hal;

use linux_embedded_hal::{Delay, I2cdev};
use bme280::i2c::BME280;

fn main() {
    let i2c_bus = I2cdev::new("/dev/i2c-1").unwrap();
    let mut delay = Delay;
    let mut bme280 = BME280::new_primary(i2c_bus);

    bme280.init(&mut delay).unwrap();

    let measurements = bme280.measure(&mut delay).unwrap();

    println!("Relative Humidity = {} %", measurements.humidity);
    println!("Temperature = {} C", measurements.temperature);
    println!("Pressure = {} hPa", measurements.pressure/100.0);
}

ビルドしてみます。

$ cargo run
Relative Humidity = 52.11411 %
Temperature = 25.01252 C
Pressure = 1015.226 hPa

データが取れました。温度が5℃くらい高い気がしますが、こんなもんなんでしょうきっと。
リリースビルドします。

$ cargo build --release

target/release/ 以下にバイナリができます。実行するとデータが表示されます。
i2c-view というコマンドにしました。

$ ./i2c-view
Relative Humidity = 52.08504 %
Temperature = 25.02518 C
Pressure = 1015.21954 hPa

良いですね。/usr/sbin/ 以下に移動して実行権限をつけておきます。

ローカルのWebサービスからデータ参照する

ラズパイ上のWebブラウザから、ローカルのデータを拾います。
今回は WebSocket サーバを起動して、Webブラウザから投げたメッセージでコマンド結果を返すサービスを作りました。
localhost でphpなりpythonなりを動かせばいいんですが、諸事情でそうはなってないので少し遠回りします。

WebSocket サーバを作る

メッセージを受け取ってコマンドの結果を返すだけなので、セキュリティなんかは無視します。
どうせLAN内からでしか見ません。

main.rs
use tokio::net::TcpListener;
use tokio_tungstenite::accept_async;
use tokio_tungstenite::tungstenite::protocol::Message;
use anyhow::Result;
use futures_util::{SinkExt, StreamExt};
use tokio::process::Command;

#[tokio::main]
async fn main() -> Result<()> {
    let addr = "127.0.0.1:8888".to_string();
    let listener = TcpListener::bind(&addr).await?;
    println!("WebSocket server started on ws://{}", addr);

    while let Ok((stream, _)) = listener.accept().await {
        tokio::spawn(handle_connection(stream));
    }

    Ok(())
}

async fn handle_connection(stream: tokio::net::TcpStream) -> Result<()> {
    let mut ws_stream = accept_async(stream).await?;
    println!("WebSocket connection established");

    while let Some(msg) = ws_stream.next().await {
        let msg = msg?;
        if msg.is_text() {
            let received_text = msg.to_text()?;
            println!("Received message: {}", &received_text);
            let mut res = "".to_string();

            if received_text == "i2c-view" {
                let output = Command::new("i2c-view").output().await.unwrap();
                res = String::from_utf8_lossy(&output.stdout).to_string();
                println!("{}", &res);
            }

            ws_stream.send(Message::Text(res)).await?;
        }
    }

    Ok(())
}

println!は無くてもいいです。分りやすいように書いただけなので。

HTML側は以下にしました。
サービス自体は別サーバに置いていても良いので、WebSocket は楽で良いですね。
※当然ラズパイ以外からはデータ取得できませんが。

var ws = new WebSocket('ws://127.0.0.1:8888');
ws.addEventListener("message", function(event) {
	var i2cs = String(event.data).split(/\r?\n/g);
	var hum = Number(i2cs[0].match(/([\d\.]+)/)[0]);
	var temp = Number(i2cs[1].match(/([\d\.]+)/)[0]);
	var pres = Number(i2cs[2].match(/([\d\.]+)/)[0]);
	document.querySelector('.humi').textContent = '湿度: ' + Math.round(hum) + '%';
	document.querySelector('.temp').textContent = '温度: ' + Math.round(temp)+ '';
	document.querySelector('.pres').textContent = '気圧: ' + Math.round(pres)+ 'hPa';
});
setInterval(function() {
	ws.send('i2c-view');
}, 10000);

エラーハンドリングがあまあまですが、必要に応じて。

BME280をラズパイに付けてデータ取得、更にWebSocketを通してWebブラウザ上に表示することができました。

所感

ラズパイ面白いですが、3+は流石に重いですね。
サイネージとかのGUI使うサービスを考えるならラズパイ4以上の方が良さそう…と買ってから思いました。
いかんせん、tauri のビルドに一晩どころか丸一日かかるとかしんどすぎます。
今回の Rust のコードのビルドは10分くらいで終わるので、スペックに合ったものを作るならいいデバイスですね。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?