Raspberry pi5に入門した

# 1. Raspberry piとは


公式
https://www.raspberrypi.com/products/raspberry-pi-5/


## 1-1. 何が嬉しいか


### 安価軽量小型Linux PCである


主機能をSOCチップ1つでまかなうことで小型、軽量、省電力、安価を実現したLinux PCデバイスと関連シリーズです。安価なので教育用途に適しますし、省電力なのでランニングコスト的にも嬉しいです


### コスパの良いサーバーである


ちょっとしたサーバーとしても使いやすいです。Linuxサーバーとしてネットワークの勉強をするのにも良いと思います。検索すると、内輪で使うマイクラのサーバーとして使ったり、自宅用のメディアサーバーにしたりといったユースケースが紹介されています。中にはラズパイサーバーを22基並列に並べてLG-WANを構築しちゃう人もいるようで、スキルがある人がガチで組めば結構なことができちゃうようです
https://x.com/dnobori/status/1357999824885272587


### 組み込み開発ができるLinux PCである


マイコンのI/Oのように使えるGPIOピンを備えていて、組み込みマイコンで使うセンサーやICを使って電子工作が出来ます


従来のマイコン開発は専用の書き込み機が必要だったり、マイコンのメモリが小さくて考えることが多かったりと開発への障壁がやや高めでしたが、ラズパイは追加デバイスなしでwifi接続できるLinux PCでマイコンI/Oが使える非常に魅力的なデバイスです


また、Raspberry piで開発したコードが動くRaspberry pi picoというマイコンモデルも存在するので、リソースが潤沢なRaspberry piで開発して組み込みデバイスとしてはRaspberry pi picoを制作するという方法も出来ます


## 1-2. Raspberry piの種類


種類がたくさんあって良く分からなくなりますが
大きく分けると以下の4種類になりそうです


Raspberry pi
Raspberry pi zero
Raspberry Pi 400
Raspberry pi pico


上3つがLinux PCとして動作するもので、Raspberry pi picoだけマイコンという扱いになるようです


### Raspberry pi


最初に登場したのがこのシリーズだと思います
最新のものがRaspberry pi5ですが、現在も3B+や4が購入できます
価格差が結構あるので用途によって旧モデルを選択することもありそうです


Raspberry pi5: 14000円ぐらい
Raspberry pi4: 10000円ぐらい
Raspberry pi3B+: 6500円ぐらい


### Raspberry pi zero


通常のRaspberry piシリーズよりも更に小型で安価なモデルです
スペック低めでピン数も少なめですがLinux PCとして動作します


消費電力も少なくて、picoが登場するより早い2015年に登場していることから推測すると、組み込みマイコン的な用途をこれでまかなっていこうという意図だったのかなと思います


Raspberry pi zero2 WH: 5000円ぐらい
Raspberry pi zero WH: 3800円ぐらい


末尾にWとはHが書かれているモデルは
wifiありモデルがW、ピンヘッダありがHです


### Raspberry pi pico


マイコンです


LinuxPCとしては動作しませんし、SDカードは差さらないし、そもそも載ってるメモリが264kByterしかないのでOSを動かすようなチップではありません。モニターも繋がらない純然たるマイコンですが、マイコンなので省電力軽量小型で安価です (公式価格は4ドルとかその辺です)。LinuxOSがない分だけ余計な処理がないのでSPI通信などの動作クロックはLinuxラズパイより速くて安定しています。高速センシングなどではむしろこちらの方がやりやすいと思います


それなら普通にその辺のマイコンで良いじゃないかと思うところですが、ラズパイと開発ツールやコードを共通化できるので、ラズパイとGPIOで開発した後に実用段階でpicoを選択するというやり方が想定されていると思います。また、wifi付きモデルもあるのでwifi IoT機器用マイコンとして考えても魅力的だと思います


