Raspberry Pi 4と表示器をシリアル通信(RS232C)でつなげたい
Q&A
Closed
解決したいこと
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()
無事送受信ができるようになりました。