1. TOP
  2. ラズベリーパイ
  3. セットアップ
  4. PLCデータをSQLiteに記録・確認

PLCのデータをSQLiteに記録して確認する(KV上位リンク × Python)

KEYENCE KVシリーズのデータを、ラズベリーパイのPythonプログラムで1秒ごとに読み出し、SQLiteデータベースに記録するサンプルです。
プログラムの作成から、Pythonの仮想環境(venv)での実行、起動時の自動実行、記録したデータの確認方法までを、このページだけで試せるようにまとめています。

SQLiteは、データベース全体が1つのファイル(例:plc_log.db)に保存される軽量なデータベースです。サーバーの設定が不要で、Pythonに標準で組み込まれているため、PLCのデータを手軽に記録するのに向いています。

概要

手順内容
1. 記録プログラムKVのDM0~DM3を1秒ごとに読み出してSQLiteに記録するPythonプログラム
2. 実行手順仮想環境(venv)の作成、ライブラリのインストール、実行、systemdでの自動起動
3. データの確認sqlite3コマンド・Python・GUIツール・CSV出力の4つの方法

環境

項目内容
PLCKEYENCE KVシリーズ(KV-8000など、Ethernet上位リンク対応機種)
ラズベリーパイRaspberry Pi 4 Model B/Raspberry Pi OS(64-bit、Bookworm以降)
PythonOS標準のPython 3 + 仮想環境(venv)
ライブラリkvhostlink-udp(上位リンク通信)、sqlite3(標準ライブラリ)
データベースplc_log.db(テーブル名:log)
ラズベリーパイの初期設定(固定IP・SSHなど)は「初期設定とサーバー構築」を参照してください。ラズベリーパイとPLCの連携構成の考え方は「ラズベリーパイとは」で紹介しています。

記録プログラム

KEYENCE KVシリーズの DM0~DM3 を1秒ごとに読み出して、SQLiteデータベースに記録する最小構成のプログラムです。

plc_logger.py
import sqlite3
import time
import datetime
from kvhostlink import kvHostLink      # pip install kvhostlink-udp

PLC_IP   = '192.168.250.10'
INTERVAL = 1.0                         # 収集周期 [秒]

db = sqlite3.connect('plc_log.db')
db.execute('''CREATE TABLE IF NOT EXISTS log(
                ts  TEXT,
                dm0 INTEGER, dm1 INTEGER, dm2 INTEGER, dm3 INTEGER)''')

kv = kvHostLink(PLC_IP)

while True:
    try:
        rcv = kv.reads('DM0.U', 4)     # 例: b'00002 00001 00002 00003\r\n'
        values = [int(v) for v in rcv.decode().split()]
        ts = datetime.datetime.now().isoformat(timespec='seconds')
        db.execute('INSERT INTO log VALUES (?,?,?,?,?)', [ts] + values)
        db.commit()
    except Exception as e:
        print('通信エラー:', e)        # 通信が切れても収集を止めない
    time.sleep(INTERVAL)

記録されるテーブルの構造は次のとおりです。

列名型内容
tsTEXT記録した時刻(例:2026-10-12T21:15:42)
dm0~dm3INTEGERDM0~DM3の値(符号なし16ビット)

OMRON(FINS)や三菱(MCプロトコル)の場合も、読出し部分を各ライブラリの関数に置き換えるだけで同じように記録できます。

実行手順(Python仮想環境 venv)

Bookworm以降のRaspberry Pi OSでは、pip install をそのまま実行すると、次のようなエラーになってライブラリを入れられません。

$ pip install kvhostlink-udp
error: externally-managed-environment

× This environment is externally managed
╰─> To install Python packages system-wide, try apt install
    python3-xyz, where xyz is the package you are trying to
    install.
    ...

これは、OSが管理しているPython環境をpipで壊さないための仕組みです。aptにないライブラリを使うときは、仮想環境(venv)というプロジェクト専用のPython環境を作り、その中にpipでインストールします。

ここでは作業ディレクトリを ~/plclog、ユーザー名を pi としています。Raspberry Pi Imagerで別のユーザー名を設定した場合は、/home/pi を自分のホームディレクトリに読み替えてください。

1. 作業ディレクトリを作る

$ mkdir -p ~/plclog
$ cd ~/plclog

2. 仮想環境を作って有効にする

