class SpikePrimeDevice(object): def __init__(self, tx_pin, rx_pin, timer=Timer.TIMER0, timer_channel=Timer.CHANNEL0, tx_gpio=GPIO.GPIO1, tx_fpioa_gpio=fm.fpioa.GPIO1, uart_num=UART.UART2): self.connected = False self.uart = None self.tx_pin_num = tx_pin self.rx_pin_num = rx_pin self.data = 0 self.current_mode = 0 self.textBuffer = bytearray(b' ') self.timer_num = timer self.timer_channel_num = timer_channel self.timer = None self.tx_gpio = tx_gpio self.tx_fpioa_gpio = tx_fpioa_gpio self.uart_num = uart_num if uart_num == UART.UART2: self.uart_tx_fpioa_num = fm.fpioa.UART2_TX self.uart_rx_fpioa_num = fm.fpioa.UART2_RX elif uart_num == UART.UART1: self.uart_tx_fpioa_num = fm.fpioa.UART1_TX self.uart_rx_fpioa_num = fm.fpioa.UART1_RX def initialize(self): assert not self.connected print("connecting...") fm.register(self.tx_pin_num, self.tx_fpioa_gpio, force=True) uart_tx = GPIO(self.tx_gpio, GPIO.OUT) uart_tx.value(0) time.sleep_ms(500) uart_tx.value(1) fm.register(self.tx_pin_num, self.uart_tx_fpioa_num, force=True) fm.register(self.rx_pin_num, self.uart_rx_fpioa_num, force=True) self.uart = UART(self.uart_num, 2400, bits=8, parity=None, stop=1, timeout=10000, read_buf_len=4096) self.uart.write(b'\x00') self.uart.write(b'\x40\x3e\x81') self.uart.write(b'\x49\x07\x07\xb6') self.uart.write(b'\x52\x00\xc2\x01\x00\x6e') self.uart.write(b'\x5f\x00\x00\x00\x02\x00\x00\x00\x02\xa0') self.uart.write(b'\xa7\x00\x66\x6c\x6f\x61\x74\x5f\x61\x72\x72\x61\x79\x00\x00\x00\x00\x00\x0e') self.uart.write(b'\x9f\x01\x00\x00\x00\x00\x00\x00\xc8\x42\xeb') self.uart.write(b'\x9f\x02\x00\x00\x00\x00\x00\x00\xc8\x42\xe8') self.uart.write(b'\x9f\x03\x00\x00\x00\x00\x00\x00\xc8\x42\xe9') self.uart.write(b'\x87\x04\x00\x7c') self.uart.write(b'\x8f\x05\x10\x00\x65') self.uart.write(b'\x97\x80\x04\x03\x02\x01\xec') time.sleep_ms(5) self.uart.write(b'\xa6\x00\x69\x6e\x74\x33\x32\x5f\x61\x72\x72\x61\x79\x00\x00\x00\x00\x00\x0d') self.uart.write(b'\x9e\x01\x00\x00\x00\x00\x00\x00\xc8\x42\xea') self.uart.write(b'\x9e\x02\x00\x00\x00\x00\x00\x00\xc8\x42\xe9') self.uart.write(b'\x9e\x03\x00\x00\x00\x00\x00\x00\xc8\x42\xe8') self.uart.write(b'\x86\x04\x00\x7d') self.uart.write(b'\x8e\x05\x10\x00\x64') self.uart.write(b'\x96\x80\x04\x02\x03\x00\xec') time.sleep_ms(5) self.uart.write(b'\xa5\x00\x69\x6e\x74\x31\x36\x5f\x61\x72\x72\x61\x79\x00\x00\x00\x00\x00\x08') self.uart.write(b'\x9d\x01\x00\x00\x00\x00\x00\x00\xc8\x42\xe9') self.uart.write(b'\x9d\x02\x00\x00\x00\x00\x00\x00\xc8\x42\xea') self.uart.write(b'\x9d\x03\x00\x00\x00\x00\x00\x00\xc8\x42\xeb') self.uart.write(b'\x85\x04\x00\x7e') self.uart.write(b'\x8d\x05\x10\x00\x67') self.uart.write(b'\x95\x80\x04\x01\x03\x00\xec') time.sleep_ms(5) self.uart.write(b'\xa4\x00\x69\x6e\x74\x38\x5f\x61\x72\x72\x61\x79\x00\x00\x00\x00\x00\x00\x36') self.uart.write(b'\x9c\x01\x00\x00\x00\x00\x00\x00\xc8\x42\xe8') self.uart.write(b'\x9c\x02\x00\x00\x00\x00\x00\x00\xc8\x42\xeb') self.uart.write(b'\x9c\x03\x00\x00\x00\x00\x00\x00\xc8\x42\xea') self.uart.write(b'\x84\x04\x00\x7f') self.uart.write(b'\x8c\x05\x10\x00\x66') self.uart.write(b'\x94\x80\x04\x00\x03\x00\xec') time.sleep_ms(5) self.uart.write(b'\x9b\x00\x66\x6c\x6f\x61\x74\x00\x00\x00\x14') self.uart.write(b'\x9b\x01\x00\x00\x00\x00\x00\x00\xc8\x42\xef') self.uart.write(b'\x9b\x02\x00\x00\x00\x00\x00\x00\xc8\x42\xec') self.uart.write(b'\x9b\x03\x00\x00\x00\x00\x00\x00\xc8\x42\xed') self.uart.write(b'\x83\x04\x00\x78') self.uart.write(b'\x8b\x05\x10\x00\x61') self.uart.write(b'\x93\x80\x01\x03\x02\x01\xed') time.sleep_ms(5) self.uart.write(b'\x9a\x00\x69\x6e\x74\x33\x32\x00\x00\x00\x17') self.uart.write(b'\x9a\x01\x00\x00\x00\x00\x00\x00\xc8\x42\xee') self.uart.write(b'\x9a\x02\x00\x00\x00\x00\x00\x00\xc8\x42\xed') self.uart.write(b'\x9a\x03\x00\x00\x00\x00\x00\x00\xc8\x42\xec') self.uart.write(b'\x82\x04\x00\x79') self.uart.write(b'\x8a\x05\x10\x00\x60') self.uart.write(b'\x92\x80\x01\x02\x03\x00\xed') time.sleep_ms(5) self.uart.write(b'\x99\x00\x69\x6e\x74\x31\x36\x00\x00\x00\x12') self.uart.write(b'\x99\x01\x00\x00\x00\x00\x00\x00\xc8\x42\xed') self.uart.write(b'\x99\x02\x00\x00\x00\x00\x00\x00\xc8\x42\xee') self.uart.write(b'\x99\x03\x00\x00\x00\x00\x00\x00\xc8\x42\xef') self.uart.write(b'\x81\x04\x00\x7a') self.uart.write(b'\x89\x05\x10\x00\x63') self.uart.write(b'\x91\x80\x01\x01\x03\x00\xed') time.sleep_ms(5) self.uart.write(b'\x90\x00\x69\x6e\x74\x38\x24') self.uart.write(b'\x98\x01\x00\x00\x00\x00\x00\x00\xc8\x42\xec') self.uart.write(b'\x98\x02\x00\x00\x00\x00\x00\x00\xc8\x42\xef') self.uart.write(b'\x98\x03\x00\x00\x00\x00\x00\x00\xc8\x42\xee') self.uart.write(b'\x80\x04\x00\x7b') self.uart.write(b'\x88\x05\x10\x00\x62') self.uart.write(b'\x90\x80\x01\x00\x03\x00\xed') time.sleep_ms(5) self.uart.write(b'\x04') time.sleep_ms(5) print("waiting for ACK...") self.connected = self._wait_for_value(b'\x04') if self.connected: print("connected") self.uart.deinit() fm.register(self.tx_pin_num, self.tx_fpioa_gpio, force=True) uart_tx = GPIO(self.tx_gpio, GPIO.OUT) uart_tx.value(0) time.sleep_ms(10) fm.register(self.tx_pin_num, self.uart_tx_fpioa_num, force=True) fm.register(self.rx_pin_num, self.uart_rx_fpioa_num, force=True) self.uart = UART(self.uart_num, 115200, bits=8, parity=None, stop=1, timeout=10000, read_buf_len=4096) self.set_data(0) self.timer = Timer(self.timer_num, self.timer_channel_num, mode=Timer.MODE_PERIODIC, period=200, callback=self._handle_message_callback) self.timer.start() else: print("not connected") return self.connected def _wait_for_value(self, expected_value, timeout=2): starttime = time.time() currenttime = starttime status = False #count = 0 while (currenttime - starttime) < timeout: time.sleep_ms(5) #print(count) #count += 1 currenttime = time.time() if self.uart.any() > 0: data = self.uart.readchar() #print(data) if data == ord(expected_value): status = True break return status def set_data(self, data): self.data = data def _get_checksum(self, values): checksum = 0xFF for x in values: checksum ^= x return checksum def _send_value(self, data): value = data & 0xFF payload = bytes([0xC0, value, self._get_checksum([0xC0, value])]) size = self.uart.write(payload) return size def _handle_message_callback(self, timer): if not self.connected: return while self.uart.any() > 0: x = self.uart.readchar() if x == 0: pass elif x == 0x02: pass elif x == 0x43: mode = self.uart.readchar() checksum = self.uart.readchar() if checksum == self._get_checksum([x, mode]): self.current_mode = mode elif x == 0x46: zero = self.uart.readchar() b9 = self.uart.readchar() if zero == 0 and b9 == 0xb9: size_mode = self.uart.readchar() size = 2 ** ((size_mode & 0b111000) >> 3) mode = size_mode & 0b111 checksum = self._get_checksum([x, zero, b9, size_mode]) for i in range(len(self.textBuffer)): self.textBuffer[i] = ord(b' ') for i in range(size): self.textBuffer[i] = self.uart.readchar() checksum ^= self.textBuffer[i] expected_checksum = self.uart.readchar() if expected_checksum == checksum: print(self.textBuffer) elif x == 0x4C: thing = self.uart.readchar() checksum = self.uart.readchar() if checksum == self._get_checksum([x, thing]): pass else: print(x) size = self._send_value(self.data) if not size: self.connected = False
class MindstromsDevice(object): def __init__(self, tx_pin, rx_pin, timer=Timer.TIMER0, timer_channel=Timer.CHANNEL0, tx_gpio=GPIO.GPIO1, tx_fpioa_gpio=fm.fpioa.GPIO1, uart_num=UART.UART2): self.connected = False self.uart = None self.tx_pin_num = tx_pin self.rx_pin_num = rx_pin self.data = 0 self.current_mode = 0 self.textBuffer = bytearray(b' ') self.timer_num = timer self.timer_channel_num = timer_channel self.timer = None self.tx_gpio = tx_gpio self.tx_fpioa_gpio = tx_fpioa_gpio self.uart_num = uart_num if uart_num == UART.UART2: self.uart_tx_fpioa_num = fm.fpioa.UART2_TX self.uart_rx_fpioa_num = fm.fpioa.UART2_RX elif uart_num == UART.UART1: self.uart_tx_fpioa_num = fm.fpioa.UART1_TX self.uart_rx_fpioa_num = fm.fpioa.UART1_RX def initialize(self): assert not self.connected print("connecting...") fm.register(self.tx_pin_num, self.tx_fpioa_gpio, force=True) uart_tx = GPIO(self.tx_gpio, GPIO.OUT) uart_tx.value(0) time.sleep_ms(410) uart_tx.value(1) fm.register(self.tx_pin_num, self.uart_tx_fpioa_num, force=True) fm.register(self.rx_pin_num, self.uart_rx_fpioa_num, force=True) self.uart = UART(self.uart_num, 115200, bits=8, parity=None, stop=1, timeout=10000, read_buf_len=4096) # wait for \x52\x00\xc2\x01\x00\x6e self.uart.write(b'\x04') # ACK? time.sleep_ms(10) self.uart.write(b'\x40\x3e\x81') # CMD_TYPE(1), TypeID:0x3e, checksum time.sleep_ms(1) self.uart.write( b'\x51\x07\x06\x08\x00\xa7' ) # CMD_MODES(4), 8 modes for EV3, 7 views for EV3, 9 modes, 0 views, checksum time.sleep_ms(1) self.uart.write(b'\x52\x00\xc2\x01\x00\x6e' ) # CMD_SPEED(4), speed:115200, checksum time.sleep_ms(1) self.uart.write( b'\x5f\x00\x00\x00\x10\x00\x00\x00\x10\xa0' ) # CMD_VERSION(8), fw-version:1.0.00.0000, hw-version:1.0.00.0000, checksum time.sleep_ms(18) self.uart.write( b'\xa0\x20\x43\x41\x4c\x49\x42\x00\x40\x40\x00\x00\x04\x84\x00\x00\x00\x00\xba' ) # INFO_NAME(16) | mode:0+8, "CALIB\0" + flags(0x40, 0x40, 0x00, 0x00, 0x04, 0x84), checksum self.uart.write( b'\x98\x21\x00\x00\x00\x00\x00\x00\x7f\x43\x7a' ) # INFO_RAW(8) | mode:0+8, min:0.0, max:255.0, checksum time.sleep_ms(1) self.uart.write( b'\x98\x22\x00\x00\x00\x00\x00\x00\xc8\x42\xcf' ) # INFO_PCT(8) | mode:0+8, min:0.0, max:100.0, checksum time.sleep_ms(1) self.uart.write( b'\x98\x23\x00\x00\x00\x00\x00\x00\x7f\x43\x78' ) # INFO_SI(8) | mode:0+8, min:0.0, max:255.0, checksum time.sleep_ms(1) self.uart.write(b'\x90\x24\x50\x43\x54\x00\x0c' ) # INFO_SYMBOL(4) | mode:0+8, "PCT\0", checksum time.sleep_ms(1) self.uart.write( b'\x88\x25\x00\x00\x52' ) # INFO_MAPPING(2) | mode:0+8, input:0, output:0, checksum time.sleep_ms(1) self.uart.write( b'\x90\xa0\x07\x00\x03\x00\xcb' ) # INFO_FORMAT(4) | mode:0+8, data-sets:7, format:0, figures:3, decimals:0, checksum time.sleep_ms(18) self.uart.write( b'\xa7\x00\x41\x44\x52\x41\x57\x00\x40\x00\x00\x00\x04\x84\x00\x00\x00\x00\xd9' ) # INFO_NAME(16) | mode:7, "ADRAW\0" + flags(0x40, 0x00, 0x00, 0x00, 0x04, 0x84), checksum self.uart.write( b'\x9f\x01\x00\x00\x00\x00\x00\x00\x80\x44\xa5' ) # INFO_RAW(8) | mode:7, min:0.0, max:1024.0, checksum time.sleep_ms(1) self.uart.write(b'\x9f\x02\x00\x00\x00\x00\x00\x00\xc8\x42\xe8' ) # INFO_PCT(8) | mode:7, min:0.0, max:100.0, checksum time.sleep_ms(1) self.uart.write(b'\x9f\x03\x00\x00\x00\x00\x00\x00\x80\x44\xa7' ) # INFO_SI(8) | mode:7, min:0.0, max:1024.0, checksum time.sleep_ms(1) self.uart.write(b'\x97\x04\x50\x43\x54\x00\x2b' ) # INFO_SYMBOL(4) | mode:7, "PCT\0", checksum time.sleep_ms(1) self.uart.write( b'\x8f\x05\x90\x00\xe5' ) # INFO_MAPPING(2) | mode:7, input:0x90, output:0, checksum time.sleep_ms(1) self.uart.write( b'\x97\x80\x01\x01\x04\x00\xec' ) # INFO_FORMAT(4) | mode:7, data-sets:1, format:1, figures:4, decimals:0, checksum time.sleep_ms(18) self.uart.write( b'\xa6\x00\x50\x49\x4e\x47\x00\x00\x40\x80\x00\x00\x04\x84\x00\x00\x00\x00\x09' ) # INFO_NAME(16) | mode:6, "PING\0\0" + flags(0x40, 0x80, 0x00, 0x00, 0x04, 0x84), checksum self.uart.write(b'\x9e\x01\x00\x00\x00\x00\x00\x00\x80\x3f\xdf' ) # INFO_RAW(8) | mode:6, min:0.0, max:1.0, checksum time.sleep_ms(1) self.uart.write(b'\x9e\x02\x00\x00\x00\x00\x00\x00\xc8\x42\xe9' ) # INFO_PCT(8) | mode:6, min:0.0, max:100.0, checksum time.sleep_ms(1) self.uart.write(b'\x9e\x03\x00\x00\x00\x00\x00\x00\x80\x3f\xdd' ) # INFO_SI(8) | mode:6, min:0.0, max:1.0, checksum time.sleep_ms(1) self.uart.write(b'\x96\x04\x50\x43\x54\x00\x2a' ) # INFO_SYMBOL(4) | mode:6, "PCT\0", checksum time.sleep_ms(1) self.uart.write( b'\x8e\x05\x00\x90\xe4' ) # INFO_MAPPING(2) | mode:6, input:0, output:0x90, checksum time.sleep_ms(1) self.uart.write( b'\x96\x80\x01\x00\x01\x00\xe9' ) # INFO_FORMAT(4) | mode:6, data-sets:1, format:0, figures:1, decimals:0, checksum time.sleep_ms(18) self.uart.write( b'\xa5\x00\x4c\x49\x47\x48\x54\x00\x40\x20\x00\x00\x04\x84\x00\x00\x00\x00\xe4' ) # INFO_NAME(16) | mode:5, "LIGHT\0" + flags(0x40, 0x20, 0x00, 0x00, 0x04, 0x84), checksum self.uart.write(b'\x9d\x01\x00\x00\x00\x00\x00\x00\xc8\x42\xe9' ) # INFO_RAW(8) | mode:5, min:0.0, max:100.0, checksum time.sleep_ms(1) self.uart.write(b'\x9d\x02\x00\x00\x00\x00\x00\x00\xc8\x42\xea' ) # INFO_PCT(8) | mode:5, min:0.0, max:100.0, checksum time.sleep_ms(1) self.uart.write(b'\x9d\x03\x00\x00\x00\x00\x00\x00\xc8\x42\xeb' ) # INFO_SI(8) | mode:5, min:0.0, max:100.0, checksum time.sleep_ms(1) self.uart.write(b'\x95\x04\x50\x43\x54\x00\x29' ) # INFO_SYMBOL(4) | mode:5, "PCT\0", checksum time.sleep_ms(1) self.uart.write( b'\x8d\x05\x00\x10\x67' ) # INFO_MAPPING(2) | mode:5, input:0, output:0x10, checksum time.sleep_ms(1) self.uart.write( b'\x95\x80\x04\x00\x03\x00\xed' ) # INFO_FORMAT(4) | mode:5, data-sets:4, format:0, figures:3, decimals:0, checksum time.sleep_ms(18) self.uart.write( b'\xa4\x00\x54\x52\x41\x57\x00\x00\x40\x00\x00\x00\x04\x84\x00\x00\x00\x00\x8b' ) # INFO_NAME(16) | mode:4, "TRAW\0\0" + flags(0x40, 0x00, 0x00, 0x00, 0x04, 0x84), checksum self.uart.write( b'\x9c\x01\x00\x00\x00\x00\x00\xc4\x63\x46\x83' ) # INFO_RAW(8) | mode:4, min:0.0, max:14577.0, checksum time.sleep_ms(1) self.uart.write(b'\x9c\x02\x00\x00\x00\x00\x00\x00\xc8\x42\xeb' ) # INFO_PCT(8) | mode:4, min:0.0, max:100.0, checksum time.sleep_ms(1) self.uart.write( b'\x9c\x03\x00\x00\x00\x00\x00\xc4\x63\x46\x81' ) # INFO_SI(8) | mode:4, min:0.0, max:14577.0, checksum time.sleep_ms(1) self.uart.write( b'\x8c\x04\x75\x53\x51') # INFO_SYMBOL(2) | mode:4, "uS", checksum time.sleep_ms(1) self.uart.write( b'\x8c\x05\x90\x00\xe6' ) # INFO_MAPPING(2) | mode:4, input:0x90, output:0, checksum time.sleep_ms(1) self.uart.write( b'\x94\x80\x01\x02\x05\x00\xed' ) # INFO_FORMAT(4) | mode:4, data-sets:1, format:2, figures:5, decimals:0, checksum time.sleep_ms(18) self.uart.write( b'\xa3\x00\x4c\x49\x53\x54\x4e\x00\x40\x00\x00\x00\x04\x84\x00\x00\x00\x00\xd0' ) # INFO_NAME(16) | mode:3, "LISTN\0" + flags(0x40, 0x00, 0x00, 0x00, 0x04, 0x84), checksum self.uart.write(b'\x9b\x01\x00\x00\x00\x00\x00\x00\x80\x3f\xda' ) # INFO_RAW(8) | mode:3, min:0.0, max:1.0, checksum time.sleep_ms(1) self.uart.write(b'\x9b\x02\x00\x00\x00\x00\x00\x00\xc8\x42\xec' ) # INFO_PCT(8) | mode:3, min:0.0, max:100.0, checksum time.sleep_ms(1) self.uart.write(b'\x9b\x03\x00\x00\x00\x00\x00\x00\x80\x3f\xd8' ) # INFO_SI(8) | mode:3, min:0.0, max:1.0, checksum time.sleep_ms(1) self.uart.write( b'\x8b\x04\x53\x54\x77') # INFO_SYMBOL(2) | mode:3, "ST", checksum time.sleep_ms(1) self.uart.write( b'\x8b\x05\x10\x00\x61' ) # INFO_MAPPING(2) | mode:3, input:0x10, output:0, checksum time.sleep_ms(1) self.uart.write( b'\x93\x80\x01\x00\x01\x00\xec' ) # INFO_FORMAT(4) | mode:3, data-sets:1, format:0, figures:1, decimals:0, checksum time.sleep_ms(18) self.uart.write( b'\xa2\x00\x53\x49\x4e\x47\x4c\x00\x40\x00\x00\x00\x04\x84\x00\x00\x00\x00\xc2' ) # INFO_NAME(16) | mode:2, "SINGL\0" + flags(0x40, 0x00, 0x00, 0x00, 0x04, 0x84), checksum self.uart.write( b'\x9a\x01\x00\x00\x00\x00\x00\x40\x1c\x45\x7d' ) # INFO_RAW(8) | mode:2, min:0.0, max:2500.0, checksum time.sleep_ms(1) self.uart.write(b'\x9a\x02\x00\x00\x00\x00\x00\x00\xc8\x42\xed' ) # INFO_PCT(8) | mode:2, min:0.0, max:100.0, checksum time.sleep_ms(1) self.uart.write(b'\x9a\x03\x00\x00\x00\x00\x00\x00\x7a\x43\x5f' ) # INFO_SI(8) | mode:2, min:0.0, max:250.0, checksum time.sleep_ms(1) self.uart.write( b'\x8a\x04\x43\x4d\x7f') # INFO_SYMBOL(2) | mode:2, "CM", checksum time.sleep_ms(1) self.uart.write( b'\x8a\x05\x90\x00\xe0' ) # INFO_MAPPING(2) | mode:2, input:0x00, output:0, checksum time.sleep_ms(1) self.uart.write( b'\x92\x80\x01\x01\x05\x01\xe9' ) # INFO_FORMAT(4) | mode:2, data-sets:1, format:1, figures:5, decimals:1, checksum time.sleep_ms(18) self.uart.write( b'\xa1\x00\x44\x49\x53\x54\x53\x00\x40\x00\x00\x00\x04\x84\x00\x00\x00\x00\xc7' ) # INFO_NAME(16) | mode:1, "DISTS\0" + flags(0x40, 0x00, 0x00, 0x00, 0x04, 0x84), checksum self.uart.write(b'\x99\x01\x00\x00\x00\x00\x00\x00\xa0\x43\x84' ) # INFO_RAW(8) | mode:1, min:0.0, max:320.0, checksum time.sleep_ms(1) self.uart.write(b'\x99\x02\x00\x00\x00\x00\x00\x00\xc8\x42\xee' ) # INFO_PCT(8) | mode:1, min:0.0, max:100.0, checksum time.sleep_ms(1) self.uart.write(b'\x99\x03\x00\x00\x00\x00\x00\x00\x00\x42\x27' ) # INFO_SI(8) | mode:1, min:0.0, max:32.0, checksum time.sleep_ms(1) self.uart.write( b'\x89\x04\x43\x4d\x7c') # INFO_SYMBOL(2) | mode:1, "CM", checksum time.sleep_ms(1) self.uart.write( b'\x89\x05\xf1\x00\x82' ) # INFO_MAPPING(2) | mode:1, input:0xf1, output:0, checksum time.sleep_ms(1) self.uart.write( b'\x91\x80\x01\x01\x04\x01\xeb' ) # INFO_FORMAT(4) | mode:1, data-sets:1, format:1, figures:4, decimals:1, checksum time.sleep_ms(18) self.uart.write( b'\xa0\x00\x44\x49\x53\x54\x4c\x00\x40\x00\x00\x00\x04\x84\x00\x00\x00\x00\xd9' ) # INFO_NAME(16) | mode:0, "DISTL\0" + flags(0x40, 0x00, 0x00, 0x00, 0x04, 0x84), checksum self.uart.write( b'\x98\x01\x00\x00\x00\x00\x00\x40\x1c\x45\x7f' ) # INFO_RAW(8) | mode:0, min:0.0, max:2500.0, checksum time.sleep_ms(1) self.uart.write(b'\x98\x02\x00\x00\x00\x00\x00\x00\xc8\x42\xef' ) # INFO_PCT(8) | mode:0, min:0.0, max:100.0, checksum time.sleep_ms(1) self.uart.write(b'\x98\x03\x00\x00\x00\x00\x00\x00\x7a\x43\x5d' ) # INFO_SI(8) | mode:0, min:0.0, max:250.0, checksum time.sleep_ms(1) self.uart.write( b'\x88\x04\x43\x4d\x7d') # INFO_SYMBOL(2) | mode:0, "CM", checksum time.sleep_ms(1) self.uart.write( b'\x88\x05\x91\x00\xe3' ) # INFO_MAPPING(2) | mode:0, input:0x91, output:0, checksum time.sleep_ms(1) self.uart.write( b'\x90\x80\x01\x01\x05\x01\xeb' ) # INFO_FORMAT(4) | mode:0, data-sets:1, format:1, figures:5, decimals:1, checksum time.sleep_ms(18) self.uart.write( b'\xa0\x08\x00\x2d\x00\x33\x05\x47\x38\x33\x30\x31\x32\x36\x00\x00\x00\x00\x05' ) self.uart.write(b'\x04') print("waiting for ACK...") self.connected = self._wait_for_value(b'\x04') if self.connected: print("connected") self.set_data(0) self.timer = Timer(self.timer_num, self.timer_channel_num, mode=Timer.MODE_PERIODIC, period=200, callback=self._handle_message_callback) self.timer.start() else: print("not connected") return self.connected def _wait_for_value(self, expected_value, timeout=2): starttime = time.time() currenttime = starttime status = False #count = 0 while (currenttime - starttime) < timeout: time.sleep_ms(5) #print(count) #count += 1 currenttime = time.time() if self.uart.any() > 0: data = self.uart.readchar() #print(data) if data == ord(expected_value): status = True break return status def set_data(self, data): self.data = data def _get_checksum(self, values): checksum = 0xFF for x in values: checksum ^= x return checksum def _send_value(self, data): mode = self.current_mode # 0:DISTL, 1:DISTS l_value = data & 0xFF h_value = (data >> 8) & 0xFF payload = bytes([ 0x46, 0x00, 0xB9, 0xC8 | mode, l_value, h_value, self._get_checksum([0xC8 | mode, l_value, h_value]) ]) size = self.uart.write(payload) return size def _handle_message_callback(self, timer): if not self.connected: return while self.uart.any() > 0: x = self.uart.readchar() if x == 0: pass elif x == 0x02: pass elif x == 0x43: mode = self.uart.readchar() checksum = self.uart.readchar() if checksum == self._get_checksum([x, mode]): self.current_mode = mode elif x == 0x46: zero_or_one = self.uart.readchar() b9_or_b8 = self.uart.readchar() if (zero_or_one == 0 and b9_or_b8 == 0xb9) or (zero_or_one == 1 and b9_or_b8 == 0xb8): size_mode = self.uart.readchar() size = 2**((size_mode & 0b111000) >> 3) mode = (size_mode & 0b111) + (zero_or_one << 3) checksum = self._get_checksum( [x, zero_or_one, b9_or_b8, size_mode]) for i in range(len(self.textBuffer)): self.textBuffer[i] = ord(b' ') for i in range(size): self.textBuffer[i] = self.uart.readchar() checksum ^= self.textBuffer[i] expected_checksum = self.uart.readchar() if expected_checksum == checksum: print(self.textBuffer) elif x == 0x4C: # ex: 4C 20 00 93 l_value = self.uart.readchar() h_value = self.uart.readchar() checksum = self.uart.readchar() if checksum == self._get_checksum([x, l_value, h_value]): pass else: print(x) size = self._send_value(self.data) if not size: self.connected = False
print('****************************************5010 board init begin!****************************************') #bg96 power up print('bg96 power up!') bg96_reset_pin.value(0) bg96_power_key_pin.value(1) bg96_w_disable_pin.value(1) time.sleep_ms(2000) bg96_power_key_pin.value(0) bg96_gps_en.value(1) uart=UART(0,115200) print('bg96 version:') buf=bytearray() uart.write('ATI') time.sleep_ms(10) bchar=uart.readchar() while bchar != -1: buf.append(bchar) bchar=uart.readchar() time.sleep_ms(1) string = str(buf,'utf-8') print(string) #i2c obj i2c=I2C(1,13,14) print('I2C device address on bus:') print('I2c scan ...') device_list=i2c.scan() if len(device_list) == 4: print('lis3dh address is 0x%x' % device_list[0])
class LTEModule(object): """Controls Quectel EC21 LTE Module.""" CR = const(0x0d) LF = const(0x0a) SOCKET_TCP = const(0) SOCKET_UDP = const(1) MAX_CONNECT_ID = const(12) MAX_SOCKET_DATA_SIZE = const(1460) def __init__(self): self.__pin_reset_module = Pin('RESET_MODULE') self.__pin_dtr_module = Pin('DTR_MODULE') self.__pin_pwrkey_module = Pin('PWRKEY_MODULE') self.__pin_module_power = Pin('M_POWR') self.__pin_module_status = Pin('STATUS') self.__pin_disable_module = Pin('W_DISABLE') self.__pin_wakeup_module = Pin('WAKEUP_IN') self.__uart = UART('LTE') self.__urcs = None self.__connections = [] from uasyncio import sleep_ms, CancelledError self.sleep_ms = sleep_ms self.CancelledError = CancelledError def initialize(self): """ Initialize I/O ports and peripherals to communicate with the module. """ self.__pin_reset_module.init(Pin.OUT) self.__pin_dtr_module.init(Pin.OUT) self.__pin_pwrkey_module.init(Pin.OUT) self.__pin_module_power.init(Pin.OUT) self.__pin_module_status.init(Pin.IN) self.__pin_disable_module.init(Pin.OUT) self.__pin_wakeup_module.init(Pin.OUT) self.__pin_dtr_module.off() self.__pin_pwrkey_module.off() self.__pin_module_power.off() self.__pin_reset_module.on() self.__pin_disable_module.on() self.__pin_wakeup_module.off() self.__uart.init(baudrate=115200, timeout=5000, timeout_char=1000) def set_supply_power(self, to_supply): """Enable/Disable power supply to the module.""" self.__pin_module_power.value(1 if to_supply else 0) async def reset(self): """Reset the module.""" self.__pin_reset_module.off() await self.sleep_ms(200) while self.__uart.any(): self.__uart.read(self.__uart.any()) self.__pin_reset_module.on() await self.sleep_ms(300) for trial in range(15): if await self.wait_response(b'RDY') is not None: return True return False async def wait_busy(self, max_trials=50): """Wait while the module is busy.""" for trial in range(max_trials): if not self.is_busy(): return True await self.sleep_ms(100) return False async def turn_on(self): """Turn on the module.""" await self.sleep_ms(100) self.__pin_pwrkey_module.on() await self.sleep_ms(200) self.__pin_pwrkey_module.off() if not await self.wait_busy(): return False for trial in range(15): if await self.wait_response(b'RDY') is not None: return True return False async def turn_on_or_reset(self): """ Turn on or reset the module and wait until the LTE commucation gets available. """ self.__urcs = [] if self.is_busy(): if not await self.turn_on(): return False else: if not await self.reset(): return False # Check if the module can accept commands. if not await self.write_command_wait(b'AT', b'OK'): return False # Disable command echo if not await self.write_command_wait(b'ATE0', b'OK'): return False # Use UART1 port to receive URC if not await self.write_command_wait(b'AT+QURCCFG="urcport","uart1"', b'OK'): return False buffer = bytearray(1024) result, responses = await self.execute_command( b'AT+QSCLK=1', buffer, expected_response_list=[b'OK', b'ERROR']) if not result: return False while True: result, responses = await self.execute_command(b'AT+CPIN?', buffer, timeout=1000) if len(responses) == 0: return False if result: return True async def get_IMEI(self): """Gets International Mobile Equipment Identity (IMEI)""" response = await self.execute_command_single_response(b'AT+GSN') return str(response, 'utf-8') if response is not None else None async def get_IMSI(self): """Gets International Mobile Subscriber Identity (IMSI)""" response = await self.execute_command_single_response(b'AT+CIMI') return str(response, 'utf-8') if response is not None else None async def get_phone_number(self): "Gets phone number (subscriber number)" response = await self.execute_command_single_response( b'AT+CNUM', b'+CNUM:') return str(response[6:], 'utf-8') if response is not None else None async def get_RSSI(self): "Gets received signal strength indication (RSSI)" response = await self.execute_command_single_response( b'AT+CSQ', b'+CSQ:') if response is None: return None try: s = str(response[5:], 'utf-8') rssi, ber = s.split(',', 2) return (int(rssi), int(ber)) except ValueError: return None async def activate(self, access_point: str, user: str, password: str, timeout: int = None): #print("Activating network...") while True: # Read network registration status. response = await self.execute_command_single_response( b'AT+CGREG?', b'+CGREG:', timeout) if response is None: raise LTEModuleError('Failed to get registration status.') s = str(response, 'utf-8') #print('AT+CGREG?:{}'.format(s)) n, stat = s.split(',')[:2] if stat == '0' or stat == '4': # Not registered and not searching (0), or unknown (4). #raise LTEModuleError('Invalid registration status.') pass elif stat == '1' or stat == '5': # Registered. break while True: # Read EPS network registration status response = await self.execute_command_single_response( b'AT+CEREG?', b'+CEREG:', timeout) if response is None: raise LTEModuleError('Failed to get registration status.') s = str(response, 'utf-8') #print('AT+CEREG?:{}'.format(s)) n, stat = s.split(',')[:2] if stat == '0' or stat == '4': # Not registered and not searching (0), or unknown (4). raise LTEModuleError('Invalid registration status.') elif stat == '1' or stat == '5': # Registered. break # Configure TCP/IP contect parameters # contextID,context_type,APN,username,password,authentication # context_type : IPv4 = 1, IPv4/v6 = 2 # authentication: None = 0, PAP = 1, CHAP = 2, PAP or CHAP = 3 command = bytes( 'AT+QICSGP=1,1,"{0}","{1}","{2}",1'.format(access_point, user, password), 'utf-8') if not await self.write_command_wait(command, b'OK', timeout): return False # Activate a PDP context if not await self.write_command_wait(b'AT+QIACT=1', b'OK', timeout): return False if not await self.write_command_wait(b'AT+QIACT?', b'OK', timeout): return False return True async def get_ip_address(self, host: str, timeout: int = 60 * 1000) -> List[str]: """ Get IP address from hostname using DNS. :param str host: An address of the remote host. :return: A list of IP addresses corresponding to the hostname. :raises LTEModuleError: If the communication module failed to open a new socket. """ assert (host is not None) await self.__process_remaining_urcs(timeout=timeout) buffer = bytearray(1024) try: # Query host address. command = bytes('AT+QIDNSGIP=1,"{0}"'.format(host), 'utf-8') if not await self.write_command_wait( command, b'OK', timeout=timeout): raise LTEModuleError('Failed to get IP.') response = await self.wait_response(b'+QIURC: "dnsgip"', timeout=timeout) # type:bytes if response is None: return None fields = str(response, 'utf-8').split(',') if len(fields) < 4 or int(fields[1]) != 0: return None count = int(fields[2]) ipaddrs = [] for i in range(count): mv = await self.wait_response_into(b'+QIURC: "dnsgip",', response_buffer=buffer, timeout=1000) if mv is not None: ipaddrs.append(str(mv[18:-1], 'utf-8')) # strip double-quote return ipaddrs except ValueError: return None except self.CancelledError: pass async def get_time(self): """ Returns an 6-touple with the current date and time. The 6-touple has following format: (year, month, day, hours, minutes, seconds) """ import ure as re response = await self.execute_command_single_response( b'AT+CCLK?', b'+CCLK:') response = response.decode('utf-8') #print('res:', response) re_res = re.match( r'\+CCLK: "(\d\d)/(\d\d)/(\d\d),(\d\d):(\d\d):(\d\d)\+(\d\d)"', response) if re_res is None: raise LTEModuleError('Failed to get time.') return ( int(re_res.group(1)) + 2000, # year int(re_res.group(2)), # month int(re_res.group(3)), # day int(re_res.group(4)), # hours int(re_res.group(5)), # minutes int(re_res.group(6))) # seconds async def socket_open(self, host, port, socket_type, timeout=30 * 1000): """ Open a new socket to communicate with a host. :param str host: An address of the remote host. :param int port: Port number of the remote host. :param int socket_type: Socket type. SOCKET_TCP or SOCKET_UDP :return: Connection ID of opened socket if success. Otherwise raise LTEModuleError. :raises LTEModuleError: If the communication module failed to open a new socket. """ assert (host is not None) assert (port is not None and 0 <= port and port <= 65535) if socket_type == LTEModule.SOCKET_TCP: socket_type_name = 'TCP' elif socket_type == LTEModule.SOCKET_UDP: socket_type_name = 'UDP' else: socket_type_name = None assert (socket_type_name is not None) await self.__process_remaining_urcs(timeout=timeout) buffer = bytearray(1024) success, responses = await self.execute_command(b'AT+QISTATE?', buffer, timeout=timeout) if not success: raise LTEModuleError('Failed to get socket status') connect_id_in_use = set() for response in responses: if len(response) < 10 or response[:10] != b'+QISTATE: ': continue s = str(bytes(response[10:]), 'utf-8') params = s.split(',', 1) connect_id = int(params[0]) connect_id_in_use.add(connect_id) new_connect_id = None for connect_id in range(LTEModule.MAX_CONNECT_ID): if connect_id not in connect_id_in_use and connect_id not in self.__connections: new_connect_id = connect_id break if new_connect_id is None: raise LTEModuleError('No connection resources available.') # Open socket. command = bytes( 'AT+QIOPEN=1,{0},"{1}","{2}",{3},0,0'.format( connect_id, socket_type_name, host, port), 'utf-8') if not await self.write_command_wait(command, b'OK', timeout=timeout): raise LTEModuleError('Failed to open socket. OK') response = await self.wait_response(bytes( '+QIOPEN: {0},'.format(connect_id), 'utf-8'), timeout=timeout) if response is None: raise LTEModuleError('Failed to open socket. QIOPEN') error = str(response, 'utf-8').split(',')[1] if error != '0': raise LTEModuleError( 'Failed to open socket. error={0}'.format(error)) self.__connections.append(connect_id) return connect_id async def socket_send(self, connect_id, data, offset=0, length=None, timeout=None): """Send a packet to destination.""" assert (0 <= connect_id and connect_id <= LTEModule.MAX_CONNECT_ID) await self.__process_remaining_urcs(timeout=timeout) if connect_id not in self.__connections: return False length = len(data) if length is None else length if length == 0: return True assert (length <= LTEModule.MAX_SOCKET_DATA_SIZE) command = bytes('AT+QISEND={0},{1}'.format(connect_id, length), 'utf-8') self.write_command(command) if not await self.wait_prompt(b'> ', timeout=timeout): return False mv = memoryview(data) self.__uart.write(mv[offset:offset + length]) return await self.wait_response(b'SEND OK', timeout=timeout) is not None async def socket_receive(self, connect_id, buffer, offset=0, length=None, timeout=None): assert (0 <= connect_id and connect_id <= LTEModule.MAX_CONNECT_ID) await self.__process_remaining_urcs(timeout=timeout) if connect_id not in self.__connections: return False length = len(buffer) if length is None else length if length == 0: return 0 assert (length <= LTEModule.MAX_SOCKET_DATA_SIZE) command = bytes('AT+QIRD={0},{1}'.format(connect_id, length), 'utf-8') self.write_command(command) response = await self.wait_response(b'+QIRD: ', timeout=timeout) if response is None: return None actual_length = int(str(response[7:], 'utf-8')) if actual_length == 0: return 0 if await self.wait_response( b'OK', timeout=timeout) is not None else None mv = memoryview(buffer) bytes_read = self.__uart.readinto(mv[offset:offset + length], actual_length) return actual_length if bytes_read == actual_length and await self.wait_response( b'OK', timeout=timeout) is not None else None async def socket_close(self, connect_id, timeout=None): assert (0 <= connect_id and connect_id <= LTEModule.MAX_CONNECT_ID) if connect_id not in self.__connections: return False command = bytes('AT+QICLOSE={0}'.format(connect_id), 'utf-8') await self.write_command_wait(command, expected_response=b'OK', timeout=timeout) self.__connections.remove(connect_id) return True def socket_is_connected(self, connect_id): return connect_id in self.__connections and ( "closed", connect_id) not in self.__urcs def is_busy(self): return bool(self.__pin_module_status.value()) def write(self, s): self.__uart.write(s) def read(self, length: int) -> bytes: return self.__uart.read(length) def write_command(self, command: bytes) -> None: self.__uart.write(command) self.__uart.write('\r') async def write_command_wait(self, command, expected_response, timeout=None): self.write_command(command) return await self.wait_response(expected_response, timeout=timeout) is not None async def read_response_into(self, buffer, offset=0, timeout=None): while True: length = await self.__read_response_into(buffer=buffer, offset=offset, timeout=timeout) mv = memoryview(buffer) if (length is not None and length >= 8 and mv[0:8] == b"+QIURC: "): if length > 17 and mv[8:16] == b'"closed"': connect_id = int(str(mv[17:length], 'utf-8')) self.__urcs.append(("closed", connect_id)) continue return length async def __read_response_into(self, buffer, offset=0, timeout=None): buffer_length = len(buffer) response_length = 0 state = 0 start_time_ms = ticks_ms() while True: c = self.__uart.readchar() if c < 0: if (timeout is not None and ticks_diff(ticks_ms(), start_time_ms) >= timeout): return None try: await self.sleep_ms(1) except self.CancelledError: return None continue if state == 0 and c == LTEModule.CR: state = 1 elif state == 1 and c == LTEModule.LF: state = 2 elif state == 1 and c == LTEModule.CR: state = 1 elif state == 1 and c != LTEModule.LF: response_length = 0 state = 0 elif state == 2 and c == LTEModule.CR: if response_length == 0: state = 1 # Maybe there is another corresponding CR-LF followed by actual response data. So we have to return to state 1. else: state = 4 elif state == 2 and c != LTEModule.CR: buffer[offset + response_length] = c response_length += 1 if offset + response_length == buffer_length: state = 3 elif state == 3 and c == LTEModule.CR: state = 4 elif state == 4 and c == LTEModule.LF: return response_length async def __process_remaining_urcs(self, timeout=None): for urc_type, urc_params in self.__urcs: if urc_type == 'closed': await self.socket_close(urc_params, timeout=timeout) self.__urcs.clear() async def wait_response(self, expected_response, max_response_size=1024, timeout=None): response = bytearray(max_response_size) expected_length = len(expected_response) while True: length = await self.read_response_into(response, timeout=timeout) if length is None: return None if length >= expected_length and response[: expected_length] == expected_response: return response[:length] async def wait_response_into(self, expected_response, response_buffer, timeout=None): expected_length = len(expected_response) mv = memoryview(response_buffer) while True: length = await self.read_response_into(response_buffer, timeout=timeout) if length is None: return None if length >= expected_length and mv[: expected_length] == expected_response: return mv[:length] async def wait_prompt(self, expected_prompt, timeout=None): prompt_length = len(expected_prompt) index = 0 start_time_ms = ticks_ms() while True: c = self.__uart.readchar() if c < 0: if ticks_diff(ticks_ms(), start_time_ms) > timeout: return False await self.sleep_ms(1) continue if expected_prompt[index] == c: index += 1 if index == prompt_length: return True else: index = 0 async def execute_command(self, command, response_buffer, index=0, expected_response_predicate=None, expected_response_list=[b'OK'], timeout=None): assert expected_response_predicate is not None or expected_response_list is not None if expected_response_predicate is None: expected_response_predicate = lambda mv: mv in expected_response_list self.write_command(command) buffer_length = len(response_buffer) responses = [] mv = memoryview(response_buffer) while True: length = await self.read_response_into(response_buffer, index, timeout=timeout) if length is None: return (False, responses) response = mv[index:index + length] responses.append(response) if expected_response_predicate(response): return (True, responses) index += length async def execute_command_single_response(self, command, starts_with=None, timeout=None): buffer = bytearray(1024) result, responses = await self.execute_command(command, buffer, timeout=timeout) if not result: return None starts_with_length = len(starts_with) if starts_with is not None else 0 for response in responses: if starts_with_length == 0 and len(response) > 0: response = bytes(response) return response if starts_with_length > 0 and len( response ) >= starts_with_length and response[: starts_with_length] == starts_with: response = bytes(response) return response return None
from machine import UART uart = UART(3, 115200, bits=8, parity=None, stop=1) uart.write('AT\r\n') ret = uart.readline() uart.read(10) # read 10 characters, returns a bytes object buf = bytearray(10) uart.readinto(buf) # read and store into the given buffer uart.write('abc') # write the 3 characters uart.readchar() # read 1 character and returns it as an integer uart.writechar(42) # write 1 character uart.any() # returns the number of characters waiting uart.deinit() # turn off the UART bus