マイコン単体としても、専用の書き込み機が不要でPCとUSB接続するだけで動かせるし、USB接続したまま開発して、完成したら本体フラッシュメモリに書いてスタンドアロンで動かすという開発方法になるのでめちゃめちゃ手軽です。PICマイコンで書き込み機にいちいち差してやってたのは何だったのかと思うような開発体験が得られます


### Raspberry pi 400


キーボード一体型のRaspberry piです
中身はRaspberry pi4同等で出先にモニタがあれば繋いで使えます
Raspberry pi5を入れたRaspberry pi 500も予定されているようです


## 1-3. どれを選ぶか


とりあえずさわってみたい人はRaspberry pi5か4が良いと思います


組み込み開発を中心にやっていきたい方の場合、GPIOを電源などに短絡すると破損することがありますので、電子工作に不慣れな方はいくつか壊すつもりで安価なモデルを選択しても良いと思います


バリバリ組み込みをやりたい人は最初からpicoを買うのでも良いかもしれませんが、そういう人はそもそもこの項を読む必要がない気がします


# 2. 購入


今回はRaspberry pi5を購入していじっていきます


## 2-1. 必要なもの


1. Raspberry pi5 本体
2. microSDカード (今回は64GB SDXCを使用)
3. USB-C電源 (純正だと5V/5Aだけど普通のUSB電源でも動くのは動く)
4. HDMI接続できるモニタ
5. micro HDMIケーブル
6. USBマウス
7. USBキーボード


リモートデスクトップなりSSHなりで使う場合は1～3だけで運用できますが、セットアップする際にモニタ、マウス、キーボードが必要だと思います


## 2-2. どこで買えるか


秋月電商、マルツ、Amazonなど、いろんなお店で買えます


# 3. OSインストール


Raspberry piはマイクロSDカードをストレージとして使用するので、マイクロSDカードにOSをインストールしてやれば動きます

2つのやり方があるようです


## 3-1. PCとSDカードリーダでOSをインストールする


PCとカードリーダーでマイクロSDカードにインストールして、インストール済みマイクロSDをラズパイに差して起動します


Raspberry pi Imagerというインストールソフトをダウンロードしてきて利用します
https://www.raspberrypi.com/software/


OSとしてはRaspberry pi OSやUbuntuが選択できます
今回はRaspberry pi OSを選択しました


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277233/e3a42393-f9c1-9bde-73be-92254456d2d1.jpeg" width=50%>


## 3-2. Raspberry pi本体でインストールする


Raspberry pi4以降では、本体だけでインストールすることができます


SDカードを差さない状態で電源を投入するとSHIFT長押しでインストールを開始するぞ、といったメッセージが画面に表示されますので画面の指示に従ってインストールを行います。こちらでやる場合はwifiが使えないようなのでLANケーブルを接続してやる必要があります


# 4. セットアップ


無事起動したら以下のような画面になると思います
普通に最近のLinuxデスクトップが起動しますので違和感なく使えると思います


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277233/60ac1112-5a9a-bd44-954b-7ff53a3c2362.jpeg" width=50%>


ここに開発用のあれこれをセットアップしていきたいと思います


## 4-1. リモートデスクトップを設定


ラズパイに画面を占有されていると困るので、リモートデスクトップできるようにしたいと思います。ラズパイ5はデフォルトでRealVNCのVNC Serverが標準でインストールされているので簡単にセットアップすることができます
https://www.realvnc.com/en/connect/download/viewer/


以下のページの手順で使えるようになります


https://techblog-ai.com/%E3%80%90raspberry-pi-5%E3%80%91%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97%E6%8E%A5%E7%B6%9A%E6%96%B9%E6%B3%95realvnc/


リモートアクセスする側にもRealVNCをインストールする必要がありますが、リモート先の選択もGUIで行えて手軽だし動作もスムーズで快適です


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277233/2c4a5363-4d6f-d259-4955-989a04cce2f9.png" width=50%>


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277233/3e4254ee-5e9d-0550-e2eb-e8d982de2d68.png" width=50%>


