実現したいこと
Pythonを使ってArduino(CANシールド搭載)とシリアル通信をして
別のArduino(CANシールド搭載)と通信をしたい。
その際に
tkinterを使って、root.after(10, readSerial)によって
シリアル信号の受信を待ち続けて、
アプリケーションのテキストウィンドウに表示したい。
前提
両社のArduinoはすでにCAN通信が相互にできていることを確認できている。
また、単純にArduinoIDEのシリアルモニタで通信の確認もできている。
↓シリアルモニタ
=> Message Sent Successfully! Sending from CAN No.1 => Message Sent Successfully! Sending from CAN No.2 => Message Sent Successfully! Sending from CAN No.3
さらに、単純な以下のシリアル受信スクリプトでは正しく受信できている。
import serial ser = serial.Serial('COM3', 9600, timeout=0.1) print('Start') a = True i = 0 while a: data = ser.readline() print(data) i = i + 1 if (i>100): a = False ser.close()
結果
b'' b'Sending from CAN No.1\r\n' b' => Message Sent Successfully!\r\n' b'Sending from CAN No.2\r\n' b' => Message Sent Successfully!\r\n' b'Sending from CAN No.3\r\n'
やったこと
以下のようなコードを作成し、実行しました。
現時点では、テキストボックスではなく、シェルへの出力にしています。
import tkinter as tk from tkinter import ttk import serial ser = serial.Serial('COM3', 9600, timeout=0, writeTimeout=0) ser.close() def readSerial(): ser = serial.Serial('COM3', 9600, timeout=0, writeTimeout=10) while True: rxData = ser.read_all() rxData2 = rxData.strip().decode('utf-8') print(rxData2) txt.insert('end', rxData2) if rxData[:2] == "rx": txt.insert('end', rxData2) if len(rxData) == 0: ser.close() break root.after(10, readSerial) def trans1(): sigID = entryBox10.get() sigDLC = entryBox11.get() sigData = [] value = "ID:" + sigID + ", DLC:" + sigDLC +", Data:" sigData.append(entryBox12.get()) sigData.append(entryBox13.get()) sigData.append(entryBox14.get()) sigData.append(entryBox15.get()) sigData.append(entryBox16.get()) sigData.append(entryBox17.get()) sigData.append(entryBox18.get()) sigData.append(entryBox19.get()) value = "ID : " + sigID + ", DLC : " + sigDLC +", Data :" for i in range(int(sigDLC)): value = value + " " + sigData[i] value = value + "\n" #label11["text"] = value txt.insert('end', value) ser = serial.Serial('COM3', 9600, timeout=0.1) #ser.write(value) ser.write(b"tx:130h,8,FE,F3,33,44,44,22,35,22\n") ser.close() def trans2(): sigID = entryBox20.get() sigDLC = entryBox21.get() sigData = [] value = "ID:" + sigID + ", DLC:" + sigDLC +", Data:" sigData.append(entryBox22.get()) sigData.append(entryBox23.get()) sigData.append(entryBox24.get()) sigData.append(entryBox25.get()) sigData.append(entryBox26.get()) sigData.append(entryBox27.get()) sigData.append(entryBox28.get()) sigData.append(entryBox29.get()) value = "ID : " + sigID + ", DLC : " + sigDLC +", Data :" for i in range(int(sigDLC)): value = value + " " + sigData[i] value = value + "\n" #label11["text"] = value txt.insert('end', value) ser = serial.Serial('COM3', 9600, timeout=0.1) ser.write(value.encode('utf-8')) ser.close() # メインウィンドウ作成 root = tk.Tk() #メインウィンドウのタイトルを変更 root.title("CAN tool for CAN box 3") #メインウィンドウを640x480にする root.geometry("640x480") #ラベルを追加 label1 = tk.Label(root, text="受信内容"+" Don't Input anything here") label1.place(x=20, y=20) #テキストボックス txt = tk.Text(root) #txt.insert(1.0, "Don't Input anything here") txt.place(x = 20, y =40, height = 220, width = 600) #ラベルを追加 label2 = tk.Label(root, text="送信内容") label2.place(x=20, y=280) #送信信号1 y_sig1 = 300 entryBox10 = tk.Entry(root, width = 10) entryBox10.insert(tk.END, "140") entryBox10.place(x=20, y=y_sig1) label11 = tk.Label(root, text="h") label11.place(x=80, y=y_sig1) entryBox11 = tk.Entry(root, width = 2) entryBox11.insert(tk.END, "8") entryBox11.place(x=120, y=y_sig1) entryBox12 = tk.Entry(root, width = 6) entryBox12.insert(tk.END, "FF") entryBox12.place(x=150, y=y_sig1) entryBox13 = tk.Entry(root, width = 6) entryBox13.insert(tk.END, "FF") entryBox13.place(x=200, y=y_sig1) entryBox14 = tk.Entry(root, width = 6) entryBox14.insert(tk.END, "FF") entryBox14.place(x=250, y=y_sig1) entryBox15 = tk.Entry(root, width = 6) entryBox15.insert(tk.END, "FF") entryBox15.place(x=300, y=y_sig1) entryBox16 = tk.Entry(root, width = 6) entryBox16.insert(tk.END, "FF") entryBox16.place(x=350, y=y_sig1) entryBox17 = tk.Entry(root, width = 6) entryBox17.insert(tk.END, "FF") entryBox17.place(x=400, y=y_sig1) entryBox18 = tk.Entry(root, width = 6) entryBox18.insert(tk.END, "FF") entryBox18.place(x=450, y=y_sig1) entryBox19 = tk.Entry(root, width = 6) entryBox19.insert(tk.END, "FF") entryBox19.place(x=500, y=y_sig1) #ボタンを作る button1 = tk.Button(root, text="送信", command=trans1) button1.place(x=560, y=y_sig1-5) #送信信号2 y_sig2 = 340 entryBox20 = tk.Entry(root, width = 10) entryBox20.insert(tk.END, "141") entryBox20.place(x=20, y=y_sig2) labe21 = tk.Label(root, text="h") labe21.place(x=80, y=y_sig2) entryBox21 = tk.Entry(root, width = 2) entryBox21.insert(tk.END, "8") entryBox21.place(x=120, y=y_sig2) entryBox22 = tk.Entry(root, width = 6) entryBox22.insert(tk.END, "FF") entryBox22.place(x=150, y=y_sig2) entryBox23 = tk.Entry(root, width = 6) entryBox23.insert(tk.END, "FF") entryBox23.place(x=200, y=y_sig2) entryBox24 = tk.Entry(root, width = 6) entryBox24.insert(tk.END, "FF") entryBox24.place(x=250, y=y_sig2) entryBox25 = tk.Entry(root, width = 6) entryBox25.insert(tk.END, "FF") entryBox25.place(x=300, y=y_sig2) entryBox26 = tk.Entry(root, width = 6) entryBox26.insert(tk.END, "FF") entryBox26.place(x=350, y=y_sig2) entryBox27 = tk.Entry(root, width = 6) entryBox27.insert(tk.END, "FF") entryBox27.place(x=400, y=y_sig2) entryBox28 = tk.Entry(root, width = 6) entryBox28.insert(tk.END, "FF") entryBox28.place(x=450, y=y_sig2) entryBox29 = tk.Entry(root, width = 6) entryBox29.insert(tk.END, "FF") entryBox29.place(x=500, y=y_sig2) #ボタンを作る button2 = tk.Button(root, text="送信", command=trans2) button2.place(x=560, y=y_sig2-5) root.after(200, readSerial) #rootを表示し無限ループ root.mainloop()
発生している問題・エラーメッセージ
エラーはありません。
ただ、シェルに文字が出てきません。
ただ、改行はしているみたいです。
上記のプログラムでは画面がスクロールされている状態です。
スクリプト内部の出力を、print(rxData2)からprint(rxData)にすると
バイナリの何かしらを受信していることはわかります。
送信と受信のタイミングでしょうか?
※ちなみにシリアルのボーレートはすべて9600に統一していますので、
スクリプトの書き方が悪いように推測しています。
b'' b'' b'' b'' b''
試したこと
readline()を
read_all()、read()に変えてみる。
⇒効果なし
シリアル通信のタイムアウトを0から10に変更
⇒効果なし
補足情報(FW/ツールのバージョンなど)
Windows10、
Arduino1.8.9
Python.Python.3.7.4
追記8/17
現在のスクリプトを記載します。
ボタンが2つあって、
1つがstartSerial()とstopSerial()を割り当てています。
startSerial()によって受信開始(とうより読み込み開始?)して、
出力。
その途中にstopSerial()のボタンを押すと中断するようにしたい。
しかし、現状では受信開始してしまうとコントロールができなくなり、
ボタンを押すことができません。
ser = serial.Serial('COM3', 9600, timeout=0.1, writeTimeout=0) def readSerial(figS): global ser, fig print("a") ''' i = 0 b = True ser = serial.Serial('COM3', 9600, timeout=0.1, writeTimeout=0) while b == True: data = ser.readall() print(data) i = i + 1 if (i>100): b = False ser.close() ''' #ser = serial.Serial('COM3', 9600, timeout=0.1, writeTimeout=0) if flgS == True: while True: rxData = ser.readall() rxData2 = rxData.strip().decode('utf-8') print(rxData) if len(rxData) > 0: txt.insert('end', rxData2) break root.after(10, readSerial(True)) def startSerial(): print("Start serial") #ser = serial.Serial('COM3', 9600, timeout=0.1, writeTimeout=0) readSerial(True) def stopSerial(): print("Stop serial") #ser.close() readSerial(False)
回答3件
あなたの回答
tips
プレビュー