Как открыть последовательный порт при использовании пакета Python Tools для последовательного порта - PullRequest
0 голосов
/ 06 января 2019

Я пытался отобразить значения датчика температуры в оболочке python, которая связана с Arduino (подключен к моему ноутбуку через порт USB)

Я пытаюсь получить значения последовательного порта, используя пакет python serial.tools.list_ports, но используя указанный ниже код

import serial
import json
import tkinter
from tkinter import messagebox
from tkinter import *
import tkinter as ttk
import serial.tools.list_ports

ard = serial.Serial();
root = ttk.Tk()
root.title("Read Sensor")

B = None
C = None 
ser_dict = {}

# Add a grid
mainframe = Frame(root)
mainframe.grid(column=0,row=0, sticky=(N,W,E,S) )
mainframe.columnconfigure(0, weight = 1)
mainframe.rowconfigure(0, weight = 1)
mainframe.pack(pady = 100, padx = 100)

# Create a Tkinter variable
tkvar1 = StringVar(root)
tkvar = StringVar(root)

#Serial Port
a=serial.tools.list_ports.comports()
for w in a:
    print(w.device)
    k = [w.device]
    print(k)
ser_dict = { i for i in k }
print (ser_dict)
val1 = tkvar1.get()
if val1 in ser_dict:
    ard.port = str (ser_dict[val1])
    ard.isOpen()
    if C:
        C.destroy()
        C = ttk.Button(root, text =val1, command = dropCall)
        C.pack()


# Dictionary with options
baud = { '9600','119200','34800'}

#Pop Up desciption
popupMenu1 = OptionMenu(mainframe, tkvar1, *ser_dict)
Label(mainframe, text="Serial Port").grid(row = 1, column = 1)
popupMenu1.grid(row = 2, column =1)

popupMenu2 = OptionMenu(mainframe, tkvar, *baud)
Label(mainframe, text="Baudrate").grid(row = 3, column = 1)
popupMenu2.grid(row = 4, column =1)


#Serial Callback Functions
def helloCallBack():
    k = ard.readline().decode('ascii');
    if(len(k)>0):
        print (k);
        size = len(k);
        #print (k[0:size-2]);
        print (size);
        messagebox.showinfo('Message From Arduino',k[0:size-2]+'\n'+str(size))  

#def portCall(*kargs):

   #global C
   #global ser_dict


#baudrate functions
def dropCall(*args):
   global B
   value = tkvar.get()
   ## using a dictionary instead of if statements
   ## to show how dictionaries are used
   baud_dict={'9600':value, '34800':value, '119200':value}
   if value in baud_dict:
      ard.baudrate = int(baud_dict[value])
      if B:
         B.destroy()
      B = ttk.Button(root, text =value, command = helloCallBack)
      B.pack()

#Link Function
tkvar.trace('w', dropCall)

Мне приходится сталкиваться с ошибкой, из-за которой я не могу открыть последовательный порт.

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\Misha\AppData\Local\Programs\Python\Python36\lib\tkinter\__init__.py", line 1702, in __call__
    return self.func(*args)
  File "C:\Users\Misha\Desktop\test\GUItest.py", line 61, in helloCallBack
    k = ard.readline().decode('ascii');
  File "C:\Users\Misha\AppData\Local\Programs\Python\Python36\lib\site-packages\serial\serialwin32.py", line 267, in read
    raise portNotOpenError
serial.serialutil.SerialException: Attempting to use a port that is not open

Предложение по этому вопросу поможет вам.

1 Ответ

0 голосов
/ 07 января 2019

Найдите пример кода, который находит и открывает соединение последовательного порта с устройством, подключенным к последовательному порту. Это проверено с Python 3.6 под Linux. Он должен работать под Windows, но я не проверял это. Я использую PID и VID, чтобы выбрать подключенное устройство как:

  1. Может быть несколько активных последовательных портов.
  2. Имя порта может измениться при повторном подключении устройства.
  3. Это более надежно в разных ОС. Windows вызывает порты «COMx», а Linux использует «ttyx».

PID и VID вашего Arduino могут отличаться от моего примера. Сценарий выведет список PID и VID всех подключенных устройств. Измените PID_VARIABLE и VID_VARIABLE на один для вашего Arduino.

import logging
import serial
import serial.tools.list_ports as list_ports
from time import sleep

BAUD =  115200
PID_TARGET = 67
VID_TARGET= 9025
TIMEOUT = 0.1

logging.basicConfig(level=logging.DEBUG, format='%(message)s')


class SerialPort():
    def __init__(self, pid=PID_TARGET, vid=VID_TARGET, baud=BAUD, timeout=TIMEOUT):
        self.serial_port = self.open_serial_port(pid, vid, baud, timeout)


    def get_serial_data(self, serial_port):
        ''' get serial port data '''
        inWaiting = serial_port.inWaiting()
        read_bytes = serial_port.readline(inWaiting)
        if not read_bytes:
            return
        return read_bytes.decode()


    def get_serial_port(self):
        ''' Return the serial port. '''
        return self.serial_port


    def open_serial_port(self, pid=PID_TARGET, vid=VID_TARGET, baud=BAUD, timeout=TIMEOUT):
        ''' Open a serial connection. '''
        print('looking for attached microbit on a serial port')
        serial_port = serial.Serial(timeout=timeout)
        serial_port.baudrate = baud
        ports = list(list_ports.comports())
        print('scanning ports')
        ports.sort(reverse=True)
        for p in ports:
            print('pid: {} vid: {} device: {}'.format(p.pid, p.vid, p.device))
            if (p.pid == pid) and (p.vid == vid):
                print('found target device pid: {} vid: {} port: {}'.format(
                    p.pid, p.vid, p.device))
                serial_port.port = str(p.device)
        if not serial:
            print('no serial port found')
            return None
        try:
            serial_port.open()
            serial_port.flush()
            print('opened serial port: {}'.format(serial_port.port))
        except Exception as e:
            print('cannot open serial port: {}'.format(e))
            return None
        sleep(0.1)
        return serial_port


if __name__ == '__main__':
    print('instatiating SerialPort()')
    serial_port = SerialPort()
    print('finished')
...