Skip to content
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

Multiple digispark USB #14

Open
PizzaProgram opened this issue Mar 8, 2020 · 12 comments
Open

Multiple digispark USB #14

PizzaProgram opened this issue Mar 8, 2020 · 12 comments

Comments

@PizzaProgram
Copy link

How do I change the I2C bus address of a ATTiny85 Digispark dongle, if I would like to use multiple of them on the same Raspberry Pi4? (Or with a USB HUB.)

I guess I have to re-compile the firmware it again for each one?
Checked both digital.h & main.c files, but did not find any "I2C_BASE_BUS_ADDRESS" or anything similar.

Raspberry Pi4 has 4 I2C buses by default, so this should start from 8+

... or ...
if the BUS address is given by Debian OS, how /where should I change the name or unique identifier of the flashed device so I can distinguish one from the others?

Sorry if my question is wrong, I'm a newbee to this. Trying to drive more than 64 IO pins:
https://community.openhab.org/t/compatible-usb-i2c-adapter-for-rpi4/93690/6

@harbaum
Copy link
Owner

harbaum commented Mar 8, 2020

It's not the hardware nor the driver that does the bus enumeration but imho the i2c subsystem of the Linux kernel. And yes, you can simply plug multiple devices into your PC and they'll get individual busses assigned.

@PizzaProgram
Copy link
Author

PizzaProgram commented Mar 8, 2020

OK, that's good news 👍
But How do I rename those similar named USBs, so I can distinguish one from the other?

If each one is named the same, I won't know if that I2C bus is the one with inputs or the outputs... :-(
... and if I configure the IO panels wrong ...

@PizzaProgram
Copy link
Author

This problem is more sever than I've thought.

