Plug & play components connected to Spark Core

@peekay123 @harrisonhjones Thanks for all of your help so far guys. I still can’t get any output here.

Does it matter whether the ATtiny is running a 1 or 8 MHz? I’ve tried a couple of ATtinys, both on and off my AVR Programmer, and get the same results.

If I try and print something out at the start of the loop, e.g. “test”, it prints out “t”…followed by a second or so delay…and then “test”.

@tw_uk, the minimum clock for TinyWireS to run is 8MHz. I am running a 20MHz ATtiny but programming it as a 16MHz on the IDE. I used v1.58Beta of the IDE with ATtiny extensions cause it doesn’t have ATtiny boards by default.

@peekay123 Have this working now! I found the I2C bus doesn’t work when using the prototyping pins on the Sparkfun programmer – it interferes in some way. I now have two ATtinys on the breadboard and it’s working fine.

When any number of I2C devices can be connected, would you usually just scan the bus first as a master, and then join as a slave at the next available address?

2 Likes

@tw_uk, good question! If all the I2C devices power up as masters and scan the bus, they will collide. I2C does not support dynamic addressing and this “auto addressing” problem is common. I am doing research and it seems there is not simple solution besides hard-coding an address in each slave device.

@peekay123 How about if the Core acts as both a master and a slave with a fixed address. When a new I2C device is connected, it asks for a new address (as another master) from this fixed Core address. The Core then hands out incrementing addresses. When each device receives its address, it switches to being just a slave?

The Core would never hand out the same address twice, avoiding that problem.

The issue with this is it assumes that devices are added one at a time. Imagine connecting 5 new devices then turning on the power. All the I2C "slaves" will try to become masters in order to fetch a new address, leading to bus collisions and basically not working.

Possibly another approach is to do the following:

  1. All I2C nodes start with address 0x77 for example
  2. Each node is added to the master ONE AT A TIME
  3. The master is put into a scan/assign mode where it will look for any 0x77 device and if found, sends a new address
  4. The node stores this address in EEPROM and uses it from then on.
  5. The master assigns addresses sequentially based on a value stored in EEPROM so it always assigns the next address even when rebooted.

Pain in the butt but you get the idea. It could be made more sophisticated if the master first gets a unique ID from the slave and then assigns an address based on the node type for example. You get the idea. :smile:

I just got my Attiny45 running so I wanted to re-join the conversation.

I have a solution for daisy chained devices but not for devices all connected to the root micro at the same time:
What if we added two extra line/pins to the mix. Pin A would connect to one of the ATTINY’s analog read pins and it would be connected to another empty pin B through a given resistor value. Any slave device could determine where it was in the chain by measuring the voltage on pin A. The next device’s pin A would be connected to the previous device’s pin B. Would require some solder jumpers to complete the circuit @ the end of the chain so I guess it wouldn’t be ideal. Hmm. Let me think on it

@harrisonhjones, the ATtiny85 is already short on pins so taking on up is a big loss and the daisy chaining does impose some physical (wiring) constraints. It’s too bad the I2C protocol was never designed for auto-address allocation.

what about a button that sets that one devices/component address to a known address just so it can set a paired address.
For the user it could be something like push the button on the device, then push the button on the core and hey presto its paired.
when the pair button is pushed change to 0x01. when the core button is pressed send a command that sets 0x01 to 0xFF. from then on that device is 0xFF. if you want to change the address just push the pair button that sets it back to 0x01.

Yea, that would work. Still awefully manual tho. Stupid I2C :smile: protocol!

What about just letting there be collision? What if each device, without a assigned address, simply waited a random number of miliseconds before trying to contact the master? If successful then the master assigns a free address, if not, then it just waits another random number of seconds. You could pre-seed different devices with different random seeds and then use noise on an analog pin to increase the entropy.

