3

I am attempting to communicate data via I2C between two Arduino Micros, but can't seem to get the "slave" device to detect a Wire.onRecieve() event.

Per the specification on this site [http://www.takktile.com/tutorial:arduino] (and verified against Arduino's own site) I am using pins 2 and 3 as SDA and SCL for I2C. I have pin2 of Arduino 1 (ARD1) connected to pin2 of Arduino 2 (ARD2), and pin3 of ARD1 connected to pin3 of ARD2.

ARD2 acts as slave, ARD1 acts as master.

I am reading in a text file from SD on ARD1. On ARD1, you then press a button to initiate transfer. ARD1 lights a red LED to indicate the transfer is underway. When I initiate the transfer, it remains solid (indicating it never gets past endTransmission to where the LED is supposed to be turned off).

Here is the code for ARD1:

// include the SD library:
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
// personal debugging routines
#include "debug.h"
/* 
 *  
 *  THIS IS THE SLAVE RECEIVING MODULE
 *  IT WILL WRITE DATA TO AN SD CARD
 */

// GLOBAL VARIABLES
const int chipSelect = 10; // 10 because this is an Adafruit SD module.
File data;
int buttonA; // the button
char c;

void sd_readstart() {
  unsigned char i = 0;
  // Open serial communications and wait for port to open:
  Serial.print("\nInitializing SD card...");
  if (!SD.begin(10)) {
    Serial.println("Card initialization failed.");
    errorblink();
    return;
  }
  Serial.println("Initialization successful.");

}

void setup() {
  pinMode(11, OUTPUT); // setup for blink
  pinMode(12, OUTPUT); // setup for blink
  pinMode(10, INPUT); // button
  Wire.begin(8); // intitalize this device as a slave on addr .
  Wire.onReceive(receiveEvent); // when data is recieved, run recieveEvent(int).
  Serial.begin(9600);
  sd_readstart();
}

void loop(void) {
  // short blink to confirm this is going down correctly 
  buttonA = digitalRead(10);
  if (buttonA == HIGH) {
    // button open
    blink(100,1000);
  } else {
    // button pressed

  }

}

void receiveEvent(int howMany) {
  data = SD.open("testoutput.txt");
  digitalWrite(12,HIGH);
  while (Wire.available() > 0) { // loop through all but the last
    c = Wire.read(); // receive byte as a character
    Serial.print(c);         // print the character
    data.print(c);
  }
  data.close();
  digitalWrite(12,LOW);
}

Here is the code for ARD2:

// include the SD library:
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
// Software Serial library: 
#include <SoftwareSerial.h>
// personal debugging routines
#include "debug.h"
/* 
 *  
 *  THIS IS THE SLAVE RECEIVING MODULE
 *  IT WILL WRITE DATA TO AN SD CARD
 */

// GLOBAL VARIABLES
const int chipSelect = 10; // 10 because this is an Adafruit SD module.
File data;
int buttonA; // the button
char c;

void sd_readstart() {
  unsigned char i = 0;
  // Open serial communications and wait for port to open:
  Serial.print("\nInitializing SD card...");
  if (!SD.begin(10)) {
    Serial.println("Card initialization failed.");
    errorblink();
    return;
  }
  Serial.println("Initialization successful.");

}

void setup() {
  pinMode(11, OUTPUT); // setup for blink
  pinMode(12, OUTPUT); // setup for blink
  pinMode(10, INPUT); // button
  Wire.begin(8); // intitalize this device as a slave on addr 8.
  Wire.onReceive(receiveEvent); // when data is recieved, run recieveEvent(int).
  Serial.begin(9600);
  sd_readstart();
}

void loop(void) {
  // short blink to confirm this is going down correctly 
  buttonA = digitalRead(10);
  if (buttonA == HIGH) {
    // button open
    blink(100,1000);
  } else {
    // button pressed

  }

}


void receiveEvent(int howMany) {
  data = SD.open("testoutput.txt");
  digitalWrite(12,HIGH);
  while (Wire.available() > 0) { // loop through all but the last
    c = Wire.read(); // receive byte as a character
    Serial.print(c);         // print the character
    data.print(c);
  }
  data.close();
  digitalWrite(12,LOW);
}

For completeness, here is my debug.h:

void blink(int h, int l) {
    digitalWrite(11, HIGH);  
    delay(h);              
    digitalWrite(11, LOW);   
    delay(l);             
}

void errorblink() {
  unsigned char counter = 0;
  while (counter < 4 ) {
    digitalWrite(12, HIGH);  
    delay(50);              
    digitalWrite(12, LOW);   
    delay(50);    
    digitalWrite(12, HIGH);  
    delay(50);              
    digitalWrite(12, LOW);   
    delay(50);    
    digitalWrite(12, HIGH);  
    delay(50);              
    digitalWrite(12, LOW);   
    delay(1000);    
    counter++;
  }
}

void goodblink() {
  unsigned char counter = 0;
  while (counter < 4 ) {
    digitalWrite(11, HIGH);  
    delay(50);              
    digitalWrite(11, LOW);   
    delay(50);    
    digitalWrite(11, HIGH);  
    delay(50);              
    digitalWrite(11, LOW);   
    delay(50);    
    digitalWrite(11, HIGH);  
    delay(50);              
    digitalWrite(11, LOW);   
    delay(1000);    
    counter++;
  }
}

I did attempt to do the minimum working example of Wire from the examples in the Arduino IDE. That didn't work either, which is to say that I didn't see any text in the serial monitor on ARD2 when I uploaded the slave reciever sketch that comes with the IDE (with send master running on ARD1) which makes me wonder if I'm doing something horribly, fundamentally wrong in hardware rather than just in software.

I hope it's not inappropriate to post up the more advanced example in order to get feedback on the larger picture of what I'm trying to accomplish -- moving a text file from the SD card on one arduino to the SD card attached to another.

  • 1
    You don't mention having the external explicit pullup resistors required for I2C. – Chris Stratton May 30 '16 at 5:44
  • Indeed I didn't. That may be the horrible, fundamental thing I overlooked. Can you elaborate? – Bradley Evans May 30 '16 at 5:46
3

I2c is an open collector setup. The pins go low, or open/input/hi-z, and let the line/bus free. Without a pull up on each line to VCC, the line never goes high. Pull up resistors are required. 4.7k typical.

Op's crudely drawn diagram is the correct way for a 5V I2C bus:

enter image description here

Keep in mind both arduinos/power supplies must have their grounds connected, as a reference ground voltage.

  • 1
    Am I correct in imagining something akin to the crude schematic I drew here: imgur.com/qhO2W4y – Bradley Evans May 30 '16 at 5:58
  • 1
    @BradleyEvans yup. See learn.sparkfun.com/tutorials/i2c – efox29 May 30 '16 at 6:25
  • 1
    Thanks. This was, indeed, my problem. With respect to the larger problem, is my intuition correct that the data transferred cannot be very large? I was trying to push a multiparagraph text file through. – Bradley Evans May 30 '16 at 6:54
  • 1
    @BradleyEvans You can transfer as much data as you want, if you are willing to wait long enough … – CL. May 30 '16 at 9:07
  • 1
    @bradleyevans you do it 8 bits at a time, as fast as the library allows you too. Standard i2c is 100 kHz to 400 kHz so that pretty snappy compared to human speed, but SPI or fat i2c or serial/uart can be faster. – cde May 30 '16 at 17:50
1

The I2C protocol and hardware don't care how much data is transferred.

The time you have for the transfer, or the transfer rate is much more important; you might get bored waiting, but it won't.

You might get over 100k bits/second transfer (allowing time to write to the SD card) if that's enough then it's fine.

The significantly faster option, using Arduino's, is SPI to SPI, and you are likely using SPI for the SD card, so I2C is a reasonable alternative, and makes your hardware and software simpler.

The only faster interface on the Arduino, excluding SPI, is the UART. That might be a bit tricky to use while you are developing, testing and debugging your software.

  • I had initially started with UART but it proved a tad too complex for the short time I have with this project. Thanks for the background. – Bradley Evans May 31 '16 at 23:59

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.