venvの機能が入っていない場合に備えて、先にパッケージを入れておきます(すでに入っていれば何も変わりません)。

$ sudo apt install -y python3-venv
$ python3 -m venv .venv
$ source .venv/bin/activate

有効になると、プロンプトの先頭に (.venv) と表示されます。この状態で実行する python や pip は、仮想環境のものになります。

3. ライブラリをインストールする

(.venv) $ pip install kvhostlink-udp
(.venv) $ pip list

pip list の一覧に kvhostlink-udp が表示されればインストール完了です。sqlite3 はPythonの標準ライブラリなので、追加のインストールは不要です。

pip install --break-system-packages でエラーを回避する方法もありますが、OSのPython環境が壊れる原因になるのでおすすめしません。

4. プログラムを保存する

(.venv) $ nano plc_logger.py

記録プログラムを貼り付け、PLC_IP を接続するKVのIPアドレスに変更して保存します(nanoは Ctrl+O → Enter で保存、Ctrl+X で終了)。

実行する前に、ラズベリーパイからPLCに通信できるか確認しておきます。

(.venv) $ ping -c 3 192.168.250.10
KV側では、Ethernetポートの上位リンク通信が使える設定になっている必要があります(ポート番号の既定値は 8501)。詳しくは「KEYENCE 上位リンク通信」を参照してください。

5. 実行する

(.venv) $ python plc_logger.py

何も表示されずに動き続けていれば、1秒ごとに記録されています(「通信エラー」が表示される場合は、IPアドレスやKV側の設定を確認してください)。止めるときは Ctrl+C を押します。
記録したデータは、次の章の方法で確認できます。

6. 次回以降の実行

ログインし直したときは、仮想環境を有効にしてから実行します。

$ cd ~/plclog
$ source .venv/bin/activate
(.venv) $ python plc_logger.py

仮想環境のPythonを直接指定すれば、source しなくても実行できます。仮想環境から抜けるときは deactivate を実行します。

$ ~/plclog/.venv/bin/python ~/plclog/plc_logger.py

7. 起動時に自動で実行する(systemd)

実運用では、ラズベリーパイの電源を入れたら自動で収集が始まるように、systemdのサービスとして登録します。ExecStartには仮想環境のPythonをフルパスで指定します。

$ sudo nano /etc/systemd/system/plc-logger.service
/etc/systemd/system/plc-logger.service
[Unit]
Description=PLC data logger (KV HostLink -> SQLite)
After=network-online.target
Wants=network-online.target

[Service]
WorkingDirectory=/home/pi/plclog
# -u : print の出力をすぐにログへ出す(バッファしない)
ExecStart=/home/pi/plclog/.venv/bin/python -u /home/pi/plclog/plc_logger.py
User=pi
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
$ sudo systemctl daemon-reload
$ sudo systemctl enable --now plc-logger.service
$ systemctl status plc-logger.service
$ journalctl -u plc-logger -f

止めるときは sudo systemctl stop plc-logger、自動起動をやめるときは sudo systemctl disable plc-logger を実行します。WorkingDirectory を指定しているので、データベースは /home/pi/plclog/plc_log.db に作られます。

データの確認(4つの方法)

SQLiteのファイルは、開いただけでは中身を見ることができません。記録したデータを確認する方法を4つ紹介します。

4つの方法の比較

方法使う場所準備向いているケース
1. sqlite3コマンドラズベリーパイ(SSH)aptで1つ入れるだけ記録できているかをすぐに確認したい。リアルタイムで増えていく様子を見たい
2. Pythonラズベリーパイ(SSH)不要(標準ライブラリ)何もインストールせずに確認したい。確認処理をスクリプトにしたい
3. GUIツールPCDB Browser for SQLite などをインストール表形式でじっくり見たい。条件を変えながら検索したい
4. CSV出力ラズベリーパイ → PC不要(sqlite3またはPython)Excelでグラフにしたい。報告用にデータを渡したい
SQLiteは、書き込み中でも別のプログラムから読み出せます。収集プログラムを止めずに、ここで紹介する方法で中身を確認できます。

確認方法1:sqlite3コマンド

SQLite公式のコマンドラインツールです。ラズベリーパイにSSHでログインして使います。

インストール

$ sudo apt install -y sqlite3
$ sqlite3 --version

対話モードで確認する

