Uart And I2c Conflict

Hello
I have one atmega 328 that I want to read some data from uart and send the result thought i2c
Atmega328 run uart and i2c as slave and one atmega2560 that run only i2c as master.
My problem is on atmega328 because Ι encounters some problems to run uart and i2c at the same time.
If i run only uart or only i2c everything works perfect.
When I run the whole code after 3-5 second the cpu freeze.

Can anyone help me, please

void setup()
{
  delay(500);
  Serial.begin(115200);
  Wire.begin(15);
  Wire.setClock(400000L);
  Wire.onRequest(requestEvent);
  Wire.onReceive(receiveEvent);
}

void loop() {
ReadCommand("Example", "Response", 1000)
}

void requestEvent() {
  Sen =  "<" + String(Variables[1], VariableDigit[1]) + "," + String(Variables[5], VariableDigit[5]) + "," + String(Variables[2], VariableDigit[2]) + "," + String(Variables[VariableNumber1], VariableDigit[VariableNumber1]) + "," + String(Variables[VariableNumber2], VariableDigit[VariableNumber2]) + ">" ;
  Sen.toCharArray(Send, 28);
  Wire.write(Send);
}

void receiveEvent(int bytes) {
  str = "";
  while (Wire.available()) { // loop through all but the last
    str = str + char(Wire.read());
  }
  if (str.substring(0, 1) == "<" &&  str.indexOf('>') == str.length() - 1) {
    int Digit1;
    int Digit2;
    Digit1 = str.indexOf(',');
    Protocol = str.substring(1, Digit1).toInt();
    Digit2 = str.indexOf(',', Digit1 + 1);
    VariableNumber1 = str.substring(Digit1 + 1, Digit2).toInt();
    VariableNumber2 = str.substring(Digit2 + 1).toInt();
  }
}

int ReadCommand(String Command, String Answer, int WTime)
{
  Serial.println(Command);
  String Str = "";
  byte RinData;
  char RinChar;
  int b = 0;
  unsigned long int t = millis();
  while (millis() - t < WTime) {

    while (Serial.available() > 0)
    {
      b++;
      RinData = 0;
      RinChar = 0;
      RinData = Serial.read();
      RinChar = char(RinData);
      Str = Str + RinChar;
    }
    if (Str.indexOf(Answer) >= 0) {
      delay(200);
      return 1;
    }
  }
  delay(200);
  return 0;

}

The code you've posted will not compile due to the absence of libraries and who knows what else. When you post your entire code we'll have another look at it.

Are you trying to say the following in your post? If not, kindly paraphrase your post and re-submit.

I have an ATmega2560 based Arduino MEGA which I want to operate as an I2C Bus Master.

I have also an ATmega328P based Arduino UNO which I want to operate as I2C Bus slave. Using UNO, I want to receive data via UART Port from Serial Monitor. The data received from the Serial monitor will be sent to MEGA over I2C Bus once request comes from the I2C Master (the MEGA).

I have problem to operate the above network. Please help!

yes this is exactly my problem

Sorry, I forgot the variables this is the code that it can be compiled.