## 4-2. SSHを設定


### SSHを有効にする


ラズパイOSはデフォルトだとSSHが無効になっているようです
手順の説明はあちこちで見つけることができます
https://raspi-school.com/ssh/


```
sudo raspi-config
```


以下の順で選ぶと有効にできます


5. Interacting Options
　↓
P4 SPI
　↓
YES


ラズパイOSはデフォルトでファイアウォールがないのでこれで接続できる筈です
インターネットに公開するような場合はこれだとあっという間に侵入されますので絶対ダメですが、自宅ネットワークなど安全なところで使うようならこれで問題ないと思います


### Windowsから接続する


最近のWindowsはopen-sshが最初から入っていて
コマンドプロンプトから接続できるようです


ユーザーhogeとして192.168.xx.xxのラズパイにアクセスする場合はコマンドプロンプトから以下を実行すると、パスワードを要求されるので入力してやります


上手くログインできた場合はラズパイOSのCLIが表示されます


```terminal:コマンドプロンプト
>ssh hoge@192.168.xx.xx
hoge@192.168.xx.xx's password:
```

　
### VSCodeから接続する


VSCodeを起動するとSSHで開くか普通にフォルダを開くか選択できます
SSHを選択したらURLとユーザー名、パスワードを要求されるので入力してやります


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277233/a6e700de-fbb9-ba35-ba2d-5aa55c92bf64.png" width=50%>


## 4-3. dockerをインストール


コミュニティに手順があったので貼っておきます
僕の環境ではこれですんなり入りました
https://docs.docker.com/engine/install/debian/


インストールした後、/var/run/docker.sockのグループがdockerになっているせいでdocker runできなかったので、自分をdockerグループに追加しておきます


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277233/136447f3-8cb5-36ba-c8c8-7559a3652f9b.png" width=70%>


```terminal:terminal
sudo usermod -aG docker <username>
```


これで実行できるようになった筈です


```terminal:terminal
$ docker run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (arm64v8)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/
```


# 5. GPIOで組み込み開発を試す


## 5-1. GPIOについての注意点


GPIOは入力と出力の両方ができる端子ですが、電子工作に慣れた方なら知っているように、過電圧をかけたり短絡したりすると簡単に壊れてしまいます


### 出力の場合


出力に設定されている端子はHIGH/LOWのどちらかの電圧を出力します


HIGHのときは3.3Vを出力して、LOWのときは0Vを出力しますが、HIGHの出力を5Vや0Vと接続してしまったり、LOWの出力を3.3Vや5Vの電源と接続してしまうと大電流が流れて端子が破損してしまいます。ラズパイではまだやったことがないですが、マイコンの場合は大抵無言で壊れてそのピンが動作しなくなります


また、定格電流が1ピンあたり16mA、全体で50mAまでなので、短絡して大電流を流すのでなくても、うっかり電流流し過ぎて壊すこともあります。LEDなんかはVfを超える電圧をかけると電流がいくらでも流れてしまうので、抵抗を入れずにLチカやるとすぐ壊れます


### 入力の場合


入力に設定されている端子は基本的に電流が流れないので出力よりは壊れにくいですが、定格電圧を超えた電圧がかかると壊れます。定格範囲が0V～3.3Vなので、5V電源ピンと接続したりすると壊れますので注意が必要です


## 5-2. Pythonパッケージをインストールする


今回はPythonでプログラムを作っていきますが、ラズパイOSの場合はpipインストールはできなくなっています。組み込み用途などでユーザーがうっかりGPIO制御などに影響を与える変更ができないようにという配慮のようで、sudo apt installからでないとインストールできません


pandasをインストールする場合、以下のように実行します


```terminal:terminal
sudo apt install python-pandas
```


## 5-3. LEDを点灯してみる


マイコン買ったら最初にやる、マイコン版ハロワであるLチカをやってみます


