Improved Initialize LTE
-
The LTE() constructor causes the modem to reboot when the call occurs after a power up. The reboot does not occur if you reset the chip. This can lead to hard to find bugs in the communication routines. I've added a wait_response('+SHUTDOWN', 4000) call to detect the modem restart and then a call to wait_response('+SYSSTART', 15000) which indicates the modem is ready.
In the lte.isattached() method, Pycom uses the AT+CFUN? command to test if radios have been turned off. If the radios are off, this indicates the modem has crashed and they try to fix with the AT+CFUN=1 command. The problem with this is all the modem setup has been lost at that point (band setup, user configured modem settings, ...). When we initialize the modem we set the SMS text mode using the at('AT+CMGF=1') command. Since the setting is reset to 0 if the modem restarts, we can use the test AT+CMGF? != 1 to detect any modem crashes so we can do a modem reset and reinitialization.
I think a better option would be for Pycom to set a python testable flag if the modem crashes.
lte = None ##################################################################### # Send AT Command To Modem ##################################################################### def at(cmd): try: log("modem command: {}".format(cmd)) util.wait() # lte.send_at_cmd(cmd, delay=10000) r = lte.send_at_cmd(cmd).split('\r\n') task_switch() r = list(filter(None, r)) log("response: {}".format(r)) task_switch() except Exception as ex: sys.print_exception(ex) r = [] return r ##################################################################### # Initialize LTE ##################################################################### def init_lte(): global lte try: log('initializing LTE...') task_switch() lte = LTE() task_switch() # modem will restart on power up situations r = wait_response('+SHUTDOWN', 4000) if r == True: wait_response('+SYSSTART', 15000) except Exception as ex: sys.print_exception(ex) util.reset(27, "LTE exception") ##################################################################### # Initialize Modem ##################################################################### def init_modem(): try: if lte == None: init_lte() g.modem_state = g.MS_INIT_MODEM log("initializing modem...") log("set SMS mode to text") at('AT+CMGF=1') # set SMS mode to text # if AT+CMFG? returns 0, the modem has crashed/restarted task_switch() lte.init() # lte.init(carrier='att') # no known advantage task_switch() g.oIni.apn = g.oIni.apn_89014 log("Kore AT&T SIM - APN: {0}".format(g.oIni.apn)) except Exception as ex: sys.print_exception(ex) util.reset(27, "LTE exception") ##################################################################### # Is Cellular Modem Attached To Base Station ##################################################################### def isattached(): # returns: True/False try: task_switch() r = lte.isattached() # Pycom uses AT+CFUN? to test if radios have been turned off # this indicates modem has crashed and they try to fix with AT+CFUN=1 # the problem is all the modem setup has been lost at that point # we will test AT+CMGF? != 1 to detect crash and then restart task_switch() if r == True: g.modem_state = g.MS_REGISTERED except Exception as ex: sys.print_exception(ex) r = False return r ##################################################################### # Modem Restarted/Crashed Check ##################################################################### def restarted(): # return True if modem has crashed / restarted # if SMS text mode is reset to zero, modem has crashed / restarted try: r = at('AT+CMGF?') # response: ['+CMGF: 1', 'OK'] if len(r) == 0: return False # state unknown s = r[0] if (s[0:6] != '+CMGF:'): return False # state unknown mode = int(s[7]) if mode != 1: return True # modem has crashed /restarted return False except Exception as ex: sys.print_exception(ex) return False # state unknown ##################################################################### # Wait For Specific Modem Response ##################################################################### def wait_response(response, msecs=10000): log('wait up to {0} msecs for modem response: {1}'.format(msecs, response)) t0 = ticks_ms() while True: try: t1 = ticks_ms() tx = ticks_diff(t1, t0) log('{0} msecs'.format(tx)) r = at('AT') t1 = ticks_ms() tx = ticks_diff(t1, t0) log('{0} msecs'.format(tx)) for x in r: if x == response: log('****modem response found****: ' + response) return True if tx > msecs: log('modem response not found: ' + response) return False sleep_ms(1000) except Exception as ex: sys.print_exception(ex)
-
You can check for modem crashes with
mood=lte.send_at_cmd('at+cpin?').split('\r\n')[1]; print('mood =', mood)
anything other than READY or +SYSSTART means the modem is crashed.