1

First of all, I'm new to arduino. Check the EDIT line below the two codes.

I have connected motor shield to arduino uno. Connection between the two arduinos are A5 to A5, A4 to A4, 5V to 5V and GND to GND. I have a stepper connected to UNO, and a button connected to nano.

EDIT5: I deleted the messy previous codes, the question was answered. However, I cant get the steppers to rotate(they only vibrate). Any advice is appreciated. The code right now is:

Master

#include <Wire.h>
#include <AFMotor.h>
//define steppers
AF_Stepper motor1(48, 1); 
AF_Stepper motor2(48, 2);

//define variables
int x = 0;
int y = 0;

void setup()
{
  Wire.begin(5); //begin i2c communication
  Wire.onReceive(receiveEvent);
  motor1.setSpeed(10);  // 10 rpm   
  motor2.setSpeed(10);  // 10 rpm 

  motor1.release();
  motor2.release();
  delay(1000);
}

void loop()
{
  delay(500); // wait 0.5 second 
}

void receiveEvent(int howMany)
{
    //read x,y from slave
    x = Wire.read();
    y = Wire.read();

    if (x == 1) //stepper1 rotate forward
    {  
      motor1.step(100, FORWARD, SINGLE); 
    }
    else if (x == 2) //stepper1 rotate backward
    {
      motor1.step(100, BACKWARD, SINGLE); 
    }
     else if (y == 1) //stepper2 rotate forward
    {
      motor2.step(100, BACKWARD, SINGLE);
    }
     else if (y == 2) //stepper2 rotate backward
    {
      motor2.step(100, BACKWARD, SINGLE);
    }
} 

Slave

#include <Wire.h>

//define buttons
const int button1 = 2; 
const int button2 = 3;
const int button3 = 4;
const int button4 = 5;

//define state of buttons
int buttonState1 = 0;
int buttonState2 = 0;
int buttonState3 = 0;
int buttonState4 = 0;

//define variables
int x = 0;
int y = 0;

void setup()
{
   //start i2c communication
   Wire.begin();
}

