# use this SerialComsPairSendInput.py with SerialComsPair_HardwareSerial_PC_UserInput ##Program layout ##This program does NOT use checksums of simplicity of coding. On the Arduino side set ##const bool USE_CHECK_SUM = false; ##const bool COMS_CONTROLLER = false; # this side is the non-controller ## ## ##haveLineOfData() reads the COM port chars and returns true when a non-empty message is received ## If we are clearToSend then discard any input. The other side should not be sending!! ## check for timeout ## collect input line ## discard any extra data after end of input line. Only one line at a time ## set clearToSend and return true if have non-empty line, else false ## ##sendNextMsg() send textToSend to the other side, if and only if clearToSendFlag is TRUE ## replaces \n with space and sends to the other side followed by terminating \n ## if the textToSend is too long the the Arduino side the whole message is ignored ## and the connection will timeout ## ##checkConnectionTimeout() check if there has been any message from the otherside within the connectionTimeout setting ## sets clearToSendFlag = False ## ##When there is nothing to send each side exchanges empty messages i.e. just newline chars, to synchronize send/recieve ## ##Globals ## connectionTimeout in python this is in secs, in Arduino it is in mS ## clearToSendFlag True/False initially False, True when connected AND a message has just been received from the other side. Set to false once a message is sent ## textToSend the message to be sent next when sentNextMsgFlag is true and connected is true. textToSend is cleared when sent ## textReceived the message just recieved. Does not include the terminating newline. Is cleared by next call to haveLineOfData() ## charsReceived, the chars received sofar for the next message. Only used internally by haveLineOfData() ## timeLastMsgRecived used to check for timeout if no messages received for connectionTimeout ## ## import serial import time import sys connectionTimeout = 0.25 # in python this is in secs, in Arduino it is in mS clearToSendFlag = False # True when connected AND a message has just been received from the other side. Set to false once a message is sent textToSend = "" # the message to be sent next when sentNextMsgFlag is true and connected is true. textToSend is cleared when sent textReceived = "" # the message just recieved. Does not include the terminating newline. Is cleared by next call to haveLineOfData() charsReceived = "" # the chars received sofar for the next message. Only used internally by haveLineOfData() timeLastMsgRecived = time.time() # used to check for timeout if no messages received for connectionTimeout startTime = time.time() #======================== # the functions def setupSerial(baudRate, serialPortName): global serialPort serialPort = serial.Serial(port= serialPortName, baudrate = baudRate, timeout=0, rtscts=False) print("Serial port " + serialPortName + " opened Baudrate " + str(baudRate)) #======================== def checkConnectionTimeout(): global clearToSendFlag, timeLastMsgRecived, connectionTimeout if time.time() - timeLastMsgRecived > connectionTimeout: timeLastMsgRecived = time.time() clearToSendFlag = False; #======================== def sendNextMsg(): global clearToSendFlag, textToSend checkConnectionTimeout() if (not clearToSendFlag): return # wait until connected and synced with otherside textToSend.replace("\n"," ") if len(textToSend) > 0: print("%.0fmS " % (1000.0*(time.time()-startTime)),end="");print("sent text '",end=""); print(textToSend,end=""); print("'"); textToSend += "\n" serialPort.write(textToSend.encode('utf-8')) # encode needed for Python3 textToSend = "" # clear for ext msg clearToSendFlag = False # stop other sends until the other side responds #======================== def haveLineOfData(): # returns True if have received non-empty msg else False global receivedText, charsReceived, timeLastMsgRecived, clearToSendFlag if (clearToSendFlag): #ignore any data if we should be sending while serialPort.inWaiting() > 0: # have something to read serialPort.read() # sets connected and clearToSendFlag to as necessary checkConnectionTimeout() receivedText = "" if serialPort.inWaiting() == 0: return False foundEOL = False while serialPort.inWaiting() > 0: # have something to read x = serialPort.read().decode("utf-8") # decode needed for Python3 if x == '\n': foundEOL = True break else: charsReceived += x if foundEOL: #clear out any following data while serialPort.inWaiting() > 0: # have something to read serialPort.read() timeLastMsgRecived = time.time() # reset timeout clearToSendFlag = True; # can send now if len(charsReceived) == 0: return False # empty msg returns False # else have non-empy msg and are connected receivedText = charsReceived charsReceived = "" return True # else still waiting for whole line return False #================== #==================== #==================== # the program setupSerial(9600, "COM5") textToSend = input("Enter an integer to send to Arduino. ") # first cmd to send while True: if haveLineOfData(): # valid response, could be just an empty line with no data print("%.0fmS " % (1000.0*(time.time()-startTime)),end="");print(" Received Data '",end=""); print(receivedText,end=""); print("'") # process textReceived here. can set textToSend in response as well if you want to textToSend = input("Enter integer to send ") if len(textToSend) == 0: textToSend += " " # don't send an empty msg as the other side won't respond # Can overwrite textToSend here if you want to send something else sendNextMsg(); # send textToSend text if connected, else wait for connection. Clears textToSend after it is sent ready for next one # to just send data ignoring textReceived ## if len(textToSend) == 0: # textToSend will be empty when is have been sent ## textToSend = input("Enter cmd to send ") ## if len(textToSend) == 0: ## textToSend += " " # don't send an empty msg as the other side won't respond