Async randomly dying
Checks
-
I agree to follow the MicroPython Code of Conduct to ensure a safe and respectful space for everyone.
-
I've searched for existing issues matching this bug, and didn't find any.
Port, board and/or hardware
RP2
MicroPython version
MicroPython v1.22.2 on 2024-02-22; Raspberry Pi Pico with RP2040
Reproduction
from machine import UART, Pin
from uasyncio import StreamReader, StreamWriter, Event, Lock, sleep_ms, run
LoRa_bands = {'EU': 868.1, 'US': 915.0}
class LoRa:
def __init__(self, uart=0, tx_pin=0, rx_pin=1, reset_pin=4, baudrate=115200,
band='US', address=2):
self.uart = UART(uart, baudrate=baudrate, tx=tx_pin, rx=rx_pin)
self.reset_pin = Pin(reset_pin, Pin.OUT)
self.reader = StreamReader(self.uart)
self.writer = StreamWriter(self.uart, {})
self._band = band
self._address = address
self.initialized = False
self.seat = Lock()
self._recv = Event()
self._received = Event()
def start(self):
from uasyncio import create_task
create_task(self.dev_init())
create_task(self.readloop())
async def send_query(self, query):
return await self.send_command(query, True)
async def send_command(self, cmd, query=False):
""" Sends an AT command to the device """
# Fix capitalization
if loc := cmd.find('=') + 1:
cmd = cmd[:loc].upper() + cmd[loc:]
else:
cmd = cmd.upper()
# Add prefix
if not cmd.startswith('AT+'):
orig_cmd = cmd
cmd = 'AT+' + cmd
else:
orig_cmd = cmd[3:]
# Add suffix for query
if query and cmd[-1] != '?':
cmd += '?'
# Add termination
cmd += '\r\n'
async with self.seat:
print("Sending command: ", cmd.rstrip())
await self.writer.awrite(cmd)
await sleep_ms(10 if query else 50)
while not self.uart.any():
print("Waiting for response...")
await sleep_ms(250)
response = await self.recv()
response = response[:-2]
print(response)
if query:
if response.startswith(f"+{orig_cmd}="):
response = response[len(f"+{orig_cmd}="):]
else:
raise ValueError("Invalid response: %s" % response)
elif response != '+OK':
raise ValueError("Error: %s" % response)
return response
async def reset(self):
print("Resetting LoRa module.")
self.reset_pin.off()
await sleep_ms(100)
self.reset_pin.on()
status = await self.recv()
if status != '+READY\r\n':
raise ValueError("Module not ready after reset: %s" % status)
async def dev_init(self):
await self.reset()
if not self.version or not self.uid:
raise ValueError("Unknown module.")
self.address = self._address
self.band = self._band
async def recv(self):
self._recv.set()
await self._received.wait()
self._received.clear()
return self._data
async def readloop(self):
while True:
await self._recv.wait()
raw_data = await self.reader.readline()
self._data = raw_data.decode()
self._recv.clear()
self._received.set()
print("wtf")
@property
def address(self):
return run(self.send_query('address'))
@address.setter
def address(self, address=None):
if address is None:
address = self._address
elif address >= 0 and address < 2 ** 16:
self._address = address
else:
raise ValueError("Invalid LoRa address: %s", address)
return run(self.send_command(f'ADDRESS={address}'))
@property
def band(self):
return run(self.send_query('band'))
@band.setter
def band(self, band=None):
if band is None:
band = self._band
else:
self._band = band
band_freq = int(LoRa_bands[band] * 1_000_000)
return run(self.send_command(f'BAND={band_freq}'))
@property
def parameter(self):
return run(self.send_query('parameter'))
@parameter.setter
def set_parameters(self, spreading_factor, bandwidth, coding_rate):
return run(self.send_command(f'PARAMETER={spreading_factor},{bandwidth},{coding_rate}'))
@property
def uid(self):
return run(self.send_query('uid'))
@property
def version(self):
return run(self.send_query('ver'))
from asyncio import get_event_loop
from lora import LoRa
lora = LoRa()
loop = get_event_loop()
lora.start()
loop.run_forever()
print("Ended.")
Connected to MicroPython at /dev/ttyACM2
Use Ctrl-] or Ctrl-x to exit this shell
MPY: soft reboot
Resetting LoRa module.
Sending command: AT+VER?
+VER=RYLR998_REYAX_V1.2.2
Sending command: AT+UID?
+UID=000500110457F1B400003E76
Sending command: AT+ADDRESS=2
+OK
Sending command: AT+BAND=915000000
+OK
Ended.
MicroPython v1.22.2 on 2024-02-22; Raspberry Pi Pico with RP2040
Type "help()" for more information.
The infinite loop seems to end withot reason, and then the run_forever is not followed.
Expected behaviour
This script should loop infinitely, instead it seems to stop after dev_init completes.
Observed behaviour
The loop stops with no exceptions, even though it's an infinite loop.
Additional Information
No, I've provided everything above.
if uart receives 0xf0 byte then mcu after entering lightsleep never wakes up
Checks
-
I agree to follow the MicroPython Code of Conduct to ensure a safe and respectful space for everyone.
-
I've searched for existing issues matching this bug, and didn't find any.
Port, board and/or hardware
RP2, STM32L4, STM32H7
MicroPython version
MicroPython v1.22.2 on 2024-02-22; Raspberry Pi Pico with RP2040
Reproduction
Example for Rpi Pico:
from machine import Pin, UART, lightsleep
from time import sleep
uart = UART(0, baudrate=115200, bits=8, tx=Pin(0), rx=Pin(1), parity=None, stop = 1, timeout=2000)
## Main Loop ##
uart.write("Start \n")
while True:
sleep(1)
buff=bytearray()
while uart.any():
buff.extend(bytearray(uart.read(uart.any())))
# to exit program send '9'
if buff.find(b"9")>=0:
break
if len(buff)>0:
buff.append(10)
uart.write(buff)
uart.write("before lightsleep \n")
lightsleep(100)
sleep(0.05)
uart.write("after lightsleep\n")
Expected behaviour
No response
Observed behaviour
If uart receives 0xf0 byte then mcu after entering lightsleep never wakes up.
If message doesn't have 0xf0 byte then it continues working ok.
I tried it on RPi Pico, and STM32 boards they have same behavior.
Additional Information
No, I've provided everything above.