i2c with multiple devices and a display

Hi all!
Im worried i might be asking too much of i2c when i plan to use it for both pin extenders, dual arduino nano´s and a 128x64px oled display.

The hardware is as follows:
Pin extenders:
MCP23007 (x3)
MCP23018 (x1)

Arduino nano clone, (x2)

i2c 128x64 0.96" oled display:
http://www.ebay.com/itm/371773219529?_trksid=p2055119.m1438.l2649&ssPageName=STRK%3AMEBIDX%3AIT

The system is used as a light controller for a vehicle, to group a bunch of lights together and control them over i2c instead of installing cables for all the lights.

The pin extenders arent really traffic intense, but they do require somewhat "immediate" execution, a noticable lagg in input > output will not suffice.
A lagg undetectable by the human eye is "immediate+", i can live with minimal delays. :slight_smile:
The pin extenders are ether input/output (handlebar unit) or pure output (light controllers)

The Light controller arduino controls all pin extenders and inputs for the system,
while the graphics processing arduino will recieve system notifications and present them onScreen.
The GPU Arduino might eventually have screen nav buttons directly attached, but we´re not there yet..

Im hoping to achieve a master/slave combinated sketch, so that for the main time, the GPU arduino is slave, but when it wants to write to display, it switches to master (while the light Arduino switches to slave) and when finished, changes back to slave.

Now, the information to be presented onScreen is going to be current speed (hall sensor and spoke magnet, as a normal bike spedometer), some status indicators, a symbol for each function i want, like a blinking arrow in the turn indicator direction, a circle that lights up if the position lights are turned on and so on.

So there isnt really a need for a multi-Hz screen refresh rate, 1fps would actually be ok, even if 2-4fps would be ideal.

This means i will have to pass multiple variables between the two arduinos, and figure out a way to pass the bus master "badge" between the two.

So what would the smart option be, regarding the data transfer between the two arduinos?
Should i merge together all the data into a string, "12312345001000" and then split them up on recieving end into SPD, DIST, (lights in specific order, if 1, then on)?
That way i would reduce the number of transfers between the units, and since there is a wee bit overhead on the transfer, that would be most efficient?

I could of course use a single-container transfer, to send "light on" to the display when the lights gets turned on, and then send the numbers (and/or text notifications) in a string separately.

What would the pro´s suggest?

And the idea of master/slave switch token, is it feasible?
Does anybody know of any good links that describe this?

I also have no clue regarding the actual bus traffic i might experience, or how a display draw in the wrong moment could affect button reaction time before activating corresponding lights.

Ive been trying to solve this project with the bare essential cabling, not a lead of wire to much so to speak, so im really hoping to be able to use the i2c for the whole project,
but if all else fails, i think i will use a softserial connection between the both arduinos and use them both as their respective masters on their own i2c buses.

It wont be nearly as pretty, especially since that will mean that the handlebar unit (with buttons and status lights) will have to interface with the display i2c bus (the only accessible bus in that area), meaning some of the light controller code has to go into the graphics sketch..

My programming level is somewhere between skilled newbie to a ignorant amateur, so i know pretty much WHAT i want, but am desperately clueless on how to get there.
So any hints or suggestions in general or on specific parts of the project are more than welcome!

Im hoping to achieve a master/slave combinated sketch, so that for the main time, the GPU arduino is slave, but when it wants to write to display, it switches to master (while the light Arduino switches to slave) and when finished, changes back to slave.

Forget about that idea. Although it's theoretically possible to have multiple masters on an I2C bus it'll probably never run correctly.

Why do you want the inter-Arduino communication to happen over I2C? Use the serial interface for that and you have both Arduino being master on the I2C. If serial is not available, use SPI for the Arduino-Arduino link.

but if all else fails, i think i will use a softserial connection between the both arduinos

If timing is a critical factor, don't use SoftwareSerial. It blocks all interrupts during communication and doesn't allow for high baud rates (<9600 baud).

After all: please specify why you want to split the project over two Arduinos. It adds complexity and latency. From what you told yet it also seems unnecessary.

My current project (with all its bells and wistles) is using about 60% of the available resources, that code is about 75% completed.

The example sketch for the graphics library i aim to use is consuming more than 50% of the available ram, and i will be needing more for the content on the screen (menu´s ´n stuff).

And i havent even started on the speedometer function, and thats a bunch of large numbers and i might want datalogging to sd-card.

So even before trying to fit everything into a single arduino sketch, my guestimations suggest that i will run out of ram primarily, but also run into other types of hardware restrictions.

Thats why, i belive, a multicore approach would be better.
And why i2c interface? because its already there.
So my dream would be to have the display + gui-arduino as optional, plug them in anywhere on the bus and im good to go (at least with everything hardware-related).

In the future i will probably want to add more functions, mp3 player with amp+speakers, bluetooth (for cellphone interaction) and so on, witch leads me to belive that a token-system of swappable masters would be a neat trick to allow me to spread the code and complexity between multiple arduinos.

And as with the comment of using x instead of y; im trying to fit a display into a already started project, i cannot simply order a new set of PCB´s and components, and throw the current project away.

