@shimamura1026

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Raspberry Pi 4と表示器をシリアル通信(RS232C)でつなげたい

解決したいこと

Raspberry Pi4と表示器のシリアル通信を可能にしたい

前提

・ラズパイとマイコンのシリアル通信にトライしているが、規定のコマンドを送信しても返信がない
・ラズパイとマイコンはRS232CとUSBの変換コードを介している
・マイコン指定の伝送コードはASCII
・フォーマットは {STX}{コマンド}{CR}{チェックサム}{ETX}
・「チェックサムが’0000’の場合は誤り検出を行わずに実行します。」との記述があったのでチェックサムは'0000'に固定している
・マイコン付属の通信確認ソフトをPCにインストールし確認してみたが、問題なく応答したので配線等の問題ではないと思う
・baudrateが9600なのは確認済み
・普段はvb.netを使っているのでコードを書いてみたが、こちらでは返信があった
・いざラズパイのpythonで実装しようとしたがうまくいかない

該当のソースコード


import serial

writeSer = serial.Serial('/dev/ttyUSB0',9600,timeout=1)
dat = send_data('ABC123') #送りたいコマンド

def send_data(s):
    s='\2'+s+'\15'+'0000'+'\3' #{STX} + コマンド + {CR} + チェックサム + {ETX}
    return s.encode('ascii')

for b in dat:
    print(hex(b).encode('ascii'))
    writeSer.write(hex(b).encode('ascii'))

writeSer.close()

readSer = serial.Serial('/dev/ttyUSB0',9600,timeout=1)
line = readSer.readline()
print("Read  serial:"+line.decode('ascii')) #返信表示
readSer.close()

試したこと

https://qiita.com/umi_mori/items/757834e0ef75f38cea19
https://teratail.com/questions/sgqssronc4bzcn

上記を参考に作成した

以下はちゃんと返信があったvb.netのコード


SerialPort1.Write(Chr(&H2)) '{STX}
text = "ABC123"             '{コマンド}
For i = 1 To Len(text)
            SerialPort1.Write(Mid(text, i, 1))
Next
SerialPort1.Write(Chr(&HD)) '{CR}
text = "0000"               '{チェックサム}
For i = 1 To Len(text)
            SerialPort1.Write(Mid(text, i, 1))
Next
SerialPort1.Write(Chr(&H3)) '{ETX}

それとpythonの{CR}のところがasciiコード表だと13となっているが、\13にしてみると0x0bとなってしまう。
0x0dだと思っていたのだがこの違いは何なのか?

追記

いろいろ試したところ、下記のコードで返信がきた。
オシロでそれっぽいデータが来ていることは確認している。
書き込みはうまくいったっぽい。


import serial

writeSer = serial.Serial('/dev/ttyUSB0',9600,timeout=1)
dat = send_data('ABC123') #送りたいコマンド

def send_data(s):
    s='\2'+s+'\r'+'0000'+'\3' #{STX} + コマンド + {CR} + チェックサム + {ETX}
    return s.encode('ascii')

for b in dat:
    print(chr(b).encode('ascii'))
    writeSer.write(chr(b).encode('ascii')) #hex(b)じゃなくてchr(b)だった

writeSer.close()

しかし今度は読み取りがうまくいかない。
print(len(line))で信号を受け取れているか確認しているが0と表記される。

readSer = serial.Serial('/dev/ttyUSB0',9600,timeout=1)
line = readSer.read()
print(len(line))
print("Read  serial:"+line.decode('ascii')) #返信表示
readSer.close()

vb.netでの受信は下記のようにしていた。
これで問題なく受信できていた。
Timer1は100ms間隔

  Dim ReceptionData As String
    Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
        ' シリアルポートからデータ受信
        Dim dat As Byte() = New Byte(SerialPort1.BytesToRead - 1) {}
        SerialPort1.Read(dat, 0, dat.GetLength(0))

        ReceptionData = System.Text.Encoding.GetEncoding("ASCII").GetString(dat)
    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        TextBox2.Text = ReceptionData

        If ReceptionData = "" Then
            TextBox2.Text = "NON"
        End If
    End Sub

正しく受信できる方法を教えてほしい。

追記-2

送信と受信でそれぞれポートを開け閉めしているのが原因だった。


import serial

writeSer = serial.Serial('/dev/ttyUSB0',9600,timeout=1)
dat = send_data('ABC123') #送りたいコマンド

def send_data(s):
    s='\2'+s+'\r'+'0000'+'\3' #{STX} + コマンド + {CR} + チェックサム + {ETX}
    return s.encode('ascii')

for b in dat:
    print(chr(b).encode('ascii'))
    writeSer.write(chr(b).encode('ascii'))