データベースファイルを指定して起動すると、sqlite> のプロンプトが表示されます。

$ sqlite3 plc_log.db
sqlite>
-- テーブルの一覧
.tables

-- テーブルの構造(CREATE文)
.schema log

-- 見やすい表示にする(列名を表示・列をそろえる)
.headers on
.mode column

-- 新しい順に10件
SELECT * FROM log ORDER BY ts DESC LIMIT 10;

-- 件数
SELECT COUNT(*) FROM log;

-- 終了
.quit

表示例です。

ts                   dm0  dm1  dm2  dm3
-------------------  ---  ---  ---  ---
2026-10-12T21:15:42  2    1    2    3
2026-10-12T21:15:41  2    1    2    3
2026-10-12T21:15:40  2    1    2    3
. で始まるのはsqlite3独自のコマンドで、行末の ; は不要です。SQL文(SELECTなど)は行末に ; が必要です。.mode table にすると罫線付きの表で表示されます。

1行のコマンドで確認する

対話モードに入らずに、SQLを直接指定して結果だけを表示することもできます。

$ sqlite3 -header -column plc_log.db "SELECT * FROM log ORDER BY ts DESC LIMIT 10;"

記録されていく様子をリアルタイムで見る

watch コマンドと組み合わせると、1秒ごとに最新のデータを表示し直します(終了は Ctrl+C)。

$ watch -n 1 'sqlite3 -header -column plc_log.db "SELECT * FROM log ORDER BY ts DESC LIMIT 5;"'

よく使うSQLの例

SQL
-- 期間を指定して取り出す(tsはISO形式の文字列なので文字列で比較できます)
SELECT * FROM log
WHERE ts BETWEEN '2026-10-12T09:00:00' AND '2026-10-12T10:00:00';

-- 最新の1件
SELECT * FROM log ORDER BY ts DESC LIMIT 1;

-- 1分ごとの平均・最大・最小(DM0)
SELECT substr(ts, 1, 16) AS minute,
       AVG(dm0) AS avg_dm0, MAX(dm0) AS max_dm0, MIN(dm0) AS min_dm0
FROM log
GROUP BY minute
ORDER BY minute DESC
LIMIT 10;

確認方法2:Python

SQLiteを扱う sqlite3 モジュールはPythonに標準で含まれているので、何もインストールせずに確認できます。

1行で確認する

$ python3 -c "import sqlite3; [print(r) for r in sqlite3.connect('plc_log.db').execute('SELECT * FROM log ORDER BY ts DESC LIMIT 10')]"

確認用のスクリプトを作る

何度も確認する場合は、テーブル一覧・件数・最新データをまとめて表示するスクリプトを作っておくと便利です。

$ nano show_db.py
show_db.py
import sqlite3
import sys

db_file = sys.argv[1] if len(sys.argv) > 1 else 'plc_log.db'
limit   = int(sys.argv[2]) if len(sys.argv) > 2 else 10

# 読み取り専用で開く(誤って書き換えたり、空のファイルを作ったりしない)
con = sqlite3.connect(f'file:{db_file}?mode=ro', uri=True)

tables = [r[0] for r in con.execute(
    "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name")]

for table in tables:
    count = con.execute(f'SELECT COUNT(*) FROM "{table}"').fetchone()[0]
    print(f'=== {table} ({count} 件) ===')

    cur  = con.execute(f'SELECT * FROM "{table}" ORDER BY rowid DESC LIMIT {limit}')
    cols = [d[0] for d in cur.description]
    print(' | '.join(cols))
    for row in cur:
        print(' | '.join(str(v) for v in row))
    print()

con.close()
$ python3 show_db.py
$ python3 show_db.py plc_log.db 20
mode=ro(読み取り専用)で開いているので、ファイル名を間違えても新しい空のデータベースが作られることはありません(エラーになります)。

確認方法3:GUIツール

表形式で見たい場合や、条件を変えながら検索したい場合は、GUIツールが便利です。

DB Browser for SQLite

無料で使える定番のSQLite用GUIツールです。Windows・Mac・Linuxに対応しています。

  1. DB Browser for SQLite のダウンロードページから、PCにインストールします。
  2. ラズベリーパイのデータベースファイルを、WinSCPなどでPCにコピーします(下の「安全にコピーする方法」を参照)。
  3. DB Browser for SQLiteでファイルを開き、データ閲覧(Browse Data)タブでテーブルを選ぶと、表形式で表示されます。
  4. SQLを実行したい場合は SQL実行(Execute SQL)タブを使います。
