4

I have this code I got from YouTube for communicating between two Arduinos. By typing 'R' manually into the serial monitor of the 'master' Arduino, the 'slave' will print "Success". I'm trying all this for the basis of a project I'm starting.

After success with the code, I am now trying to make it automatic. I want the 'master' Arduino to print "R" itself and for the 'slave' to read this and print "Success". println doesn't work here, maybe it'll work if the slave code is changed? Both original codes are below, any ideas on how to do what I need?

Master:

#include <Wire.h>
char incomingByte;
int x = 0;
void setup() {
 Serial.begin(9600);
 Wire.begin();
}
void loop() 
{
 Wire.beginTransmission(9);
 if (Serial.available()) {
 while (Serial.available() > 0) {
 incomingByte = Serial.read();
 Wire.write(incomingByte);
 Serial.println(incomingByte);
 Wire.endTransmission();
 }
 }
}

Slave:

#include <Wire.h>
int x = 0;
void setup() {
 Wire.begin(9);
 Wire.onReceive(recieveEvent); 
 Serial.begin(9600);
}
void recieveEvent(int bytes) {
 x = Wire.read();
}
void loop() {
 if (x == 'R'){
 Serial.println("Success");
 delay(100);
 }
}
Michel Keijzers
13k7 gold badges41 silver badges58 bronze badges
asked Mar 7, 2019 at 22:12
7
  • Your Master supposedly should send 'R'. Where is the place in the code this happen? Commented Mar 7, 2019 at 23:17
  • Look at what the master is doing. It's reading from serial and writing what it reads to Wire. How do you think you would make it send an R rather than what it reads from serial? Commented Mar 8, 2019 at 2:44
  • make x volatile. volatile int x = 0; Commented Mar 8, 2019 at 7:51
  • @MarkSmith That's what I'm unsure of. I am new at this so I don't know what to change in either codes. Commented Mar 8, 2019 at 15:34
  • @smajli I have to manually type 'R' into the serial monitor. Commented Mar 8, 2019 at 15:40

2 Answers 2

2

The I2C communication is not easy and there are many things that can go wrong. Two Arduino boards instead of one board are often used for the wrong reason in the first place.

Using a serial port is easier. The Arduino Leonardo has an extra hardware serial port, you could use the serial port to communicate between two Arduino boards. The Arduino Mega 2560 has three extra serial ports.

Sometimes two Arduino boards are used because multiple things have to be done at the same time.
When you use the Blink Without Delay example with millis, then the Arduino can do many things at the same time.

Sometimes two Arduino boards are used because there is some distance between the Arduino boards.
The I2C bus is a "bus", but that does not mean that you can use a long cable. You can go up to 20 inch (50 cm).

When two Arduino Uno boards are connected with the I2C bus, then three wires are needed:

  1. GND to GND
  2. SDA to SDA (plus pullup resistor)
  3. SCL to SCL (plus pullup resistor)

For a small test with short jumper wires, it is possible to do that without pullup resistors. For the final project pullup resistors should be used for SDA and SCL, for example 4k7 or 10k.

The example below uses a flag in the Slave Arduino. That extra variable makes it easier.
In the Slave receiveEvent function, there is a extra check to check if exactly one byte is received. That extra check is not required, but it can be useful.

I show this example as something to start with, because there are too many bad examples for I2C between Master and Slave.

Master

#include <Wire.h>
byte dataTransmit;
void setup() {
 Wire.begin();
}
void loop() {
 Wire.beginTransmission(9); // sending to slave with i2c address 9
 Wire.write(dataTransmit); // the data to send
 Wire.endTransmission();
 dataTransmit++; // all numbers from 0 to 255
 delay(250); // 250ms delay, to send 4 times per second
}

Slave

#include <Wire.h>
volatile byte dataReceive;
volatile bool newData; // a flag to indicate that new data has arrived
void setup() {
 Wire.begin(9); // create i2c slave at i2c address 9
 Wire.onReceive(receiveEvent); 
 Serial.begin(9600);
}
void loop() {
 if(newData) { // is there new data?
 Serial.print("Received: ");
 Serial.println(int(dataReceive)); // convert to integer to print the number
 newData = false; // reset flag
 }
}
void receiveEvent(int howMany) {
 if(howMany == 1) { // extra check, to check if one byte is received
 dataReceive = Wire.read();
 newData = true; // set flag, there is new data
 }
}
answered Mar 8, 2019 at 22:40
0

Here is my proposal to solve your issue:

  • Use the second Serial communication line of the master by connecting Rx and Tx Pins of Serial2 (this done only on master, practically a shortcut between Rx and Tx on Master)
  • Setup Serial2 if necessary: HardwareSerial Serial2(2); (that how it is necessary/done for my M5Stack)
  • Define baud rate for Serial2: Serial2.begin(9600);
  • Start your Automation by Serial2.write("R\n"); at an appropriate place in your code
  • Change conditions of if(..) and while(..) in your master's code from Serial.available() to Serial2.available()
  • Change incomingByte = Serial.read(); to incomingByte = Serial2.read();

With that solution you can still see your start signal printed out on your Serial monitor via the first Serial communication line. The communication to the slave is still working over IC2, Serial2 is only the proposal for the automation solution on master. Looks complicated, but this is how I understood the question, of course you also could directly use incomingByte="R\n"; to start your Automation and skip all that stuff with Serial2 :-)

answered Mar 8, 2019 at 21:51

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.