Skip to content

Memory allocation failed when reconnecting and activating BLE UART to multiple devices #10222

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
gkecskes78 opened this issue Apr 4, 2025 · 0 comments

Comments

@gkecskes78
Copy link

CircuitPython version and board name

Adafruit CircuitPython 9.2.7 on 2025-04-01; PCA10059 nRF52840 Dongle with nRF52840
Board ID:pca10059
UID:9B577D0F0B41F302

Code/REPL

##### Central code
import os,gc,zlib,binascii,digitalio
import time,board,busio,_bleio,pwmio
import storage,analogio,microcontroller,supervisor
import adafruit_ads1x15.ads1015 as ADS
from adafruit_mcp230xx.mcp23017 import MCP23017
from adafruit_ble import BLERadio
from adafruit_ble.services.nordic import UARTService
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
ble=BLERadio()
uart=UARTService()
advert=ProvideServicesAdvertisement(uart)
import adafruit_logging as logging
logger=logging.getLogger('test')
logger.setLevel(logging.INFO)

class Connection:
    ble_connection=None
    uart_service=None
    counter=0
    def __init__(self,name,MAC):
        self.Name=name
        self.MAC=MAC
        self.counter=0
    def Connect(self):
        if self.ble_connection and self.ble_connection.connected:
            return
        while True:
            try:
                if (not self.ble_connection) or (self.ble_connection and not self.ble_connection.connected):

                    if self.ble_connection:
                        self.ble_connection.disconnect()
                    self.ble_connection=None
                    self.uart_service=None
                    gc.collect()

                    logger.info("Start scanning for device "+str(self.Name)+"/"+str(self.MAC)+", timeout=5s  Free memory: "+str(gc.mem_free())+" Allocated memory: "+str(gc.mem_alloc()))
                    found=False
                    for adv in ble.start_scan(ProvideServicesAdvertisement,timeout=5):
                        if UARTService in adv.services and self.MAC in str(adv.address):
                            found=True
                            logger.info(" -> device found !")
                            logger.info("Connecting to device "+str(self.Name)+"/"+str(self.MAC))
                            self.ble_connection=ble.connect(adv)
                            logger.info(" -> connected at object: "+str(self.ble_connection))
                            break
                    if not found:
                        logger.info(" -> device NOT found !")
                    logger.info("Stopping BLE scan...")
                    ble.stop_scan()
                    if self.ble_connection and self.ble_connection.connected:
                        logger.info("Activating UART service...")
                        self.uart_service=self.ble_connection[UARTService]
                        self.ble_connection.connection_interval=8
                        logger.info("Counter: "+str(self.counter)+" -> activated !")
                        self.counter+=1
                        break
            except Exception as e:
                ble.stop_scan()
                if self.ble_connection:
                    self.ble_connection.disconnect()
                self.ble_connection=None
                self.uart_service=None
                gc.collect()
                logger.info("Connection error:")
                logger.info(e)
                time.sleep(1)

class ConnectionManager:
    connections=[]
    def Add(self,connection):
        logger.info("Adding forward connection "+str(connection.Name)+"/"+str(connection.MAC)+" "+str(connection.ble_connection))
        self.connections.append(connection)
    def ConnectAndCheck(self):
        for c in self.connections:
            c.Connect()

manager=ConnectionManager()
conn1=Connection("188","e9:67:f5:9b:46:60")
conn2=Connection("193","f0:af:93:29:c4:98")
conn3=Connection("194","e4:4a:37:f5:5d:2b")
conn4=Connection("205","ea:c0:1d:9b:03:38")
manager.Add(conn1)
manager.Add(conn2)
manager.Add(conn3)
manager.Add(conn4)
while True:
    manager.ConnectAndCheck()





##### Peripheral code
import time,digitalio,board,_bleio
from adafruit_ble import BLERadio
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
from adafruit_ble.services.nordic import UARTService

ble = BLERadio()
uart = UARTService()
advertisement = ProvideServicesAdvertisement(uart)

led1=digitalio.DigitalInOut(board.LED1)
led1.direction=digitalio.Direction.OUTPUT
print(_bleio.adapter.address)

reply=False
led1.value=True
print("Waiting to connect")
tstart=time.monotonic()
while True:
    try:
        if not ble.advertising:
            print("Advertising started")
            ble.start_advertising(advertisement)
        if not ble.connected:
            if reply:
                led1.value=True
                print("Waiting to connect")
                time.sleep(1)
            reply=False
        if ble.connected:
            if not reply:
                led1.value=False
                print("Connected")
                tstart=time.monotonic()
            reply=True
            tend=time.monotonic()
            if tend-tstart>20:
                tstart=time.monotonic()
                print("Disconnecting...")
                for b in ble.connections:
                    b.disconnect()
    except Exception as e:
        print("Error:")
        print(e)
        time.sleep(1)

Behavior

.
.
.
2025-04-04 16:41:15.624302 3536.639: INFO -
2025-04-04 16:41:16.685596 3537.708: INFO - Start scanning for device 205/ea:c0:1d:9b:03:38, timeout=5s Free memory: 8784 Allocated memory: 127296
2025-04-04 16:41:16.799425 3537.822: INFO - -> device found !
2025-04-04 16:41:16.811482 3537.826: INFO - Connecting to device 205/ea:c0:1d:9b:03:38
2025-04-04 16:41:16.952994 3537.922: INFO - -> connected at object: <BLEConnection object at 0x20039200>
2025-04-04 16:41:16.964279 3537.978: INFO - Stopping BLE scan...
2025-04-04 16:41:16.976053 3537.980: INFO - Activating UART service...
2025-04-04 16:41:19.477170 3540.500: INFO - Connection error:
2025-04-04 16:41:19.488508 3540.503: INFO -
2025-04-04 16:41:20.551612 3541.573: INFO - Start scanning for device 205/ea:c0:1d:9b:03:38, timeout=5s Free memory: 8704 Allocated memory: 127376
2025-04-04 16:41:20.659925 3541.684: INFO - Connection error:
2025-04-04 16:41:20.672164 3541.686: INFO - memory allocation failed, allocating 512 bytes

.
.
.

Description

I have this issue on a bigger setup in a form of binary tree, where a dongle connects to 4 other dongles, and so on, see here:
https://forums.adafruit.com/viewtopic.php?p=1047796&hilit=disconnect#p1047796
After several hours, no reconnection was possible anymore.

To reproduce the same behaviour faster with the attached codes, the peripherals are disconnecting intentionally 20 seconds after being connected in order to trigger the central to reconnect.
The code is working for a while, than errors occur when activating the UART service and finally memory allocation fail happens.

Additional information

Here the complete logs:

COM11.txt
COM14.txt
COM210.txt
COM221.txt
COM222.txt

@gkecskes78 gkecskes78 added the bug label Apr 4, 2025
@dhalbert dhalbert changed the title Memory allocation failed when reconnecting and activating UART to multiple devices Memory allocation failed when reconnecting and activating BLE UART to multiple devices Apr 4, 2025
@tannewt tannewt added this to the Long term milestone Apr 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants