Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 4985

MicroPython • Two way bluetooth

$
0
0
Since a few weeks I work with two pico w's for a cosplay project and its a pretty new world for me (python).
With the help of this forum I was already able to play sounds with a dfplayer (with an arduino it was way easier...) and I would say Im kind of proud of my project. The two picos are connectd via bluetooth. One is like a remote and triggers several events the other can execute.
For the bluetooth connection I used the code from KevinsBots (see below).

(Remote)

Code:

import sysimport aiobleimport bluetoothimport machineimport uasyncio as asynciofrom micropython import constfrom pimoroni import Buttondef uid():    """ Return the unique id of the device as a string """    return "{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}".format(        *machine.unique_id())MANUFACTURER_ID = const(0x02A29)MODEL_NUMBER_ID = const(0x2A24)SERIAL_NUMBER_ID = const(0x2A25)HARDWARE_REVISION_ID = const(0x2A26)BLE_VERSION_ID = const(0x2A28)button_a = Button(12)button_b = Button(13)button_x = Button(14)button_y = Button(15)led = machine.Pin("LED", machine.Pin.OUT)_ENV_SENSE_UUID = bluetooth.UUID(0x180A)_GENERIC = bluetooth.UUID(0x1848)_ENV_SENSE_TEMP_UUID = bluetooth.UUID(0x1800)_BUTTON_UUID = bluetooth.UUID(0x2A6E)_BLE_APPEARANCE_GENERIC_REMOTE_CONTROL = const(384)# Advertising frequencyADV_INTERVAL_MS = 250_000device_info = aioble.Service(_ENV_SENSE_UUID)connection = None# Create characteristics for device infoaioble.Characteristic(device_info, bluetooth.UUID(MANUFACTURER_ID), read=True, initial="KevsRobotsRemote")aioble.Characteristic(device_info, bluetooth.UUID(MODEL_NUMBER_ID), read=True, initial="1.0")aioble.Characteristic(device_info, bluetooth.UUID(SERIAL_NUMBER_ID), read=True, initial=uid())aioble.Characteristic(device_info, bluetooth.UUID(HARDWARE_REVISION_ID), read=True, initial=sys.version)aioble.Characteristic(device_info, bluetooth.UUID(BLE_VERSION_ID), read=True, initial="1.0")remote_service = aioble.Service(_GENERIC)button_characteristic = aioble.Characteristic(    remote_service, _BUTTON_UUID, read=True, notify=True)print('registering services')aioble.register_services(remote_service, device_info)connected = Falseasync def remote_task():    """ Send the event to the connected device """    while True:        if not connected:            print('not connected')            await asyncio.sleep_ms(1000)            continue        if button_a.read():            print(f'Button A pressed, connection is: {connection}')            button_characteristic.write(b"a")               button_characteristic.notify(connection,b"a")        elif button_b.read():            print('Button B pressed')            button_characteristic.write(b"b")            button_characteristic.notify(connection,b"b")        elif button_x.read():            print('Button X pressed')            button_characteristic.write(b"x")            button_characteristic.notify(connection,b"x")        elif button_y.read():            print('Button Y pressed')            button_characteristic.write(b"y")            button_characteristic.notify(connection,b"x")        else:            button_characteristic.write(b"!")        await asyncio.sleep_ms(10)            # Serially wait for connections. Don't advertise while a central is# connected.    async def peripheral_task():    print('peripheral task started')    global connected, connection    while True:        connected = False        async with await aioble.advertise(            ADV_INTERVAL_MS,             name="KevsRobots",             appearance=_BLE_APPEARANCE_GENERIC_REMOTE_CONTROL,             services=[_ENV_SENSE_TEMP_UUID]        ) as connection:            print("Connection from", connection.device)            connected = True            print(f"connected: {connected}")            await connection.disconnected()            print(f'disconnected')        async def blink_task():    print('blink task started')    toggle = True    while True:        led.value(toggle)        toggle = not toggle        blink = 1000        if connected:            blink = 1000        else:            blink = 250        await asyncio.sleep_ms(blink)        async def main():    tasks = [        asyncio.create_task(peripheral_task()),        asyncio.create_task(blink_task()),        asyncio.create_task(remote_task()),    ]    await asyncio.gather(*tasks)asyncio.run(main())

