Parsing keyboard data to I2C Master sender to slave receivers

I am working through the issues of sending serial data from the PC to the I2C master in my I2C Arduino network. I simply want to have the user enter the address/node # and then a single decimal value for PWM rate intended for the specific address to use it in its program. Any assistance would be greatly appreciated.

Master code

#include <Wire.h>
#define NODE_SEND_DELAY 1000 // Some delay between I2C transmits 

int rate;
int node;
int loopCnt;
int no;
int ra;

void setup()
{
  Serial.begin(9600);  // start serial port
  Serial.println("Enter node # then rate #.");
  Wire.begin();  // Activate I2C network
}

void loop()
{
  if (Serial.available())
  {

    if (loopCnt == 0)
    {
      char no = Serial.read();
      if (no >= '0' && no <= '9') // is this ascii digit between 0 and 9?
      {
      node = no; 
      Serial.println("The node # is.");
      Serial.println(node);
      loopCnt = 1;
     }
    }
    else if (loopCnt == 1)
    {
      char ra = Serial.read();
      if (ra >= '0' && ra <= '9') // is this ascii digit between 0 and 9?
      {
      rate = ra;
      Serial.println("The rate # is.");
      Serial.println(rate);
      loopCnt = 0;
      }   // END of if 
    }  


    Wire.beginTransmission(no);    // Point to a specific node#
          Serial.println("The sent node in # is."); //for debug purposes only 
          Serial.println(no); //for debug purposes only 
    Wire.write (ra);    // send data to node#
          Serial.println("The sent rate in # is."); //for debug purposes only 
          Serial.println(ra); //for debug purposes only 
    Wire.endTransmission();

    delay(NODE_SEND_DELAY);
    
  }  
}

Slave code

// Include the required Wire library for I2C


#include <Wire.h>
int LED = 9;
int x = 0;

void setup() 
{
  // Define the LED pin as Output
  pinMode (LED, OUTPUT);
  // Start the I2C Bus as Slave on address 3, char "3" is decimal 51
  Wire.begin(51); 
  // Attach a function to trigger when something is received.
  Wire.onReceive(receiveEvent);
}


void receiveEvent(int bytes) 
{
  x = Wire.read();    // read one character from the I2C
}


void loop() 
{
  //If the value received is Decimal "0" turn the LED off. This is stricly for debugging purposes
  if (x == 48) 
  {
    digitalWrite(LED, LOW);
  }
  //If the value received is Decimal "1" turn the LED on. This is stricly for debugging purposes
  else if (x == '49') 
  {
    digitalWrite(LED, HIGH);
  }

}

You don’t say what issue(s) you are having. In any case I see an issue in your slave code. This line is incorrect:

  else if (x == '49')

I would suggest replacing the following:

  if (x == 48) 
  {
    digitalWrite(LED, LOW);
  }
  //If the value received is Decimal "1" turn the LED on. This is stricly for debugging purposes
  else if (x == '49') 
  {
    digitalWrite(LED, HIGH);
  }

with:

  if (x == '0') 
  {
    digitalWrite(LED, LOW);
  }
  //If the value received is Decimal "1" turn the LED on. This is stricly for debugging purposes
  else if (x == '1') 
  {
    digitalWrite(LED, HIGH);
  }

Thank you for replying so quickly, Todd1962. Thanks for the help with the slave code. About the problem, I can't get the slaves to respond to the data presented to them. I'm an EE so the I2C bus is connected correctly as are common grounds.

stephenweiss1:
Thank you for replying so quickly, Todd1962. Thanks for the help with the slave code. About the problem, I can’t get the slaves to respond to the data presented to them. I’m an EE so the I2C bus is connected correctly as are common grounds.

Good. I would suggest a simple slave script to display the data received to the serial console. Then you can replace that with more sophisticated code once you determine that the code is working.

I would suggest the following for your slave code:

#include <Wire.h>

void setup() 
{
  // Start the I2C Bus as Slave on address 3, char "3" is decimal 51
  Wire.begin(51); 
  Serial.begine(9600);
}

void loop() 
{
  while(Wire.available())
  { 
    char c = Wire.read();    // receive a byte as character
    Serial.print(c);         // print the character
  }
}

Just wondering, is there some compelling reason for you to use a receive event as opposed to just monitoring for available data on the slave?

Thank you, ToddL1962. No specific reason for using a receive event versus just monitoring for available data on the slave. In researching how to network 5 or more Arduinos most of the sample code out there uses a receive event versus monitoring for data. I appreciate your guidance on that specific matter.

I have not even passed the second line in the first post.
What kind of data do you want to send via the serial port ?

For example "123".
Is that node 12 value 3 or node 1 value 23 ? Is there a Carriage Return after it or a LineFeed ? or both ? What should be done when the data is incomplete and there is a timeout ? Should the sketch have a timeout ?

I suggest the format "12,3\n".
Where the '\n' can be a '\r' as well or both. With a timeout of 1 second.

stephenweiss1:
Thank you, ToddL1962. No specific reason for using a receive event versus just monitoring for available data on the slave. In researching how to network 5 or more Arduinos most of the sample code out there uses a receive event versus monitoring for data. I appreciate your guidance on that specific matter.

You can do either way but if you use a receive event you may want to have a flag that can be reset from loop() function. The way you had it coded once a value is received it would be constantly doing digital writes.

Thanks, Koepel. It's node 12 value 3. I'm unclear on your formatting suggestion. Are you suggesting to use comma-separated values followed by the new line character?

stephenweiss1:
Are you suggesting to use comma-separated values followed by the new line character?

Yes, or anything else, as long as it is known what it is.

You could for example go with “123” with or without LineFeed. But if you send a “456” after that without LineFeed, then you don’t know where the start is. The “345” could be the command and the the rest could be of other commands.
You could define the first digit as the module number, but what if you have more than 10 modules ?
You could define the last digit as PWM value, but what if you upgrade to 12-bit PWM ?