PyCosmicSDK
Summary
Section titled “Summary”pycosmicsdk is the Python SDK for the Binho Supernova and Binho Pulsar host adapters and the Binho Atira debug probe. One package covers all three and every protocol they offer. The host adapters use a blocking API (Device) and an asyncio API (AsyncDevice); the Atira uses DebugProbe and AsyncDebugProbe.
It replaces the older per-product packages (BinhoSupernova, SupernovaController and BinhoPulsar) and ships drop-in compatibility layers for them, so existing scripts keep working during the move. See Migrating to PyCosmicSDK.
| Protocol | What it can do | Supernova | Pulsar | Atira |
|---|---|---|---|---|
| I2C | Controller (write, read, bus scan) and target mode | Bus A | Buses A and B | No |
| I3C | Controller, Common Command Codes (CCCs), target mode | Yes | No | No |
| SPI | Controller and target mode | Controller; target mode not on rev B | Yes | Controller, with SPI flash programming |
| UART | Send, query and receive | Yes | Yes | Bridge port |
| GPIO | Digital I/O and interrupts | Yes | Yes | No |
The Atira is a debug probe. Besides SPI and the UART bridge, DebugProbe covers target power and SWD debug. It needs PyCosmicSDK 1.7.0 or newer. See Binho Atira and the debug probe guide.
Large transfers travel over a second USB pipe instead of the ordinary 1024-byte limit: up to 32,768 bytes on a Supernova (32,767 for I3C) and 16,384 bytes on a Pulsar. The SDK asks the adapter for its limit, so the limit never needs hard-coding. See Large transfers.
Prerequisites
Section titled “Prerequisites”- Python 3.10 to 3.14.
- One of: Windows (x64), macOS on Apple Silicon, or Linux (x86_64). Other platforms, such as Intel Macs and Linux on ARM, have no package yet.
- A Binho Supernova or Pulsar running firmware 4.x, or a Binho Atira running Atira firmware 1.0 or newer. Firmware 3.x cannot be reached by this package; see Updating Firmware.
- On Linux, allow the current user to access the adapter once: Solving USB Connection Issues on Linux. Windows and macOS need no driver install.
Installation
Section titled “Installation”pip install pycosmicsdkThe package includes everything it needs, the native USB library included, so there is nothing else to install.
https://pypi.org/project/pycosmicsdk/
Check the Adapter First
Section titled “Check the Adapter First”list_devices() reads each connected adapter’s model, serial number and firmware version straight from USB, without opening it:
from pycosmicsdk import list_devices
for found in list_devices(): print(found.model.name, found.serial_number, "firmware", found.fw_version)- A version like
4.6.1is ready to use. 3.x.xmeans firmware 3.x: update the firmware before using this package.bootloadermeans the adapter is waiting in its bootloader instead of running firmware.
Opening an adapter whose firmware is too old raises an SDK error that says so, instead of timing out.
Getting Started
Section titled “Getting Started”This example opens the first adapter it finds, brings up I2C bus A at 400 kHz, scans the bus, and writes and reads back three bytes of an I2C EEPROM at address 0x50:
import time
from pycosmicsdk import Device, I2cBus, I2cPullUp, list_devices
# List every connected adapter. This only reads USB information; it opens nothing.for found in list_devices(): print(found.model.name, found.serial_number, "firmware", found.fw_version)
# Open the first adapter found (or pass serial="..." to pick one).with Device.open() as dev: i2c = dev.i2c(bus=I2cBus.A) i2c.set_voltage(voltage_mv=3300) # target voltage first i2c.bring_up(frequency_hz=400_000, pull_up=I2cPullUp.KOHM_2_2)
print("Devices on the bus:", [hex(a) for a in i2c.scan().addresses_7bit])
i2c.write(0x50, b"\x01\x02\x03", subaddress=b"\x00\x10") # 3 bytes at 0x0010 time.sleep(0.01) # an EEPROM ignores its address while it finishes the write print("Read back:", i2c.read(0x50, 3, subaddress=b"\x00\x10").hex())Device.open()also acceptsserial="...",model=...orpath="..."when more than one adapter is connected.bring_up()can be run again safely: if the bus is already up, it applies the new settings instead of failing.- The other protocols follow the same pattern:
dev.i3c(),dev.spi(),dev.uart(),dev.gpio(), anddev.i2c_target(),dev.spi_target()anddev.i3c_target()for target mode.
Using asyncio
Section titled “Using asyncio”Every class has an asyncio twin with the same methods. Use AsyncDevice in place of Device and await each call:
import asyncio
from pycosmicsdk import AsyncDevice, I2cBus, I2cPullUp
async def main() -> None: async with AsyncDevice.open() as dev: i2c = dev.i2c(bus=I2cBus.A) await i2c.set_voltage(voltage_mv=3300) await i2c.bring_up(frequency_hz=400_000, pull_up=I2cPullUp.KOHM_2_2) print([hex(a) for a in (await i2c.scan()).addresses_7bit])
asyncio.run(main())When Something Fails
Section titled “When Something Fails”Every error the SDK raises derives from CosmicError and carries the status_code the adapter or the SDK reported. Catch the subclass that can be acted on:
| Error | Meaning |
|---|---|
ValidationError | The call was rejected before anything was sent to the adapter. |
CapabilityError | This adapter model or hardware revision cannot do it. Nothing was sent. |
FirmwareError (I2cError, I3cError, SpiError, …) | The adapter refused the command. exc.status_code says why, for example FW_I2C_NACK_ADDRESS. |
CosmicTimeoutError | No answer in time. Also caught by except TimeoutError. |
The errors reference lists every error and status code.
Examples
Section titled “Examples”The SDK comes with more than 50 runnable example scripts, one folder per protocol, for both the blocking and the asyncio API. PyCosmicSDK Examples has the download link, how to run them, and copy-paste snippets for I2C, SPI, I3C, UART and GPIO.
Documentation
Section titled “Documentation”The full documentation is at binhollc.github.io/pycosmicsdk. Start with the guide for the protocol:
| Guide | Covers |
|---|---|
| I2C | Bring-up, pull-ups, duty cycle, write, read, scan |
| I3C | Bus voltage and ports, dynamic addressing, SDR and HDR-DDR transfers, CCCs, legacy I2C on the I3C port |
| SPI | Modes, chip selects, full-duplex and half-duplex transfers |
| UART | Baud rates, request/response, streaming reception |
| GPIO | Digital I/O and interrupts |
| Large transfers | The bulk USB pipe and its size limits |
| Target mode | The adapter as an I2C, SPI or I3C target |
| Device lifecycle | Discovery, opening by serial or model, closing, rebooting |
| Testing | Testing code without an adapter, using pycosmicsdk.testing |
Also in the documentation:
- Getting started: install, platform setup, first device.
- Blocking and asyncio: where
DeviceandAsyncDevicediffer. - Migrating from the legacy packages: every difference per package.
- Errors and the API reference: every class, method, enum and status code.
- Support: what to include in a problem report.
Target Voltage
Section titled “Target Voltage”With firmware 4.7.0 or later (coming soon), set_voltage() on a port that already has an external supply leaves the adapter’s supply off and raises an error with status FW_EXTERNAL_VOLTAGE_DETECTED (0x0102).
Getting Help
Section titled “Getting Help”If something does not work as described here, contact us or email [email protected]. Include:
- the version printed by
python -c "import pycosmicsdk; print(pycosmicsdk.__version__)", - the Python version and operating system,
- the output of the
list_devices()example above (model, serial number, firmware), - the full traceback, or the
status_codeof the error raised.