ラズベリーパイのデスクトップ環境で使う場合は、sudo apt install -y sqlitebrowser でインストールできます。
データを書き換えるつもりがない場合は、メニューの「ファイル」>「読み取り専用でデータベースを開く」を使うと安全です。

安全にコピーする方法

収集プログラムが書き込んでいる最中のファイルをそのままコピーすると、まれに壊れたファイルになることがあります。sqlite3の .backup コマンドでコピーを作ってから転送すると確実です。

$ sqlite3 plc_log.db ".backup plc_log_copy.db"

作成した plc_log_copy.db をPCに転送して開きます。

VS Codeで見る

VS Codeを使っている場合は、拡張機能「SQLite Viewer」を入れると、.db ファイルをクリックするだけで表形式で表示できます。拡張機能「Remote - SSH」でラズベリーパイに接続すれば、ファイルをコピーせずにラズベリーパイ上のファイルを直接開くこともできます。

確認方法4:CSVに書き出してExcelで見る

CSVに書き出せば、Excelでグラフにしたり、報告用にデータを渡したりできます。

sqlite3コマンドで書き出す

$ sqlite3 -header -csv plc_log.db "SELECT * FROM log ORDER BY ts;" > plc_log.csv

期間を指定して書き出す例です。

$ sqlite3 -header -csv plc_log.db "SELECT * FROM log WHERE ts >= '2026-10-12T00:00:00' ORDER BY ts;" > plc_log_1012.csv

Pythonで書き出す

sqlite3コマンドを入れていない場合は、Pythonの標準ライブラリだけで書き出せます。

export_csv.py
import csv
import sqlite3

con = sqlite3.connect('file:plc_log.db?mode=ro', uri=True)
cur = con.execute('SELECT * FROM log ORDER BY ts')

# utf-8-sig にすると、Excelで開いたときに日本語が文字化けしません
with open('plc_log.csv', 'w', newline='', encoding='utf-8-sig') as f:
    writer = csv.writer(f)
    writer.writerow([d[0] for d in cur.description])   # 列名
    writer.writerows(cur)

con.close()
$ python3 export_csv.py

書き出したCSVをWinSCPなどでPCにコピーし、Excelで開きます。

Excelで開ける行数は約104万行までです。1秒ごとに記録している場合、約12日分で上限を超えるので、期間を区切って書き出してください。

データが表示されないとき

症状原因と対処
.tables で何も表示されない別の場所にある空のファイルを開いている可能性があります。SQLiteは、存在しないファイル名を指定すると空のデータベースを新しく作ります。収集プログラムを実行したディレクトリ(この手順では ~/plclog)で ls -l plc_log.db を実行し、ファイルサイズが増えているか確認してください。
テーブルはあるが件数が0のままPLCとの通信でエラーが起きている可能性があります。収集プログラムを実行しているターミナルに「通信エラー」が表示されていないか確認してください。
database is locked と表示されるGUIツールなどでファイルを開いたまま編集している(書き込み中の)状態です。GUIツールを閉じるか、読み取り専用で開いてください。
ファイルを開けない(Permission denied)収集プログラムを sudo で実行したため、ファイルの所有者がrootになっています。sudo chown pi:pi plc_log.db で所有者を変更してください。

まとめ

PythonとSQLiteを使えば、ラズベリーパイ1台で、PLCのデータを手軽に記録できます。仮想環境(venv)を使うことで、OSのPython環境を壊さずにライブラリを追加でき、systemdに登録すれば電源を入れるだけで収集が始まります。
記録できているかをすぐに確認するなら sqlite3コマンド、何も入れずに確認するなら Python、じっくり表で見るなら GUIツール、Excelで加工するなら CSV出力 が便利です。

関連ページ

ラズベリーパイとは

ラズベリーパイとは

歴史・現行機種のスペック・PLCとの連携構成を紹介します

初期設定とサーバー構築

初期設定とサーバー構築

固定IP・Apache・PHP・MariaDBのセットアップ手順

KEYENCE 上位リンク通信

KEYENCE 上位リンク通信

PythonからKEYENCE PLCと上位リンク通信します

参考

この記事へのコメント