### 配線


ラズパイのHIGH出力は3.3Vで、大抵のLEDのVfが2.3～2.7ぐらいなので、残った電圧である0.6～1.0Vぐらいで16mAより低くなるようにしてやります。1kΩ入れると0.6～1.0mAぐらい、330Ω入れると1.8～3.0mAぐらいなのでその辺が良いでしょう


ラズパイのピンには5V電源、3.3V電源、Ground(0V電源)が設定されているので、この辺とGPIOを組み合わせて配線してやれば簡単に回路が構成できると思います
https://www.raspberrypi.com/documentation/computers/raspberry-pi.html


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277233/18667d41-c9da-0c4e-6c00-5b37d5124d91.png" width=50%>


こんな感じです
GPIOを接続する前に抵抗とLEDだけで動作確認してからやると良いと思います


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277233/6c0b5c8e-0cf7-8ca1-4891-8fc5c4ef893b.png" width=50%>


### コーディング


ラズパイOSは最初からいろいろインストールされているので、Python入れたりしなくてもすぐにコーディングがはじめられます。ラズパイのコーディングではPythonやCが使えますが、良く使われるPythonを選択したいと思います


エディタとしてもThonnyやGeanyが選べますが、今回は軽量エディタであるThonnyを使ってやっていきます


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277233/05d3efe5-4832-eb29-c8b3-fc0b1e283a5b.png" width=50%>


PythonでRaspberry pi5のGPIOを操作するにはRPi.GPIO、gpiozeroが選択できます
今回はコード量が少なくて済むgpiozeroを使いたいと思います


```python:test1.py
from gpiozero import LED
import time
led = LED(17)
while True:
    led.on()
    time.sleep(0.1)
    led.off()
    time.sleep(0.1)
```


これを実行するとGPIO17がHIGH/LOW出力を繰り返し、LEDが0.2秒間隔で点滅します


## 5-4. SPI通信する


ADコンバータでセンサー計測をやってみます


### ADC0834とSPI通信


ラズパイはアナログ入力がないので、センサー計測をやるにはADコンバータICを使って電圧や電流を測定してやる必要があります。ADコンバータICはSPI通信で制御するものが多いですが、ラズパイにはSPI通信機能があるピンが設定されていて安定した通信が実現できるようになっています


今回は8ビット4チャンネルADコンバータADC0834CCNを使いたいと思います
https://www.ti.com/lit/ds/symlink/adc0832-n.pdf


以下がデータシートのタイミングチャートです


クロックを送りながらCSとDINで指示を入れてやると、DOUTから出てくるデジタル出力が受け取れる、という仕組みになっているのが分かります。このADCは8ビットADCですが、DOUTは最大ビット(MSB) から順に出力され最小ビット(LSB)まで到達した後に、最小ビットから順に最大ビットまで再度出力されます


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277233/329d459f-b750-eaeb-1512-c9a58106aa19.png" width=50%>


クロック周波数は10kHz～400kHzで指定されていますが、Pythonのtime.sleep()でクロックを管理するのはPythonの制約とOSのスケジューリングの影響で100µs（10kHz）以下では安定しないことが多いようですので、直接ハードウェアSPIを利用するのが良さそうです


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277233/e44f6cdd-6b7e-74dd-888d-00ee56e19d5a.png" width=50%>


### SPIを有効にする


出荷時にSPIが有効になっていないようなので以下で有効にしてやります


```
sudo raspi-config
```


以下の順で選ぶと有効にできます


5. Interacting Options
　↓
P4 SPI
　↓
YES


### ピン配置


ピン配置は以下のようにします


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277233/b669cb2a-a3f2-9679-62e8-ccbdb602f997.png" width=70%>



ラズパイのSPI用端子がSCLK, SOSI, SISOなので、こちらは決まったピンをそのまま利用します。また、Chip Selector用に設定されているCE0 (GPIO8) を使用することで、コード量を最小にすることができます


