Limit Switches and stepper and servo

Hi

I want to expand on the project I am working on. I have done some work already but as I am a newbie so not sure If am heading towards right direction. Its a Pan and tilt camera system with emerging through robot with a door . (like a convertible car).
I want my system to works as follows:
components: Pan and tilt camera system mounted on a vertical linear actuator powered by a bipolar stepper motor.
working.
Step 1. check if the pan and tilt camera is at bottom position.
step 2. if at bottom or default position. Open the door or canopy via servo motor.
step 3. if door fully opened stepper motor should run extending the pan and tilt system.
step 4. if pan and tilt system fully extended door should close.

after playing around with robot its time for the camera to retract inside the robot.

step5. open the door.
step 6. retract the pan/tilt system
step 7 close the door.

#include <Stepper.h>

#include <Servo.h>

#define pushButton 4
#define topSwitch 3
#define bottomSwitch 2

#define servoPin 7
#define closeCanopy 1500
#define openCanopy 1900

Servo canopyServo;

#define stepperStepPin 9
#define stepperDirectionPin 8

const int stepperMaxRPM = 300;
const int stepsPerRevolution = 200;

Stepper myStepper (stepsPerRevolution, stepperStepPin, stepperDirectionPin);

int servoSpeed = 5;
int servoDelay = 15;

int canopyPosition;

void setup()
{
  Serial.begin(9600);
  pinMode (topSwitch, INPUT_PULLUP);
  pinMode (bottomSwitch, INPUT_PULLUP);

  canopyServo.attach (servoPin, closeCanopy, openCanopy);
  canopyServo.writeMicroseconds (closeCanopy);



  myStepper.setSpeed(stepperMaxRPM);

 // Serial.println ("In SETUP");
  //Serial.println (closeCanopy);
  //Serial.println("Canopy CLOSED FIRST TIME");

}


void loop()
{
	

	
  if (digitalRead (bottomSwitch) == LOW)
  {
    canopyServo.writeMicroseconds(openCanopy);
    delay(1000);
    Serial.println("CANOPY OPEN");
  }

  if (digitalRead(bottomSwitch) == LOW && digitalRead(topSwitch) == HIGH)
  {
    while (digitalRead (topSwitch) != LOW)
    {
      myStepper.step(1);
      
    }
    //Serial.println("Actuator GOING UP");
  }

  if(digitalRead (topSwitch) == LOW && digitalRead(bottomSwitch) == HIGH)
  {
    canopyServo.writeMicroseconds(closeCanopy);
    Serial.println("CANOPY CLOSES 2nd time");
  }

  if (digitalRead(pushButton) == HIGH)
  {
    canopyServo.writeMicroseconds(openCanopy);
    Serial.println("Canopy OPENS AGAIN");
    delay(3000);
    while (digitalRead (bottomSwitch) != LOW)
    {
      myStepper.step(-1);
      //Serial.println("Actuator GOING DOWN");
      //if(digitalRead(bottomSwitch) == LOW)
        //break;
    }
  }

  if(digitalRead(bottomSwitch) == LOW && digitalRead(topSwitch) == HIGH)
  {
    canopyServo.writeMicroseconds(closeCanopy);
    //Serial.println("CANOPY CLOSES FINALLY");
  }




}

I want my system to works as follows:

So, what's the problem?

It is not working the way I intend to. On step 6 when the pan/tilt system is going down and the moment it touches the bottom limit switch it starts to move upwards again. The first while loops gets initiated somehow. So after step 6 it goes back to step 3 and starts over at from step 3.

I want to somehow break out of the while loop once the pan/tilt has reached its position and has hit the limit switch so that it does not go back to it again until the code till last curly bracket has been taken care of in the void loop().

So after step 6 it goes back to step 3 and starts over at from step 3.

It would be nice to see some comments in the code that show what code you think is related to steps 3 and 6.

How does the Arduino know when "after playing around with robot its time for the camera to retract inside the robot." should happen?

#include <Stepper.h>

#include <Servo.h>

#define pushButton 4                  // to turn on the steps to open the canopy and for pan/tilt to go down
#define topSwitch 3                     // limit switch at the top of actuator
#define bottomSwitch 2             // limt switch at bottom of actuator

