1

Python は初めてで、Raspberry Pi と Python を使用してスマート メーターの P1 ポートを読み取りたいと考えています。問題: 入力が一部のコンポーネントが酔っているように見えます。修正するのはかなり簡単だと思いますが、数時間検索して試した後、助けを求めなければなりませんでした.

P1ポートをCUなどで読み込めば問題ないのでハードウェアなどはOKです。dx.com のシリアルから USB へのコンバーターの使用 ( this one )

コマンドと出力 (の一部): cu -l /dev/ttyUSB0 -s 9600 --parity=none

0-0:96.1.1(205A414246303031363631323463949271)
1-0:1.8.1(03118.000*kWh)

ただし、Python から読み込もうとすると、入力が意味不明になります (ただし、少なくとも一貫性があります)。

0-0:96.±.±(²05A´±´²´630303±39363±3²3´639·3±3²©
±-0:±.¸.±(03±±¸.000ªë×è©

これを修正する方法は?私が使用しているコードは次のとおりです。

import serial

ser = serial.Serial()
ser.baudrate = 9600
ser.bytesize=serial.SEVENBITS
ser.parity=serial.PARITY_EVEN
ser.stopbits=serial.STOPBITS_ONE
ser.xonxoff=0
ser.rtscts=0
ser.timeout=20
ser.port="/dev/ttyUSB0"

ser.close()
ser.open()
print ("Waiting for P1 output on "  + ser.portstr)

counter=0
#read 20 lines    
while counter < 20:
    print ser.readline()
    counter=counter+1

try:
    ser.close()
    print ("Closed serial port.")
except:
    sys.exit ("Couldn't close serial port.")

すでにボーレートなどをいじってみましたが、違いはありません。

4

5 に答える 5

2

私はこのモジュールにあまり詳しくありませんが、あなたのコマンドはパリティ ビットがないことを想定している ( ) のに対し、Python スクリプトは偶数パリティ ビットがあることを想定しserialていることに気付きました ( )。私は試してみますcu--parity=noneser.parity=serial.PARITY_EVEN

ser.parity=serial.PARITY_NONE

また、パリティ ビットがない場合は、おそらく

ser.bytesize=serial.EIGHTBITS
于 2013-09-25T09:56:55.393 に答える
0

OPはもうなくなっていますが、問題は十分に一般的なものなので、ここに新鮮な答えがあります. ユーザー @Brionius は正しいです。関連するビット パターンを見ると、これは間違いなくパリティの問題であることがわかります。"1"文字とのビットパターンを検査する方法は次の"±"とおりです。

>>> "{0:b}".format(ord("1"))
'110001'
>>> "{0:b}".format(ord("±"))
'10110001'

それを得る?上位 (8 番目) ビットをオンにすると、文字が破損します。または、 ascii の上位ビットを設定することでこれを確認できます"1"

>>> chr(ord("1") | 0b10000000)
'±'

現在、"1", "2"3"4"つのビットが設定されており (奇数パリティ)、破損しています。"0", "3", "5",などは偶数パリティ (2 ビットまたは 4 ビットが設定されている) を持ち、保持されます。そのため、通信チャネルは偶数パリティを使用しており、受信側で正しくデコードされません。

于 2016-01-06T19:49:05.320 に答える
0

P1 プロトコル DSMR 3.0 のスマート メーターをお持ちですか?次に、これらはすでに持っている正しいシリアル ポート設定です。

serialport = serial.Serial(  # Configure Serial communication port
                            baudrate = 9600,
                            timeout  = 11,
                            bytesize = serial.SEVENBITS,
                            parity   = serial.PARITY_EVEN,
                            stopbits = serial.STOPBITS_ONE )

おそらく、データのエンコードまたは解釈が間違っている可能性があります。スマートメーターを読み取る別の方法は次のとおりです。

p1 プロトコルの読み取りをできるだけ簡単にするために、TextIOWrapper を使用することをお勧めします。この方法では、readline メソッドでシリアル ポートを読み取ることができます。「!」常に P1 テレグラムを終了するため、メッセージの終了を検出するために使用できます。完全なテレグラムが受信されると、テレグラムを処理できます。例:

import io
p1port = io.TextIOWrapper(io.BufferedReader(serialport, buffer_size=1), newline='\n', encoding='ascii')

P1Message = []

while True:
    try:
         rawline = self.p1port.readline()
    except UnicodeDecodeError:
         print "Encode error on readline"

    if '!' in rawline:
        # Process your P1Message here

        P1Message = [] # Clear message, wait for new one
    else:
        P1Message.append(rawline)
于 2014-08-13T12:02:05.090 に答える
0

P1スマートメーターポートのコンテキストでも同じ問題があり、それを見つけるのにかなりの時間がかかりました.

「cu」はデータを正しく表示していましたが、Python はそうではありませんでした (他のプログラムも同様でした)。どうやらパリティビットが正しく処理されていないようです。以下は、この問題を解決します。

p1_raw = ser.readline()
print 'raw:', p1_raw

decoded = ''.join(chr(ord(ch) & 0x7f) for ch in p1_raw)
print 'decoded:', decoded

スマート メーターの出力を 2 回目に読み取ろうとしたときに実際に起こっていたので、これが起こっていることは今でも奇妙に感じます。別の家にある別のスマートメーターを数年間正常に監視するスクリプトが既にありましたが、この問題に遭遇したことはありません.

おそらく、これを引き起こす USB-シリアル アダプタに小さな違いがあるのでしょうか?!?

于 2016-03-20T17:15:20.160 に答える