Louvre control code

Please help, Arduino coders, you’re my only hope!

Standard motor wiring, I am using dual L298N and an Arduino, OK so I have 8 important pins, 2 pins for each motor.

IN1, IN2, IN3, IN4, IN5, IN6, IN7, IN8

(see http://forum.arduino.cc/index.php?topic=361022.0 where I am trying to figure out if EN is also important, or it will just stay EN if jumpered to VCC)

So to open louvre 1, I drive IN1 high and IN2 low, to close 1, I drive IN1 low and IN2 high.

To keep it simple for me lets just say I have eight physical buttons, a button to open and a button to close each of the four louvres, when I quickly push the open louvre 1 button the motor should move slightly, if I hold it down the motor should keep running.

Can someone please assist with the Arduino code to do this for four motors?

I have a working implementation on a different Arduino board which runs all motors at the same time for 15 seconds (it has two physical buttons (open and close) and uses two case statements with a delay and a ton of digitalwrites, a quick press of the open button opens all the louvres fully) but I can't get my head around all the conditional logic to code the eight different permutations that I really want.

Thanks.

Richard

This is a complex job.

To break it up, I would tend to use classes. Each class has a setup() and loop() method which are called by the main setup() and loop()

The "Motor" class is set up with the two motor pins. It presents three methods - move(milliseconds), start(), and stop(). It's job is to work the motor, which may involve series of digitalwrites if it's a stepper.

The "Button" class is set up with a button and a reference to a motor. It watches a button pin and calls the motor methods appropriately. It's job is to note when the button was pressed, decide that a hold is in progress, start and stop it's motor appropriately.

The scaffolding looks like this:

class Motor {
    const int pin1;
    const int pin2;
    
  public:
    Motor(int pin1, int pin2) :
      pin1(pin1), pin2(pin2) {
    }

    void setup() {
    }

    void loop() {
    }
    
    void moveMs(unsigned long ms) {
    }
    
    void start() {
    }
    
    void stop() {
    }
};

class Button {
    const int pin;
    Motor &motor;
    
  public:
    Button(int pin, Motor &motor):
      pin(pin), motor(motor) {
    }

    void setup() {
    }

    void loop() {
    }
};

Motor motor[] {
  Motor(2, 3),
  Motor(4, 5),
  Motor(6, 7),
  Motor(8, 9),
};

Button button[] {
  Button(10, motor[0]),
  Button(11, motor[1]),
  Button(12, motor[2]),
  Button(13, motor[3]),
};

void setup() {
  for (int i = 0; i < 4; i++) {
    motor[i].setup();
    button[i].setup();
  }
}

void loop() {
  for (int i = 0; i < 4; i++) {
    motor[i].loop();
    button[i].loop();
  }
}

Every component gets a slice of time, and every component cares only about its own little world. Components can call methods on other components to signal them. Those other methods generally should not do things that take a long time: they should just setup the variables so that when loop() gets called, it will be doing the right thing.

The main body of the sketch initialises the components, assigns pins, wires them together and calls setup() and loop() for each one.

(EDIT)

Now, your motors are in sets of two. So I'd build another class "MotorSet". Its job would be to make sure that we are not running both the up and the down motor simultaneously. It would have move, start, and stop same as the motor() class, but with an additional parameter indicating direction. When a move was required it would make sure that the other motor of the pair was stopped (and handle the other motor not stopping immediately, eg there might be a decceleration delay). Button takes a MotorSet and an indication of whether it it the up or the down button for that set, and passes that though as the direction.

The other way to do this would be to make "Motor" aware of its partner, but this potentially creates loops in the control graph. Bad idea. I mean - in this instance it would work (because all a motor is doing is calling "stop" on its mirror), but its bad design.

Don't cross-post, your other thread deleted.

If I was going to the trouble of creating classes I think I would take the extra step and have methods such as UP and DOWN which take care of any internal conflicts that might arise.

I am not attracted to the idea of having loop() methods in the classes themselves as that creates the conceptual environment in which a class method can hog resources unless you take pains to ensure it does not.

If the control process just happens in the ordinary loop() function (with calls to the various class methods) the allocation of resources will be more transparent IMHO.

As an alternative to classes it would be possible to create arrays of motors and buttons - but I have to say that @PaulMurrayCbr's approach in neat.

...R