Control steppers with Photocell Code Help

Hi everyone... having a lot of fun learning here but I ran into a road block with my code...

Basically its almost working....

Here is the code as it sits.

void runWithButton()
{
  if(digitalRead(button) == LOW) while (analogRead(lightpin) > (initialReading + 100))
  {
   stepper2.setSpeed(500);
   stepper2.runSpeed();
  }
  if(digitalRead(button) == LOW) while (analogRead(lightpintwo) < (initialReadingtwo + 100))
  {
  stepper2.setSpeed(18);
  stepper2.runSpeed();
  }
}

Basically what is happening is that when I push the button the stepper runs until it trips the photocell at the faster speed.

I then have to push the button again to run at the slower speed and it stops when it trips the photocell.

I tried a bunch of things but wasn't able to get it to run at the faster speed and have it automatically switch to the slower speed...

Can someone give me a hint please? I'm stuck...

How many buttons do you have control the stepper motor.

void runWithButton()
{
  if(digitalRead(button) == LOW) while (analogRead(lightpin) > (initialReading + 100))
  {
   stepper2.setSpeed(500);
   stepper2.runSpeed();
  }
  if(digitalRead(button) == LOW) while (analogRead(lightpintwo) < (initialReadingtwo + 100))
  {
  stepper2.setSpeed(18);
  stepper2.runSpeed();
  }
}

Can you elobrate the problem compeltely

Why have you separated this question from your earlier Thread which has all the background?

I had to waste my time finding your earlier Thread.

Why haven't you posted a complete program?

What is this line supposed to do

if(digitalRead(button) == LOW) while (analogRead(lightpin) > (initialReading + 100))

Is it meant to be

if(digitalRead(button) == LOW) {
   while (analogRead(lightpin) > (initialReading + 100)) {
     stepper2.setSpeed(500);
     stepper2.runSpeed();
  }
}

If so it is hardly surprising if "the stepper runs until it trips the photocell"

I wonder if you intend to use WHILE at all ?

Even if it is intended to be as I have shown why set the speed over and over again inside the WHILE loop?

If the purpose of the WHILE is to call .runSpeed() repeatedly you should redesign the program so that runSpeed is called in loop()

...R

Robin2,

I apologize, I should have kept it in the same thread... and I should have posted the entire code set. For some reason I thought it was be less... "clutter".

Here is the complete code for my program.

I also formatted the code like you said... thank you for that input. I am only trying to work on the items inside the runWithButton(); under the void loop.

In regards to your commends about speed... I am calling out for two separate speeds and I honestly thought it was easier to just call out the values I wanted under the void runWithButton() area.

#include <AccelStepper.h>
#include <AFMotor.h>

#define encoderPinA  3
#define encoderPinB  2
#define button  0
#define buttontwo  1

int encoderPos = 0;
int encoderPinALast = LOW;
int encoderPinBLast = LOW;
int n = LOW;
int potpin = A0;
int val;
int lightpin = A1;
int lightpintwo = A2;
int initialReading;
int initialReadingtwo;


AF_Stepper motor2(200, 2);

// wrappers for the motor! SINGLE is default, can also use INTERLEAVE DOUBLE MICROSTEP
void forwardstep2() {  
  motor2.onestep(BACKWARD, INTERLEAVE);
}
void backwardstep2() {  
  motor2.onestep(FORWARD, INTERLEAVE);
}

// Motor shield has two motor ports, now we'll wrap them in an AccelStepper object
AccelStepper stepper2(forwardstep2, backwardstep2);

void setup()
{  
    stepper2.setMaxSpeed(1000.0);
    stepper2.setAcceleration(100.0);
    stepper2.moveTo(0);
    
    pinMode(encoderPinA, INPUT_PULLUP); 
    pinMode(encoderPinB, INPUT_PULLUP);
    pinMode(button, INPUT);
    pinMode(buttontwo, INPUT);
    initialReading = analogRead(lightpin);
    initialReading = analogRead(lightpintwo);
}

void loop() {
  runWithEncoder();
  runWithButton();
  runWithButtontwo();
}

void runWithEncoder()
{
  n = digitalRead(encoderPinA);
   if ((encoderPinALast != n )) {
     if (((n == HIGH) && (digitalRead(encoderPinB) == LOW)) || 
         ((n == LOW) && (digitalRead(encoderPinB) == HIGH))) {
       motor2.step(1, BACKWARD, INTERLEAVE);
     } else {
       motor2.step(1, FORWARD, INTERLEAVE);
     }
   } else {
     n = digitalRead(encoderPinB);
     if ((encoderPinBLast != n )) {
       if (((n == HIGH) && (digitalRead(encoderPinA) == LOW)) || 
           ((n == LOW) && (digitalRead(encoderPinA) == HIGH))) {
         motor2.step(1, FORWARD, INTERLEAVE);
       } else {
         motor2.step(1, BACKWARD, INTERLEAVE);
       }
     }
   }
   encoderPinALast = digitalRead(encoderPinA);
   encoderPinBLast = digitalRead(encoderPinB);
}

void runWithButton()
{
  if(digitalRead(button) == LOW) while (analogRead(lightpin) > (initialReading + 100))
  {
   stepper2.setSpeed(500);
   stepper2.runSpeed();
  }
  if(digitalRead(button) == LOW) while (analogRead(lightpintwo) < (initialReadingtwo + 100))
  {
  stepper2.setSpeed(18);
  stepper2.runSpeed();
  }
}

void runWithButtontwo()
{
  val = analogRead(potpin);
  val = map(val, 0, 1024, 1, 600);
  if(digitalRead(buttontwo) == LOW)
  {
    stepper2.setSpeed(val);
    stepper2.runSpeed();
  }
}

The code in Reply #3 has the same problem that I commented on in Reply #2

And you haven't commented on your decision to use WHILE (which seems to me to be the problem)

Maybe the second IF should be if(digitalRead(button) == HIGH)

If none of my suggestions solves the problem I think you need to write down very carefully in plain language (not code) exactly what you want to happen.

...R

So I made a video to help show what I am trying to accomplish and what I am having trouble with...

YouTube Video Here:

