NRav
NRav

Reputation: 407

Stuck in a While True loop... any ideas on how to get out?

Edit #1: Here is the working code, however I sometimes get a UnicodeDecodeError which halts the loop from continuing. Is there anyway to cause a break or pass in the loop when this occurs? I have tried changing the code to Try instead of If statements and its not working...

My issue is in the while True: statement...

def SerialRead(dataReadEvent):
    delay1 = DT.datetime.now()                
    dataReadEvent.set()


    #Serial Reading    
    ser = serial.Serial(port='COM4', baudrate=9600, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, timeout=None)   

    global last_received
    buffer = ''
    amountAppended = 0
    while True:
        buffer += ser.read(ser.inWaiting()).decode('ascii')
        if '\n' in buffer:
            last_received, buffer = buffer.split('\n')[-2:] 
            amountAppended += 1
        if amountAppended == 2:
            amountAppended =0
            break      
    else:
        ser.close()

    global plaintext1
    plaintext1 = last_received.replace(' ', ', ')    
    plaintext = plaintext1.replace('=', ', ')
    global listvalue
    listvalue = plaintext.split(", ")

    #Writing to csv
    outputfile = open(location, mode='a', newline='')
    outputWriter = csv.writer(outputfile)
    outputWriter.writerow([plaintext])
    outputfile.close()     

    delay2 = DT.datetime.now()
    differencetime = (delay2 - delay1).total_seconds()
    restart = (writedelay - differencetime)
    threading.Timer(restart, SerialRead, args=(dataReadEvent,)).start()    

I have trying to get it so that my serial connection reads the last line of input every 5 seconds. However, I have seeded a While True loop inside a threading command and I cannot get out of the While True loop... its always once it is engaged.

The While True Loop allows me to get one complete line of serial data from my unit. I need a full proper line and this was the way to do it, but it snags every time. How can I get out of the Loop?

from PyQt4 import QtGui, QtCore
import sys
import masimo
import csv
import time
import datetime as DT
import threading
from threading import Thread
import serial
import os

os.chdir(r"C:\Users\SpO2\Desktop\Data")
time1 = time.strftime("%d %b %Y %H%M%S")
location = r'%s.csv' % time1
outputfile = open(location, mode='x', newline='')
outputWriter = csv.writer(outputfile)
outputWriter.writerow(["start"])
outputfile.close()
writedelay = int(5)
last_received = ''

class ExampleApp(QtGui.QMainWindow, masimo.Ui_MainWindow):            
    def __init__(self, event, parent=None):
        super(self.__class__, self).__init__()
        self.setupUi(self)

        self.dataWasReadEvent = event
        self.checkThreadTimer = QtCore.QTimer(self)
        self.checkThreadTimer.setInterval(500) #.5 seconds
        self.checkThreadTimer.timeout.connect(self.readListValues) 
        self.checkThreadTimer.start()

    def readListValues(self):
        if self.dataWasReadEvent.is_set():
                #Read your events from the list and update your fields
            self.SPO2text.setText(str(listvalue[5]))
            self.HRtext.setText(str(listvalue[7]))
            self.PItext.setText(str(listvalue[9]))
            self.timestamptext.setText(str(listvalue[1]))
            self.rawdata.setText(str(plaintext1))
            self.dataWasReadEvent.clear() #Clear the event set flag so that nothing happens the next time the timer times out

def SerialRead(dataReadEvent):
    delay1 = DT.datetime.now()                
    dataReadEvent.set()


    #Serial Reading    
    ser = serial.Serial(port='COM4', baudrate=9600, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, timeout=2)   

    global last_received
    buffer = ''
    while True:
        buffer += ser.read(ser.inWaiting()).decode('ascii')
        if '\n' in buffer:
            last_received, buffer = buffer.split('\n')[-2:] 
    else:
        ser.close()



    global plaintext1
    plaintext1 = last_received.replace(' ', ', ')    
    plaintext = plaintext1.replace('=', ', ')
    global listvalue
    listvalue = plaintext.split(", ")

    #Writing to csv
    outputfile = open(location, mode='a', newline='')
    outputWriter = csv.writer(outputfile)
    outputWriter.writerow([plaintext])
    outputfile.close()     

    delay2 = DT.datetime.now()
    differencetime = (delay2 - delay1).total_seconds()
    restart = (writedelay - differencetime)
    threading.Timer(restart, SerialRead, args=(dataReadEvent,)).start()    

def main(dataReadEvent):
    app = QtGui.QApplication(sys.argv)
    form = ExampleApp(dataReadEvent)
    form.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    dataReadEvent = threading.Event()
    Thread(target = SerialRead, args=(dataReadEvent,) ).start()
    Thread(target = main, args=(dataReadEvent,) ).start()

Upvotes: 0

Views: 1496

Answers (4)

Paradizigmania
Paradizigmania

Reputation: 81

The

while True:

function will never end and will never exit, you can use "break" to exit a loop. if this isn't what you want you will have to tell it when the while statement should be active ie:

While amountOfTimesToLoop < 0: do whatever

If you want to check for when things have been appended to your list you can do something like

while True:
    buffer += ser.read(ser.inWaiting()).decode('ascii')
    if '\n' in buffer:
        last_received, buffer = buffer.split('\n')[-2:] 
    if last_received.length == 2:
        break
else:
    ser.close()

or if you aren't clearing the list you could something like

amountAppended = 0
while True:
    buffer += ser.read(ser.inWaiting()).decode('ascii')
    if '\n' in buffer:
        last_received, buffer = buffer.split('\n')[-2:] 
        amountAppended += 1
    if amountAppended == 2:
        amountAppended = 0
        break
else:
    ser.close()

Upvotes: 2

nazia
nazia

Reputation: 75

As you want to "run the loop until i have two lines of data appended to 'last_received'", you can use a counter which increments inside the if statement and then break when the counter value is equals to 2. Something like this:

counter = 1
while True:
   buffer += ser.read(ser.inWaiting()).decode('ascii')
       if '\n' in buffer:
           last_received, buffer = buffer.split('\n')[-2:] 
           if counter == 2:
               break
           counter += 1

Upvotes: 0

Ajay
Ajay

Reputation: 407

Your loop begins with

 while True:

This will always continue forever look at these two examples and note the differences

a=0 
while a<10:
   print a
   a = a+1

This will print 0 1 2 3 4 ... 9 and then a is incremented to 10. the expression evaluates to false and the loop exits.

Now:

a=1
while a>0:
   print a 
   a = a+1 

This will run forever since a always greater than 0

In response to your comment:

Use the having two lines in last_recieved as the test then.

while last_received_count <2:
  .... 
  ....
    if '\n' in buffer:
       last_received, buffer = buffer.split('\n')[-2:]
       last_received_count = last_received_count+1

Upvotes: 0

Luke B
Luke B

Reputation: 2121

Use the break keyword to exit any loop. It will exit whatever loop the break is in.

Upvotes: 0

Related Questions