Using wire to send strings of numbers and letters from one uno to another

Hello all,

I'm New to programming with an arduino, my background is Visual Basic. I'm Trying to get to uno's to talk to each other through the wire, I can send text strings back-and-forth fine but when I include numbers in the strings it just locks. Do I have to convert them to a character array and then send them one byte at a time or is there another way? Thanks Stuart

Which wire do you use? Maybe you tell use what connections you have between the two Arduinos and post both sketches so we know a bit about what you're doing.

If you mean "Wire", as in "I2C", you should use the write function just once in the interrupt routine. Transmit a structure or array with just one "write" if you need to transmit more data. I read about improvements with that, but I don't know if they are in the current version Arduino 1.0.5. http://arduino.cc/en/Tutorial/MasterReader If you mean serial UART data with the "Serial" library, that is a "Stream" class with many possibilities. http://arduino.cc/en/Reference/Stream

I'm using the wire.write and also have tried the wire.print . I can include my code later when I get home , but the master write is the example I started with .. Hope that helps

I'm using the wire.write and also have tried the wire.print . I can include my code later when I get home , but the master write is the example I started with .

So you're using the Wire library. "The wire" is not a clear indication that you're talking about a library that's called "Wire". BTW, Wire is started uppercase and case is relevant in C/C++.

Using I2C you need code on the master and code on the slave and the two are not identical. So please post both sketches. And also post a wiring diagram how you connected the two Arduinos, include every wire.

When the string, test_key, is all text it transmits fine and the second uno receives the data…

 test_key = "test";

    Wire.beginTransmission(4); // transmit to device #4
    Wire.print(test_key);
    Wire.endTransmission();    // stop transmitting

But, if I change test_key to this …

 test_key = "test123";

    Wire.beginTransmission(4); // transmit to device #4
    Wire.print(test_key);
    Wire.endTransmission();    // stop transmitting

once it hits the wire.begin…wire.end section it all locks up.

So maybe I should re-word my orginal question… why wont the wire library send numbers when using a string?
Also… is there a way to get a string , it will be numbers, letters and sometimes a combo of both at a length between 4 and 32 characters, to be simply converted on the fly and sent using the wire library?

Thanks

I think that everything is transmitted, so maybe there is something wrong in the receiver.
Or you use that code in an interrupt, that is not how it should be used.
There could be even a hardware problem that could cause this, for example a missing ground.

We like to have links to the used products, and schematics or drawings, photos of the wires and full sketches. Please give us at least the full sketches, or make small test sketches.

I'm quite sure both strings get transferred but as Caltoa already wrote, these are just code fragments, maybe the error is in another part of the code or even on the slave side. Post complete sketches.

BTW: What is visible in the code fragment, that's the ignorance of the return values of the Wire methods. The code does not check if the bytes really reaches the slave. I would start with that.

it good to see so many responses from people that have used the wire library and know it inside and out.

The wiring of the two UNO’s are directly from the example… A4-A4, A5-A5 and Ground to Ground.

included are the complete sketches…

Here is the complete send side -

#include <Wire.h>

// send side

void setup() {
  Wire.begin(1);                // join i2c bus with address #1
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(9600);  // initialize seri
}

void loop() {

If (Serial.available() > 0) {    // if key is pressed send test_key 
test_key = "test";
Serial.print("Data Sent - ");              // - only prints this when numbers are included and locks here... the receive side prints nothing when that happens
    Wire.beginTransmission(4); // transmit to device #4
    Wire.print(test_key);
    Wire.endTransmission();    // stop transmitting
Serial.print(test_key);
 }
delay(500);
}

Here is the receive side

#include <Wire.h>
String  wire_in;

void setup() {
  Wire.begin(4);                // join i2c bus with address #4
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(9600);  // initialize serial communication
}

void loop () {

if  (wire_in != "") {
Serial.println(wire_in); 
}
void receiveEvent(int howMany)
{
  Serial.println("Event - Recieve");
  while(Wire.available() > 0) // loop through all but the last
  {
    char c = Wire.read(); // receive byte as a character
    wire_in.concat(c);
   delay(10);
    Serial.print("Data in - ");         // print the character
  }
delay(500);
}

I have inserted the “Serial.print” statements to see where the lock up is… the project locks up when “test_key” contains numbers. I can change “test_key” to anything and it works great, but put a number in the string and it locks up on the send side and only will print to the serial monitor the ("Data Sent - ") but nothing else and the receive will print nothing when this happens.

I dont mind converting my string to something it will accept but what?

Thanks

I see three things that can delay, and a String class in the receiving handler function (receiveEvent). I would like to get them all out of that function.

To make the test even smaller, can you remove the address “1” for the Master, and remove the call to Wire.onReceive() ?

In the Slave, you can not use a delay() or Serial.print() in the receiveEvent handler.
Remove them all.
You don’t have to do a while loop, use the variable howMany, that is exactly how many bytes are in the buffer.

Please be very tidy with the layout of the code. Use the ‘{’ always in the same way, and use the indents properly. That will make it a lot easier to read and maintain the code.

A normal array is easier than a String, so let’s fill a normal array:

boolean flagRx = false;
char buf[40];

void loop () 
{
  if (flagRx) 
  {
    Serial.println(buf);
    flagRx = false;
  }
}

void receiveEvent (int howMany) 
{
  int i;
  for (i=0; i<howMany; i++)
  {
    buf[i] = Wire.read();     // receive byte as a character
  }
  buffer[i] = '\0';  // assume it is a string, add zero-terminator
  flagRx = true;    // set flag, we received something.
}

After fixing your code, please upload the Master and Slave sketch again… even if it is working :slight_smile:

I agree with what Caltoa wrote.

Additionally:

// send side

void setup() {
  Wire.begin(1);                // join i2c bus with address #1
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(9600);  // initialize seri
}

On the sending side you shouldn't set a I2C address because the sending side should be the master and on the master there must not be a onReceive event handler.

I don't know where these examples are from but if they are literally copied you should take that site as a reference for the use of I2C.

ok .. can you please tell me then, how making the sketch smaller is going to make the wire library transmit numbers when they are contained in a string?

Caltoa:
I see three things that can delay, and a String class in the receiving handler function (receiveEvent). I would like to get them all out of that function.

To make the test even smaller, can you remove the address “1” for the Master, and remove the call to Wire.onReceive() ?

In the Slave, you can not use a delay() or Serial.print() in the receiveEvent handler.
Remove them all.
You don’t have to do a while loop, use the variable howMany, that is exactly how many bytes are in the buffer.

Please be very tidy with the layout of the code. Use the ‘{’ always in the same way, and use the indents properly. That will make it a lot easier to read and maintain the code.

A normal array is easier than a String, so let’s fill a normal array:

boolean flagRx = false;

char buf[40];

void loop ()
{
  if (flagRx)
  {
    Serial.println(buf);
    flagRx = false;
  }
}

void receiveEvent (int howMany)
{
  int i;
  for (i=0; i<howMany; i++)
  {
    buf[i] = Wire.read();     // receive byte as a character
  }
  buffer[i] = ‘\0’;  // assume it is a string, add zero-terminator
  flagRx = true;    // set flag, we received something.
}




After fixing your code, please upload the Master and Slave sketch again... even if it is working :)

Interesting, ok… i will give that a shot.