if else or what?1

What programming approach is apt for this:

I have a project which uses four electromagnets, one is on at any one time and a stepper motor moving between three positions. (There will also be some com stuff but that’s later).

I’d like to approach coding this so that I can change which electromagnet is on and in relation to where the stepper is, (and where it’s been and going to).

I was trying to use if else statements that someone had helped me with when it was just 2 electromagnets, but is there a better technique when choosing one of four?

LOOP INSTRUCTIONS:

A=====================

MAGNETS:

1 OFF
2 OFF
3 ON
4 OFF

STEPPER: MOVE FROM 0 to POSITION +1 (0-40 deg)

B=====================

MAGNETS:

1 ON
2 OFF
3 OFF
4 OFF

STEPPER: MOVE FROM +1 to POSITION 0 (-40 deg)

C=====================

MAGNETS:

1 OFF
2 OFF
3 OFF
4 ON

STEPPER: MOVE FROM 0 TO POSITION -1 (-80 deg)

D=====================

MAGNETS:

1 OFF
2 ON
3 OFF
4 OFF

STEPPER: MOVE FROM 0 TO POSITION 0 (+40 degrees)

ta

K

Part code attached

CHESS_AUG_11.ino.zip (1.98 KB)

Have a look at the Several Things at the same time sketch. It is a good approach. You basically want a state machine to step through each of your states. You also will want to make sure you don't do they entire servo move before finishing loop() so the program can be moving the servos as well as respond to COM port input, etc.

Next time, please post your updated code - in line - using code tags. That way we can actually see what you’ve posted.

Here’s an attempt previously done with if else for 2 magnets. I can’t get my head around doing this for 4 magnets. Any pointers? Ta

// 4 emagnets and stepper motor logic and order attempt.
// BOARD initial setup for stepper position

// BOARD starts at 0


//include stepper accel library
#include <AccelStepper.h>


AccelStepper stepper(2, 12, 13);

//stepper setup
const int pwmA = 3;
const int pwmB = 11;
const int brakeA = 8;
const int brakeB = 9;

//define an array of angles and timings (They must be the same length)
const int angles[] = {0, 80, 0, -80, 0}; // STARTS at 0 goes FORWARD to +1 then GOES BACK to 0, then goes to -1 POSITION then goes FORWARD to 0
const int accelerations[] = {40, 40, 40, 40, 40}; // this seems slowest can do with july gearing.

//this index is where we are right now in the array i.e. which index/position (starts at zero)
int index = 0;
//numberOfMoves is the length of the arrays (angles and timings WHICH MUST BE THE SAME LENGTH)
int numberOfMoves = 5;
int whichMagnet = 3;



int Electromagnet1 = 10; // NOW WHITE ROW 3 LEFT  - D10 ok
int Electromagnet2 = 4; // NOW WHITE ROW 3 RIGHT - D4 ok
int Electromagnet3 = 5; // NOW BLACK ROW 5 LEFT - D5 check  it's ok for shield
int Electromagnet4 = 6; // NOW BLACK ROW 5 RIGHT - D6 check it's ok for shield

int switchPin = 2;
int switchState ;
int lastSwitchState = LOW;   // the previous reading from the input pin

unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers


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

  //set output for stepper pins
  pinMode(pwmA, OUTPUT);
  pinMode(pwmB, OUTPUT);
  pinMode(brakeA, OUTPUT);
  pinMode(brakeB, OUTPUT);

  //set output for electromagnet pins
  pinMode(Electromagnet1, OUTPUT);
  pinMode(Electromagnet2, OUTPUT);
  pinMode(Electromagnet3, OUTPUT);
  pinMode(Electromagnet4, OUTPUT);



  pinMode(switchPin, INPUT_PULLUP);

  digitalWrite(pwmA, HIGH);
  digitalWrite(pwmB, HIGH);
  digitalWrite(brakeA, LOW);
  digitalWrite(brakeB, LOW);

  stepper.setMaxSpeed(1200);
  stepper.setSpeed(800);

  stepper.setAcceleration(40);
  delay(4000);
  switchState = 0;//digitalRead(switchPin);
  stepper.moveTo(0);

  Serial.println("going to zero");

  //
  setZeroPoint();

}