I've just tested to plug in 2 keys, than unplugged and switched:
(I've attacked multiple boards to the first, none to the other)

[23:11:05] openhabian@openhab:~$ sudo i2cdetect -y 7
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- 21 22 23 -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- 51 -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

Depending which device I've plugged first and what USB order, the BUS# got reordered.
It can cause big problems, if board were previously configured for inputs but suddenly start get output signals. (Planning to plug in similar board to each one.)

[23:15:30] openhabian@openhab:~$ sudo i2cdetect -l
i2c-1   i2c             bcm2835 I2C adapter                     I2C adapter
i2c-8   i2c             i2c-tiny-usb at bus 001 device 006      I2C adapter
i2c-7   i2c             i2c-tiny-usb at bus 001 device 004      I2C adapter
[23:15:59] openhabian@openhab:~$ sudo i2cdetect -l
[sudo] password for openhabian:
i2c-1   i2c             bcm2835 I2C adapter                     I2C adapter
i2c-8   i2c             i2c-tiny-usb at bus 001 device 010      I2C adapter
i2c-7   i2c             i2c-tiny-usb at bus 001 device 008      I2C adapter
[19:45:40] openhabian@openhab:~$ sudo i2cdetect -y 7
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

@PizzaProgram
Copy link
Author

Found this, but don't know how to implement it.
Also opened a Topic at RPi forum, but no answers yet.

@harbaum
Copy link
Owner

harbaum commented Mar 12, 2020

Other possible solution: Add an i2c eeprom to each bus with some unique ID. Then read the IDs from eeprom to know which bus you are talking to.

@PizzaProgram
Copy link
Author

PizzaProgram commented Mar 12, 2020

I still believe it is easier to modify the name of each firmware.
Found these 2 lines at usbconfig.h :

#define	USB_CFG_DEVICE_NAME	'i','2','c','-','t','i','n','y','-','u','s','b'
#define	USB_CFG_DEVICE_NAME_LEN 12

So, if I find out how to recompile 10x with alternate numbered names, like:

#define	USB_CFG_DEVICE_NAME	'i','2','c','-','t','i','n','y','-','u','s','b','-','5','1'
#define	USB_CFG_DEVICE_NAME_LEN 15

main51.hex
main52.hex
... etc... than I can maybe put an overlay to boot loader of RPi. (config.txt) to define a fixed I2C BUS address attached 1-1 to each name.

My fear is:

  • What if the diver won't recognise it, because of the name-change?

@harbaum
Copy link
Owner

harbaum commented Mar 12, 2020

The driver recognizes the device by USB IDs. Changing the name should not hurt.

@drawkula
Copy link

Maybe setting

/*#define USB_CFG_SERIAL_NUMBER   'N', 'o', 'n', 'e' */                                               
/*#define USB_CFG_SERIAL_NUMBER_LEN   0 */                                                            

and trying to detect this in an own UDEV rule is safer.

I don't know what UDEV can do with I2C devices, but for others it e.g. can make symlinks with names you want.

See: http://hintshop.ludvig.co.nz/show/persistent-names-usb-serial-devices

@zgyarmati
Copy link
Contributor

Indeed, using udev is the canonical way to solve this kind of issues under Linux.
If you run udevadm monitor (as root), while plugging in/unplugging the device, you will see the corresponding udev events, for instance on my laptop:

KERNEL[860.626226] add /devices/pci0000:00/0000:00:14.0/usb3/3-2 (usb)
KERNEL[860.626618] add /devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0 (usb)
KERNEL[860.627646] add /devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0/i2c-21/i2c-dev/i2c-21 (i2c-dev)
KERNEL[860.628248] add /devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0/i2c-21 (i2c)
KERNEL[860.628390] bind /devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0 (usb)
KERNEL[860.628478] bind /devices/pci0000:00/0000:00:14.0/usb3/3-2 (usb)
UDEV [860.655529] add /devices/pci0000:00/0000:00:14.0/usb3/3-2 (usb)
UDEV [860.657505] add /devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0 (usb)
UDEV [860.659043] add /devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0/i2c-21/i2c-dev/i2c-21 (i2c-dev)
UDEV [860.659981] add /devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0/i2c-21 (i2c)
UDEV [860.661190] bind /devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0 (usb)
UDEV [860.662590] bind /devices/pci0000:00/0000:00:14.0/usb3/3-2 (usb)

------>8------>8------>8------>8------>8------>8--- UNPLUG--->8------>8------>8------>8------>8------->8

KERNEL[862.914521] remove /devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0/i2c-21/i2c-dev/i2c-21 (i2c-dev)
KERNEL[862.914563] remove /devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0/i2c-21 (i2c)
KERNEL[862.914591] unbind /devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0 (usb)
KERNEL[862.914629] remove /devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0 (usb)
KERNEL[862.914692] unbind /devices/pci0000:00/0000:00:14.0/usb3/3-2 (usb)
KERNEL[862.914728] remove /devices/pci0000:00/0000:00:14.0/usb3/3-2 (usb)
UDEV [862.916721] remove /devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0/i2c-21/i2c-dev/i2c-21 (i2c-dev)
UDEV [862.917911] remove /devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0/i2c-21 (i2c)
UDEV [862.919546] unbind /devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0 (usb)
UDEV [862.921160] remove /devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0 (usb)
UDEV [862.922226] unbind /devices/pci0000:00/0000:00:14.0/usb3/3-2 (usb)
UDEV [862.928742] remove /devices/pci0000:00/0000:00:14.0/usb3/3-2 (usb)

As you can see, also the USB port is identified, so if you plug the devices always to the same port, you can also identify them, and creating a symlink to the freshly created I2C device accordingly.

If the USB port is not predictable, than you can also run an external program from the udev rule to create the desired name for the device (ie. i2cdetect via a bash script to get the available i2c slave addresses on the plugged in i2c bus), and based on the available addresses, you can figure out which bus you are on. See http://www.reactivated.net/writing_udev_rules.html#external-naming.

@harbaum
Copy link
Owner

harbaum commented Apr 15, 2020

You can also distinguish the devices by their position in the physical USB device tree. This information can be gathered from the sysfs or indirectly using tools line usb-devices.

@PizzaProgram
Copy link
Author

PizzaProgram commented Apr 16, 2020

while plugging in/unplugging the device

That's not possible if working remotely. The device HAS TO HAVE a unique name so it can be identified. Like: i2c-tiny-usb-pushbuttons-inputs or i2c-tiny-usb-rollersh-outputs

You can also distinguish the devices by their position in the physical USB device tree

That's an other possibility that CAN happen in real life scenarios and needs to be prevented:

  • what if someone is switching the order? Or the USB HUB needs to be replaced? etc...

A unique identification is needed to set FIXed I2C Bus addresses, so no accidents may happen even if:

  • one of the devices gets unplugged and plugged in into an other USB slot or to a HUB
  • if the system reboots and order changes

A wrong identification of the bus number or device name can cause serious problems.
(After a power-outage the solar system overheats, or the roller shutter goes suddenly down to the kids head.. etc.)

@zgyarmati
Copy link
Contributor

zgyarmati commented Apr 16, 2020

while plugging in/unplugging the device

That's not possible if working remotely. The device HAS TO HAVE a unique name so it can be identified. Like: i2c-tiny-usb-pushbuttons-inputs or i2c-tiny-usb-rollersh-outputs

Ah, i meant that you can use the udevadm monitor during development, to figure out what events/filters to implement in your udev rule.

You can also distinguish the devices by their position in the physical USB device tree

That's an other possibility that CAN happen in real life scenarios and needs to be prevented:

* what if someone is switching the order? Or the USB HUB needs to be replaced? etc...

A unique identification is needed to set FIXed I2C Bus addresses, so no accidents may happen even if:

* one of the devices gets unplugged and plugged in into an other USB slot or to a HUB

* if the system reboots and order changes

A wrong identification of the bus number or device name can cause serious problems.
(After a power-outage the solar system overheats, or the roller shutter goes suddenly down to the kids head.. etc.)

Well, in this scenario either you have to physically make impossible to connect the devices to other USB plugs or/and indeed identify the bus somehow, for example by the available I2C addresses on the bus (if they are different), or as @harbaum suggested, by placing an i2c eeprom to each bus with some unique ID.
Of course it's also possible to flash different fw-s (with different name or PID) to your i2c-tiny-usb boards as suggested above, but in my experience it's can get messy if one site have multiple devices with almost the same fw (what if you have to replace because of malfunction or anything).
If you can share same details about your I2C busses (and about the differences between them on which it's possible to distinguish them, if any), i think we can lay out a more specific example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants