2012-10-22 15 views
14

Tôi có chương trình python đang đọc dữ liệu từ cổng nối tiếp qua mô-đun PySerial. Hai điều kiện tôi cần lưu ý là: Tôi không biết dữ liệu sẽ phát triển mạnh như thế nào, và tôi không biết khi nào cần dữ liệu.Sử dụng PySerial là nó có thể chờ dữ liệu không?

Dựa trên này, tôi đã nảy ra snipets đang sau:

#Code from main loop, spawning thread and waiting for data 
s = serial.Serial(5, timeout=5) # Open COM5, 5 second timeout 
s.baudrate = 19200 

#Code from thread reading serial data 
while 1: 
    tdata = s.read(500) # Read 500 characters or 5 seconds 

    if(tdata.__len__() > 0):  #If we got data 
    if(self.flag_got_data is 0): #If it's the first data we recieved, store it 
     self.data = tdata   
    else:       #if it's not the first, append the data 
     self.data += tdata 
     self.flag_got_data = 1 

Vì vậy, mã này sẽ lặp mãi mãi nhận được dữ liệu ra khỏi cổng nối tiếp. Chúng tôi sẽ nhận được tối đa 500 ký tự lưu trữ dữ liệu, sau đó cảnh báo vòng lặp chính bằng cách đặt cờ. Nếu không có dữ liệu, chúng tôi sẽ quay lại ngủ và đợi.

Mã đang hoạt động, nhưng tôi không thích thời gian chờ của 5s. Tôi cần nó bởi vì tôi không biết bao nhiêu dữ liệu để mong đợi, nhưng tôi không thích rằng nó thức dậy mỗi 5 giây ngay cả khi không có dữ liệu có mặt.

Có cách nào để kiểm tra khi dữ liệu có sẵn trước khi thực hiện read không? Tôi đang suy nghĩ một cái gì đó giống như lệnh select trong Linux.

EDIT:
Chỉ cần nghĩ rằng tôi muốn lưu ý rằng tôi tìm thấy phương pháp inWaiting(), nhưng thực sự mà dường như nó chỉ cần thay đổi tôi "ngủ" tới thăm dò, do đó không phải là những gì tôi muốn ở đây. Tôi chỉ muốn ngủ cho đến khi dữ liệu vào, sau đó đi lấy nó.

Trả lời

15

Ok, tôi thực sự có một cái gì đó với nhau mà tôi thích cho việc này. Sử dụng một sự kết hợp của read() không có thời gian chờ và inWaiting() phương pháp:

#Modified code from main loop: 
s = serial.Serial(5) 

#Modified code from thread reading the serial port 
while 1: 
    tdata = s.read()   # Wait forever for anything 
    time.sleep(1)    # Sleep (or inWaiting() doesn't give the correct value) 
    data_left = s.inWaiting() # Get the number of characters ready to be read 
    tdata += s.read(data_left) # Do the read and combine it with the first character 

    ... #Rest of the code 

Điều này dường như cho kết quả tôi muốn, tôi đoán kiểu này chức năng không tồn tại như một phương pháp duy nhất trong Python

+1

'time.sleep (1)' có vẻ giống như một hack khá xấu mà thêm một loạt các chậm trễ để nhận dữ liệu của bạn. – TJD

+0

@TJD - Không có đối số ở đó, dường như nó hoạt động mà không có giấc ngủ là tốt, nhưng 'data_left' trở nên rất không đáng tin cậy (một chuỗi gồm 19 ký tự là 3, sau đó 10, 6 ngân hàng). Vì vậy, tôi vẫn không hài lòng với nó, nhưng nó gần gũi hơn với những gì tôi đang nghĩ đến. Ngủ cho đến khi dữ liệu, sau đó đọc dữ liệu, sau đó quay trở lại giấc ngủ. – Mike

+0

Tôi không thấy làm thế nào đó là "không đáng tin cậy". Đó chính là cách các byte đến khi bạn đọc chúng.Bạn có thể muốn sử dụng 'interCharTimeout', cho phép bạn phát hiện khi người nhận đã ngừng xem bất kỳ byte mới nào. – TJD

10

Bạn có thể đặt timeout = None, sau đó cuộc gọi read sẽ chặn cho đến khi số byte được yêu cầu ở đó. Nếu bạn muốn đợi cho đến khi dữ liệu đến, chỉ cần thực hiện read(1) với thời gian chờ None. Nếu bạn muốn kiểm tra dữ liệu mà không chặn, hãy thực hiện read(1) với thời gian chờ bằng 0 và kiểm tra xem nó có trả về bất kỳ dữ liệu nào không.

(xem tài liệu http://pyserial.sourceforge.net/pyserial_api.html)

+1

Nhưng tôi cũng nghĩ rằng có hoàn toàn là không có gì sai với việc sử dụng một thời gian chờ 5s và có nó wakeup và ngay lập tức quay trở lại để đọc. Nó rất đơn giản và sẽ không có chi phí có thể đo lường được. – TJD

+0

Cảm ơn thông tin, tôi đã xem tài liệu đọc chỉ không thể tìm ra cách để làm cho nó làm những gì tôi muốn. Tôi đồng ý có một vòng lặp với một thời gian chờ không phải là tốn kém khủng khiếp trên một máy tính để bàn, nhưng (đến từ một nền nhúng) nó cảm thấy rất sai với tôi để thăm dò ý kiến ​​ – Mike

+0

Giải pháp tốt hơn theo ý kiến ​​của tôi (ít nhất là cho nhu cầu của tôi). Cám ơn vì đã chia sẻ. – Marcel

0
def cmd(cmd,serial): 
    out='';prev='101001011' 
    serial.flushInput();serial.flushOutput() 
    serial.write(cmd+'\r'); 
    while True: 
     out+= str(serial.read(1)) 
     if prev == out: return out 
     prev=out 
    return out 

gọi nó là như thế này:

cmd('ATZ',serial.Serial('/dev/ttyUSB0', timeout=1, baudrate=115000)) 
Các vấn đề liên quan