Going through a series of "while's" for a result

Hey folks me again.

I've made some good progress on my project, right now I'm trying to index the stepper motor axis

This runs through a few steps.

1: If the stepper is on the switch, continue rotating until it is no longer on the switch 2. rotate until the switch is pressed another time 3. back off of the switch until it is no longer pressed 4. set the table is indexed.

I need to figure out how to interrupt it with if the "STOP" switch is pressed too at some point, Right now I was trying to track this by "do step 1 until the state is good to go, then set a variable to "i'm done" and step 2 picks up if the "i'm done" variable is set to its value

Now this sort of kind of works, it appears my IF statements aren't good enough and aren't capturing from the previous loop since it will jump to the bottom instead of to the next step (or so it appears).

I'm almost 100% sure this is a terrible way of going about this, I dont need the code rewritten just show me how I should be doing this kinda flow

Thanks folks!

// index procedure function int indexfunction() { int indexresult = 0; //indexresult vars: --0=unindexed --1=indexed --2=first stage done --3=second stage done 4= third stage done int indexstate; int estopstate; indexstate = digitalRead(indexswitch); estopstate = digitalRead(estopbutton);

while (indexresult == 0) { while (indexstate == HIGH && estopstate != HIGH) { //Get off the switch if it is currently pressed digitalWrite(indexmotor, HIGH); delay(500); digitalWrite(indexmotor, LOW); indexstate = digitalRead(indexswitch); estopstate = digitalRead(estopbutton); lcd.setCursor(0, 0); lcd.print("Index Stage 1 "); //display indexing stage delay (200); } lcd.setCursor(0, 0); lcd.print("Index St 1 done"); //display indexing stage indexresult = 2; }

while (indexresult == 2) { //Step 2, keep rotating until switch is presed again while (indexstate == LOW && estopstate != HIGH) { //double loop for the variable digitalWrite(indexmotor, HIGH); delay(50); digitalWrite(indexmotor, LOW); delay(50); indexstate = digitalRead(indexswitch); estopstate = digitalRead(estopbutton); lcd.setCursor(0, 0); lcd.print("Index Stage 2 "); //display indexing stage } indexresult = 3; //after loop finishes check and set index stage lcd.setCursor(0, 0); lcd.print("Index St 2 done"); //display indexing stage delay (200); }

if (indexresult == 3) { //if index switch pressed and not estop and not indexed while (indexstate == HIGH && estopstate != HIGH) { //do this until index is no longer pressed digitalWrite(indexdir, HIGH); //rev stepper direction digitalWrite(indexmotor, HIGH); delay(50); digitalWrite(indexmotor, LOW); digitalWrite(indexdir, LOW); //untoggle stepper direction indexstate = digitalRead(indexswitch); estopstate = digitalRead(estopbutton); lcd.setCursor(0, 0); lcd.print("Index Stage 3 "); delay (200); } if (indexstate == LOW && estopstate != HIGH) { indexresult = 1; //after loop finishes check and set index stage lcd.setCursor(0, 0); lcd.print("Index Complete "); //display indexing stage lcd.setCursor(2, 1); lcd.print("P"); } } indexed = 1; lcd.setCursor(0, 0); lcd.print("Index exit "); //display indexing stage } //index function end

You seem to have this code in two places

while (indexstate == LOW && estopstate != HIGH) {

It would make the code easier to follow if all the code for that WHILE was put into a function - perhaps

void moveToSwitch() {
   while (indexstate == LOW && estopstate != HIGH) {
   // etc

}

and then the other code could be simplified to

while (indexresult == 2) {             //Step 2, keep rotating until switch is presed again
    moveToSwitch();
    indexresult = 3;                            //after loop finishes check and set index stage
    lcd.setCursor(0, 0);
    lcd.print("Index St 2 done");                   //display indexing stage
    delay (200);
  }

and then I ask myself if that while (indexresult == 2) would be better as if (indexresult == 2)

Putting code into functions avoids the need for repetitive typing and possible errors. It also allows the the function to be tested in isolation.

...R

Correct me if I’m wrong here robin

But while = continue looping until the condition is no longer true
and if would be = run this once

I need a while because it should continue running the motor until the condition is met, right?

True, but your while (indexresult == 0) { and while (indexresult == 2) { will always only be run once.

It is the inner while that repeats until condition is met, and as soon it finish, you change value of indexresult preventing the outer while to repeat.

Gabriel_swe:
It is the inner while that repeats until condition is met, and as soon it finish, you change value of indexresult preventing the outer while to repeat.

Yep. That is the sort of thing that was in my mind - without having formulated it as neatly.

…R

You've described a series of states with rules for when you change from one state to the other. I suggest you re-write the whole thing as a state machine.

The best tutorial I know of is from one of the forum members here: www.thebox.myzen.co.uk/Tutorial/State_Machine.html

metalmm: But while = continue looping until the condition is no longer true and if would be = run this once

I need a while because it should continue running the motor until the condition is met, right?

Remember though that the nature of while is to block other stuff, and don't forget that loop() keeps looping so your if is seen many thousands of times a second.

MorganS: You've described a series of states with rules for when you change from one state to the other. I suggest you re-write the whole thing as a state machine.

The best tutorial I know of is from one of the forum members here: www.thebox.myzen.co.uk/Tutorial/State_Machine.html

Thanks I'll look into it This blogs formatting sucks!

metalmm: This blogs formatting sucks!

Maybe because it's not a blog ;)

I dunno man, any website shouldn't have 2/3rds of his space solid white and restrict its content to a thin column :P

I did some searching and found this one too which seems to make more sense to me: https://learn.adafruit.com/multi-tasking-the-arduino-part-1/now-for-two-at-once

It looks like you make a loop, and then keep checking the time since last change rather than delaying on every pass, which is a neat idea.

I should have this done in a few hours then i'll post it back up to see if I'm doing this right

metalmm:
It looks like you make a loop, and then keep checking the time since last change rather than delaying on every pass, which is a neat idea.

Yep that’s Blink Without Delay thinking: probably similar to the example in the IDE at File > Examples > 2. Digital.

The adafruit tuts are usually very good.

Okay here's my cleaned up indexing function, first the table moves, I left delays in here because these are called on by the main function and I didnt see a reason to make it that complex

I'll probably swap around some variables and stuff so I'm not hammering the LCD with changes like this but that'll be later I also called a variable in my delays so I can play with that without editing so much stuff, which appears to work.

void motorcw() { digitalWrite(indexdir, LOW); digitalWrite(indexmotor, HIGH); delay(stepspeed); digitalWrite(indexmotor, LOW); lcd.setCursor(0, 3); lcd.print(" "); lcd.print("Moving Table"); //display indexing stage }

void motorccw() { digitalWrite(indexdir, HIGH); digitalWrite(indexmotor, HIGH); delay(stepspeed); digitalWrite(indexmotor, LOW); digitalWrite(indexdir, LOW); lcd.setCursor(0, 3); lcd.print(" "); lcd.print("Moving Table"); //display indexing stage }

Okay and the new indexing function is much smaller and cleaner without any delays so it should cycle really quickly like in the state example, but I haven't found a reason to do a state system yet.

It tracks indexresult for each stage of the process and since it now cycles really fast it should break out of the loop if estop is pressed just about instantly I think this is much better, let me know if I'm on the right track

// index procedure function int indexfunction() { int indexresult = 0; //indexresult vars: --0=unindexed --1=indexed --2=first stage done --3=second stage done --4=finishing up int indexstate; int estopstate; lcd.setCursor(0, 0); lcd.print(" "); // clear lcd lcd.setCursor(0, 0); lcd.print("Indexing table"); //display indexing table on lcd delay (200);

while (indexresult != 1 && startup == 1) { //Keep looping the function until indexed indexstate = digitalRead(indexswitch); estopstate = digitalRead(estopbutton); lcd.setCursor(0, 4); lcd.print("Loop start ");

if (indexstate == HIGH && estopstate != HIGH && indexresult == 0 ) { //Step 1 Get off the switch if it is currently pressed int motorcw(); lcd.setCursor(0, 4); lcd.print("Index Stage 1a "); //display indexing stage } if (indexstate == LOW && estopstate != HIGH && indexresult == 0 ) { //Step 1 part 2, keep rotating until switch is presed again while (indexstate == LOW && estopstate != HIGH) { //double loop for the variable indexstate = digitalRead(indexswitch); estopstate = digitalRead(estopbutton); int motorcw(); lcd.setCursor(0, 4); lcd.print("Index Stage 1b "); } indexresult = 3; //after loop finishes check and set index stage to enable next step lcd.setCursor(0, 4); lcd.print("Index Stage 1c "); } if (indexstate == HIGH && estopstate != HIGH && indexresult == 3 ) { //Step 3, Back off the switch for a good zero while (indexstate == HIGH && estopstate != HIGH) { //double loop for the variable indexstate = digitalRead(indexswitch); estopstate = digitalRead(estopbutton); int motorccw(); //back up off the switch lcd.setCursor(0, 4); lcd.print("Index Stage 2 "); lcd.setCursor(0, 0); lcd.print("Index Stage 2 "); } indexresult = 4; //after loop finishes Trigger final loop } if (estopstate != HIGH && indexresult == 4 ) { //Step 4, Housecleaning

lcd.setCursor(0, 0); lcd.print("Index Complete "); lcd.setCursor(2, 1); lcd.print("P"); indexresult = 1; //Set index variable to indexed } estopstate = digitalRead(estopbutton); if (estopstate = HIGH){ //if estop is pressed startup = 0; //unset variables indexresult = 0; //unset indexed int motorccw(); //back off one step to unload any stresses on table lcd.setCursor(0, 0); lcd.print("Table Stopped "); lcd.setCursor(0, 4); lcd.print("Table Stopped "); } } } //index function end

metalmm:
Okay here’s my cleaned up indexing function,

It’s a bit cheeky to complain about this Website in Replies #7 and #9 and then not use its features properly in Reply #11

You should post code using the code button </>

so your code looks like this

and is easy to copy to a text editor. See How to use the Forum

…R

Robin2: It's a bit cheeky to complain about this Website in Replies #7 and #9 and then not use its features properly in

So You want me to continue posting the steps where I'm hitting my head against the wall with this timer stuff and you can continue to be unhelpful or what?

If you don't use [ code ] tags when posting code then the forum software will eat some of your code. You are not allowed to complain about this. It's just one of the forum rules that helps us to help you.

Your functions that combine the motor outputs and LCD output are going to cause you problems in the future. Split them into separate functions.

metalmm: So You want me to continue posting the steps where I'm hitting my head against the wall with this timer stuff and you can continue to be unhelpful or what?

If you want help then help us to help you.

If you just want to bitch, that's fine too.

...R

So I've made a handful of progress for someone about 3 weeks into learning how to code, and I think I'm closer to best practices than the mess I had before.

Here's where I am:

I've broken out all of the individual operations into their own functions, the screen update checks to see if there has been a change before updating, the indexing function is controlled by a variable, and I've been finding problems by setting "feedback" variable to lines of code which get printed out on the LCD if that line is reached. I'm down to just one delay on the steps being fired but I've used millis() successfully in another test so I'll get around to fixing that later

So here's the deal At the last indexing line " search for feedback = 16" the arduino mega appears to sometimes lock up for from a second to like 5 seconds for some reason (after that time it responds to the estop button and will stop properly), I'm not sure why. I've even added an if to the main loop to bypass the indexing function if it has already run. Ideas?

I put the code up on pastebin:

https://pastebin.com/4gLd0WRX

metalmm: So here's the deal At the last indexing line " search for feedback = 16" the arduino mega appears to sometimes lock up for from a second to like 5 seconds for some reason (after that time it responds to the estop button and will stop properly),

I can't figure where that is in your program?

And, given that you now have the function buttoncheck(); why do you also have line 430

estopstate = digitalRead(estopbutton);

Can you provide a reminder of what the program is trying to do and how it is intended to operate?

...R

Robin2:
I can’t figure where that is in your program?

if (estopstate != HIGH && indexstep == 4 ) { //Step 4, Housecleaning
hstatus = 5;
mstatus = 6;
feedback = 16;
indexstep = 0;
indexresult = 1;

Thanks. There is nothing obvious in the few lines of code from Line 423 that would cause the Mega to lock up. Why do you think it is happening there?

Try putting a Serial.println("Houseclean done"); as the last thing in that IF clause.

Where does the program go when that IF completes?

I wonder if the code from line 431 onwards is needed at all? Or if it should be where it is - inside that function.

...R