Hi all. The Ic2 protocol is originally designed for communication between chips on one board. The chips developed for I2c are mainly io extenders adc dac and diplays. The distances that can be bridged by I2c are short. Typical 3 meters.
All off these chips have semi fixed addresses with one or two bits variable.
I made a plug and play system based on these facts. I used an eight bit io port chip on each board for identification. The chips have 3 address bits. And there are 2 versions available (pcf8579). This gives you 16 possible boards per system with 8 io bits per board. 4 of them where used as board type id.
my arduino scanned the bus. Read the nibble and knew the board type. Ready. 16 different board types where available on 16 different boards. Enough for most projects. And keeping the bus drive capabilities in the safe zone of 32 (?). This solutions is solid cheap and simple. For intelligent boards add your processor next to the id chip. Give it a known fixed address that is identified by the previousely mentioned system.
I would like to suggest to check the I2c addresses used by excisting chips at nxp
and find a range of free addresses for your project. Use these to create a new standard.

@harrisonhjones Random timing in setup went though my mind too. I need to look into how the TinyWireS/TinyWireM libraries deal with collisions. Hopefully they fail elegantly…does anyone know?

@tw_uk, the problem with random is that it is not always random. I don’t believe the Arduino or Core support collision detection. Collisions won’t cause any problems due to the open-gate operation of I2C. However, the questions is what do the I2C libraries do when data collides (timeout, stay stuck?).

The I2C spec includes bus arbitration and the STM32F103 supports that. The bus is indicated free for a master by both SDA and SCL being high at the start of a transaction and remaining high for what would be one clock cycle at 100/400 kHz. If that is not the case, Arbitration Lost Error is set, and if enabled an interrupt is generated. TR RM0008 has details. I doubt the Spark or Arduino I2C implementations handle this condition gracefully, but if you wrote your own driver, this feature might solve your problem of coping with multiple masters at startup.

2 Likes

Hey @pra, interesting info. Could you perhaps provide a bit more info or a page number in the STM datasheet for reference?

Section 25.3.4 Error Conditions (Page 714/715) of the STM32 Reference Manual (RM008) defines the error. The NXP (nee Phillips) I2C Specification UM10204 section 3.1.8 Arbitration discusses in some detail how multiple bus masters are supported and I2C bus arbitration takes place.

Hope this is helpful.

2 Likes

It seems like the Arduino Wire library deals with this fine. It automatically switches to being a master when sending data to a specific address, and appears to support multi-master. The ATtinys don’t though:

http://www.robotroom.com/Atmel-AVR-TWI-I2C-Multi-Master-Problem.html

Adapting the TinyWire libraries might be the way forward? I also found that SMBus, based on I2C, has dynamic address resolution. For that to work on the Arduino, we’d have to solve these same multi-master problems though.

@modulo Can you help on any of this?

Hi @tw_uk! Sorry I didn’t see your message until now. For some reason community.particle.io notifications keep getting filtered into my junk folder, which they certainly are not! Just noticed it when I happened to log into the site for other reasons.

Anyway, you might be interested in taking a look at the Modulo protocol spec and arduino library:

http://www.modulo.co/technical-specs

It’s intended for exactly this sort of thing. I haven’t yet published the attiny firmware, but I would be happy to go ahead and do that if you’re interested in it. I was just waiting until I have a chance to clean it up a bit.

A few key points:

  1. Based on I2C
  2. Handles dynamic device discovery and address asssignment (using collision/arbitration)
  3. Has some fixes for deadlocks in the arduino avr Wire implementation that can occur on bus errors (need to clean up and submit back to Arduino for inclusion)
  4. Has nice a nice well defined way to represent a device as an object on the client side

I am working on some changes to the protocol. The biggest changes are that I may use multi-master instead of arbitration for device discovery, and I’m making the protocol asynchronous to better support physical connections other than I2C.

Let me know if you have any questions. I hope it’s helpful.
Erin

3 Likes

Looks really interesting – thanks. I’ll have a proper read and let you know if I have any questions!