(Device/receiver)

Code:

import aiobleimport bluetoothimport machineimport uasyncio as asyncio# Bluetooth UUIDS can be found online at https://www.bluetooth.com/specifications/gatt/services/_REMOTE_UUID = bluetooth.UUID(0x1848)_ENV_SENSE_UUID = bluetooth.UUID(0x1800) _REMOTE_CHARACTERISTICS_UUID = bluetooth.UUID(0x2A6E)led = machine.Pin("LED", machine.Pin.OUT)connected = Falsealive = Falseasync def find_remote():    # Scan for 5 seconds, in active mode, with very low interval/window (to    # maximise detection rate).    async with aioble.scan(5000, interval_us=30000, window_us=30000, active=True) as scanner:        async for result in scanner:            # See if it matches our name            if result.name() == "KevsRobots":                print("Found KevsRobots")                for item in result.services():                    print (item)                if _ENV_SENSE_UUID in result.services():                    print("Found Robot Remote Service")                    return result.device                return Noneasync def blink_task():    """ Blink the LED on and off every second """        toggle = True        while True and alive:        led.value(toggle)        toggle = not toggle        # print(f'blink {toggle}, connected: {connected}')        if connected:            blink = 1000        else:            blink = 250        await asyncio.sleep_ms(blink)async def peripheral_task():    print('starting peripheral task')    global connected    connected = False    device = await find_remote()    if not device:        print("Robot Remote not found")        return    try:        print("Connecting to", device)        connection = await device.connect()            except asyncio.TimeoutError:        print("Timeout during connection")        return          async with connection:        print("Connected")        connected = True        alive = True        while True and alive:            try:                robot_service = await connection.service(_REMOTE_UUID)                print(robot_service)                control_characteristic = await robot_service.characteristic(_REMOTE_CHARACTERISTICS_UUID)                print(control_characteristic)            except asyncio.TimeoutError:                print("Timeout discovering services/characteristics")                return            while True:                if control_characteristic != None:                    try:                        command = await control_characteristic.read()#                         print(f"Command: {temp_deg_c}")                        if command == b'a':                            print("a button pressed")                        if command == b'b':                            print("b button pressed")                        if command == b'x':                            print("x button pressed")                        if command == b'y':                            print("y button pressed")                    except TypeError:                        print(f'something went wrong; remote disconnected?')                        connected = False                        alive = False                        return                    except asyncio.TimeoutError:                        print(f'something went wrong; timeout error?')                        connected = False                        alive = False                        return                    except asyncio.GattError:                        print(f'something went wrong; Gatt error - did the remote die?')                        connected = False                        alive = False                        return                else:                    print('no characteristic')                await asyncio.sleep_ms(10)async def main():    tasks = []    tasks = [        asyncio.create_task(blink_task()),        asyncio.create_task(peripheral_task()),    ]    await asyncio.gather(*tasks)    while True:    asyncio.run(main())

For the last 10% to make my project perfect I would need a two way connection. So that the remote could receive a few informations from the (kevins example) bot. For example : bot got a low battery, a led on the remote turns on.
I tried to modify its code and I think I got the remote the receive data, but I couldnt figure out to send data from the bot.
I also tried a few other bluetooth example codes. But they didnt work at all for me...
Can anybody tell me if its really that difficult to modify the code so both picos can send and receive data?

Best reagards
Greg

Statistics: Posted by Greg50007 — Tue Jun 25, 2024 10:39 am



Viewing all articles
Browse latest Browse all 4985

Trending Articles