#writeSer.close() ここでcloseしているのがいけなかった

readSer = serial.Serial('/dev/ttyUSB0',9600,timeout=1)
line = readSer.readline()
print(len(line))
print("Read  serial:"+line.decode('ascii')) #返信表示
readSer.close()

無事送受信ができるようになりました。

0 likes

2Answer

それとpythonの{CR}のところがasciiコード表だと13となっているが、\13にしてみると0x0bとなってしまう。
0x0dだと思っていたのだがこの違いは何なのか?

CRは 0x0d で 10進数 で 13 です。
\13ではなく、\0xdと書けばよいはずです。
\13だと、8進数の13の意味なので、10進数の11、16進数の0bになります。

1Like

Comments

  1. > ラズパイとマイコンのシリアル通信を可能にしたい

    「ラズパイ」とは、「Raspberry Pi 4」とかでしょうか?
    「マイコン」とは何を指しているのでしょうか?

    UART(シリアル通信)で接続するなら、GND、TXD、RXDの3ピンを接続するだけです。
    USBが出てくるので、相手はPCでしょうか?

  2. ↑ ラズパイ(Raspberry Pi 2/3/4)と マイコン(Raspberry Pi Pico)をUART(シリアル通信)で接続する例です。

  3. @shimamura1026

    Questioner

    「ラズパイ」は「Raspberry Pi 4」です。
    すみません、「マイコン」は「マイコン用表示器」です。
    このマイコン用表示器はシリアル通信がRS232C指定です。

    UARTを使用するにはレベル変換をする必要があると思ったので、まずは表示器に付属のRS232C用コードを接続し、そこにUSB変換ケーブルを差してRaspberry Pi 4と接続させています。

  4. UARTを使用するにはレベル変換をする必要があると思ったので、まずは表示器に付属のRS232C用コードを接続し、そこにUSB変換ケーブルを差してRaspberry Pi 4と接続させています。

    それで通信できているのなら問題ないと思います。

    ちなみに、
    「マイコン用表示器」の型名が不明のため 不確実ですが、5Vで動作するなら、
    マイコン側のRS232-Cのpin2(TXD)、pin3(RXD)、pin7(GND)をラズパイの該当するピンに直接接続することもできます。(TXDとRXDはクロスで接続する)

  5. @shimamura1026

    Questioner

    print(writeSer) を入れてみると open=True と表記されるので接続はできていると思っています。
    5VDCなので直接接続は可能そうです。
    試してみます。

  6. ラズパイでUARTを使用する場合は、raspi-configでuartを有効にする必要があります。
    また、デバイスは、/dev/ttyXXX になります。

質問がわかりづらすぎるのでこんな感じですかね?

質問
RS-232Cで接続する表示器がありRaspberry Pi 4と接続したい
本体内蔵のUARTで接続するにはレベルを変換する必要があるので
USB<->RS-232C変換器を使って接続したが何も表示されない

vb.netで作ったのはちゃんと動作したのでpythonで実装したい

手順
ラズパイのUSBポートに挿す
USBシリアルを確認する

pi@raspberrypi:~/work/python $ ls -l /dev/ttyUSB*
複数挿してなければ/dev/ttyUSB0になる
シリアルのアクセス権限を追加
モジュールをインストール

0Like

Comments

  1. @shimamura1026

    Questioner

    質問内容はそれで合っています。
    どの情報が必要なのかわからなかったので、とりあえずわかることを書いてしまい逆にわかりづらくしてしまいました。すいません。

  2. @shimamura1026

    Questioner

    ・複数挿してなければ/dev/ttyUSB0になる
    $ ls -l /dev/ttyUSB* 
    で /dev/ttyUSB0 が表示されています

    ・シリアルのアクセス権限を追加
    $ stty -F /dev/ttyUSB0 
    で各種値が表示されているので権限はあるという認識でよろしいのでしょうか。

    ・モジュールをインストール
    $ pip list

    pyserial 3.5b0
    を確認しました。

  3. そこまでできていて vb.netで動作しているということなのであとは言語の違いによる問題だと思いますが
    シリアルポートから本当に信号が出ているのか?というのは非常にやっかいな問題です
    お手持ちの機材や環境でRS-232C信号が出ているのか確認できますか?

    1.オシロスコープでTXD GNS間の信号を見る
     それっぽい信号が出ていればとりあえずOK
     正常に動作している方でも出力して比較する

    2.表示器ではなくパソコンと接続する
     ※接続がクロスになるかもしれません
     RS-232Cをモニタするアプリで確認する

  4. @shimamura1026

    Questioner

    オシロで確認しました。
    信号は出ているようでレベルもPCと同様です。

Your answer might help someone💌