1
\$\begingroup\$

i have one arduino mega that communicates with one arduino leonardo.

the leonardo controls some motors (mega tell to the leonardo how many step to do... leonardo is a coprocessor for the motor in other words).

for testing i try to send the number 20 from the mega to the leonardo. i sent the number as a sequence of char, with 2 char of haeder so in this case i'm sending 'M>0020' as 6 char (6 byte). leonardo send the status (ready/busy) back to the master through the pin4 (this is to avoid the interrputs in Wire.h that can add delay in the motor code if the master require data to the slave).

communication seems ok, but if i plug power supply (12V) communication crashes. if i reset the mega the leonardo read 11049 (i haven't the board there, could be a different number, but it is always the same), the recives for 5/6 times the correct number 20, then communication crash, and mega crash.

i tried to unplug every motor-related stuff from leonardo, so i have only 4 wire:

  1. common ground
  2. sda
  3. slc
  4. the wire for the state (ready/busy) of the slave.

the problems occurs every time i plugged the power supply. sometimes it happens that the problem occurs even without 12v external power (so onlu usb cable that power leonardo) after some time (half an hour)

the 2 arduino boards are linked with a 8m cable (i've used the tester and the cable seems ok, it was a cable for a lan network).

any suggestion?

\$\endgroup\$
  • \$\begingroup\$ I think 8m is too long for un-driven I2C bus. I'm guessing that when you plug in the 12V supply it is connecting the ground loop, generating a some current and interfering with the I2C signals. Additionally the noise from the 12V supply will cause some current in the ground wire as it will be varying from the ground of the other supply, causing interference with the I2C lines. \$\endgroup\$ – geometrikal Oct 5 '12 at 23:39
  • 1
    \$\begingroup\$ Try - shorter cable; powering both devices from one power supply (extra power cable); slowing down I2C bus; change comms to RS-232 or better yet - XBee. XBee is wireless - win. \$\endgroup\$ – geometrikal Oct 5 '12 at 23:41
  • \$\begingroup\$ what other protocol can i try to use for sending a number (from 0 to 1000) between several arduino boardswith that distance? i'm looking for the easiest solution. \$\endgroup\$ – nkint Oct 5 '12 at 23:42
  • \$\begingroup\$ More than two boards? i really like XBee stuff because it is wireless, but it might not be the easiest. I think maybe try slowing down the I2C speed. \$\endgroup\$ – geometrikal Oct 5 '12 at 23:48
  • \$\begingroup\$ Change i2c speed: arduino.cc/forum/index.php/topic,12518.0.html this page: arduino.cc/forum/index.php/topic,16793.0.html says you have to "delete the files hardware/libraries/Wire/Wire.o hardware/libraries/Wire/utility/twi.o" \$\endgroup\$ – geometrikal Oct 5 '12 at 23:49
1
\$\begingroup\$

Note: this answer is based on the comments above.

Possibly the cause of the problem is: * Long I2C cable length, combined with * Different power supplies causing current to flow in the ground wire of the cable, causing noise on the I2C lines.

The solution that worked was to reduce the I2C bus speed. It is usually 100kHz but one can reduce it to 10kHz by making the following code changes (taken from http://arduino.cc/forum/index.php/topic,12518.0.html)

Modify hardware/libraries/Wire/utility/twi.h:

Old:

#ifndef TWI_FREQ
#define TWI_FREQ 100000L
#endif

New:

#ifndef TWI_FREQ
#define TWI_FREQ 10000L  /* 10kHz */
#define PRESCALER_10KHZ 4
#endif

Modify hardware/libraries/Wire/utility/twi.c

Old:

cbi(TWSR, TWPS0);
cbi(TWSR, TWPS1);

TWBR = ((CPU_FREQ / TWI_FREQ) - 16) / 2;

New:

/* Select 4 as the prescaler value - see page 239 of the data sheet */
cbi(TWSR, TWPS1);
sbi(TWSR, TWPS0);

TWBR = ((CPU_FREQ / TWI_FREQ) - 16) / 2 / PRESCALER_10KHZ;
/*
  The documentation in twi.c is assuming a prescaler value of 1.  
  The actual equation (data sheet page 218) is 
  SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR * prescaler))
  For a rate of 10kHz with a clock speed of 16MHz, TWBR is 198.
*/

This post (http://arduino.cc/forum/index.php/topic,16793.0.html) also advises that ".. you also have to the delete the files:

  • hardware/libraries/Wire/Wire.o
  • hardware/libraries/Wire/utility/twi.o"

to make sure the changes are recompiled.

\$\endgroup\$
  • \$\begingroup\$ ok now a little question: has this method got some side effects? \$\endgroup\$ – nkint Oct 8 '12 at 21:46
  • \$\begingroup\$ I2C is synchronous, so it could probably be clocked as slow as you like. I think the only side effect is the speed of communications will be slower. But you are using 10kHz and only sending a few characters so this should not be a problem. \$\endgroup\$ – geometrikal Oct 8 '12 at 22:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.