def __init__(self, portNum, baud=19200, sendInit=False): if 0 <= portNum <=5 and portNum != 3: # Uart - serial ports - 0,1,2,4 and 5 # Port 3 is not available via headers # Port 0 refers to the USB. This doesn't need pin, mode & port # settings but I've put those in as zero values (which can be tested for) # just for completeness self.commPortInfo = [ {'name': 'usb', 'dev': 'ttyACM0', 'txPin': 0, 'rxPin': 0, 'mode': 0, 'port': 0}, {'name': 'uart1', 'dev': 'ttyO1', 'txPin': 24, 'rxPin': 26, 'mode': 0, 'port': 9}, {'name': 'uart2', 'dev': 'ttyO2', 'txPin': 21, 'rxPin': 22, 'mode': 1, 'port': 9}, 0, {'name': 'uart4', 'dev': 'ttyO4', 'txPin': 13, 'rxPin': 11, 'mode': 6, 'port': 9}, {'name': 'uart5', 'dev': 'ttyO5', 'txPin': 37, 'rxPin': 38, 'mode': 4, 'port': 8} ] self.uart = portNum self.dev = '/dev/' + self.commPortInfo[self.uart]['dev'] self.name = self.commPortInfo[self.uart]['name'] self.baudRate = baud # default self.byteSize = EIGHTBITS self.parity = PARITY_NONE # this is pySerial default anyway self.stopBits = STOPBITS_ONE # also pySerial default self.timeOut = 3 self.message = '' self.port = 0 self.txPin = 0 self.rxPin = 0 self.mode = 0 if self.uart > 0: # this is one of the uart ports rather than usb self.port = self.commPortInfo[self.uart]['port'] self.txPin = self.commPortInfo[self.uart]['txPin'] self.rxPin = self.commPortInfo[self.uart]['rxPin'] self.mode = self.commPortInfo[self.uart]['mode'] self.tx = GPIO_pin(self.port, self.txPin, BB.OUTPUT) self.tx.setMode(self.mode) self.rx = GPIO_pin(self.port, self.rxPin, BB.INPUT) self.rx.setMode(self.mode) try: self.serPort = Serial(self.dev, baudrate = self.baudRate, #parity = self.parity, #bytesize = self.byteSize, #stopbits = self.stopBits, timeout=0.1, xonxoff=0, rtscts=0, interCharTimeout=None) self.serPort.flushOutput() self.serPort.flushInput() except serial.serialutil.SerialException as e: print(e) exit() if sendInit: # Opening a serial connection to an Arduino can cause it to # reset, so let's send it an init message then give it a moment # to get its act together self.send('++INIT++') time.sleep(2) self.serPort.flushOutput() self.serPort.flushInput() else: # throw an exception one day, but for time being print a message print('*** ERROR: ' + str(portNum) + 'is not a valid uart number') exit()
class CommPort: ''' commPort class USAGE: Needs to be instantiated with the following params: portNum 0, 1, 2, 4 or 5 required baud <baud rate> optional defaults to 19200 sendInit boolean optional ''' def __init__(self, portNum, baud=19200, sendInit=False): if 0 <= portNum <=5 and portNum != 3: # Uart - serial ports - 0,1,2,4 and 5 # Port 3 is not available via headers # Port 0 refers to the USB. This doesn't need pin, mode & port # settings but I've put those in as zero values (which can be tested for) # just for completeness self.commPortInfo = [ {'name': 'usb', 'dev': 'ttyACM0', 'txPin': 0, 'rxPin': 0, 'mode': 0, 'port': 0}, {'name': 'uart1', 'dev': 'ttyO1', 'txPin': 24, 'rxPin': 26, 'mode': 0, 'port': 9}, {'name': 'uart2', 'dev': 'ttyO2', 'txPin': 21, 'rxPin': 22, 'mode': 1, 'port': 9}, 0, {'name': 'uart4', 'dev': 'ttyO4', 'txPin': 13, 'rxPin': 11, 'mode': 6, 'port': 9}, {'name': 'uart5', 'dev': 'ttyO5', 'txPin': 37, 'rxPin': 38, 'mode': 4, 'port': 8} ] self.uart = portNum self.dev = '/dev/' + self.commPortInfo[self.uart]['dev'] self.name = self.commPortInfo[self.uart]['name'] self.baudRate = baud # default self.byteSize = EIGHTBITS self.parity = PARITY_NONE # this is pySerial default anyway self.stopBits = STOPBITS_ONE # also pySerial default self.timeOut = 3 self.message = '' self.port = 0 self.txPin = 0 self.rxPin = 0 self.mode = 0 if self.uart > 0: # this is one of the uart ports rather than usb self.port = self.commPortInfo[self.uart]['port'] self.txPin = self.commPortInfo[self.uart]['txPin'] self.rxPin = self.commPortInfo[self.uart]['rxPin'] self.mode = self.commPortInfo[self.uart]['mode'] self.tx = GPIO_pin(self.port, self.txPin, BB.OUTPUT) self.tx.setMode(self.mode) self.rx = GPIO_pin(self.port, self.rxPin, BB.INPUT) self.rx.setMode(self.mode) try: self.serPort = Serial(self.dev, baudrate = self.baudRate, #parity = self.parity, #bytesize = self.byteSize, #stopbits = self.stopBits, timeout=0.1, xonxoff=0, rtscts=0, interCharTimeout=None) self.serPort.flushOutput() self.serPort.flushInput() except serial.serialutil.SerialException as e: print(e) exit() if sendInit: # Opening a serial connection to an Arduino can cause it to # reset, so let's send it an init message then give it a moment # to get its act together self.send('++INIT++') time.sleep(2) self.serPort.flushOutput() self.serPort.flushInput() else: # throw an exception one day, but for time being print a message print('*** ERROR: ' + str(portNum) + 'is not a valid uart number') exit() def send(self, sendStr, encoding='utf-8', addNewline=True, cleanString=True): ''' Send a message. A newline is appended, so don't need to include that in the string. ''' if cleanString: sendStr = sendStr.strip() # clean it up first if addNewline: sendStr = sendStr + '\n' self.serPort.write(sendStr.encode(encoding, 'replace')) #self.serPort.flush() return def newMsgs(self, encoding='utf-8'): ''' Obtain list of incoming messages. Assumes each message is terminated by newline. Dodgy bytes are treated using the .replace() method which does standard replacing according to codec. This avoids the program falling over should a bad byte appear that the utf-8 codec can't handle. But might be better to do some error handling here - maybe some basic flow control to request resending of message ''' msgList = [] while self.serPort.inWaiting() > 0: # using readline could create a problem where data has been sent # but isn't terminated by a newline. In this case, the while above # would cause this program to wait forever. For time being that's tolerable # because we'll be strict about always using a newline msgList.append(self.serPort.readline().decode(encoding, 'replace').strip()) return msgList def newMsg(self): ''' DEPRECATED: Reads one newline-terminated message from buffer. This might cause incoming messages to stack up, so using newMsgs() method above is preferable and this method might be removed. ''' if self.serPort.inWaiting() > 0: self.message = self.serPort.readline().decode('utf-8', 'replace').strip() result = True else: result = False return result def __str__(self): ''' Print information about this port ''' print('COMM PORT', self.uart, '-', self.name,'on', self.dev,'-', str(self.baudRate) + ' baud', str(self.byteSize) + '-' + self.parity + '-' + str(self.stopBits)) if self.uart > 0: print('port:', self.port, '| tx pin:', self.txPin, '| rx pin:', self.rxPin, '| mode:', self.mode) print('--') print('TX:', self.tx) print('RX:', self.rx) return ' '