void loop() {


  // If no idea how to do this bit!

  if (stepper.distanceToGo() == 0) {
    stepper.run();                   // let the AccelStepper to disable motor current after stop
    delay(4000);                     // wait 2 sec in final position
    Serial.print("moving to ");
    Serial.print(angles[index]);
    Serial.print(" : ");
    Serial.println(accelerations[index]);
    ///turn magnet one off
    if (whichMagnet == 1) {
      magnetOneOnTwoOff();
      whichMagnet = 2;
    }
    //turn magnet two on
    //else mag 2 on one off
    else {
      magnetTwoOnOneOff();
      whichMagnet = 1;
    }

    stepper.setAcceleration(accelerations[index]);
    stepper.moveTo(angles[index]);
    index ++;
    //if we hit the end of the array then make the index 0 again
    if (index >= numberOfMoves) {
      index = 0;
    }
  }
  stepper.run();

}
void allMagnetsOff() { // (was bothMagnetsOff)
  digitalWrite(Electromagnet1, LOW);
  digitalWrite(Electromagnet2, LOW);
}

// VOID MAGNETS IN THIS ORDER 3,1,4,2 (A, B, C, D)

//A THREE ON.........................................3

void magnetThreeOnOneTwoFourOff() {
  Serial.println("magnet 3 on");
  digitalWrite(Electromagnet1, LOW);
  digitalWrite(Electromagnet2, LOW);
  digitalWrite(Electromagnet3, HIGH);
  digitalWrite(Electromagnet4, LOW);

}

//B ONE ON.........................................1
void magnetOneOnTwoThreeFourOff() {
  Serial.println("magnet 1 on");
  digitalWrite(Electromagnet1, HIGH);
  digitalWrite(Electromagnet2, LOW);
  digitalWrite(Electromagnet3, LOW);
  digitalWrite(Electromagnet4, LOW);

}

//C FOUR ON.......................................4
void magnetFourOnOneTwoThreeOff() {
  Serial.println("magnet 4 on");
  digitalWrite(Electromagnet1, LOW);
  digitalWrite(Electromagnet2, LOW);
  digitalWrite(Electromagnet3, LOW);
  digitalWrite(Electromagnet4, HIGH);
}

//D TWO ON.......................................2
void magnetTwoOnOneThreeFourOff() {
  Serial.println("magnet 2 on");
  digitalWrite(Electromagnet1, LOW);
  digitalWrite(Electromagnet2, HIGH);
  digitalWrite(Electromagnet3, LOW);
  digitalWrite(Electromagnet4, LOW);

}

//keep stepping until you get to the switch
//then move from there back to the middle
void setZeroPoint() {
  //switch all the magnets off (TODO)
  allMagnetsOff(); // was bothMagnetsOff


  Serial.print("switch state: ");
  Serial.println(switchState);
  //int lastSwitchState = !switchState;
  //
  //  int readings[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  //  int numReadings = 15;
  //  int readingIndex = 0;
  //  int totalNumReadings = 0;
  while (switchState == 0) {
    if ( digitalRead(switchPin) == 1) {

      switchState = 0;
    }
    else {
      switchState = 1;
    }
    Serial.print("step reading : ");
    Serial.println(switchState);

    stepper.moveTo(80);//change this to near end of rail just on initial setup position switch*******************************
    stepper.run();
    delay(10);

  }
  stepper.stop();
  stepper.setCurrentPosition(0);
  Serial.println("found zero");
  //steps back to middle will need to be manually calibrate once. once we know this we can just leave it
  int stepsBackToMiddle = -30;


  delay(4000); // TAKE THIS OUT ONCE SET******************************
  stepper.moveTo(stepsBackToMiddle);
  stepper.stop();
  stepper.setCurrentPosition(0);


  //switch first magnet on (TODO)

}

Have you tried extending this to 4 states - one after the other?

    if (whichMagnet == 1) {
      magnetOneOnTwoOff();
      whichMagnet = 2;
    }
    //turn magnet two on
    //else mag 2 on one off
    else {
      magnetTwoOnOneOff();
      whichMagnet = 1;
    }

Or maybe I don't understand what you want to achieve.

...R

Why not something like:

  switchOff (whichMagnet) ;
  whichMagnet += 1 ;
  if (whichMagnet > 4)
    whichMagnet = 1 ;
  switchOn (whichMagnet) ;

