Better way to control 4 dc motors with 4 buttons?

I'm making a program that controls 4 motors with 4 buttons. I need to know if there is a better way of achieving my desired outcome.
It's function:
when the button one is pressed motor one should move forward for a certain time. stop and reverse till it reaches its original position. User can select multiple motors or any combination of motors by pressing a certain combination of those 4 buttons.
JC button library is useful for debouncing and long presses etc. so I'm using that.

what i want:
for a way to reduce the repeated coding and an efficient way of achieving this.

my current code:

#include <JC_Button.h>


//i'm  using stm32 instead  of arduino. which is why the port numbers  are different.
Button btnM1(PB1);  //initialising button object  which will then initialize by pulling  up the pins.. (required by  library)
Button btnM2(PB0);
Button btnM3(PB10);
Button btnM3(PB11);


#define m11 PB3   //motor1 in1 
#define m12 PB4   //motor1 in2
#define m21 PB5   //motor2 in1   etc...
#define m22 PB6
#define m31 PB7
#define m32 PB8
#define m41 PA12
#define m42 PA15

int pin[8] = {m11, m12, m21, m22, m31, m32, m41, m42}; //just so i can initialize and read  the states quickly.
int values[8];   //for storing values.

enum states_t {M1, M2, M3, M4, M1M2, M1M3, M1M4, M2M3, M2M4, M3M4};  //M1 = ONLY RUN MOTOR ONE,   M3M4,  ONLY RUN MOTOR 1 AND MOTOR 4.
void setup() {
  btnM1.begin();
  btnM2.begin();
  btnM3.begin();
  btnM4.begin();  //INITIALISES THE PINS PULLED UP
  for (int i = 0; i < 8; i++)
  {
    pinMode(pin[i], OUTPUT);
  }
  for (int i = 0; i < 8; i++) //TURNED THEM ALL HIGH  TO CHECK WETHER THEY ARE WORKING.
  {
    digitalWrite(pin[i], HIGH);
  }
  // Initialize the built-in LED pin as an output:
  pinMode(PC13, OUTPUT);  //LED OUTPUT FOR CHECKING
  Serial.begin(115200);
}



void loop() {
  // Check if the button is pressed.
  static states_t STATE;
  btnM1.read();
  btnM2.read();
  btnM3.read();
  btnM4.read();

  for (int i = 0;  i < 8; i++)
  {
    values[i]  =  digitalRead(pin[i]);   //READING MOTOR PIN STATES
  }
  //move motor 1,  stop and reverse.


  if (btnM1.pressedFor(2000)) STATE = M1;
  if (btnM2.pressedFor(2000)) STATE = M2;
  if (btnM3.pressedFor(2000)) STATE = M3;
  if (btnM4.pressedFor(2000)) STATE = M4;
  if (btnM1.pressedFor(2000) && btnM2.pressedFor(2000)) STATE = M1M2;
  if (btnM1.pressedFor(2000) && btnM3.pressedFor(2000)) STATE = M1M3;
  if (btnM1.pressedFor(2000) && btnM4.pressedFor(2000)) STATE = M1M4;
  if (btnM2.pressedFor(2000) && btnM3.pressedFor(2000)) STATE = M2M3;
  if (btnM2.pressedFor(2000) && btnM4.pressedFor(2000)) STATE = M2M4;
  if (btnM3.pressedFor(2000) && btnM4.pressedFor(2000)) STATE = M3M4;
  if (btnM1.pressedFor(2000) && btnM2.pressedFor(2000)) STATE = M1M2;

  //as you can see i have to repeat this process  for all 8 possibillities. 

  Switch(STATE)
  {
  case M1:
    digitalWrite(m11, HIGH);   //go forward
    digitalWrite(m12, LOW); 
    delay(2000);               //for a while
    digitalWrite(m11,LOW); 
    digitalWrite(m12, HIGH);   //go back to original  position  
    delay(2000); 
    digitalWrite(m11,LOW); 
    digitalWrite(m12, LOW);   //stop  motor     
    break;


  case M2:
    break;

  case M3:
    break;

  case M4:
    break;

  case M1M2:  //now motor 1 and motor 2 will move in the same manner as m1 simultaneously.. 
    digitalWrite(m11, HIGH);   //go forward
    digitalWrite(m12, LOW); 
    digitalWrite(m21, HIGH);
    digitalWrite(m22, LOW);
    delay(2000);               //for a while
    digitalWrite(m11,LOW); 
    digitalWrite(m12, HIGH);   //go back to original  position  
    digitalWrite(m21, LOW);
    digitalWrite(m22, HIGH);
    delay(2000); 
    digitalWrite(m11,LOW); 
    digitalWrite(m12, LOW);   //stop  motor  
    digitalWrite(m21, LOW);
    digitalWrite(m22, LOW);
    break;

  }

}