#define servoPin 7                       //servo motor to open and close the canopy
#define closeCanopy 1500        // minimum angle in microseconds. canopy closes at this value
#define openCanopy 1900       // maximum angle in microseconds. canopy opens at this value

Servo canopyServo;

#define stepperStepPin 9       //output pin for stepper motor
#define stepperDirectionPin 8      //output pin for stepper motor

const int stepperMaxRPM = 300;
const int stepsPerRevolution = 200;

Stepper myStepper (stepsPerRevolution, stepperStepPin, stepperDirectionPin);

int servoSpeed = 5;
int servoDelay = 15;

int canopyPosition;

void setup()
{
  Serial.begin(9600);
  pinMode (topSwitch, INPUT_PULLUP);
  pinMode (bottomSwitch, INPUT_PULLUP);
 pinMode(pushButton, INPUT_PULLUP);

  canopyServo.attach (servoPin, closeCanopy, openCanopy);
  canopyServo.writeMicroseconds (closeCanopy);



  myStepper.setSpeed(stepperMaxRPM);

 // Serial.println ("In SETUP");
  //Serial.println (closeCanopy);
  //Serial.println("Canopy CLOSED FIRST TIME");

}


void loop()
{
	

	
  if (digitalRead (bottomSwitch) == LOW)             //checking if the bottom limit switch is presses. if yes then open the canopy
  {
    canopyServo.writeMicroseconds(openCanopy);  //opening canopy/door
    delay(1000);
    Serial.println("CANOPY OPEN");
  }

  if (digitalRead(bottomSwitch) == LOW && digitalRead(topSwitch) == HIGH)   //next checking both upper and lower limit //switches
  {
    while (digitalRead (topSwitch) != LOW)   // to check if the top limit switch has been pressed.
    {
      myStepper.step(1);                     //stepper motor turns to push actuator up until the top limit switch is pressed.
      
    }
    //Serial.println("Actuator GOING UP");
  }

  if(digitalRead (topSwitch) == LOW && digitalRead(bottomSwitch) == HIGH)   //actuator reached top position
  {
    canopyServo.writeMicroseconds(closeCanopy);                              //if above conditions true then close the canopy
    Serial.println("CANOPY CLOSES 2nd time");
  }

// time to retract the pan/tilt system

  if (digitalRead(pushButton) == LOW)              //push button telling robot to open the canopy door and retract the pan/tilt
  {
    canopyServo.writeMicroseconds(openCanopy);       //opens canopy
    Serial.println("Canopy OPENS AGAIN");
    delay(3000);                                                                             //waits for 3 seconds
    while (digitalRead (bottomSwitch) != LOW)                //actuator moves down till the bottom limit switch is pressed
    {
      myStepper.step(-1);
      //Serial.println("Actuator GOING DOWN");
      //if(digitalRead(bottomSwitch) == LOW)
        //break;                                                       //trying to use break command to break out of while loop once it has reached bottom
    }
  }

  if(digitalRead(bottomSwitch) == LOW && digitalRead(topSwitch) == HIGH)  //checks for the states of limit switches again
  {
    canopyServo.writeMicroseconds(closeCanopy);                        // if pan/tilt at bottom, then canopy closes
    //Serial.println("CANOPY CLOSES FINALLY");
  }

Thanks for pointing that out.

There is a push button which when pressed should open the canopy, retract the pan/tilt and close the canopy.

Sorry, I can't do the scrolling back and forth as well as up and down.

Useful comments explain what a block of code is going to do:

// This is step one
if(stepOneSwitchPressed)
   stepOne();

They, therefore, do NOT go at the end of a line of code.

Notice in the snippet of code above that the comment is pretty much unnecessary, since it is obvious from the name of the function what will happen. Notice, too, that the work is NOT done in loop(). It is done in a separate function. Your loop() function should be very short. All it should do is read some switches and call some functions, as appropriate.

All right, Thanks for the help. I will try to modify according to your advice.

You should separate the reading of switches into one function and the movement of motors into another.

You need a series of variables to define the different states of the system - such as atBottom, doorOpen, isRising etc. These will probably fit neatly into an expanded version of the steps you listed in your first post.

Then your movement code will move from one state to the next. The states will probably be set by the various limit switches and the user push button.

...R

You should separate the reading of switches into one function and the movement of motors into another.

I'll have to disagree, to some extent.

One of the functions is to open the door, until a limit switch indicates that the door is all the way open. In that case, the limit switch needs to be read in the openTheDoor() function.

PaulS:

You should separate the reading of switches into one function and the movement of motors into another.

I'll have to disagree, to some extent.

One of the functions is to open the door, until a limit switch indicates that the door is all the way open. In that case, the limit switch needs to be read in the openTheDoor() function.

I understand the logic of what you are saying. I had understood the door to be opened by a servo so that it would not need a limit switch to know it was open. I thought the limit switches are just for the camera device that goes up and down.

...R

I thought the limit switches are just for the camera device that goes up and down.

Even so, those switches need to be read in the function that extends or retracts the camera.

In general, I agree that reading switches should be done in loop(), except in the case of a function that moves something until a limit switch is triggered.

I think I have finally managed to refine the code a little bit. I thought of only using two limit switches each for registering camera unit extended position and retracted position.

I have put the code to check the default position of the canopy and pan/tilt system in the setup function and rest of the code in the loop function. It seems to be working but I think I have to implement another push button at the beginning to start the whole operation and to make sure the whole loop only runs once until I press the button.

#include <Stepper.h>
#include <Servo.h>

#define pushButtonAfterFlash 4 
#define topSwitch 3                            // top limit switch
#define bottomSwitch 2                      //bottom limit switch
#define servoPin 7 
#define ServoCloseCanopy 1450         // value in microseconds
#define ServoOpenCanopy 1600        //value in microseconds
#define stepperStepPin 9                  //stepper pin output
#define stepperDirectionPin 8         //stepper pin output

Servo oServo;                   // creation of servo object
const int stepperMaxRPM = 200;          // max rpm of stepper
const int stepsPerRevolution = 200;     // steps per revolution of stepper

Stepper myStepper(stepsPerRevolution, stepperStepPin, stepperDirectionPin);

void setup()
{
	Serial.begin(115200);
	pinMode(topSwitch, INPUT_PULLUP);
	pinMode(bottomSwitch, INPUT_PULLUP);
	pinMode(pushButtonAfterFlash, INPUT_PULLUP);

	oServo.attach(servoPin, ServoCloseCanopy, ServoOpenCanopy);
	oServo.writeMicroseconds(ServoCloseCanopy);                                             // to check if the canopy is closed

	myStepper.setSpeed(stepperMaxRPM);
	
	while (digitalRead(bottomSwitch) != LOW)//bottom not pressed
	{
		Serial.println("In setup stepper going to bottom switch");                                // to check if the pan/tilt is at bottom
		myStepper.step(-1);
	}

	Serial.println("end of SETUP");
	Serial.println(ServoCloseCanopy);
}

void loop()
{
	if (digitalRead(bottomSwitch) == LOW)//bottom switch is pressed
	{
		oServo.writeMicroseconds(ServoOpenCanopy);
		Serial.println(ServoOpenCanopy);
		delay(5000);
	}

	while (digitalRead(topSwitch) != LOW)//till top switch is not pressed
	{
		Serial.println("In While Loop");
		myStepper.step(1);//move stepper upwards
	}
	
	if (digitalRead(topSwitch) == LOW && oServo.readMicroseconds()!=ServoCloseCanopy)//top switch is pressed && canopyis not closed
	{
		Serial.println("in Close canopy IF loop");
		oServo.writeMicroseconds(ServoCloseCanopy);//close the canopy
		delay(5000);

	}
	//--------
	//Push Button Operation
	
	//--------
	if (digitalRead(pushButtonAfterFlash) == LOW)//if button is pressed after playing around
	{
		oServo.writeMicroseconds(ServoOpenCanopy);
		delay(1000);
	
	 while (digitalRead(bottomSwitch) != LOW)//bottom not pressed
	 {
		Serial.println("In While Loop 2");
		myStepper.step(-1);

     //will run till it preses bottom switch
	 }
	 if (digitalRead(bottomSwitch) == LOW)// if bottom swith is pressed
	 {
		oServo.writeMicroseconds(ServoCloseCanopy);
		delay(5000);                                                                                                                // after this the loop begins again. I need                   //additional button to make sure it runs only once until button is pressed
	 }

	}

}