So to explain things better; i have 4x i2c-connected breakout boards, each operating thru a MCP230x pin extender and communicating with a central arduino nano.
So i have a single cable (with 4 cores) that covers all power and signal needs on the vehicle.
By adding another bus for arduino<->arduino comms, i will have to add a separate cable.

And so far ive spent about 200usd on tools, PCB´s, components and so on, just to get rid of the bunch of "redundant" cables on my previous setup (and add a few new features), witch means its all "for nothing" if i would be forced to install yet another cable after all.

The only available alternative would be to physically install the two arduinos next to each other, and to use the handlebar leg of the bus to connect to the display AND the handlebar buttons, therefore moving the button part of the light project into the graphics project.

By highjacking the handlebar cable, i would still only have a single cable running to the handlebar, hence; goal achieved, but it would be a ugly duckt-tape type solution.

I could see another solutions, by using dual i2c interfaces on the graphics arduino, and simply never connect the two separate buses, but that would force me to place the GPU arduino in close proximity to the display.

Also, i havent found a soft-i2c library that allows for full 100khz speed on 16mhz, so im not sure how my other components would like the lower bandwidth..

In the future i will probably want to add more functions, mp3 player with amp+speakers, bluetooth (for cellphone interaction) and so on, witch leads me to belive that a token-system of swappable masters would be a neat trick to allow me to spread the code and complexity between multiple arduinos.

I've never seen a successful project with two masters on one I2C bus and I never heard of any that uses more than two. If you want a bus that allows multiple masters to catch the bus and send and receive data, use a technology that is designed to do that, p.e. RS-485. I2C is made to have one master and multiple slaves. But even if you increase the number of slaves above a few you'll end in problems with bus capacitance and edges that get to flat. I2C is good to control some sensors in an easy and fast way but it's not an inter-MCU communication interface.

I guess you won't find any experience forum user that seriously suggest you to go with the solution you've drawn here.

If RAM is a problem you usually did the programming without the necessary adjustments. Especially things like menus use RAM if you don't explicitly store the strings in the flash memory. If RAM really exhausts buy one of the ARM based Arduinos and you get plenty of RAM and a much faster processor. But adding another Arduino to the bus and dealing with the collisions is more complex than you currently imagine, I guess.

pylon:
I've never seen a successful project with two masters on one I2C bus and I never heard of any that uses more than two. If you want a bus that allows multiple masters to catch the bus and send and receive data, use a technology that is designed to do that

en.wikipedia.org/wiki/I²C

Thats what i did, i chose a multimaster/multislave i2c bus.

Im not sure why everyone is afraid of multi-masters, but here´ a link that does make that work:
http://forum.arduino.cc/index.php?topic=13579.0

It only covers the basics tho, giving me some hints, but no answers..

According to some pages i found online (been searching and reading for hours), the atmega328 has dedicated hardware for serial, and specifically i2c comms, so there is a layer that takes care of the low-level stuff, and in combination with the wire library, would sort out packet collisions and so on, and packet losses i can deal with by repetition.

Regarding the bus capacitance problem, you can use internal pullup resistors on the arduino for a single or a few i2c slaves, after that, you must use external pull-ups. You size your pull-up resistors according to your circuits capacitance and power requirements, as described in the i2c bus documentation.
If your i2c bus is "more than a few" devices, and/or over long distances (or very high speeds), you might need other means of powering the lines.
Other solutions are mentioned in the i2c bus documentation, but my head is /dev/null at 1 AM..

Im not sure about any of this, and as i hinted earlier, im far from being a experienced programmer or electronics engineer, but thats why im here, eager to learn. :slight_smile:

So your input is much appreciated, but you might want to read up on i2c before you say that it is unsuitable. :slight_smile:

And yes, i know, bigger processor with more bells is always an option.. just found one "arduino nano-like" board with builtin wifi and bluetooth that would definitely float my boat with 4mb ram and 30mhz...
But thats not the "right" option right now, since i already have my stated project, but "just" want to add a display.
So im "stuck" with the hardware on hand, at least until next hardware revision, witch im hoping to avoid.. :slight_smile:

Hi,
This is in a CAR, right? Out of physical space?

Why not use a Mega with LOTS more of everything? See THIS

According to some pages i found online (been searching and reading for hours), the atmega328 has dedicated hardware for serial, and specifically i2c comms

Correct.

in combination with the wire library, would sort out packet collisions and so on, and packet losses i can deal with by repetition

Wrong, the Wire library has no multimaster support. You'll have to access the registers directly by either patching the Wire library or writing your own library.

Regarding the bus capacitance problem, you can use internal pullup resistors on the arduino for a single or a few i2c slaves, after that, you must use external pull-ups. You size your pull-up resistors according to your circuits capacitance and power requirements, as described in the i2c bus documentation.

The number of slaves is not the only factor relevant for the capacitance, the length of the bus is another. The internal pullups are good for a few centimeters only, in most cases you need external pullups to get a reliable communication.
You know that the maximum length of the bus is in the range of 0.5-1m, do you?

So your input is much appreciated, but you might want to read up on i2c before you say that it is unsuitable.

If you read some older topics I attended you might learn that I read quite some stuff about I2C and I also used it in many of my own projects. You can try the multimaster setup and hit your head yourself. You'll learn a lot but it's probably the hardest way.