#include <Wire.h>
String Sen;
float Variables[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
byte VariableDigit[] = {2, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0};
int Protocol = 0;
String str;
char Send[28];
int VariableNumber1=23;
int VariableNumber2=23;


void setup()
{
  delay(500);
  Serial.begin(115200);
  Wire.begin(15);
  Wire.setClock(400000L);
  Wire.onRequest(requestEvent);
  Wire.onReceive(receiveEvent);
}

void loop() {
ReadCommand("Example", "Response", 1000);
}

void requestEvent() {
  Sen =  "<" + String(Variables[1], VariableDigit[1]) + "," + String(Variables[5], VariableDigit[5]) + "," + String(Variables[2], VariableDigit[2]) + "," + String(Variables[VariableNumber1], VariableDigit[VariableNumber1]) + "," + String(Variables[VariableNumber2], VariableDigit[VariableNumber2]) + ">" ;
  Sen.toCharArray(Send, 28);
  Wire.write(Send);
}

void receiveEvent(int bytes) {
  str = "";
  while (Wire.available()) { // loop through all but the last
    str = str + char(Wire.read());
  }
  if (str.substring(0, 1) == "<" &&  str.indexOf('>') == str.length() - 1) {
    int Digit1;
    int Digit2;
    Digit1 = str.indexOf(',');
    Protocol = str.substring(1, Digit1).toInt();
    Digit2 = str.indexOf(',', Digit1 + 1);
    VariableNumber1 = str.substring(Digit1 + 1, Digit2).toInt();
    VariableNumber2 = str.substring(Digit2 + 1).toInt();
  }
}

int ReadCommand(String Command, String Answer, int WTime)
{
  Serial.println(Command);
  String Str = "";
  byte RinData;
  char RinChar;
  int b = 0;
  unsigned long int t = millis();
  while (millis() - t < WTime) {

    while (Serial.available() > 0)
    {
      b++;
      RinData = 0;
      RinChar = 0;
      RinData = Serial.read();
      RinChar = char(RinData);
      Str = Str + RinChar;
    }
    if (Str.indexOf(Answer) >= 0) {
      delay(200);
      return 1;
    }
  }
  delay(200);
  return 0;

}

I read that maybe is ram error but I try the same code on the atmega2560 and I had the same result.

As you are saying that the Post#2 describes your programming problem, you may try to write program in your own style rather copying and pasting codes from the net, which are helpful to some extent. Let us try to convert the following steps into programming language using UNO/MEGA Platform ans observe the result.

1. Program UNO to receive the message "Arduino" from the Serial Monitor-1 (SM1) and save it in a character type array named char msg1Array[]. Also, program the UNO to work as an I2C slave. UNO will send the message 'Arduino" to the MEGA when 'data transfer command' comes from the MEGA over the I2C Bus.

2. Program MEGA to receive the message "Request" from Serial Monitor-2 (SM2) and save it in a character type array named char msg2Array[]. After the reception of this message, the MEGA will command the UNO to send the content of the array msg1Array[] (the Arduino message) to the MEGA via I2C Bus. MEGA will receive the message and will show it on SM2.

3. The Hardware Setup

The code that I have post I don't find on the net I have write it.

The ReadCommand function has 3 parameters the command that it send the command that it wait and the timeout.This fuction read some values from another device through(this device i can simulate it though serial monitor) serial and fill the Variables[] array.

The master (Mega)before the request send to the slave what data need so on the request the salve send the string with this data.

Before i write this code i had less variables so i was using only requestEvent fuction and it was working good.

That is good that you have tried to write program yourself but be attentive to check that the coding follows the steps that you have thought to be executed to produce the desired result(s). Let us insert codes into the following program structure so that they produce the results of Post#2.

A: I2C Bus Master Codes for MEGA

#include<Wire.h>

void setup()
{
   Serial.begin(9600);
   Wire.begin();
   //---------------
}

void loop()
{
   //Write codes to check that message "Request" is coming from SM2 and save it in array

}

B: I2C Bus Slave Codes for UNO

#include<Wire.h>

void setup()
{
   Serial.begin(9600);   //
   Wire.begin(0x20);         //UNO will be seen as I2C slave at address 0b0100000 
   //---------------------
}

void loop()
{
    //write codes to check the message "Arduino" is coming from SM1 and save it in array.

}

the problem it that i want to run the i2c with interrupt (request and receive)
If i put the request on the loop the atmega328 will run all the code until it read the request.

As i have understand the main problem is when i have i2c interrupt while i am reading the serial.

If i write the code in loop function maybe will work because always it will run one (uart or i2c)
But it doesn't that i want

This post may work as a tutorial guide as to the the applications of various I2C Bus commands for exchanging data between Master MEGA and Slave UNO.

A: Hardware Setup (repeated)

B: Master MEGA Codes

#include<Wire.h>

char msg2Array[8] = "";
char msg3Array[8] = "";
bool flag2 = LOW;

void setup()
{
  Serial.begin(9600);
  Wire.begin();
}

void loop()
{
  if (flag2 == HIGH)
  {
    Wire.requestFrom(0x20, 7);
    for(int i=0; i<7; i++)
    {
      msg3Array[i] = Wire.read();
    }
    flag2 = LOW;
    Serial.print(msg3Array);
  }
}

void serialEvent()
{
  if (Serial.available() == 7) //Request = 7 charcaters
  {
    for (int i = 0; i < 7; i++)
    {
      msg2Array[i] = Serial.read();
    }
    Serial.println(msg2Array);
    flag2 = HIGH;
  }
}

C: Slave UNO Codes

#include<Wire.h>

char msg1Array[8] = "";
bool flag1 = LOW;

void setup()
{
  Serial.begin(9600);
  Wire.begin(0x20);

  Wire.onRequest(sendEvent);
}

void loop()
{

}

void sendEvent(int howmany)
{
  if (flag1 == HIGH)
  {
    for (int i = 0; i < 7; i++)
    {
      Wire.write(msg1Array[i]);
    }
  }
}
void serialEvent()
{
  if (Serial.available() == 7) //Request = 7 charcaters
  {
    for (int i = 0; i < 7; i++)
    {
      msg1Array[i] = Serial.read();
    }
    Serial.println(msg1Array);
    flag1 = HIGH;
  }
}

D: Operating Procedures
(1) Upload Master Codes into MEGA.

(2) Upload Slave Codes in UNO.

(3) Simultaneously, press RESET buttons of bothe MEGA and UNO.

(4) Open SM1 and SM2 -- the Serial Monitors for UNO and MEGA.

(5) Enter Arduino from the Input Box of SM1; check that the message Arduino has appeared on the Output Box of SM1.

(6) Enter Request from the Input Box of SM2; check that the message Request and Arduino have appeared on the Output Box of SM2.

E: Working Principles of the Program Codes
(1) By virtue of the program codes, the MEGA/UNO receive the messages "Request"/'Arduino" from SM2/SM1 and then sets the flag2/flag1 value to HIGHs.

(2) Master will use flag2's status to issue the Wire.requestFrom() command; the slave will use the flag1's status to know that it has message ready that is to be sent to the MEGA (the Master) when request comes.

(3) In response to the Wire.requestFrom() command, the UNO goes to the sendEvent() routine, stores the message into local buffer using Wire.write() commands. The Master collects the message from the local buffer of the Slave on fully handshaking protocol through the execution of the Wire.read() commands.

(4) In hardware UART Port communication, the MCU jumps to the serialEvent() procedure when a character arrives from the Serial Monitor. This feature is not available in software UART Port communication.

This code work perfect
But in my case serial run continuously
and before the request the master must sent thought i2c what of variables want.

My main problem is while running the serial communication and interrupt from i2c request.
In this case the cpu freeze and thats my problem