0

The goal of my project is to be able to control two steppers with 4 buttons. Steppers are connected to Adafruit Motor shield(the older one) which is stacked on Arduino UNO, buttons are connected to Arduino NANO. I'm using I2C between the two Arduinos. However, if I push a button, the steppers won't rotate, only vibrate, but if I'm using only Arduino UNO with the motor shield stacked on it, button connected directly to the motor shield, it's working well. Arduino UNO is Master Reader, while NANO is Slave Writer. There is a fritzing image of the circuit. I don't know where's the problem, if it's in the circuit, if it's because of my battery(i bought it like 10 minutes ago) or the code. Any help is apreciated.

Master code:

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

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

void setup()
{
  Wire.begin(5); //begin i2c communication
  Wire.onReceive(receiveEvent);
  motor1.setSpeed(200);  // 10 rpm   
  motor2.setSpeed(200);  // 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 code:

#include <Wire.h>

//define buttons
const int button1 = 2; 
const int button2 = 3;
const int button3 = 8;
const int button4 = 7;

//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();
    }
} 
4
  • int are 2 bytes, but Wire.write() transmits only a byte at a time. Commented Mar 17, 2018 at 16:12
  • have you ran any test code on the Arduino Uno to make sure that the motors are connected correctly?
    – jsotola
    Commented Mar 17, 2018 at 18:10
  • @jsotola yes, they work if I don't use I2C. Commented Mar 17, 2018 at 18:12
  • Don't you know the solution for that? @jose can u c Commented Mar 17, 2018 at 18:13

1 Answer 1

0

In both master and slave, you have x and y declared in the broadest scope possible. Different devices, shouldn't matter. But x and y usual mean coordinates, which is not what you are trying to say - properly named variables help with understanding and maintenance.

I think your biggest issue, and one that confuses your attempts to debug, is the underlying logic.

  • You have 4 independent buttons, but prioritise one button over the other. What happens if both buttons are pressed together?
  • You have 2 independent motors but prioritise one after the other.
  • Your slave uses repeating code.
  • You use your slave as both a writer and decider. In this case, your writer is making the decisions over which motor to move and which direction.
  • Your master only makes one move at a time - but you have two motors and 4 buttons, so you should be able to move both motors in one loop.
  • Your handler expects the number of bytes to be read but you don't use that to control your reading.
  • Your consecutive reading does not differentiate on where the data comes from. x could be filled with any of the button presses, and so could y.
  • If the event handler is doing the work, why have a blocking delay in the code?

Effectively, you are taking a random read and expecting the device to do something deterministic. Hence your jittering.

To help you debug your device, you can first clean up your code.

  • reconfigure your slave to send a single response each loop. You only need 4 bits, where each bit represents whether buttons 1-4 are pressed. Only 1 variable to be written.
  • Use your master to decipher the input. This is where you can put the safety in (e.g. if both 1&2 are pressed/HIGH then ignore). This also reduces the possibility that your code is sending a forward then backwards signal.
  • Use your master to determine how many bytes have to be read and use this properly.

You will find your code cleaner, easier to read and easier to debug. Perhaps you will also see a way to directly slave the NANO to the UNO without i2C in the middle, simplifying your set up even more.

EDIT (additional information):

  • You can use the built in functions (see Arduino function reference under "Bits and Bytes") such as BitWrite/BitSet/BitClear and BitRead to set/clear the relevant bits on the variable you create (e.g. Byte ButtonStates). Note the use of Byte instead of Int
  • You can then use the slave to write the information and the master to read the information (Wire.write and Wire.read), you then know that each byte is complete and reflects what you intend.
2
  • Wow, you're pretty skilled in this area. This is a pretty great advice, however the problem is that I can't do the steps you mentioned alone. How is "reconfigure your slave to send a single response each loop. You only need 4 bits, where each bit represents whether buttons 1-4 are pressed. Only 1 variable to be written." possible? I'll try my best and thanks for the answer! @AJD Commented Mar 17, 2018 at 22:07
  • @RóbertPollák: answer updated to help you a little bit more.
    – AJD
    Commented Mar 18, 2018 at 0:26

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.