【実機解説】SQL Serverに溜めたPLCデータを、Grafanaでリアルタイム監視ダッシュボードにする方法
導入:結論から先に
SQL Serverに溜めたPLCのデータは、Grafana(グラファナ)を使えば、リアルタイムで動く監視ダッシュボードにできます。しかも全部無料です。
このシリーズでは、これまでFANUCロボットの電流値・位置座標をPLCで常時取得する方法、そしてそのデータをPythonでSQL Serverに自動保存する方法を解説してきました。
データが溜まると、次に来るのはこの疑問です。
「溜めたはいいけど、どうやって見るのか?」
SSMSで表を眺めても、数字の羅列では異常に気づけません。グラフにして初めて「いつもと違う」が見えるようになります。この記事では、無料のGrafanaでその環境を作ります。
- 完全無料(Grafana・SQL Server Express、共有も無料)
- 数秒ごとに自動更新されるリアルタイム監視画面
- しきい値を超えたら一目でわかるグラフ
この記事で作る画面がこちらです。緑が正常な設備、黄色が電流値の上がっている設備。赤い線がしきい値(4.5A)です。

この記事で使う環境
| 役割 | ソフト | 費用 |
|---|---|---|
| データベース | SQL Server 2022 Express(前回構築済み) | 無料 |
| 可視化ツール | Grafana 13 | 無料 |
| 対象データ | ロボットの電流値・座標(robot_logテーブル) | ― |
SQL Server側の構築がまだの方は、前回の記事を先にご覧ください。この記事はその続きです。
ステップ1:Grafanaをインストールする
Grafana公式サイトからWindows版のインストーラーをダウンロードします。
👉 Grafana公式:ダウンロードページ(Windows)
OSS版(無料版)のインストーラー(.msi)を実行し、画面の指示に従うだけです。インストールが完了すると、GrafanaはWindowsのサービスとして自動起動します。
ブラウザで http://localhost:3000 を開くとログイン画面が出ます。初期のユーザー名・パスワードはどちらも admin で、初回ログイン後に新しいパスワードの設定を求められます。

つまずきポイント:パスワードを忘れたら
「パスワードを忘れた場合」からメールを送ろうとしても、メール送信の設定をしていないと届きません。その場合は管理者権限のPowerShellで次の3行を順に実行すればリセットできます(Grafanaがデータベースを使用中だと失敗するので、いったんサービスを止めるのがコツです)。
Stop-Service Grafana & "C:\Program Files\GrafanaLabs\grafana\bin\grafana.exe" cli --homepath "C:\Program Files\GrafanaLabs\grafana" admin reset-admin-password "新しいパスワード" Start-Service Grafana
ステップ2:SQL Server側の準備(3つ)
ここがこの記事で一番大事なパートです。GrafanaからSQL Serverに接続するには、SQL Server側に3つの準備が必要です。
| 準備 | なぜ必要か |
|---|---|
| 混合モード認証 | Grafanaは専用のSQLアカウントで接続するため。Windows認証のみでは繋げない |
| TCP/IP通信を有効化 | Grafanaはネットワーク経由で接続する。SQL Server Expressは初期状態でTCP/IPが無効 |
| 読み取り専用ユーザー | 可視化ツールに書き込み権限は不要。閲覧だけに絞るのが実務の鉄則 |
SSMSの「新しいクエリ」で、次のSQLを実行します(パスワードはご自身で決めたものに変えてください)。
-- ① 混合モード認証を有効化(SQLアカウントでのログインを許可) EXEC xp_instance_regwrite N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'LoginMode', REG_DWORD, 2; -- ② TCP/IP通信を有効化+固定ポート1433に設定 EXEC xp_instance_regwrite N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer\SuperSocketNetLib\Tcp', N'Enabled', REG_DWORD, 1; EXEC xp_instance_regwrite N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer\SuperSocketNetLib\Tcp\IPAll', N'TcpPort', REG_SZ, N'1433'; EXEC xp_instance_regwrite N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer\SuperSocketNetLib\Tcp\IPAll', N'TcpDynamicPorts', REG_SZ, N''; -- ③ Grafana用の「読み取り専用」ユーザーを作成 CREATE LOGIN grafana_reader WITH PASSWORD = 'ここにパスワード', CHECK_POLICY = OFF; USE plc_iot; CREATE USER grafana_reader FOR LOGIN grafana_reader; ALTER ROLE db_datareader ADD MEMBER grafana_reader; -- 閲覧のみ。書き込み・削除は不可
実行後は必ずSQL Serverを再起動してください。①②は再起動して初めて有効になります。SSMSの左ツリーでサーバー名を右クリック →「再起動」が簡単です。
読み取り専用にする意味:
db_datareaderは「SELECTだけ許可」のロールです。仮にGrafana側の設定が漏れても、データを書き換えられたり消されたりする心配がありません。可視化ツールを繋ぐときの基本作法です。
ステップ3:GrafanaからSQL Serverに接続する
Grafanaの画面で、左メニューの「Connections」→「Data sources」→「Add new data source」と進み、「Microsoft SQL Server」を選びます。設定内容は次のとおりです。「この値の出どころ」列を確認して、ご自身の環境に合わせて読み替えてください(そのまま真似するのではなく、ステップ2で作成したものと一致させます)。
| 項目 | 入力する値 | この値の出どころ |
|---|---|---|
| Host | localhost:1433 | SQL Serverが動いているPCとポート。Grafanaと同じPCならこのまま。別PCならそのIPアドレス(例:192.168.0.50:1433) |
| Database | plc_iot | ステップ2で作成したデータベース名(前回記事で作ったもの)。別の名前にした方はご自身の名前に |
| Authentication | SQL Server Authentication | 固定。ステップ2で混合モードにしたのでこれを選ぶ |
| User | grafana_reader | ステップ2で作成した読み取り専用ユーザー名。変更した方はその名前に |
| Password | (各自の値) | ステップ2でご自身が決めたパスワード |
| 暗号化(Encrypt) | disable(無効) | 固定。ここが重要(理由は下記) |