### プログラム


ライブラリとしてはSPI制御用のspidevパッケージを使っていきます
https://gpiozero.readthedocs.io/en/stable/api_spi.html#spidevice


MCP3204とかだとgpiozeroに専用クラスがあるので、ADCを今から買う人はそっちの方が簡単だと思います


bus=0でCE0を指定して、周波数を設定、xfer2メソッドで指示を送ってその間に返ってきたDOの出力を受け取ります。送る指示ビットと受け取りビットはICによって違うので、ここは自前で書いてやる事になりそうです


```python:test1.py
import spidev
import time

def f(num):
    binary_16bit = f'{num:08b}'  # 16ビットの2進数にゼロ埋め
    binary_8x2bit = ' '.join(binary_16bit[i:i+2] for i in range(0, len(binary_16bit), 2))
    return binary_8x2bit

class ADC0834:
    def __init__(self, bus=0, device=0):
        self.spi = spidev.SpiDev()
        self.spi.open(bus, device)
        self.spi.max_speed_hz = 100 * 1000  # 最大通信速度（100kHz）

    def read_channel(self, channel):
        if channel < 0 or channel > 3:
            raise ValueError("Channel must be between 0 and 3.")

        # コマンド構築
        start_bit = 0x01
        mode_bit = 0x80  # シングルエンドモード
        channel_bits = channel << 4
        command = [start_bit, mode_bit | channel_bits, 0x00, 0x00]

        # SPI通信 (spidev の xfer2 メソッドを使用)
        result = self.spi.xfer2(command)

        # データ処理
        print('{} / {} / {} / {}'.format(f(result[0]), f(result[1]), f(result[2]), f(result[3])))
        high_byte = result[1] & 0x0f  # 上位4ビット
        low_byte = result[2] & 0xf0  # 下位4ビット
        value = (high_byte << 4) | (low_byte >> 4)
        return value

    def close(self):
        self.spi.close()


while True:
    adc = ADC0834(bus=0, device=0)  # ADC0834 の初期化    
    try:
        channel = 0
        value = adc.read_channel(channel)  # チャンネル0のデータを取得
        print("Channel {} Value: {}".format(channel, value))
    finally:
        adc.close()
    time.sleep(1)
```


以下のように出力されれば正常です


```
Channel 0 Value: 57
Channel 0 Value: 58
Channel 0 Value: 58
```


上手くいったのでCdSフォトレジスタと抵抗で適当な入力を作って繋いでおきます


3.3V → 10kΩ → ADC入力 → CdSフォトレジスト → 接地 と接続しているので暗くなってフォトレジストの抵抗が増すと3.3Vに近くなり、明るくなって抵抗が減ると電圧が下がります


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277233/af64362a-fb94-991c-cf4b-dd7b86ab29d1.jpeg" width=50%>


僕のはぐちゃぐちゃですが
皆さんはもっとキレイに配線しましょう


## 5-5. SQLiteDBを使う


センサーデータを記録したいのでSQLiteで保存してみようと思います


Python標準パッケージのsqlite3でSQLiteが操作できます
ID、現在時刻、測定値を記録するような構成にしています


```python:sqlite_save.py
import sqlite3
import pandas as pd
from datetime import datetime

dbpath = './hoge_db.sqlite'

table = 'cds'

def add(value=0):
    connection = sqlite3.connect(dbpath)
    cursor = connection.cursor()
    try:
        cursor.execute(f'''
            CREATE TABLE IF NOT EXISTS {table} (
                ID INTEGER PRIMARY KEY AUTOINCREMENT,
                datetime TEXT NOT NULL,
                value INTEGER NOT NULL
            )
        ''')
        
        current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')  # 現在時刻をISO 8601形式で取得
        cursor.execute('INSERT INTO cds (datetime, value) VALUES (?, ?)', (current_time, value))

        connection.commit()
        connection.close()
        print("Record inserted successfully!")

    except sqlite3.Error as e:
        print('sqlite3.Error occurred:', e.args[0])


def load():
    connection = sqlite3.connect(dbpath)
    df = pd.read_sql_query('SELECT * FROM cds', connection)
    connection.close()
    return df

if __name__ == "__main__":
    add()
    print(load())
```