(I did make one mistake, I called the jog wheel a pot when it is actually a rotary encoder.

Here is the code as it sits... this is what I used in the video.

I basically need help with the void runWithButton() part of my void loop.

#include <AccelStepper.h>
#include <AFMotor.h>

#define encoderPinA  3
#define encoderPinB  2
#define button  0
#define buttontwo  1

int encoderPos = 0;
int encoderPinALast = LOW;
int encoderPinBLast = LOW;
int n = LOW;
int potpin = A0;
int val;
int lightpin = A1;
int lightpintwo = A2;
int initialReading;
int initialReadingtwo;


AF_Stepper motor2(200, 2);

// wrappers for the motor! SINGLE is default, can also use INTERLEAVE DOUBLE MICROSTEP
void forwardstep2() {  
  motor2.onestep(BACKWARD, INTERLEAVE);
}
void backwardstep2() {  
  motor2.onestep(FORWARD, INTERLEAVE);
}

// Motor shield has two motor ports, now we'll wrap them in an AccelStepper object
AccelStepper stepper2(forwardstep2, backwardstep2);

void setup()
{  
    stepper2.setMaxSpeed(1000.0);
    stepper2.setAcceleration(100.0);
    stepper2.moveTo(0);
    
    pinMode(encoderPinA, INPUT_PULLUP); 
    pinMode(encoderPinB, INPUT_PULLUP);
    pinMode(button, INPUT);
    pinMode(buttontwo, INPUT);
    initialReading = analogRead(lightpin);
    initialReading = analogRead(lightpintwo);
}

void loop() {
  runWithEncoder();
  runWithButton();
  runWithButtontwo();
}

void runWithEncoder()
{
  n = digitalRead(encoderPinA);
   if ((encoderPinALast != n )) {
     if (((n == HIGH) && (digitalRead(encoderPinB) == LOW)) || 
         ((n == LOW) && (digitalRead(encoderPinB) == HIGH))) {
       motor2.step(1, BACKWARD, INTERLEAVE);
     } else {
       motor2.step(1, FORWARD, INTERLEAVE);
     }
   } else {
     n = digitalRead(encoderPinB);
     if ((encoderPinBLast != n )) {
       if (((n == HIGH) && (digitalRead(encoderPinA) == LOW)) || 
           ((n == LOW) && (digitalRead(encoderPinA) == HIGH))) {
         motor2.step(1, FORWARD, INTERLEAVE);
       } else {
         motor2.step(1, BACKWARD, INTERLEAVE);
       }
     }
   }
   encoderPinALast = digitalRead(encoderPinA);
   encoderPinBLast = digitalRead(encoderPinB);
}

void runWithButton()
{
  if(digitalRead(button) == LOW) {
    while (analogRead(lightpin) > (initialReading + 100)) {
      stepper2.setSpeed(500);
      stepper2.runSpeed();
    }
  }
  if(digitalRead(button) == LOW) {
    while (analogRead(lightpintwo) < (initialReadingtwo + 100)) {
      stepper2.setSpeed(18);
      stepper2.runSpeed();
    }
  }
}

void runWithButtontwo()
{
  val = analogRead(potpin);
  val = map(val, 0, 1024, 1, 600);
  if(digitalRead(buttontwo) == LOW)
  {
    stepper2.setSpeed(val);
    stepper2.runSpeed();
  }
}

I've looked at your video and I can't say it added much to my knowledge - perhaps because it does not show the stepper motor.

If I understand correctly you want two options that don't interfere with each other.

On the one hand you want to be able to press a button (briefly) and cause the motor to move all the way as far as the point where a photodetector is tripped. You have a second button that causes the same action but in the opposite direction. Either of these buttons can leave the motor in any position between the two limits, or at one or other of the limits.

On the other hand you have a rotary encoder which you want to be able to rotate manually and have the motor move step-by-step as the encoder moves.

When using the encoder what is supposed to happen if the motor is already at one of the limits? I don't see any reference to the limits in the encoder function.

What happens if you comment-out the calls to the button functions? Does the encoder function then work properly?

I have to say that I don't immediately see why the encoder function won't work automatically after the motor has come to a stop following a button press.

I think I mentioned before that it would be better to take the actual movement code into a function of its own that is called by both the encoder function and the button functions. That way you would have only a single piece of motor code and the problem might be more obvious.

Another thought ... you don't make use of the absolute position of the motor. In most cases the limit switch is used to detect the zero position and all movements after that are done by telling the motor to move by a certain number of steps to some other specific position. For example a limit switch at the other end would be unnecessary because that end would be defined as (eg) step number 2765.

...R

There is no need for any limit switch for positional data.

I am working on making a 2nd video here... I didn't show any of the material in the 1st video because I am still waiting on parts.

Its connected to a powder tickler which only needs to be rotated in one direction (everything (buttons) moves it clockwise) you can move it counter clockwise using the rotary encoder but its not like that does anything for my setup.

The photosensors will be attached to a beam balance scale...
The bottom sensor will be obstructed by default like I mentioned in the video.
The button moves the tickler at a fast speed and the moment it starts to move, it stops per the video.
Pressing the button again will make it move at the slower speed.
The "high" sensor which moves at a slower speed, stops when tripped.

The extra button and rotary encoder are just there if you wanted manual control over the process.

Per the video, the automated process needs to be pressed twice in order for it to be completed. I wanted to automatically move from fast trickle to a slow trickle without used intervention.

I hope that helps, if not, stand by for a 2nd video which would hopefully clarify everything.

ProtoNoob:
There is no need for any limit switch for positional data.

Then why do you have one (or two) ?

Can you explain your problem by reference to Paragraphs 2, 3, 4, 5 and 6 of my Reply #6.
I'm afraid I find your descriptions very confusing.

...R