I just wanted to remind the OP of this post:
ANSI E1.20 has a nice way of dealing with this, allowing a controller to discover the unique fixed 48-bit unique ID of every device on a bus relatively quickly via binary search. That unique ID can then be used to direct subsequent messages, and/or to assign an address.
- Controller broadcasts a discovery message asking every device with an address >= X and <= Y to send a response. Responding devices send a message containing an encoded form of their unique ID and a checksum.
- No response means no devices in that range and the controller will try the next range.
- A correct response means there is exactly one device in that range, and the controller now knows its ID. So the controller can add that device to its internal list, and send a message to "mute" the device, so that it will not respond to further discovery messages.
- A garbled response means there is more than one device in the range (because their responses collided), so the controller will bisect the range and try again.
By the end of the process, the controller has a list of the unique IDs of all devices present. The controller can periodically send discovery messages covering the entire address range to see if any new devices have joined the bus--because all of the previously discovered devices should be muted, only undiscovered devices or devices that have been power cycled or otherwise reset will respond.
This is a really nice way to discover random-but-unique addresses as you might get if you used the unique chip ID. Once the devices are all discovered you can assign them a shorter "alias" address if you like.
And going to a single-wire open-collector TX+RX bus makes it easier to detect collisions and implement something like the old ethernet exponential backoff method.