このファイルは後でimportして使いますのでadd()とload()を関数にしておきました


## 5-6. グラフを出力する


以下のようにするとグラフ画像を書き出したり表示したりできます


```python:python
plt.plot(values)
plt.savefig('./plot.png')  # グラフを画像で書き出し
plt.show()  # 画面上でグラフを確認する
```


先ほどのADCのコードに追加して以下のようにしてやります


```python:~/cds_sensor.py
import spidev
import time
import sqlite_save as sql
import matplotlib.pyplot as plt
from tqdm import tqdm

class ADC0834:
    def __init__(self, bus=0, device=0):
        self.spi = spidev.SpiDev()
        self.spi.open(bus, device)
        self.spi.max_speed_hz = 100 * 1000  # 最大通信速度（100kHz）

    def read_channel(self, channel):
        if channel < 0 or channel > 3:
            raise ValueError("Channel must be between 0 and 3.")

        # コマンド構築
        start_bit = 0x01
        mode_bit = 0x80  # シングルエンドモード
        channel_bits = channel << 4
        command = [start_bit, mode_bit | channel_bits, 0x00, 0x00]

        # SPI通信 (spidev の xfer2 メソッドを使用)
        result = self.spi.xfer2(command)

        # データ処理
        high_byte = result[1] & 0x0f  # 上位4ビット
        low_byte = result[2] & 0xf0  # 下位4ビット
        # print('{} / {}'.format(f(high_byte), f(low_byte)))
        value = (high_byte << 4) | (low_byte >> 4)
        return value

    def close(self):
        self.spi.close()


def measure(channel):
    adc = ADC0834(bus=0, device=0)  # ADC0834 の初期化

    try:
        value = adc.read_channel(channel)
        print("Channel {} Value: {}".format(channel, value))
        sql.add(value)
        df = sql.load()
        print(df.tail(50))
        plot(df)
    finally:
        adc.close()
        
def plot(df):
    values = df['value']
    plt.plot(values)
    plt.savefig('./plot.png')
    # plt.savefig('/var/www/html/cds.png')  # 後で有効にする
    plt.close()
    # plt.show()  # 画面上で確認したいときに有効にする


while True:
    measure(channel=0)
    for _ in tqdm(range(300)):
        time.sleep(1)
```


画像ファイルとしてグラフが書き出されるようになりました
部屋の灯りを消すと255に張り付いてます


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277233/519cc6bd-2e21-18e9-1106-2d2353edf0ed.png" width=50%>


## 5-7. ウェブサイトをつくる


上で書き出したグラフを表示するウェブサイトを作ってみます


### apache2のインストール


httpサーバーであるapacheをインストールします


```terminal:terminal
sudo apt-get install apache2
```


入っているか確認します


```terminal:インストールできていたらバージョンが表示される
apachectl -v
```


```terminal:サーバーが起動していたらindex.htmlが表示される
curl http://localhost
```


これでapacheが起動している筈なので、確認してみましょう
ラズパイの接続IPをifconfigで確認します


```terminal:terminal
ifconfig
```


wifiで接続している他の端末からブラウザで開いて表示してみます
今回の環境では以下IPでした
http://192.168.11.14/


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277233/f30d9032-e13b-c50a-4106-9f2a6d8e5db5.png" width=50%>


### ウェブサイトを作成する


以下のファイルを追加すると
http://localhost/example に作ったhtmlファイルが表示されます


```html:/var/www/html/example.html
<h1>HelloWorld!!</h1>
<p>example!!</p>
```


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277233/448930aa-6c1e-69af-c0d0-0f0c15b0d4cc.png" width=50%>