暗号化の設定に注意
ここを既定のままにすると「証明書が信頼できない」というエラーで接続できません。自分のPC内だけの通信なので disable(無効) で問題ありません。
なおブラウザの日本語自動翻訳をONにしていると、選択肢のfalseが「間違い」と誤訳されて表示されます。意味が通じず混乱するので、Grafanaは翻訳をOFF(英語表示)で使うことを強くおすすめします。
入力できたら一番下の「Save & test」をクリック。緑色で「Database Connection OK」と出れば成功です。

ステップ4:グラフを作る(ここに2つの罠)
ダッシュボードを新規作成し、パネルを追加してデータソースにmssqlを選びます。クエリ欄は「Code」モードに切り替え、「Format」を「Time series」に設定します。
そして、貼り付けるSQLがこちらです。
SELECT time_utc AS time, equipment_name AS metric, current_j1 AS value FROM ( SELECT DATEADD(hour, -9, r.recorded_at) AS time_utc, e.equipment_name, r.current_j1 FROM robot_log r JOIN equipment e ON e.equipment_id = r.equipment_id ) AS t WHERE $__timeFilter(time_utc) ORDER BY time_utc
このSQLには、実際に私がハマった2つの落とし穴への対策が入っています。順に説明します。
時刻が9時間ズレる(UTCの問題)
設定は合っているのに「No data」しか出ない——最初にぶつかったのがこれでした。
原因はタイムゾーンです。Grafanaは表示期間を必ずUTC(世界標準時=日本より9時間前)でデータベースに問い合わせます。ところが前回の記事では、Pythonの datetime.now()(=日本時間)で保存していました。
| 時刻 | |
|---|---|
| Grafanaが問い合わせる範囲 | 15:41〜21:41(UTC) |
| データベースに入っている値 | 03:29〜06:29(日本時間) |
| 結果 | 該当0件 → No data |
そこで DATEADD(hour, -9, r.recorded_at) で日本時間から9時間引き、UTCに変換しています。Grafanaは表示時に自動で日本時間へ戻すので、グラフの目盛りは正しく日本時間で表示されます。
※ -9 は日本時間(JST)の場合の時差です。他のタイムゾーンの環境では、その地域の時差に読み替えてください。
本来の正解は「最初からUTCで保存する」ことです。Python側を
datetime.now()からdatetime.now(timezone.utc)(UTCで取得)に変えておけば、この変換自体が不要になります。※datetime.utcnow()はPython 3.12以降で非推奨のため使いません。これから作る方はUTC保存を強くおすすめします。上記の変換は、すでに動いているシステムを変更できない場合の現実解です。
$__timeFilter に関数を入れてはいけない
これが最も気づきにくい罠でした。時刻のズレに気づいた私は、最初こう書きました。
-- ❌ これは動きません WHERE $__timeFilter(DATEADD(hour, -9, r.recorded_at))
一見正しそうですが、エラーも出ないのに結果は0件。原因はGrafanaが生成した実際のSQLを見て判明しました。
-- Grafanaが生成したSQL(壊れている) WHERE DATEADD(hour BETWEEN '2026-07-21T15:43:55Z' AND '2026-07-21T21:43:55Z')
$__timeFilter() は、カッコの中を「最初のカンマまで」しか列名として認識しません。そのため DATEADD(hour だけを取り出して置換してしまい、SQLが壊れていたのです。
対策はサブクエリで先に変換を済ませ、$__timeFilter() には列名だけを渡すこと。先ほどのSQLがその形になっています。
覚えておくと一生使える切り分け方
「設定は合っているのにデータが出ない」ときは、Query inspector(クエリ欄の右にあるボタン)を開いてください。Grafanaが実際に投げたSQLが見られます。エラーが出ないタイプの不具合は、これを見ないと永久に気づけません。
ステップ5:監視ダッシュボードに仕上げる
グラフが出たら、右側の設定パネルで仕上げます。ここを整えるだけで、一気に「監視画面」らしくなります。
- Panel options → Title:
ロボット電流値(J1軸)など分かりやすい名前に - Standard options → Unit:
ampで検索して Ampere (A) を選択(縦軸に単位が付く) - Thresholds:既定の
80を4.5に変更(異常とみなす電流値。この値は設備ごとに、正常運転時の最大値に余裕を足して決めます。今回は例として4.5Aとしています) - Graph styles → Show thresholds:As lines を選択 ← これを忘れると赤線が描かれません
Thresholdsに値を入れただけでは線は出ません。「Show thresholds」を「As lines」にして初めて赤い水平線が引かれます。ここは分かりにくいので注意してください。
リアルタイム更新にする
最後に、画面右上の更新間隔(「Refresh」ボタンの隣)をクリックし、「5s」や「10s」を選びます。これで数秒ごとにグラフが自動更新され、現場のモニターに映しっぱなしにできる監視画面が完成します。

設備の値が変化すると、グラフの右端がリアルタイムで伸びていきます。しきい値を超えた設備は赤線の上に出るので、数字を読まなくても「異常が起きている」と分かります。これがダッシュボードの価値です。
つまずきポイントまとめ
今回の構築で実際に遭遇したものを、症状別にまとめます。
| 症状 | 原因 | 対処 |
|---|---|---|
| 接続できない(証明書エラー) | 暗号化設定が既定のまま | Encrypt を disable(無効) に |
| 選択肢が「間違い」と表示される | ブラウザ翻訳が false を誤訳 | 翻訳をOFFにして英語表示で使う |
| No data(データが出ない) | GrafanaはUTCで問い合わせる | UTCで保存するか、DATEADD(hour,-9,…) で変換 |
| エラーは出ないが0件 | $__timeFilter() に関数を入れた | サブクエリで変換し、列名だけを渡す |
| しきい値の赤線が出ない | Show thresholds が Off | As lines を選択 |
| グラフが動いて見えない | 表示期間が広すぎる | Last 5 minutes など短い期間にする |
【締め】これで「取る→溜める→活かす」がつながった
シリーズを通して、設備IoTの一連の流れが完成しました。
FANUCロボット(電流値・座標) │ ① プロトコルスタジオで常時取得 ▼ Keyence PLC(DMデバイスに保持) │ ② Pythonで読み出してINSERT ▼ SQL Server(robot_logに蓄積) │ ③ Grafanaが読み取り専用ユーザーで参照 ▼ リアルタイム監視ダッシュボード ← 今回はここ
ここまで来ると、次のような発展が現実的に見えてきます。
- アラート通知:Grafanaにはしきい値超過をメールやSlackに通知する機能があります
- 複数設備の一覧監視:設備リストとリレーションを組んであるので、設備が増えてもグラフの系列が自動で増えます
- 長期傾向の分析:同じデータを日単位・月単位で見れば、劣化の進行が見えてきます
今回のダッシュボードで設備ごとに色分けされたグラフが自動で出せたのは、前回の記事で「設備リスト」と「データ収集」を設備IDでリレーションしておいたおかげです。最初のテーブル設計が、こういうところで効いてきます。
データは「取る」だけでは価値になりません。溜めて、見える形にして、初めて判断材料になります。この流れを一気通貫で構築できるのが、FA-Tech Labの強みです。
関連記事
- 【実機解説】Keyence PLCでFANUCロボットの電流値・位置座標を常時取得する方法(プロトコルスタジオ)
- 【実機解説】PythonでKeyence PLCのデータをSQL Serverに自動保存する方法
- PythonでKeyence PLCのデバイスを読み出す方法(上位リンク通信)
お問い合わせ
「設備の稼働状況をリアルタイムで見える化したい」「PLCのデータを収集・監視する仕組みを作りたい」
そんなご相談を承っています。PLC側の設定から、データベース設計・蓄積・可視化まで一気通貫で対応できます。お気軽にお問い合わせください。

