Continuously Loop whilst a condition is true when a case has been triggered

Hey guys, so basically I’m trying to build a tennis machine, and my first obstacle is turning a stepper motor 90 degrees, but ONLY each time that the laser signal is broken, after the case has been loaded (I’m using serial monitor and inputting case numbers to simulate).
The case number will be sent across using bluetooth from an android app (but that’s a separate topic).

The problem i’m having is that once I input the case number, the code runs once; then I have to input the case number again, and it will run again. I need the code to run continuously once I input the case number once, until I input a different case number.

I’ve been through the forums trying various FOR and WHILE loop variations, but to no avail.

Any help would be greatly appreciated!

#include <AccelStepper.h>

const int stepsPerRevolution = 200;

AccelStepper ballHopperStepper = AccelStepper (2, 3, 4);
#define DETECT 28 // pin 28 for  sensor
#define pwmPin1 12
#define pwmPin2 13
#define controlPin1 A0
#define controlPin2 A1
#define stepsPerRevolution 200
int val = 0;
int state = 0;
int start = 0;
int stop1 = 49;

void setup() {
  pinMode(DETECT, INPUT);
  ballHopperStepper.setMaxSpeed(1000);
  ballHopperStepper.setAcceleration(500);
  Serial.begin(9600);
}

void loop() {

  //int potValue = analogRead(controlPin1);

  //int pwm1 = map(potValue, 0,1023, 0,255);


  if (Serial.available() > 0) {
    state = Serial.read();

    int detected = digitalRead(DETECT);

    Serial.println(ballHopperStepper.currentPosition());

    switch (state) {
      case '0':

        while (start <= stop1) {
          if (detected == LOW) {
            Serial.println("Ball detected!");
            delay(2000);
            ballHopperStepper.moveTo(ballHopperStepper.currentPosition() + 400);
            ballHopperStepper.runToPosition();
            delay(2000);
          } else {
            Serial.println("Waiting for ball in play");
          }

          break;

        case '1':
          ballHopperStepper.moveTo(ballHopperStepper.currentPosition() - 400);
          ballHopperStepper.runToPosition();
          delay(2000);
          break;

        }
    }

When does change the value of variable start?

You mean the Case value? That has no predefined time, it’s whenever the user presses a button that corresponds to the case.

Unless I missed something, it looks like variable start is only initialized to zero, and never changed () the same for stop1), so the while loop runs forever.

I tried using for (int i = 0; i < stop1; i++), but same problem.

Okay, so i’m doing a bit of testing again…when I change it to this, the rotate90() function continues to loop, however, if I point laser to receiver (i.e. convert detected == LOW to detected == HIGH), there is no change; the code continues to run function rotate90()

#define DETECT 28
#include <AccelStepper.h>
AccelStepper ballHopperStepper = AccelStepper (2, 3, 4);
int state = 0;

void setup() {
  pinMode (DETECT, INPUT);
  ballHopperStepper.setMaxSpeed(1000);
  ballHopperStepper.setAcceleration(500);
  Serial.begin(9600);
}

void loop() {
  int detected = digitalRead(DETECT);
  // put your main code here, to run repeatedly:
  if (Serial.available() > 0) {
    state = Serial.read();
  }
  for (int i = 0; (i < 1000) && detected == LOW && state == '0'; i++) {
    rotate90();

  }
}

void rotate90() {
  Serial.println("Ball detected!");
  delay(2000);
  ballHopperStepper.moveTo(ballHopperStepper.currentPosition() + 400);
  ballHopperStepper.runToPosition();
  delay(2000);
}

Whatever is the type of the loop, if you do not change the value of at least one of the variable involved in the test, the loop will loop forever (a.k.a. infinite loop).

Okay, but in my most recent version, the detected variable must be LOW along with other conditions in order for the code to loop. So why is it that when I change the variable by pointing the laser to the receiver, it does not update to change detected to HIGH?

Referring to the code in Reply #5

This FOR loop

  for (int i = 0; (i < 1000) && detected == LOW && state == '0'; i++) {

will prevent any change in the value of detected or state from being checked until the 1000 iterations are done.

Do it much more simply like this

if (detected == LOW and state == '0') {

and allow loop() to do the repetition.

…R

Hi Robin, I've changed the code to the following, however, still the same issue.

void loop() {
  int detected = digitalRead(DETECT);
  if (Serial.available() > 0) {
    state = Serial.read();
  }
  if (state == '0' && detected == LOW) {
        rotate90();
    }else{
      Serial.println("Waiting for ball in play");
    }
  }

What I did notice however, is that if I remove state == '0', and just have it look for detection, it works in real time, but this is because it is continuously sending a response to the serial monitor when detected == LOW or HIGH. When I enter 0 in the serial monitor, that is only once, so it makes sense that the code is only looped each time I type 0 and send. However, in real life, I need the program to receive that state value ONCE, and loop through rotate90() whilst detected == LOW; and then stop running when detected == HIGH.

I come to this very late, but it sounds like you have state changing when you don't want it to?

state only gets updated when Serial.read() happens which only happens when Serial.availale() is >0.

That means in theory, state will stay 0 until you send something else, otherwise there will be no Serial.read().

What's your serial monitor line ending? If it's not set to none, there will be a new line and or a carriage return in the buffer that will get read next time round, and change state away from 0.

(But I apologise if my tardiness to the party means I misread the problem :wink: )

Ah that makes sense! However, if I change the state to '1', it still only runs the code once. I think I need it to check for the state number entered each time it loops.

I haven't looked very closely, truth be told; more of a sort of en passant.

jubukraa:
What's your serial monitor line ending? If it's not set to none, there will be a new line and or a carriage return in the buffer that will get read next time round, and change state away from 0.

This is critical - what do you have it set to?

paulsamaroo:
Hi Robin, I've changed the code to the following, however, still the same issue.

Please post the complete program (always).

...R

I think the problem is that my logic is wrong. I think that getting state == ‘1’ to continuously send whilst loop is running, is the only way to achieve what I want, which is to continuously check if detected == LOW or HIGH, once state entered is 1.

#define DETECT 28
#include <AccelStepper.h>
AccelStepper ballHopperStepper = AccelStepper (2, 3, 4);

void setup() {
  pinMode (DETECT, INPUT);
  ballHopperStepper.setMaxSpeed(1000);
  ballHopperStepper.setAcceleration(500);
  Serial.begin(9600);
}

int state = 0;

void loop() {
  int detected = digitalRead(DETECT);
  if (Serial.available() > 0) {
    state = Serial.read();
  }
  if (state == '1') {
    if(detected == LOW){
      rotate90();
    }else{
      Serial.println("Waiting for ball in play");
    }
  }
}



void rotate90() {
  Serial.println("Ball detected!");
  delay(2000);
  ballHopperStepper.moveTo(ballHopperStepper.currentPosition() + 400);
  ballHopperStepper.runToPosition();
  delay(2000);
}

void rotateNeg90() {
  Serial.println("Ball Not detected!");
  delay(2000);
  ballHopperStepper.moveTo(ballHopperStepper.currentPosition() - 400);
  ballHopperStepper.runToPosition();
  delay(2000);
}

That's not a complete (= compileable) sketch.

You've still not said what the line end is (bottom middle):

Okay, I’ve edited the code above accordingly.

Also, see below for output window

You surely want that to be "No line ending"

edit... If you do a serial print of state, you'll see your 0 or 1 or whatever you send, followed next time through loop by a 10, the code for Newline.

edit edit: actually you'll get a 48 or 49 (the code for 0 or 1) followed by a 10.

WTF! LOL so all I had to do was change it from New Line to No Line Ending for it to work as intended?!
Amazing! Thanks very much @jubukraa and everyone else!
See below for final code.

#define DETECT 28
#include <AccelStepper.h>
AccelStepper ballHopperStepper = AccelStepper (2, 3, 4);

void setup() {
  pinMode (DETECT, INPUT);
  ballHopperStepper.setMaxSpeed(1000);
  ballHopperStepper.setAcceleration(500);
  Serial.begin(9600);
}

int state = 0;

void loop() {
  int detected = digitalRead(DETECT);
  if (Serial.available() > 0) {
    state = Serial.read();
  }
  if (state == '1') {
    if(detected == LOW){
      rotate90();
    }else{
      Serial.println("Waiting for ball in play");
    }
  }

  if(state == '2'){
    rotateNeg90();
  }
}



void rotate90() {
  Serial.println("Ball detected!");
  delay(2000);
  ballHopperStepper.moveTo(ballHopperStepper.currentPosition() + 400);
  ballHopperStepper.runToPosition();
  delay(2000);
}

void rotateNeg90() {
  Serial.println("Ball Not detected!");
  delay(2000);
  ballHopperStepper.moveTo(ballHopperStepper.currentPosition() - 400);
  ballHopperStepper.runToPosition();
  delay(2000);
}