権限がなくて書けないようなら/var/www/html/のユーザーをsudo chownで自分に変更すればファイルを置けるようになります


### センサーデータを表示する


グラフ画像をapacheのドキュメントルート以下に置いてやるようにします


```python:~/cds_sensor.pyに追記
plt.savefig('/var/www/html/plot.png')
```


グラフ表示用のhtmlファイルを作成します


```html:/var/www/html/sensor.html
<h1>Sensor Data</h1>
<img src="plot.png">
```


今回の環境では以下に表示される筈です
http://192.168.11.14/plot


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277233/33bb1265-61eb-fe7b-95b6-00494f7947e9.png" width=50%>


上手く表示できました


センサー読み取りとグラフ書き出しを繰り返させておけば、このURLを開く度に最新のグラフが閲覧できる筈です


## 6. この後やりたいこと


### いろいろ作りたい


センシングサーバーとしてやりたいことがあるのでそれを完成させようと思います


また、サーバー単体としても面白そうなので、運用しているサイトで負荷の低いものを置いてみようとおもっています


### 壊れても簡単に置き換えられるようにしたい


現状ラズパイのローカルにコードを書いていっているのでコードをGithub管理して、環境もいちいちCLIで作っているのでdockerで作れるようにしたいと思います。dockerでGPIOを使おうと思うとdocker runするときにGPIOとの接続を指示してやらないといけないようなので、ちょっと手間取りそう


### 電源断故障対策


ラズパイは電源断に弱いようなので対策したいところですが、いまのところ電源は落とさない運用を想定しているので後回すと思います
https://zenn.dev/su_/articles/97b9e25d0ae41c?utm_source=chatgpt.com


### ヒートシンク


気温の高い季節になると熱が心配なのでヒートシンクつけたりするんだと思います
https://akizukidenshi.com/catalog/g/g129559/


### インターネットに公開


Claudflare Tunnelを使うとグローバルIPが取れてなくてもウェブページをインターネットに公開することができますし、インバウンドはhtmlに限定されるので比較的安全ですから、これで何かしら公開してみようと思っています
https://qiita.com/studio_haneya/items/17e48d0b03f673602fa5


以下みたいな備えを最低限やった上で普通に公開しちゃってアクセスログを眺めたり、ハニーポッド入れてログを見たりするのも面白いかも
https://raspi-katsuyou.com/index.php/2020/07/21/22/55/34/1188/#google_vignette


# まとめ


ミニPCや簡易サーバーのようなイメージで思っていたラズパイですが、GPIOとの組み合わせでセンシング可能なサーバーとして、IoTデバイスの開発機としても非常に魅力的なデバイスだと感じました


マイコンを扱った経験があったせいで面倒で制約の多いイメージを勝手に持っていましたが、ラズパイの上位モデルなら廉価VPSなんかよりハイスペックなぐらいだし、リモートデスクトップが思った以上に快適で開発がやりやすかったりと予想外の良さがありました。スペックから考えると驚くほど消費電力が少ないので電気代を気にしないで済むのも嬉しいです。マイコンさわってた頃にラズパイがあったら間違いなくこれで開発していたと思う程度にはラズパイは良いです


一方で、まったくの初学者が電子工作もやりながらサーバー運用もやって、となるとかなり覚えることが多くて大変だと思います。僕は電子工作もマイコンもウェブもサーバーもさわったことがあるのですんなり入れましたが、初学者が難しさを感じずに学んでいけるルートがどういうものになるのかは良く分かりません。電子工作だけならマイコンより簡単なぐらいだし、サーバーとしてなら普通のサーバーと同じなので、1つ1つやっていくのが良いのかな。両方が1つのデバイスで出来るというのがラズパイのすごいところだと思うので、両方やる人がどんどん出てきてほしいと思います


気になってた人は試してみて損はないと思います
レッツトライ