NOTE: the motors only need to go forward and backward.. no speed control is necessary.

There is a LOT more engineering needed to be done.

  1. You need to have some way for your program to know where motor one begins movement and how to know when it returns to the location.
  2. You need some way to reverse the polarity of the power to the motor so it will run in the opposite direction.
    You need to have the identical components for EACH motor.
    Forget the code for now, until you have the design completed and the components on hand.
  3. You need to plan for a power supply that will supply the voltages and current necessary for all the motors and other components.

hi. i have already done that part. for now I'm simply going to operate the motors with delay. later I'm going to install limit switches.. the power supply and everything else has been resolved. just need the code right now. for polarity I'm using relay module configured as h bridge. i should have added a note saying "electrical side is done and working"

Yes, that would have been such a big help.
Begin with a small part of what code you need and get that working. Then add the next component and test, test, test.
Never try to write a masterpiece at one time and then try to test.

consider (only had 3 buttons)

// check multiple buttons and toggle LEDs

enum { Off = HIGH, On = LOW };
enum { Forward = LOW, Reverse = HIGH };

const byte    PinMot1  = 10;
const byte    PinMot2  = 11;
const byte    PinMot3  = 12;
const byte    PinDir   = 13;

byte pinsMot [] = { PinMot1, PinMot2, PinMot3 };
byte pinsBut [] = { A1, A2, A3 };
#define N_BUT   sizeof(pinsBut)

byte butState [N_BUT];

#define Period 1500

// -----------------------------------------------------------------------------
int
chkButtons ()
{
    for (unsigned n = 0; n < sizeof(pinsBut); n++)  {
        byte but = digitalRead (pinsBut [n]);

        if (butState [n] != but)  {
            butState [n] = but;

            delay (10);     // debounce

            if (On == but)
                return n;
        }
    }
    
    return -1;
}

// -----------------------------------------------------------------------------
void
driveMotor (
    byte          pin,
    unsigned long period )
{
    digitalWrite (pin, On);
    digitalWrite (PinDir, Forward);
    delay (period);

    digitalWrite (PinDir, Reverse);
    delay (period);
    digitalWrite (pin, Off);
}

// -----------------------------------------------------------------------------
void
loop ()
{
    switch (chkButtons ())  {
    case 2:
        driveMotor (PinMot3, Period);
        break;

    case 1:
        driveMotor (PinMot2, Period);
        break;

    case 0:
        driveMotor (PinMot1, Period);
        break;
    }
}

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

    for (unsigned n = 0; n < sizeof(pinsBut); n++)  {
        pinMode (pinsBut [n], INPUT_PULLUP);
        butState [n] = digitalRead (pinsBut [n]);
    }

    for (unsigned n = 0; n < sizeof(pinsMot); n++)  {
        digitalWrite (pinsMot [n], Off);
        pinMode      (pinsMot [n], OUTPUT);
    }

    pinMode      (PinDir, OUTPUT);
}

thanks for such a detailed reply. appreciate it. as you can see in switch case I'll have to make many cases for each button combination and as a result, call driveMotor function many times. i wanted to get around this repeating behavior.

doesn't sound very complicated, seems you want to do the same thing for each pair of button/motor

capture a behavior in a sub-function with arguments for the motor or pins

sure... i'll try this.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.