Python/PySerial/Arduino 读取串行数据,然后将此精确的串行数据写入 txt 文件 [英] Python / PySerial / Arduino Reading serial data and later writing this exact serial data to the txt file

查看:94
本文介绍了Python/PySerial/Arduino 读取串行数据,然后将此精确的串行数据写入 txt 文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在写一篇关于这个案例的新帖子,因为我在第一个帖子中被误解了......

I am making a new post regarding this case because I was misunderstood in the first one...

我有一个代码可以从 Arduino 读取串行数据,当在键盘上按下某些特定数字时,它会将这些数字写入 Arduino.这个确切的代码在我运行时完美运行,它读取串行数据并且我能够将数据写入 Arduino.我使用线程和 PySerial 库来实现这一点.

I have a code that reads the serial data from the Arduino and when some specific digits are pressed on the keyboard it writes these digits to the Arduino. This exact code works perfectly when I run it, it reads the serial data and I am able to write data to the Arduino. I use threading and PySerial library to achieve this.

from pynput import keyboard
import threading
import serial
import sys


ser = None

class SerialReaderThread(threading.Thread):


    def run(self):

        global ser

        ser = serial.Serial('COM3', baudrate = 9600, timeout = 5)

        while True:

            print(ser.readline().decode('utf-8'))


class KeyboardThread(threading.Thread):

    def run(self):

        def on_press(key):

            try:
                format(key.char)

                if key.char == "1":
                    ser.write(b'1\r\n') #serial write - 1

                elif key.char == "2":
                    ser.write(b'2\r\n') #serial write - 2

                elif key.char == "3":
                    ser.write(b'3\r\n') #serial write - 3

                elif key.char == "4":
                    ser.write(b'4\r\n') #serial write - 4

                elif key.char == "5":
                    ser.write(b'5\r\n') #serial write - 5    

                elif key.char == "6":
                    ser.write(b'6\r\n') #serial write - 6

                elif key.char == "0":
                    ser.write(b'0\r\n') #serial write - 0      
            except AttributeError:
                format(key)


        with keyboard.Listener(on_press=on_press) as listener:
            listener.join()

        listener = keyboard.Listener(on_press=on_press)
        listener.start()


serial_thread = SerialReaderThread()
keyboard_thread = KeyboardThread()

serial_thread.start()
keyboard_thread.start()

serial_thread.join()
keyboard_thread.join()

在此之后我有了一个想法,我也可以将这个串行数据与我打印到 Windows 上的 .txt 文件的内容完全相同.所以我创建了一个名为 FileWriting 的新线程,并决定只将 ser.readline().decode('utf-8') 写入它,但是它没有不再工作...这是我写的新修改的代码,用于写入 .txt 文件.

After this I got an idea that I could also write this serial data exactly what I was printing to the .txt file on windows. So I made a new thread called FileWriting and decided to just write ser.readline().decode('utf-8') to it, however it doesn't work anymore... This is the newly modified code which I wrote to write to the .txt file.

from pynput import keyboard
import threading
import serial
import sys
import io


ser = None

class SerialReaderThread(threading.Thread):


    def run(self):

        global ser

        ser = serial.Serial('COM3', baudrate = 9600, timeout = 5)

        while True:

            print(ser.readline().decode('utf-8'))



class FileWriting(threading.Thread):


   def run(self):

       while True:
             with io.open("output.txt", "a", encoding="utf-8") as f:
                    f.write(ser.readline().decode('utf-8'))



class KeyboardThread(threading.Thread):

    def run(self):

        def on_press(key):

            try:
                format(key.char)

                if key.char == "1":
                    ser.write(b'1\r\n') #serial write - 1

                elif key.char == "2":
                    ser.write(b'2\r\n') #serial write - 2

                elif key.char == "3":
                    ser.write(b'3\r\n') #serial write - 3

                elif key.char == "4":
                    ser.write(b'4\r\n') #serial write - 4

                elif key.char == "5":
                    ser.write(b'5\r\n') #serial write - 5    

                elif key.char == "6":
                    ser.write(b'6\r\n') #serial write - 6

                elif key.char == "0":
                    ser.write(b'0\r\n') #serial write - 0      
            except AttributeError:
                format(key)


        with keyboard.Listener(on_press=on_press) as listener:
            listener.join()

        listener = keyboard.Listener(on_press=on_press)
        listener.start()


serial_thread = SerialReaderThread()
keyboard_thread = KeyboardThread()
file_thread = FileWriting()

serial_thread.start()
keyboard_thread.start()
file_thread.start()

serial_thread.join()
keyboard_thread.join()
file_thread.join()

很明显,我只添加了一个名为 file_thread 的新线程,现在当我运行时,串行数据的代码打印工作正常以及向 Arduino 写入数据,但是,代码不会将任何内容写入 .txt 文件并给我一个错误:

As it's clear I only added a new thread called file_thread, now as I run the code printing of the serial data works fine as well as the writing data to the Arduino, however, the code doesn't write anything to the .txt file and gives me an error:

Exception in thread Thread-3:
Traceback (most recent call last):
  File "C:\Python\lib\threading.py", line 932, in _bootstrap_inner
    self.run()
  File "C:\Users\ultra\Desktop\work\menucode.py", line 32, in run
    f.write(ser.readline().decode('utf-8'))
AttributeError: 'NoneType' object has no attribute 'readline'

如果有人在读取串行数据和写入文本文件时遇到了与 Arduino 类似的问题,或者如果有人知道如何解决这个问题,请告诉我我现在非常绝望,我们不胜感激.

推荐答案

在文件的顶部,您声明 ser = None.您收到的错误消息表明在 FileWriting 线程尝试访问它之前,ser 对象尚未设置为 Serial 对象.

At the top of your file, you declare ser = None. The error message you get indicate that the ser object has not yet been set to a Serial object before the FileWriting thread tries to access it.

解决此问题的快速方法是执行

A quick way to fix this issue is by doing

ser = serial.Serial('COM3', baudrate = 9600, timeout = 5)

在开始任何线程之前.

然而,这可能会使程序行为异常,因为您在不同的线程中有两个相互竞争的 ser.readline() 调用.这可能会导致每个线程捕获大约一半的 Arduino 输出数据(取决于 pyserial 如何处理对同一资源的多个请求).为了避免这个问题,我建议让一个单线程接口与 ser 对象,并让该线程使用 队列.

However, that would probably make the program behave strangely, as you have two competing ser.readline() calls in different threads. This would probably result in roughly half of the Arduino's output data being captured by each of the threads (depending on how pyserial handles multiple requests for the same resource). To avoid this issue, I would recommend letting a single thread interface with the ser object, and having that thread pass data to other threads using a queue.

此数据交换方式的简单示例:

A simple example of how this data exchange could go:

import queue
import serial
q = queue.Queue()
ser = serial.Serial('COM3', baudrate = 9600, timeout = 5)

class SerialReaderThread(threading.Thread):
    def run(self):
        while True:
            # Read output from ser
            output = ser.readline().decode('utf-8')
            print(output)
            # Add output to queue
            q.put(output)

class FileWriting(threading.Thread):
   def run(self):
       while True:
             output = q.get()  # This will wait until an item is available in the queue
             with open("output.txt", "a+") as f:
                    f.write(output)
                    f.write("\n")  # If you want outputs separated by newlines

这篇关于Python/PySerial/Arduino 读取串行数据,然后将此精确的串行数据写入 txt 文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