No need for conditionals, just switch the magnet off by its number, step to next, switch it on...

Then if you need to dispatch inside switchOff() and switchOn() use switch/case syntax.

You can use switch/case statement to switch between more options, though it is very easy to forget the break; statement at the end of each case (when the syntax was designed, it was the very early days of computing, and it wasn't obvious that 99% of the use-cases for switch/case would have a break; at the end of every case).

I think the compiler is smart enough that a switch/case and chain of if/else-if statements that do the same thing will generate the same output, ie, there isn't a difference in compiled sketch size. Personally I only use switch/case when there are a LOT of options, because it's so easy to forget a break; and then be baffled by the behavior of the sketch so produced.

How are you tracking the 0 position? I've noticed that A & B is on opposite directions (180 apart) same as C & D. To keep track of the prev position you might declare a global name.

When the stepper arrive in posA -does it change the magnetic flux in the electromagnet? How do you track this?

fnb111: How are you tracking the 0 position? I've noticed that A & B is on opposite directions (180 apart) same as C & D. To keep track of the prev position you might declare a global name.

When the stepper arrive in posA -does it change the magnetic flux in the electromagnet? How do you track this?

For tracking where 0 is on the stepper I have a mechanical switch when the board starts up it goes minus steps, stops, then counts forward to zero.

Not sure how to keep track of previous position.

Not sure how to keep track of previous position.

Variables are good for that. Normally call them lastPosition, make them equal to the new position just before you exit a loop.

Robin2: Have you tried extending this to 4 states - one after the other?

    if (whichMagnet == 1) {
      magnetOneOnTwoOff();
      whichMagnet = 2;
    }
    //turn magnet two on
    //else mag 2 on one off
    else {
      magnetTwoOnOneOff();
      whichMagnet = 1;
    }

Or maybe I don't understand what you want to achieve.

...R

Can you point me in the direxction of how I go about extending it? Do I need multiple if's, multiple else's one after another for each of the possible combos? I'd started to write these below.

(I am trying to get 3 magnets off and one magnet on in a particular order with a series of steppers.)

// VOID MAGNETS IN THIS ORDER 3,1,4,2
(A, B, C, D)

//A THREE ON.........................................3

void magnetThreeOnOneTwoFourOff() {
 Serial.println("magnet 3 on");
 digitalWrite(Electromagnet1, LOW);
 digitalWrite(Electromagnet2, LOW);
 digitalWrite(Electromagnet3, HIGH);
 digitalWrite(Electromagnet4, LOW);

}

//B ONE ON.........................................1
void magnetOneOnTwoThreeFourOff() {
 Serial.println("magnet 1 on");
 digitalWrite(Electromagnet1, HIGH);
 digitalWrite(Electromagnet2, LOW);
 digitalWrite(Electromagnet3, LOW);
 digitalWrite(Electromagnet4, LOW);

}

//C FOUR ON.......................................4
void magnetFourOnOneTwoThreeOff() {
 Serial.println("magnet 4 on");
 digitalWrite(Electromagnet1, LOW);
 digitalWrite(Electromagnet2, LOW);
 digitalWrite(Electromagnet3, LOW);
 digitalWrite(Electromagnet4, HIGH);
}

//D TWO ON.......................................2
void magnetTwoOnOneThreeFourOff() {
 Serial.println("magnet 2 on");
 digitalWrite(Electromagnet1, LOW);
 digitalWrite(Electromagnet2, HIGH);
 digitalWrite(Electromagnet3, LOW);
 digitalWrite(Electromagnet4, LOW);

}
byte order = {3,1,4,2}
// Then to step through them in order
for(int i = 0; i < 4; i++){ // magnets on one at a time
    for(int j =0; j< 4; j++){
       digitalWrite (order [j], LOW); // turn everything off
      }
  digitalWrite (order[i], HIGH); // turn next one on
// do stuff here like delay or count the number of steps or whatever 
}

Is this order the pins you have attached the motor windings to? The above code assumes it. if not then replace the numbers in the order array with the pin numbers you want to turn on in the order you want them on.

Thanks Mike, not the pins.

Mag 1 is pin 10 Mag 2 is pin 4 Mag 3 is pin 5 Mag 4 is pin 6

So for order 3, 1, 4, 2 should it be

byte order = {5,10,6,4}

Ok, it will still work if you change it like that.