def coms_test(): crc_valid = None blue_wire_oe_n = Pin('P11', mode=Pin.OUT, pull=Pin.PULL_UP) blue_wire_oe_n.value(1) uart1 = UART(1, 25000) uart1.init(25000, bits=8, parity=None, stop=1) tx_buffer_flushed = None (data,crc_valid) = ctrl.data_frame(run_crc=True) print("Sending: {}\r".format(ubinascii.hexlify(data)),end='\n') start_time = time.ticks_us() blue_wire_oe_n.value(0) t_2_heater = time.ticks_diff(time.ticks_us(), start_time) print("t_2_heater {}us OE low".format(t_2_heater)) start_time = time.ticks_us() uart1.write(data) tx_buffer_flushed = uart1.wait_tx_done(25) t_2_heater = time.ticks_diff(time.ticks_us(), start_time) print("t_2_heater {}us Tx".format(t_2_heater)) start_time = time.ticks_us() blue_wire_oe_n.value(1) t_2_heater = time.ticks_diff(time.ticks_us(), start_time) print("t_2_heater {}us OE high buf flushed{}".format(t_2_heater,tx_buffer_flushed)) start_time = time.ticks_us() num_bytes = uart1.any() while (num_bytes < 24) : num_bytes = uart1.any() t_2_heater = time.ticks_diff(time.ticks_us(), start_time) print("t_2_heater {}us to get heater data".format(t_2_heater)) start_time = time.ticks_us() data = util.extractValidFrameFromUART(uart1) t_2_heater = time.ticks_diff(time.ticks_us(), start_time) print("t_2_heater {}us to extract and load".format(t_2_heater)) print("Halting") machine.idle() while True: pass
class SEN0219_SERIAL: # byte mhzCmdReadPPM[9] = {0xFF,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79}; # byte mhzResp[9]; // 9 bytes bytes response # byte mhzCmdCalibrateZero[9] = {0xFF,0x01,0x87,0x00,0x00,0x00,0x00,0x00,0x78}; # byte mhzCmdABCEnable[9] = {0xFF,0x01,0x79,0xA0,0x00,0x00,0x00,0x00,0xE6}; # byte mhzCmdABCDisable[9] = {0xFF,0x01,0x79,0x00,0x00,0x00,0x00,0x00,0x86}; # byte mhzCmdReset[9] = {0xFF,0x01,0x8d,0x00,0x00,0x00,0x00,0x00,0x72}; def __init__(self, TX, RX): self.uart = UART(1, 9600, bits=8, parity=None, stop=1, pins=(TX,RX)) #self.uart.write(b'\xFF\x01\x8D\x00\x00\x00\x00\x00\x72') #Reset def deinit(self): self.uart.deinit() def SEN_Serial_ABCOn(self): self.uart.write(b'\xFF\x01\x79\xA0\x00\x00\x00\x00\xE6') #ABC On self.uart.wait_tx_done(1000) def SEN_Serial_ABCOff(self): self.uart.write(b'\xFF\x01\x79\x00\x00\x00\x00\x00\x86') #ABC Off self.uart.wait_tx_done(1000) def SEN_Serial_read(self): self.uart.write(b'\xFF\x01\x86\x00\x00\x00\x00\x00\x79') #get gas command self.uart.wait_tx_done(1000) Attempts=5 while(Attempts>0): data=self._SerialRead() if(data!=False): return data Attempts-=1 utime.sleep(1) return False def _SerialRead(self): print(str(self.uart.any())) if(self.uart.any()>=9): data=self.uart.read(9) return data else: return False
class Serial: def __init__(self, uart_id, baudrate=9600, data_bits=8, stop_bits=1, parity=None, pins=None, ctrl_pin=None): self._uart = UART(uart_id, baudrate=baudrate, bits=data_bits, parity=parity, \ stop=stop_bits, timeout_chars=2, pins=pins) if ctrl_pin is not None: self._ctrlPin = Pin(ctrl_pin, mode=Pin.OUT) else: self._ctrlPin = None if baudrate <= 19200: self._t35chars = (3500000 * (data_bits + stop_bits + 2)) // baudrate else: self._t35chars = 1750 def _calculate_crc16(self, data): crc = 0xFFFF for char in data: crc = (crc >> 8) ^ Const.CRC16_TABLE[((crc) ^ char) & 0xFF] return struct.pack('<H', crc) def _bytes_to_bool(self, byte_list): bool_list = [] for index, byte in enumerate(byte_list): bool_list.extend([bool(byte & (1 << n)) for n in range(8)]) return bool_list def _to_short(self, byte_array, signed=True): response_quantity = int(len(byte_array) / 2) fmt = '>' + (('h' if signed else 'H') * response_quantity) return struct.unpack(fmt, byte_array) def _exit_read(self, response): if response[1] >= Const.ERROR_BIAS: if len(response) < Const.ERROR_RESP_LEN: return False elif (Const.READ_COILS <= response[1] <= Const.READ_INPUT_REGISTER): expected_len = Const.RESPONSE_HDR_LENGTH + 1 + response[ 2] + Const.CRC_LENGTH if len(response) < expected_len: return False elif len(response) < Const.FIXED_RESP_LEN: return False return True def _uart_read(self): response = bytearray() for x in range(1, 40): if self._uart.any(): response.extend(self._uart.readall()) # variable length function codes may require multiple reads if self._exit_read(response): break time.sleep(0.05) return response def _uart_read_frame(self, timeout=None): bytes = bytearray() start_ms = time.ticks_ms() while timeout == None or time.ticks_diff(start_ms, time.ticks_ms()) <= timeout: last_byte_ts = time.ticks_us() while time.ticks_diff(last_byte_ts, time.ticks_us()) <= self._t35chars: r = self._uart.readall() if r != None: bytes.extend(r) last_byte_ts = time.ticks_us() if len(bytes) > 0: return bytes return bytes def _send(self, modbus_pdu, slave_addr): serial_pdu = bytearray() serial_pdu.append(slave_addr) serial_pdu.extend(modbus_pdu) crc = self._calculate_crc16(serial_pdu) serial_pdu.extend(crc) if self._ctrlPin: self._ctrlPin(1) self._uart.write(serial_pdu) if self._ctrlPin: while not self._uart.wait_tx_done(2): machine.idle() time.sleep_us(self._t35chars) self._ctrlPin(0) def _send_receive(self, modbus_pdu, slave_addr, count): # flush the Rx FIFO self._uart.read() self._send(modbus_pdu, slave_addr) return self._validate_resp_hdr(self._uart_read(), slave_addr, modbus_pdu[0], count) def _validate_resp_hdr(self, response, slave_addr, function_code, count): if len(response) == 0: raise OSError('no data received from slave') resp_crc = response[-Const.CRC_LENGTH:] expected_crc = self._calculate_crc16(response[0:len(response) - Const.CRC_LENGTH]) if (resp_crc[0] != expected_crc[0]) or (resp_crc[1] != expected_crc[1]): raise OSError('invalid response CRC') if (response[0] != slave_addr): raise ValueError('wrong slave address') if (response[1] == (function_code + Const.ERROR_BIAS)): raise ValueError('slave returned exception code: {:d}'.format( response[2])) hdr_length = (Const.RESPONSE_HDR_LENGTH + 1) if count else Const.RESPONSE_HDR_LENGTH return response[hdr_length:len(response) - Const.CRC_LENGTH] def read_coils(self, slave_addr, starting_addr, coil_qty): modbus_pdu = functions.read_coils(starting_addr, coil_qty) resp_data = self._send_receive(modbus_pdu, slave_addr, True) status_pdu = self._bytes_to_bool(resp_data) return status_pdu def read_discrete_inputs(self, slave_addr, starting_addr, input_qty): modbus_pdu = functions.read_discrete_inputs(starting_addr, input_qty) resp_data = self._send_receive(modbus_pdu, slave_addr, True) status_pdu = self._bytes_to_bool(resp_data) return status_pdu def read_holding_registers(self, slave_addr, starting_addr, register_qty, signed=True): modbus_pdu = functions.read_holding_registers(starting_addr, register_qty) resp_data = self._send_receive(modbus_pdu, slave_addr, True) register_value = self._to_short(resp_data, signed) return register_value def read_input_registers(self, slave_addr, starting_address, register_quantity, signed=True): modbus_pdu = functions.read_input_registers(starting_address, register_quantity) resp_data = self._send_receive(modbus_pdu, slave_addr, True) register_value = self._to_short(resp_data, signed) return register_value def write_single_coil(self, slave_addr, output_address, output_value): modbus_pdu = functions.write_single_coil(output_address, output_value) resp_data = self._send_receive(modbus_pdu, slave_addr, False) operation_status = functions.validate_resp_data( resp_data, Const.WRITE_SINGLE_COIL, output_address, value=output_value, signed=False) return operation_status def write_single_register(self, slave_addr, register_address, register_value, signed=True): modbus_pdu = functions.write_single_register(register_address, register_value, signed) resp_data = self._send_receive(modbus_pdu, slave_addr, False) operation_status = functions.validate_resp_data( resp_data, Const.WRITE_SINGLE_REGISTER, register_address, value=register_value, signed=signed) return operation_status def write_multiple_coils(self, slave_addr, starting_address, output_values): modbus_pdu = functions.write_multiple_coils(starting_address, output_values) resp_data = self._send_receive(modbus_pdu, slave_addr, False) operation_status = functions.validate_resp_data( resp_data, Const.WRITE_MULTIPLE_COILS, starting_address, quantity=len(output_values)) return operation_status def write_multiple_registers(self, slave_addr, starting_address, register_values, signed=True): modbus_pdu = functions.write_multiple_registers( starting_address, register_values, signed) resp_data = self._send_receive(modbus_pdu, slave_addr, False) operation_status = functions.validate_resp_data( resp_data, Const.WRITE_MULTIPLE_REGISTERS, starting_address, quantity=len(register_values)) return operation_status def send_response(self, slave_addr, function_code, request_register_addr, request_register_qty, request_data, values=None, signed=True): modbus_pdu = functions.response(function_code, request_register_addr, request_register_qty, request_data, values, signed) self._send(modbus_pdu, slave_addr) def send_exception_response(self, slave_addr, function_code, exception_code): modbus_pdu = functions.exception_response(function_code, exception_code) self._send(modbus_pdu, slave_addr) def get_request(self, unit_addr_list, timeout=None): req = self._uart_read_frame(timeout) if len(req) < 8: return None if req[0] not in unit_addr_list: return None req_crc = req[-Const.CRC_LENGTH:] req_no_crc = req[:-Const.CRC_LENGTH] expected_crc = self._calculate_crc16(req_no_crc) if (req_crc[0] != expected_crc[0]) or (req_crc[1] != expected_crc[1]): return None try: request = Request(self, req_no_crc) except ModbusException as e: self.send_exception_response(req[0], e.function_code, e.exception_code) return None return request
class uModBusSerial: def __init__(self, uart_id, baudrate=9600, data_bits=8, stop_bits=1, parity=None, pins=None, ctrl_pin=None): pinsLen = len(pins) if pins == None or pinsLen < 2 or pinsLen > 4 or pinsLen == 3: raise ValueError( 'pins should contain pin names/numbers for: tx, rx, [rts, cts]' ) tx = pins[0] rx = pins[1] if pinsLen == 4: rts = pins[2] cts = pins[3] self._uart = UART(uart_id, baudrate=baudrate, bits=data_bits, parity=parity, \ stop=stop_bits, timeout_char=10, tx=tx, rx=rx, rts=rts, cts=cts) else: self._uart = UART(uart_id, baudrate=baudrate, bits=data_bits, parity=parity, \ stop=stop_bits, timeout_char=10, tx=tx, rx=rx) #self._uart = UART(uart_id, baudrate=baudrate, bits=data_bits, parity=parity, \ # stop=stop_bits, timeout_chars=10, pins=pins) if ctrl_pin is not None: self._ctrlPin = Pin(ctrl_pin, mode=Pin.OUT) else: self._ctrlPin = None self.char_time_ms = (1000 * (data_bits + stop_bits + 2)) // baudrate def _calculate_crc16(self, data): crc = 0xFFFF for char in data: crc = (crc >> 8) ^ Const.CRC16_TABLE[((crc) ^ char) & 0xFF] return struct.pack('<H', crc) def _bytes_to_bool(self, byte_list): bool_list = [] for index, byte in enumerate(byte_list): bool_list.extend([bool(byte & (1 << n)) for n in range(8)]) return bool_list def _to_short(self, byte_array, signed=True): response_quantity = int(len(byte_array) / 2) fmt = '>' + (('h' if signed else 'H') * response_quantity) return struct.unpack(fmt, byte_array) def _exit_read(self, response): if response[1] >= Const.ERROR_BIAS: if len(response) < Const.ERROR_RESP_LEN: return False elif (Const.READ_COILS <= response[1] <= Const.READ_INPUT_REGISTER): expected_len = Const.RESPONSE_HDR_LENGTH + 1 + response[ 2] + Const.CRC_LENGTH if len(response) < expected_len: return False elif len(response) < Const.FIXED_RESP_LEN: return False return True def _uart_read(self): response = bytearray() for x in range(1, 40): if self._uart.any(): response.extend(self._uart.read()) #response.extend(self._uart.readall()) # variable length function codes may require multiple reads if self._exit_read(response): break time.sleep(0.05) return response def _send_receive(self, modbus_pdu, slave_addr, count): serial_pdu = bytearray() serial_pdu.append(slave_addr) serial_pdu.extend(modbus_pdu) crc = self._calculate_crc16(serial_pdu) serial_pdu.extend(crc) # flush the Rx FIFO self._uart.read() if self._ctrlPin: self._ctrlPin(1) self._uart.write(serial_pdu) if self._ctrlPin: while not self._uart.wait_tx_done(2): machine.idle() time.sleep_ms(1 + self.char_time_ms) self._ctrlPin(0) return self._validate_resp_hdr(self._uart_read(), slave_addr, modbus_pdu[0], count) def _validate_resp_hdr(self, response, slave_addr, function_code, count): if len(response) == 0: raise OSError('no data received from slave') resp_crc = response[-Const.CRC_LENGTH:] expected_crc = self._calculate_crc16(response[0:len(response) - Const.CRC_LENGTH]) if (resp_crc[0] != expected_crc[0]) or (resp_crc[1] != expected_crc[1]): raise OSError('invalid response CRC') if (response[0] != slave_addr): raise ValueError('wrong slave address') if (response[1] == (function_code + Const.ERROR_BIAS)): raise ValueError('slave returned exception code: {:d}'.format( response[2])) hdr_length = (Const.RESPONSE_HDR_LENGTH + 1) if count else Const.RESPONSE_HDR_LENGTH return response[hdr_length:len(response) - Const.CRC_LENGTH] def read_coils(self, slave_addr, starting_addr, coil_qty): modbus_pdu = functions.read_coils(starting_addr, coil_qty) resp_data = self._send_receive(modbus_pdu, slave_addr, True) status_pdu = self._bytes_to_bool(resp_data) return status_pdu def read_discrete_inputs(self, slave_addr, starting_addr, input_qty): modbus_pdu = functions.read_discrete_inputs(starting_addr, input_qty) resp_data = self._send_receive(modbus_pdu, slave_addr, True) status_pdu = self._bytes_to_bool(resp_data) return status_pdu def read_holding_registers(self, slave_addr, starting_addr, register_qty, signed=True): modbus_pdu = functions.read_holding_registers(starting_addr, register_qty) resp_data = self._send_receive(modbus_pdu, slave_addr, True) register_value = self._to_short(resp_data, signed) return register_value def read_input_registers(self, slave_addr, starting_address, register_quantity, signed=True): modbus_pdu = functions.read_input_registers(starting_address, register_quantity) resp_data = self._send_receive(modbus_pdu, slave_addr, True) register_value = self._to_short(resp_data, signed) return register_value def write_single_coil(self, slave_addr, output_address, output_value): modbus_pdu = functions.write_single_coil(output_address, output_value) resp_data = self._send_receive(modbus_pdu, slave_addr, False) operation_status = functions.validate_resp_data( resp_data, Const.WRITE_SINGLE_COIL, output_address, value=output_value, signed=False) return operation_status def write_single_register(self, slave_addr, register_address, register_value, signed=True): modbus_pdu = functions.write_single_register(register_address, register_value, signed) resp_data = self._send_receive(modbus_pdu, slave_addr, False) operation_status = functions.validate_resp_data( resp_data, Const.WRITE_SINGLE_REGISTER, register_address, value=register_value, signed=signed) return operation_status def write_multiple_coils(self, slave_addr, starting_address, output_values): modbus_pdu = functions.write_multiple_coils(starting_address, output_values) resp_data = self._send_receive(modbus_pdu, slave_addr, False) operation_status = functions.validate_resp_data( resp_data, Const.WRITE_MULTIPLE_COILS, starting_address, quantity=len(output_values)) return operation_status def write_multiple_registers(self, slave_addr, starting_address, register_values, signed=True): modbus_pdu = functions.write_multiple_registers( starting_address, register_values, signed) resp_data = self._send_receive(modbus_pdu, slave_addr, False) operation_status = functions.validate_resp_data( resp_data, Const.WRITE_MULTIPLE_REGISTERS, starting_address, quantity=len(register_values)) return operation_status def close(self): if self._uart == None: return try: self._uart.deinit() except Exception: pass
class Serial: def __init__(self, uart_id, baudrate=9600, data_bits=8, stop_bits=1, parity=None, pins=None, ctrl_pin=None): self._uart = UART(uart_id, baudrate=baudrate, bits=data_bits, parity=parity, stop=stop_bits, timeout_chars=7, pins=pins) if ctrl_pin is not None: self._ctrlPin = Pin(ctrl_pin, mode=Pin.OUT) else: self._ctrlPin = None self.char_time_ms = (1000 * (data_bits + stop_bits + 2)) // baudrate self.reply_timeout_ms = 1000 def _calculate_crc16(self, data): crc = 0xFFFF for char in data: crc = (crc >> 8) ^ Const.CRC16_TABLE[((crc) ^ char) & 0xFF] return struct.pack('<H', crc) def _bytes_to_bool(self, byte_list): bool_list = [] for index, byte in enumerate(byte_list): bool_list.extend([bool(byte & (1 << n)) for n in range(8)]) return bool_list def _to_short(self, byte_array, signed=True): response_quantity = int(len(byte_array) / 2) fmt = '>' + (('h' if signed else 'H') * response_quantity) return struct.unpack(fmt, byte_array) def _exit_read(self, response): if response[1] >= Const.ERROR_BIAS: if len(response) < Const.ERROR_RESP_LEN: return False elif (Const.READ_COILS <= response[1] <= Const.READ_INPUT_REGISTER): expected_len = Const.RESPONSE_HDR_LENGTH + 1 + response[ 2] + Const.CRC_LENGTH if len(response) < expected_len: return False elif len(response) < Const.FIXED_RESP_LEN: return False return True def _uart_read(self): response = bytearray() tickRead = time.ticks_ms() machine.idle() inBuffer = self._uart.any() while not inBuffer: if abs(time.ticks_diff(tickRead, time.ticks_ms())) > self.reply_timeout_ms: print('nothing') return response machine.idle() inBuffer = self._uart.any() tickRead = time.ticks_ms() while True: if inBuffer: chunk = self._uart.read(inBuffer) if len(response) + len(chunk) > 240: raise OSError('RX Buffer Overflow') response.extend(chunk) tickRead = time.ticks_ms() elif abs(time.ticks_diff( tickRead, time.ticks_ms())) >= self.char_time_ms * 4: break machine.idle() inBuffer = self._uart.any() return response def _send_receive(self, modbus_pdu, slave_addr, count): serial_pdu = bytearray() serial_pdu.append(slave_addr) serial_pdu.extend(modbus_pdu) crc = self._calculate_crc16(serial_pdu) serial_pdu.extend(crc) # flush the Rx FIFO self._uart.read() if self._ctrlPin: self._ctrlPin(1) self._uart.write(serial_pdu) if self._ctrlPin: while not self._uart.wait_tx_done(2): machine.idle() time.sleep_ms(1 + self.char_time_ms) self._ctrlPin(0) time.sleep_ms(1 + self.char_time_ms) self._uart.read() return self._validate_resp_hdr(self._uart_read(), slave_addr, modbus_pdu[0], count) def _validate_resp_hdr(self, response, slave_addr, function_code, count): if len(response) == 0: raise OSError('no data received from slave') resp_crc = response[-Const.CRC_LENGTH:] expected_crc = self._calculate_crc16(response[0:len(response) - Const.CRC_LENGTH]) if (resp_crc[0] != expected_crc[0]) or (resp_crc[1] != expected_crc[1]): raise OSError('invalid response CRC') if (response[0] != slave_addr): raise ValueError('wrong slave address') if (response[1] == (function_code + Const.ERROR_BIAS)): raise ValueError('slave returned exception code: {:d}'.format( response[2])) hdr_length = (Const.RESPONSE_HDR_LENGTH + 1) if count else Const.RESPONSE_HDR_LENGTH return response[hdr_length:len(response) - Const.CRC_LENGTH] def read_coils(self, slave_addr, starting_addr, coil_qty): modbus_pdu = functions.read_coils(starting_addr, coil_qty) resp_data = self._send_receive(modbus_pdu, slave_addr, True) status_pdu = self._bytes_to_bool(resp_data) return status_pdu def read_discrete_inputs(self, slave_addr, starting_addr, input_qty): modbus_pdu = functions.read_discrete_inputs(starting_addr, input_qty) resp_data = self._send_receive(modbus_pdu, slave_addr, True) status_pdu = self._bytes_to_bool(resp_data) return status_pdu def read_holding_registers(self, slave_addr, starting_addr, register_qty, signed=True): modbus_pdu = functions.read_holding_registers(starting_addr, register_qty) resp_data = self._send_receive(modbus_pdu, slave_addr, True) register_value = self._to_short(resp_data, signed) return register_value def read_input_registers(self, slave_addr, starting_address, register_quantity, signed=True): modbus_pdu = functions.read_input_registers(starting_address, register_quantity) resp_data = self._send_receive(modbus_pdu, slave_addr, True) register_value = self._to_short(resp_data, signed) return register_value def write_single_coil(self, slave_addr, output_address, output_value): modbus_pdu = functions.write_single_coil(output_address, output_value) resp_data = self._send_receive(modbus_pdu, slave_addr, False) operation_status = functions.validate_resp_data( resp_data, Const.WRITE_SINGLE_COIL, output_address, value=output_value, signed=False) return operation_status def write_single_register(self, slave_addr, register_address, register_value, signed=True): modbus_pdu = functions.write_single_register(register_address, register_value, signed) resp_data = self._send_receive(modbus_pdu, slave_addr, False) operation_status = functions.validate_resp_data( resp_data, Const.WRITE_SINGLE_REGISTER, register_address, value=register_value, signed=signed) return operation_status def write_multiple_coils(self, slave_addr, starting_address, output_values): modbus_pdu = functions.write_multiple_coils(starting_address, output_values) resp_data = self._send_receive(modbus_pdu, slave_addr, False) operation_status = functions.validate_resp_data( resp_data, Const.WRITE_MULTIPLE_COILS, starting_address, quantity=len(output_values)) return operation_status def write_multiple_registers(self, slave_addr, starting_address, register_values, signed=True): modbus_pdu = functions.write_multiple_registers( starting_address, register_values, signed) resp_data = self._send_receive(modbus_pdu, slave_addr, False) operation_status = functions.validate_resp_data( resp_data, Const.WRITE_MULTIPLE_REGISTERS, starting_address, quantity=len(register_values)) return operation_status