void loop()
{
  //read state of buttons
  buttonState1 = digitalRead(button1);
  buttonState2 = digitalRead(button2);
  buttonState3 = digitalRead(button3);
  buttonState4 = digitalRead(button4);

    //if button1 is pressed,send x to master
    if(buttonState1 == HIGH){
      x = 1;
      Wire.beginTransmission(5);
      Wire.write(x);
      Wire.endTransmission();
    }
    //if button2 is pressed,send x to master
    else if(buttonState2 == HIGH)
    {
      x = 2;
      Wire.beginTransmission(5);
      Wire.write(x);
      Wire.endTransmission();
    }
    //if button3 is pressed,send y to master
    if(buttonState3 == HIGH){
      y = 1;
      Wire.beginTransmission(5);
      Wire.write(y);
      Wire.endTransmission();
    }
    //if button4 is pressed,send y to master
    else if(buttonState4 == HIGH)
    {
      y = 2;
      Wire.beginTransmission(5);
      Wire.write(y);
      Wire.endTransmission();
    }
} 
22
  • slave uses onReceive. your "Slave" code is master code
    – Juraj
    Commented Mar 16, 2018 at 14:47
  • @Juraj Yeah, I realised it. Don't you know how is it possible to make it work ? Commented Mar 16, 2018 at 14:52
  • @RóbertPollák What did you realise? If you realised, can't you fix it? In any case Arduino has a tutorial for when you want to transfer data from the slave to the master
    – frarugi87
    Commented Mar 16, 2018 at 15:07
  • @frarugi87 That tutorial is great, I followed the steps and worked. However, the problem was when I wanted to create what I wrote above. Button to control the stepper. Commented Mar 16, 2018 at 15:16
  • Well, instead of sending "hello" you have to send the button status. From the other part, instead of printing it you have to use it properly. Try modifying first the servo to send you '0' or '1' and the master prints it on the serial, then when it works modify the master to interprete it as a command. If you have problems (but I think you won't, since you already did it) you can ask showing what you did in the meantime
    – frarugi87
    Commented Mar 16, 2018 at 15:34

1 Answer 1

0

There are many ways to do this. The master could be the central unit which makes all the decisions, or the slave could preprocess the information.

It is best to start with a single byte to make it work. But I have made examples for two bytes anyway.

The next examples requests two buttons via i2c. You can change the HIGH and LOW into an integer value, but this is a start to make it work.

Master (without checking)

void loop()
{
  Wire.requestFrom(8,2);    // request 2 bytes from slave device #8
  int button1 = Wire.read();
  int button2 = Wire.read();

  Serial.print("button1=");
  Serial.println(button1 == HIGH ? "HIGH" : "LOW");

  Serial.print("button2=");
  Serial.println(button2 == HIGH ? "HIGH" : "LOW");

  // Some delay is needed, to prevent a 100% i2c bus load.
  // Perhaps 1 ms is enough, now 500 ms for testing.
  delay(500);
}

Master (with checking)

void loop()
{
  Wire.requestFrom(8,2);    // request 2 bytes from slave device #8
  if(Wire.available() == 2)   // are 2 bytes received ?
  {
    int button1 = Wire.read();
    int button2 = Wire.read();

    Serial.print("button1=");
    Serial.println(button1 == HIGH ? "HIGH" : "LOW");

    Serial.print("button2=");
    Serial.println(button2 == HIGH ? "HIGH" : "LOW");
  }
  else
  {
    Serial.println("The slave was not found");
  }

  // Some delay is needed, to prevent a 100% i2c bus load.
  // Perhaps 1 ms is enough, now 500 ms for testing.
  delay(500);
}

Slave (very simple)

void requestEvent()
{
  buttonState1 = digitalRead(button1);
  buttonState2 = digitalRead(button2);
  Wire.write( (byte) buttonState1);
  Wire.write( (byte) buttonState2);
}

Slave (advanced, update button state in the loop)

#include <Wire.h>

const int button1Pin = 2;
const int button2Pin = 3;

// Variables that are used in a interrupt and also outside
// that interrupt must be declared as volatile.
// Then the compiler knows that they can change at any moment.
volatile byte buttonState1;
volatile byte buttonState2;

void setup()
{
  pinMode(button1Pin,INPUT);
  pinMode(button2Pin,INPUT);
  Wire.begin(8);                // join i2c bus with address #8
  Wire.onRequest(requestEvent); // register event
}

void loop()
{
  // keep the variables updated with the latest information.
  buttonState1 = (byte) digitalRead(button1Pin);
  buttonState2 = (byte) digitalRead(button2Pin);
}

// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent()
{
  // send the two bytes.
  Wire.write(buttonState1);
  Wire.write(buttonState2);
}
4
  • Avoid comments like "+1" or "thanks", but still, thank you @Jot. Anyways, I managed to write a code that's running, but the steppers are just vibrating, not rotating. Any solution for it? Commented Mar 16, 2018 at 21:15
  • That is an other problem. Try to make a small test sketch (without using the i2c bus and the other board) to test it. It means there not enough power or the wrong driver or electrical noise that backfires into the arduino board. You know that the motor shield that you are using is the worst, cheapest, weakest motor shield there is? It can drive only a very, very, very small toy motor. Maybe not even that.
    – Jot
    Commented Mar 16, 2018 at 21:21
  • When I used it without i2c bus, only with the shield and one button(because only pin D2 is free on that shield and analog pins) it was working okay, but now, with this setup, its not working. Commented Mar 16, 2018 at 21:25
  • You could add a check in the receiveEvent if the howMany == 1. Since a single byte is expected it should be 1. Calling the motor.step from an interrupt function might cause problems. If possible, you should do such things in the Arduino loop(). Don't fill the i2c bus with 100% load. Add a delay in the master Arduino. Start at least with 100 ms. Work cleaner! with the code and explanation. You have now called the master the slave and the other way around.
    – Jot
    Commented Mar 16, 2018 at 21:34

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.