LoginSignup
1
3

More than 5 years have passed since last update.

京セラモニタ(PMD47A)とのシリアル通信データ解析

Last updated at Posted at 2017-05-28
1 / 4

はじめに

  • 京セラ製太陽光発電システムが稼働している関係で、エコノナビット(PMD47A)という発電状況をモニタする装置(以下、モニタ)を設置しています。
  • このモニタはPCとシリアル通信ポートで繋がっていて、京セラから提供されている通信ソフトを使うと、モニタから収集したデータがCSVファイルで出力されます。
  • 定期的にモニタからのデータ収集を行いたいのですが、それだとPCを常時稼働させる必要があります。
  • このデータ収集をラズパイで行いたいと思い、その通信内容を把握することが今回の目的となります。

UART通信のキャプチャ

  • ラズパイと秋月電子製USB-シリアル2ch変換モジュールを使って、モニターPC間のUART通信をキャプチャし、解析してみることにしました。
  • 構成図
    linemon.png

  • 回路図

    • CN1がシリアルポートの9ピンDSUBとなっており、RxD(2番)、TxD(3番)とも上記モジュールの受信入力に繋がるようにします。
    • ラズパイは、3.3Vの供給に使い、上記モジュールとはUSBケーブルで接続します。 スクリーンショット 2017-05-28 18.18.57.png
  • プログラム

    • 2chのUART受信を行い、そのデータを標準出力するだけのものです。
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import time
import datetime
import threading
import serial

event = threading.Event()
lock = threading.Lock()

def cap(dev, baud, ch) :
  ser = serial.Serial(dev, baud, timeout=5)
  while event.is_set() != True :
    data = ser.read()
    if data.__len__() > 0 :
      lock.acquire()
      try :
        if ch == 0 :
          print("{0:02X},".format(ord(data)))
        else :
          print(",{0:02X}".format(ord(data)))
      finally :
        lock.release()

def wait(msg) :
  code = raw_input("")
  event.set()

thread1 = threading.Thread(target=cap, args=('/dev/ttyUSB0', 38400, 0,))
thread2 = threading.Thread(target=cap, args=('/dev/ttyUSB1', 38400, 1,))
thread3 = threading.Thread(target=wait, args=('>>> ',))
thread1.start()
thread2.start()
thread3.start()
thread1.join()
thread2.join()
thread3.join()

解析結果

  • プロトコル
    • 下記の流れでやり取りされる。(全データを送り終わるまで、5と6が繰り返される)
      1. PCからの要求電文
      2. モニタからのACK電文
      3. モニタからの開始電文
        • この電文から、全データ数を抽出できる。
      4. PCからのACK電文
      5. モニタからのデータフレーム
      6. PCからのACK電文
      7. モニタからの終了電文
      8. PCからのACK電文
    • とりあえず、全データを取得するには、下記の電文フォーマットを把握できれば問題なさそう。
      • PCからの要求電文(1)
      • モニタからの開始電文(3)
      • PCからのACK電文(4,6)
      • モニタからのデータフレーム(5)
  1. PCからの要求電文構成

    • STX(02h)から始まり、ETX(03h)で終わる電文。
      • STX, CMD1000FFFF50, ETX
      • 何度かキャプチャして比較したが、毎回同じだった。固定文字列でよさそう。
  2. PCからのACK電文構成

    • STX(02h)、ACK(06h)、ETX(03h)の3バイト。
  3. モニタからの開始電文構成

    • STX(02h)から始まり、ETX(03h)で終わる電文。
      • STX, CMD01000000214FCB, ETX
      • この電文から、全データ数214Fh(8527byte)が得られる。
      • 何度かキャプチャして比較したが、毎回同じだった。
      • 8527byte固定でよいかもしれないが、電文から取得すべきと思われる。
    • 具体例
    02434D44303130303030303032313446434203
    
  4. モニタからのデータフレーム構成

    • フレームの正常性確認は、BCCを含めたn+2バイトを加算して、下位8ビットがFF(16進値)となるかどうかで判定。
      • データ長が1バイト、ペイロードがnバイト、BCCが1バイト。
    • 具体例
      • データ長=21h(33byte)
      • BCC=93h
      • チェックサム(16進)=21+45+43+4E+56+00+01+00+68+21+4F+00+68+00+14+00+7C+00+03+00+23+00+E5+00+02+06+90+0E+05+00+02+06+90+93=5FFh
    2145434E5600010068214F00680014007C0003002300E5000206900E050002069093
    
  5. データ・レイアウト

    • データフレームのペイロードを抽出して、順に並べたもの。
    • 30分毎のデータ、日毎のデータ、月毎のデータが下表に示すようなレイアウトで配置されている。
項番 種別 アドレス範囲 備考
1 30分毎のデータの日付 007C〜00E4 年月日の3バイトが、35日分
2 30分毎の発電データ 00E5〜0E04 10倍した値が2バイト(16進値)で1データ、48データが1日分で35日。未取得の時間帯は、7530hとなっている。
3 30分毎の買電ー売電データ 0E05〜1B24 10倍した値が2バイト(16進値)で1データ、48データが1日分で35日。未取得の時間帯は、7530hとなっている。
4 日毎のデータの日付 1B48〜1C73 年月日の3バイトが100日分
5 日毎の発電データ 1C74〜1D3B 1日分が2バイト(16進値)で、100日分
6 日毎の買電ー売電データ 1D3C〜1E03 1日分が2バイト(16進値)で、100日分
7 月毎のデータの日付 1E04〜1EB7 年月日の3バイトが、60ヶ月分
8 月毎の発電データ 1EB8〜1F2F 1月分が2バイト(16進値)で、60ヶ月分
9 月毎の買電ー売電データ 1F30〜1FA7 1月分が2バイト(16進値)で、60ヶ月分
1
3
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
1
3