I2C Between Arduino Sending incorrect chars

I am trying to send a String, one character at a time, from one Arduino to another. The String contained a list of numbers. It appears that for each char sent (one digit of the number), the other Arduino receives a value that is 48 greater than the number sent (See the image below).


I know I can just subtract 48 but I want to know why this is happening.

The code for the master Arduino is as follows:

//Master
#include <Wire.h>

#include <util/atomic.h>

String i2c_rcv;               //data received from I2C bus
unsigned long time_start;   //start time in milliseconds

//Encoder Lists
String posList_uno;
int numSteps_uno = 0;

String posList_server;
int numSteps_server = 0;


void setup() {
  //Connect to Computer
  Serial.begin(9600);

  // join I2C bus as Slave with address 0x08
  Wire.begin(8);
  Serial.println("Arduino Connected");

  // initialize global variables
  i2c_rcv = "";
  time_start = millis();
  Serial.println("Time Started");

  Wire.onReceive(dataRcv);

  signalArduino(5);
  getPathFromArduino();
  Serial.println("posList_uno");
  Serial.println(posList_uno);

}


void loop() {
 
}

//Send val to other Arduino
void signalArduino(int val) {

  Wire.beginTransmission(8);
  Serial.println("began transmission");
  Wire.write(val);
  Serial.println("Value Written");
  Wire.endTransmission();
  //Serial.println(val + " sent to Arduino");

}

void getPathFromArduino() {

  posList_uno = "";

  while(posList_uno.length() == 0){
  
  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
    posList_uno = i2c_rcv;
    i2c_rcv = "";
  }
  }
}


void sendArduinoPath() {

  Wire.beginTransmission(8);

  for (int i = 0; i < posList_server.length(); i++) {
    Wire.write(posList_server[i]);
  }

  Wire.endTransmission();
  Serial.println("lists sent to arduino");

}


void dataRcv(int numBytes) {
  Serial.println("RCV Triggerred");
  while (Wire.available()) { // read all bytes received
    i2c_rcv += Wire.read();
    Serial.print("Recieved Data: ");
    Serial.println(i2c_rcv);
  }
}

The code for the slave Arduino is as follows:

//Slave
#include <Wire.h>

String i2c_rcv;               // data received from I2C bus
unsigned long time_start;   // start time in milliseconds
int message; 
int prevMessage;

//Encoder Lists
String posList;
int numSteps = 0;

int posAList_rcv[20];
int posBList_rcv[20];
int numSteps_rcv = 0;

void setup() {
  //Connect to Computer
  Serial.begin(9600);

  // join I2C bus as Slave with address 0x08
  Wire.begin(8);
  Serial.println("Arduino Connected");

  // initialize global variables
  i2c_rcv = "";
  time_start = millis();
  Serial.println("Time Started");
  message = 0;
  prevMessage = 0;

// event handler initializations
  Wire.onReceive(dataRcv);            // register an event handler for received data

Serial.println("Create List");
  posList = "1234567890";
  numSteps = 5;
Serial.println("List Created");
Serial.println(posList);
Serial.print("numSteps: ");
Serial.println(numSteps);
}

void loop() {

  message = i2c_rcv.toInt();

  if (message == 5) {
    Serial.println("Entered Loop");
    sendEncoderList();
    message = 0;
    i2c_rcv = "";
  }
  
}

//received data handler function
void dataRcv(int numBytes) {
  while (Wire.available()) { // read all bytes received
    i2c_rcv += Wire.read();
    Serial.print("Recieved Data");
    Serial.println(i2c_rcv);
  }
}


void sendEncoderList() {
    Wire.beginTransmission(8);

    for (int i = 0; i < posList.length(); i++) {
      Wire.write(posList[i]);
      Serial.print(posList[i]);
    }

    Wire.endTransmission();
    Serial.println("lists sent");
  
}


void getPath() {

  String result = i2c_rcv;
  int nextComma = 0;
  Serial.println(result);

  nextComma = result.indexOf(",");

  if (nextComma > 0) {
    numSteps_rcv = result.substring(0, nextComma).toInt();
  } else {
    Serial.println("error");
  }

  for (int i = 0; i < numSteps; i++) {

    result = result.substring(nextComma);
    nextComma = result.indexOf(",");
    posAList_rcv[i] = result.substring(0, nextComma).toInt();
    result = result.substring(nextComma);
    nextComma = result.indexOf(",");
    posBList_rcv[i] = result.substring(0, nextComma).toInt();

  }

}```
Thank you

Because : ASCII

You are sending a character representing a digit, not the digit itself

But how come the correct character representing the digit is not being recieved?

What data type does Wire.read() return ?

Change the above to the following:

Serial.println((char)i2c_rcv);

Can you do your project with a single Arduino board ?
Using the I2C bus to communicate between two Arduino boards is a bad idea.

If you still want to use the I2C bus, then I suggest to start all over.
If you start all over, then you don't need to read all of this:

  • Keep the interrupt routines the onReceive and onRequest handlers as short as possible. You may use 'Serial.println()' there for a test, but not in the final version.
  • Please don't use a 'String' object in the onReceive and onRequest handlers. The allocating and freeing of the heap takes time.
  • Can you send binary data instead of text ? The I2C bus is for packages of binary data.
  • If you want to start with I2C between two Arduino boards, then start with a simple sketch. More than half of your sketches is only there to make it harder.
  • Your Master and Slave have both the Slave address 8. That is not allowed.
  • There is no synchronization in the Slave. How do you know in the loop() that everything is received.
  • The Slave also sends data to the Master. Then you have a Multi-Master bus. That will not work.
  • You work with a String object (allocating and freeing heap) in a atomic protected part. I don't know if that is possible. It does not feel good.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.