{"id":20277418,"url":"https://github.com/ekspla/micropython_aioble_examples","last_synced_at":"2026-05-06T14:36:56.406Z","repository":{"id":203639424,"uuid":"710069030","full_name":"ekspla/micropython_aioble_examples","owner":"ekspla","description":"A few aioble (asyncio BLE) examples of MicroPython using esp32","archived":false,"fork":false,"pushed_at":"2026-03-27T09:46:56.000Z","size":360,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-27T20:56:58.291Z","etag":null,"topics":["aioble","asyncio","ble","bluetooth-low-energy","esp32","heart-rate","hioki","micropython","multimeter","nordic-uart-service","nus","python","voltmeter","ymodem"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ekspla.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-10-26T00:41:23.000Z","updated_at":"2026-03-27T09:47:01.000Z","dependencies_parsed_at":null,"dependency_job_id":"04bae27f-befc-4744-bd6d-7e3425ac853a","html_url":"https://github.com/ekspla/micropython_aioble_examples","commit_stats":null,"previous_names":["ekspla/micropython_aioble_examples"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ekspla/micropython_aioble_examples","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekspla%2Fmicropython_aioble_examples","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekspla%2Fmicropython_aioble_examples/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekspla%2Fmicropython_aioble_examples/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekspla%2Fmicropython_aioble_examples/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ekspla","download_url":"https://codeload.github.com/ekspla/micropython_aioble_examples/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ekspla%2Fmicropython_aioble_examples/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32698602,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-06T08:33:17.875Z","status":"ssl_error","status_checked_at":"2026-05-06T08:33:17.221Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aioble","asyncio","ble","bluetooth-low-energy","esp32","heart-rate","hioki","micropython","multimeter","nordic-uart-service","nus","python","voltmeter","ymodem"],"created_at":"2024-11-14T13:18:23.817Z","updated_at":"2026-05-06T14:36:56.400Z","avatar_url":"https://github.com/ekspla.png","language":"Python","funding_links":[],"categories":["Libraries"],"sub_categories":["Communications"],"readme":"# micropython_aioble_examples\nA few aioble (asyncio bluetooth low energy) examples of MicroPython using ESP32\n\n(C) 2023-2025 [ekspla](https://github.com/ekspla/micropython_aioble_examples)\n\nThe following examples were tested with [MicroPython](https://micropython.org/) 1.21.0-1.23.0 and \n[aioble](https://github.com/micropython/micropython-lib/tree/master/micropython/bluetooth/aioble) on \n[ESP32-DevKitC-32E](https://www.espressif.com/en/products/devkits/esp32-devkitc).\n\n\n## Read measured values from a [HIOKI](https://www.hioki.com/) voltmeter via BLE\n`hioki_z3210.py`\n\nAn example to read measured values from HIOKI's voltmeter, DT4261, via \n[Z3210 BLE interface](https://www.hioki.com/global/products/specialized-solutions/connecting-instruments/id_6780).\nOther mesurement tools of HIOKI equipped with the BLE interface may also work (with/without a bit of modification).\nThough the ways (e.g. commands; [references](https://www.hioki.com/global/support/download/software/versionup/detail/id_235) \navailable from their website) to communicate with the tools are similar to those of \nUSB ([DT4900-01](https://www.hioki.com/global/support/download/software/versionup/detail/id_235)), RS232 and GPIB interfaces, \nI found this BLE interface very useful in probing hazardous high voltages/currents at a safe place because of the wireless nature.  \n\nI feel like using a home-built tiny display device equipped with an ESP32 is more convenient than using HIOKI's proprietary \nsoftware with a smartphone.\n\n```python\nMicroPython v1.21.0 on 2023-10-05; Generic ESP32 module with ESP32\nType \"help()\" for more information.\n\u003e\u003e\u003e\n\u003e\u003e\u003e import hioki_z3210\n\u003e\u003e\u003e hioki_z3210.start()\nDevice(ADDR_PUBLIC, a4:9e:69:xx:yy:zz)\nConnecting to Device(ADDR_PUBLIC, a4:9e:69:xx:yy:zz)\nConnected.\n(2023, 10, 26, 9, 37, 3, 3, 299)        +1.00000000E-04\n(2023, 10, 26, 9, 37, 3, 3, 299)        +1.00000000E-04\n(2023, 10, 26, 9, 37, 4, 3, 299)        +1.00000000E-04\n(2023, 10, 26, 9, 37, 4, 3, 299)        +1.00000000E-04\n\n ...\n \n```\n\n## Read heart rate values from a heart rate sensor via BLE\n`hr_read.py`\n\nAn example to read heart rate values (BPM) from \n[Magene's H64](https://support.magene.com/hc/en-us/categories/900000170623-H64-Heart-Rate-Sensor).  \nChange the device name `_HR_SENSOR_NAME` or the `address` to specify your device.  The code should work for most \nof the BLE heart-rate sensors because the service and the characteristics are common.\n\n```python\nMicroPython v1.21.0 on 2023-10-05; Generic ESP32 module with ESP32\nType \"help()\" for more information.\n\u003e\u003e\u003e\n\u003e\u003e\u003e import hr_read\n\u003e\u003e\u003e hr_read.start()\nConnecting to Device(ADDR_RANDOM, d8:75:ba:xx:yy:zz)\n(2000, 1, 1, 6, 27, 59, 5, 1)\t45\n(2000, 1, 1, 6, 28, 0, 5, 1)\t45\n(2000, 1, 1, 6, 28, 1, 5, 1)\t45\n(2000, 1, 1, 6, 28, 2, 5, 1)\t46\n\n ...\n\n```\n\n## Handling of connections to multiple peripherals and disconnect/reconnect\n`conn_multiple.py`\n\nBased on the codes of voltmeter and heart rate monitor, an example is shown.\n\nYou may want to change the maximum allowed number of connections in bluetooth stack.  \nESP32_GENERIC ([ESP-IDF](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/kconfig.html)) for example, \nchange `CONFIG_BT_NIMBLE_MAX_CONNECTIONS` and `CONFIG_BTDM_CTRL_BLE_MAX_CONN` in config file (default to 4 and 3, \nrespectively). I have changed these (to 5 and 4) and got successfull concurrent connections to 4 peripherals.\n\nIf you have to find peripheral devices, write and use a loop of scan/connect/service-discovery to list the target devices \nin the beginning.\n\n```\nConnecting to Device(ADDR_RANDOM, d8:75:ba:xx:yy:zz)             # Heart rate sensor, switched on.\nConnected. \u003cDeviceConnection object at 3ffedf70\u003e\nConnecting to Device(ADDR_PUBLIC, a4:9e:69:xx:yy:zz)             # Voltmeter DT4261, switched off.\n(2024, 5, 22, 7, 32, 27, 2, 143)        48 [bpm]\n(2024, 5, 22, 7, 32, 29, 2, 143)        48 [bpm]\n(2024, 5, 22, 7, 32, 30, 2, 143)        48 [bpm]\n(2024, 5, 22, 7, 32, 31, 2, 143)        48 [bpm]\nTimeout during connection\n(2024, 5, 22, 7, 32, 32, 2, 143)        48 [bpm]\n(2024, 5, 22, 7, 32, 34, 2, 143)        48 [bpm]\n(2024, 5, 22, 7, 32, 35, 2, 143)        48 [bpm]\nConnecting to Device(ADDR_PUBLIC, a4:9e:69:xx:yy:zz)             # Power on DT4261.\nConnected. \u003cDeviceConnection object at 3fff1240\u003e\n(2024, 5, 22, 7, 32, 37, 2, 143)        47 [bpm]\n(2024, 5, 22, 7, 32, 37, 2, 143)        DT4261;+0.00000000E+00\n(2024, 5, 22, 7, 32, 37, 2, 143)        47 [bpm]\n(2024, 5, 22, 7, 32, 38, 2, 143)        DT4261;+0.00000000E+00\n(2024, 5, 22, 7, 32, 38, 2, 143)        DT4261;+0.00000000E+00\n(2024, 5, 22, 7, 32, 39, 2, 143)        47 [bpm]\n(2024, 5, 22, 7, 32, 39, 2, 143)        DT4261;+0.00000000E+00\n(2024, 5, 22, 7, 32, 40, 2, 143)        DT4261;+0.00000000E+00\n(2024, 5, 22, 7, 32, 40, 2, 143)        47 [bpm]\n(2024, 5, 22, 7, 32, 40, 2, 143)        DT4261;-1.00000000E-04\n(2024, 5, 22, 7, 32, 41, 2, 143)        DT4261;-1.00000000E-04\n(2024, 5, 22, 7, 32, 41, 2, 143)        46 [bpm]\n(2024, 5, 22, 7, 32, 42, 2, 143)        DT4261;-1.00000000E-04\n(2024, 5, 22, 7, 32, 42, 2, 143)        DT4261;-1.00000000E-04\n(2024, 5, 22, 7, 32, 43, 2, 143)        46 [bpm]\nError!                                                           # Power off DT4261.\n(2024, 5, 22, 7, 32, 44, 2, 143)        45 [bpm]\n(2024, 5, 22, 7, 32, 45, 2, 143)        45 [bpm]\n(2024, 5, 22, 7, 32, 46, 2, 143)        46 [bpm]\nConnecting to Device(ADDR_PUBLIC, a4:9e:69:xx:yy:zz)\n(2024, 5, 22, 7, 32, 48, 2, 143)        46 [bpm]\n(2024, 5, 22, 7, 32, 49, 2, 143)        45 [bpm]\n(2024, 5, 22, 7, 32, 51, 2, 143)        46 [bpm]\n(2024, 5, 22, 7, 32, 52, 2, 143)        45 [bpm]\nTimeout during connection\n(2024, 5, 22, 7, 32, 53, 2, 143)        45 [bpm]\n(2024, 5, 22, 7, 32, 55, 2, 143)        45 [bpm]\n(2024, 5, 22, 7, 32, 55, 2, 143)        45 [bpm]\n(2024, 5, 22, 7, 32, 57, 2, 143)        45 [bpm]\nConnecting to Device(ADDR_PUBLIC, a4:9e:69:xx:yy:zz)             # Power on DT4261 again.\nConnected. \u003cDeviceConnection object at 3ffd3450\u003e\n(2024, 5, 22, 7, 32, 58, 2, 143)        DT4261;+0.00000000E+00\n(2024, 5, 22, 7, 32, 58, 2, 143)        46 [bpm]\n(2024, 5, 22, 7, 32, 59, 2, 143)        DT4261;+0.00000000E+00\n(2024, 5, 22, 7, 32, 59, 2, 143)        DT4261;+0.00000000E+00\n(2024, 5, 22, 7, 33, 0, 2, 143)         46 [bpm]\n(2024, 5, 22, 7, 33, 0, 2, 143)         DT4261;+0.00000000E+00\n(2024, 5, 22, 7, 33, 1, 2, 143)         DT4261;-1.00000000E-04\n(2024, 5, 22, 7, 33, 1, 2, 143)         46 [bpm]\n(2024, 5, 22, 7, 33, 1, 2, 143)         DT4261;-1.00000000E-04\n(2024, 5, 22, 7, 33, 2, 2, 143)         DT4261;-1.00000000E-04\n(2024, 5, 22, 7, 33, 2, 2, 143)         45 [bpm]\n(2024, 5, 22, 7, 33, 3, 2, 143)         DT4261;-1.00000000E-04\n(2024, 5, 22, 7, 33, 3, 2, 143)         45 [bpm]\n(2024, 5, 22, 7, 33, 3, 2, 143)         DT4261;-1.00000000E-04\n(2024, 5, 22, 7, 33, 4, 2, 143)         DT4261;-1.00000000E-04\nmain_hr closed                                                   # Stop the loop.\n(2024, 5, 22, 7, 33, 4, 2, 143)         DT4261;-1.00000000E-04\nmain_4261 closed\nEnd.\n\n```\n\n## How can we handle successive notified packets as a client using aioble?\n(A link to discussion of this topic can be found \n[here](https://github.com/orgs/micropython/discussions/15544).)\n\nIn the current version of `aioble/client.py`, a data of a notified \npacket can be overwritten by those of the successive notified packets in \nthe queue to which the data are appended.  This is because the size of the \nqueue by default is 1:  `self._notify_queue = deque((), 1)`\n\nSo *a `while True:` loop* with *a `charateristic.notified()`* \nshown in the official examples, as well as `hr_read.py` shown above, are not \nnecessarily useful; **notified packets should be well separated in time from each other**.\n\nThough I do not know exactly what is the future plan of the core developers to \nsolve the issue, there is a comment in `aioble/client.py` as follows:\n\n```\n# Append the data. By default this is a deque with max-length==1, so it\n# replaces. But if capture is enabled then it will append.\n```\n\nAs a workaround for Nordic UART client used in [mpy_xoss_sync.py](https://github.com/ekspla/xoss_sync), \nI changed the size of the queue and retrieved the accumulated notified data from the queue as followings.\n\n```python\nbuffer = bytearray()\nasync with connection:\n    service = await connection.service(_SERVICE_UUID) # A Nordic UART Service.\n    tx_characteristic = await service.characteristic(_TX_CHARACTERISTIC_UUID)\n    rx_characteristic = await service.characteristic(_RX_CHARACTERISTIC_UUID)\n    tx_characteristic._notify_queue = deque((), 7) # Change the size of the queue.\n    await self.tx_characteristic.subscribe(notify=True)\n\n    while True:\n         await request_transport(rx_characteristic) # Send command to request transport.\n         data = await tx_characteristic.notified()\n         await asyncio.sleep(1) # Wait until the queue is filled.\n         buffer.extend(data)\n         while len(queue := tx_characteristic._notify_queue) \u003e= 1:\n             buffer.extend(queue.popleft())\n         tx_characteristic._notify_event.clear() # Make sure to clear the flag.\n\n         # Do something with the buffer.\n```\n\nThe workaround is useful in this case because the server (peripheral) always waits for the response of the \nchunk of data from the client (micropython/aioble) before going to the next, and this waiting time can be used \nby the client to process (e.g. concatinate) the data in the queue.\n\n\nA pair of test codes, `nus_modem_client.py` and `nus_modem_server.py`, were prepared as the complete \nset of working example.  In this case, a primitive YMODEM file transfer protocol was implemented on \n[Nordic UART service's](https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/libraries/bluetooth_services/services/nus.html) \nTX/RX channels.  Athough there are limitations as described below, it works well as expected and has been \nalready applied to [one of my projects](https://github.com/ekspla/xoss_sync).\n\nThe throughput measured was 27.7 kbps using 7.5 ms connection interval and tick rate of 1 ms (CONFIG_FREERTOS_HZ=1000) \nwith ESP32-S3-WROOM-1-N16R8 and micro-SD card, while the theoretical limit assuming 3 connection events/128-byte data block \nis 45.5 kbps.\n\nThe limitations are due mainly to the implementation of YMODEM in part as follows:\n- The script expects a transport with MTU of 23, 128-byte data per block, and CRC16/ARC (not CRC16/XMODEM).\nLarger MTU by DLE (Data Length Extension) and 1024-byte data in YMODEM (STX), that make throughput higher, are not \nsupported (not implemented yet).\n\nUpdate MAR 2025: \n[A full-featured version of the pair was also prepared](https://github.com/ekspla/micropython_aioble_examples/blob/main/nus_modem_full_ver/) \nto test the higher throughput.  Using conn_intervals = 7.5 ms, STX (1024-byte block) and fragmentation of MTU = 209 via L2CAP \n94.3 kbps was obtained.\nBy using the client code for CPython/Bleak (`nus_modem_full_ver/bleak_nus_modem_client.py`) on Win11/Intel Wireless with MTU=512, \n125.7, 55.5 and 18.7 kbps were obtained for *ThroughputOptimized*, *Balanced* and *PowerOptimized* WinRT parameters, respectively.\nFurther increase in throughput would require `LE Data Packet Length Extension` and `LE 2M PHY`.\n  \n## ESP32 chip as a USB bluetooth dongle (HCI H4) for use with unix-port (Linux) of micropython and aioble\n\nA cheap USB bluetooth dongle was easily built by using an ESP32, a USB-UART chip ([CH340E](https://www.wch.cn/search?t=all\u0026q=CH340E)) \nand a 600-mA LDO ([RT9080](https://www.richtek.com/Products/Linear%20Regulator/Single%20Output%20Linear%20Regulator/RT9080?sc_lang=en)). \nAs shown in the figures below, I tried to reduce the lengths of the cables as short as possible to obtain the \nhighest reliable speed.  USB-UART/LDO built on frontside and ESP32 mounted on backside were sticked together to form the \nhome-made USB dongle. \n![PHOTO_FRONTSIDE_CH340_LDO](https://github.com/ekspla/micropython_aioble_examples/blob/main/figs/Frontside_CH340_LDO.jpg \"Frontside\")\n![PHOTO_BACKSIDE_ESP32](https://github.com/ekspla/micropython_aioble_examples/blob/main/figs/Backside_ESP32.jpg \"Backside\")\n\nThe firmware on the ESP32, which was written through the pin sockets shown in the photo above, was built on `controller_hci_uart_esp32`, \n[an example of Espressif's ESP-IDF](https://github.com/espressif/esp-idf/tree/master/examples/bluetooth/hci), with the following parameters.\n\nUART baudrate = 1 Mbps; \nhardware flow control; \nFreeRTOS tick rate = 1 ms; \nCPU frequency = 240 MHz; \nGPIO pins 5, 18, 23, 19 are used as TxD, RxD, CTS, RTS, respectively.\n\nI had to modify the codes as followings to set the parameters as above.\n\nModify `ESP-IDF/components/bt/controller/esp32/Kconfig.in`:\n\n``` Diff\n    config BTDM_CTRL_HCI_UART_BAUDRATE\n        int \"UART Baudrate for HCI\"\n        depends on BTDM_CTRL_HCI_MODE_UART_H4\n-       range 115200 921600\n-       default 921600\n+       range 115200 3000000\n+       default 1000000\n        help\n```\nModify `sdkconfig.defaults`:\n\n```\nCONFIG_BT_BLUEDROID_ENABLED=n\nCONFIG_BT_CONTROLLER_ONLY=y\nCONFIG_BTDM_CTRL_HCI_MODE_UART_H4=y\nCONFIG_BTDM_CTRL_HCI_UART_NO=1\nCONFIG_BTDM_CTRL_HCI_UART_BAUDRATE=1000000\nCONFIG_BTDM_CTRL_MODEM_SLEEP=n\n\n# Other config\nCONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y\nCONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=240\nCONFIG_FREERTOS_HZ=1000\n```\nRun `idf.py menuconfig`, then `idf.py build`.\n\nTo use the other baudrate, you have to modify it also in `MPY/ports/unix/mpbthciport.c`, which defaults to 1 Mbps. \nBecause I could not obtain reliable connections at 1.5, 2 and 3 M bps, the baudrate was set to 1 Mbps in my case.\n\n[The MPY on Linux machine using NimBLE stack was built](https://github.com/orgs/micropython/discussions/10234) as \nfollows: \n\n``` Shell\nmake -C ports/unix MICROPY_PY_BLUETOOTH=1 MICROPY_BLUETOOTH_NIMBLE=1\n```\n\nBecause the built-in USB-UART kernel module did not work reliably at a very high speed, I had to compile the module \nusing the latest source code (V1.8 on 2024.08) of the manufacturer (WCH) obtained from \n[their website](http://www.wch.cn/download/CH341SER_LINUX_ZIP.html) \nor from [their github repository](https://github.com/WCHSoftGroup/ch341ser_linux). Default latency of the UART using \nthis module was minimized by an `ASYNC_LOW_LATENCY` flag in the source code. \nBefore start using it, set an appropriate permission of the USB-UART device you are using (e.g. `chmod 666` or `adduser` \nto the `dialout` group).\n\nYou have to specify the USB-UART device if it is not `/dev/ttyUSB0` as written in `MPY/ports/unix/mpbthciport.c`.\n\nIn my case `MICROPYBTUART=/dev/ttyCH341USB0`:\n\n``` Python\nMICROPYBTUART=/dev/ttyCH341USB0 micropython\nMicroPython v1.23.0 on 2024-11-18; linux [GCC 11.5.0] version\nUse Ctrl-D to exit, Ctrl-E for paste mode\n\u003e\u003e\u003e from bluetooth import BLE\n\u003e\u003e\u003e BLE().active(1)\nTrue\n\u003e\u003e\u003e import aioble\n\u003e\u003e\u003e \n```\n\nThis dongle/unix-port MPY combination was successfully used with my aioble test code, \n[nus_modem_client.py](https://github.com/ekspla/micropython_aioble_examples/blob/main/nus_modem_client.py), \nin this repository.\n\nAdditional notes:  \n - You can also use this USB dongle from the other softwares such as [BlueZ](https://github.com/bluez/bluez), \n[BTstack](https://github.com/bluekitchen/btstack) and \n[Google Bumble](https://github.com/google/bumble) because the APIs of HCI H4 are common.  \n\n - It may be wise for Windows users to stick on to the old WCH's driver version (V3.5 on 2019), while the latest one works great on Linux as shown above. \n[As reported in this forum](https://answers.microsoft.com/en-us/windows/forum/all/usb-serial-ch340-chipset-not-working-after-windows/88b0ab19-9e1b-46bb-82d4-f806e34b2ed9),\na few percent of my devices stops working with updated V3.9 driver on Windows.  I am not quite sure if the non-working chips are of counterfeit though.\n\n - A note for users of MicroPython on Windows port:  \n\nThere is [a long standing PR from a core developer](https://github.com/micropython/micropython/pull/7781) \nto implement NimBLE on Windows port of MicroPython.  \n\nOne of the most big issue to use this PR *in my case* was latencies in USB serial devices. \nThe default latency of 16 ms/packet and a large USB buffer size made serial communications (HCI H4) \nunreliable. In worst-case scenario with a 4096-byte USB buffer (64 packet * 64 bytes/packet), \nthis latency resuts in 64 packet * 16 ms = 1024 ms delay, which is not tolerable.  \n\nThe best workaround would be to use a legacy COM port (such as 16550A), which is not available \nin most of the PCs these days. Another workaround is to decrease the USB latency timer and/or the \nbuffer size of the device from properties in the device manager, which is not available for all \nof the devices. FTDI drivers, for example, have these settings though. Changing the buffer size \nby SetupComm() almost always does not work for the USB serial devices.  \n\nSo an easy and versatile workaround for me was to force the device to flush the buffer when desired, \nbut FlushFileBuffers() did not work for the USB. An application note \n[\\(AN232B-04, FTDI\\)](https://www.ftdichip.com/Documents/AppNotes/AN232B-04_DataLatencyFlow.pdf) \ndescribes that an unused modem status line (DSR in this case) can be used for this purpose; the \nbuffer is flushed when the state of DTR tied to DSR is changed. This seems to work almost all \nof the USB serial devices that I have. In prior to ReadFile(), check if there is a character to \nbe read in the queue with ClearCommError() and COMSTAT.cbInQueue. If not, change the state of DTR, \nwait some time (say, 1 ms) and check the queue once again. Avoid using Sleep(1) here because of \nsystem timer precision of ca. 16 ms.  \n\nHowever, changing the state of DTR (and also RTS) by an API of EscapeCommFunction() does not \nnecessarily work.  Note that the `usbser.sys` of Microsoft which is used by most of the USB CDC \ndevices of today does not work, while some proprietary drivers such as FTDI's ones do.  \n\nSo a workaround here is using a sequence of GetCommState(), SetCommState() and EscapeCommFunction() \nto change the DTR state which is shown in [newlib-cygwin](https://sourceware.org/pipermail/cygwin-cvs/2022q4/015643.html) \nand also in \n[a Microsoft's code](https://github.com/microsoft/referencesource/blob/main/System/sys/system/IO/ports/SerialStream.cs).  \n\nThere is also a good instruction for how to set COMMTIMEOUTS with USB serial devices as a comment in \nthe Microsoft's code shown above; ReadIntervalTimeout, ReadTotalTimeoutMultiplier and \nWriteTotalTimeoutMultiplier do not make sense in USB serial devices where characters are transferred \nin a packet.  \n\n - Round-trip times on Windows 10.  \n\nTXD-RXD 1-byte loop-back test as the scheme shown above at 1 Mbps, except for \nthe real COM1 port at 115.2 kbps. All of the USB devices were connected via an \nexternal USB hub. These values in milliseconds might be affected by the 1-ms \nwaiting time in checking the queue more than once.  \n\n| Chip    | Driver     | USB latency timer | DTR-DSR      | Min   | Max   | Avg   |\n| ------- | ---------- | ----------------- | ------------ | ----- | ----- | ----- |\n| FT232RL | 2.12.28.0  | 16                | connected    | 2.66  | 5.22  | 2.87  |\n| FT232RL | 2.12.28.0  | 16                | disconnected | 3.37  | 21.31 | 12.40 |\n| FT232RL | 2.12.28.0  | 1                 | connected    | 2.68  | 5.33  | 2.83  |\n| FT232RL | 2.12.28.0  | 1                 | disconnected | 2.65  | 5.80  | 2.80  |\n| CP2102  | 11.3.0.176 | 1                 | connected    | 7.96  | 13.01 | 10.00 |\n| CP2102  | 11.3.0.176 | 1                 | disconnected | 7.99  | 13.81 | 10.21 |\n| CP2102  | 11.4.0.393 | 1                 | connected    | 7.96  | 13.73 | 10.21 |\n| CP2102  | 11.4.0.393 | 1                 | disconnected | 7.96  | 20.89 | 9.49  |\n| CH9102F | 1.5.2021.8 | 0.5               | connected    | 2.24  | 4.98  | 2.43  |\n| CH9102F | 1.5.2021.8 | 0.5               | disconnected | 2.24  | 5.59  | 2.38  |\n| CH9102F | 2.0.2025.3 | 0.5               | connected    | 2.24  | 3.44  | 2.33  |\n| CH9102F | 2.0.2025.3 | 0.5               | disconnected | 2.25  | 5.55  | 2.45  |\n| CH340C  | 3.5.2019.1 | 1.5               | connected    | 1.98  | 2.98  | 2.44  |\n| CH340C  | 3.5.2019.1 | 1.5               | disconnected | 1.87  | 5.13  | 2.49  |\n| CH340C  | 3.9.2024.9 | 1.5               | connected    | 2.24  | 5.29  | 2.65  |\n| CH340C  | 3.9.2024.9 | 1.5               | disconnected | 2.08  | 5.26  | 2.59  |\n| COM1    |            | NA                | disconnected | 2.08  | 3.20  | 2.14  |\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fekspla%2Fmicropython_aioble_examples","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fekspla%2Fmicropython_aioble_examples","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fekspla%2Fmicropython_aioble_examples/lists"}