How to limit steppers to max & min angle? (solar-tracker code)

Hi everybody,
a couple of friends and i are working on a double axis solar tracker with a Adafruit Motor-shield V2 and 2x Adafruit bipolar stepper motors (200/rev).
We got the following code so far but are stuck with getting the steppers to stop at a certain angle (90° for vertical and 180° for horizontal) so that we dont tangle up the wires and avoid unnecessary movement.

Any help and sugestions would be much appreciated.
Cheers

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"

Adafruit_MotorShield AFMS = Adafruit_MotorShield(); 
Adafruit_StepperMotor *stepperh = AFMS.getStepper(200, 1);  // declaring horizontal stepper
Adafruit_StepperMotor *stepperv = AFMS.getStepper(200, 2);  // declaring vertical stepper

int ldr1 = A0;  // right ldr        
int ldr2 = A1;  // centre ldr
int ldr3 = A2;  // left ldr
int ldr4 = A3;  // top ldr
int ldr5 = A4;  // bottom ldr

const int threshold = 550;  // limit to stop tracker from moving at night

const int tol = 50;  // tolerance for ldrs // maybe vertical AND horizontal depending on difference?

//int = countv
//int = counth

//const int maxh = ?    // to prevent overturning horizontal (50 steps = 90°) 
//const int minh = ?    // combine with count int's // i.e. if counth > 90 - stop
//const int maxv = ?    // to prevent overturning vertical
//const int minv = ?

void setup()
{
  AFMS.begin();
  stepperv->setSpeed(10);  
  stepperh->setSpeed(10);    
}

void loop()
{
  int right = analogRead(ldr1);  
  int centre = analogRead(ldr2);
  int left = analogRead(ldr3);
  int up = analogRead(ldr4);
  int down = analogRead(ldr5);

  //STOP MOVEMENT//
  if ((left < threshold) && (right < threshold) && (up < threshold) && (down < threshold)) {}  // stop any movement if sensor values below threshold 
                                                                                               // at begining to check after every sensor reading

  //HORIZONTAL MOVEMENT//
  if((right > centre + tol) && (left + tol < centre))   // && (right - ? > tol)     
  {
    stepperh->onestep(BACKWARD,DOUBLE);  // add +1 to int counth // if (minh < counth < maxh) - move // else - stop // counth=counth++ , counth=counth--                            
  }
  else if((left > centre + tol) && (right + tol < centre))  // && (left - ? > tol)  
  {
    stepperh->onestep(FORWARD,DOUBLE);                      
  }
  else {}  // do nothing

  //VERTICAL MOVEMENT//
  if((up > centre + tol) && (down + tol < centre))  // && (up - ? > tol)  
  {
    stepperv->onestep(BACKWARD,DOUBLE);   
  }
  else if((down + tol > centre) && (up + tol < centre))  // && (down - ? > tol)  
  {
    stepperv->onestep(FORWARD,DOUBLE);  
  }
  else{}  // do nothing
}

check the page about constrain()

angle = constrain(angle, min, max);

Your Arduino will have to know where the steppers are at startup if it is to implement any limits in code.

Simplest thing would probably to install limit switches that identify when the extremes of movement are reached.

...R

thanks robtillaart, thats great. One question though is it possible to assign a negative number as the lower end of the range?
i.e. counth = constrain(counth, -90, 90);

Robin2, how would i implement a limit switch?

darellon:
thanks robtillaart, thats great. One question though is it possible to assign a negative number as the lower end of the range?
i.e. counth = constrain(counth, -90, 90);

  1. you have the freedom to write a minimal test sketch and you will know.
  2. Or look in the source code which is part of the distribution and check if it is forbidden.
  3. Or ask on the forum

Think
(1) is fastest
and you will learn more
(2) is most sure ?
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
is it
(3) is slowest

advice: go for 1 :slight_smile:

Simplest type of limit switch is probably a microswitch that is pushed by some part of the structure when it gets to the llimit of its movement.

The Arduino code continually monitors the settings of the limit switches and will stop incrementing the motion in that direction when a switch is pressed.

...R

Limit switches are best, but failing that you can often just use hard stops. Put something in the motor's way and it won't go past it! That may be a problem if you're moving a heavy load wherein there might be damage if you crash it into the stops though; I obviously don't know the mechanical details of your tracker.

Thanks for all the replies. Could i maybe use a magnetic switch or an accelerometer - something like this: SparkFun Triple Axis Accelerometer Breakout - ADXL345 - SEN-09836 - SparkFun Electronics ? How accurate are these things?

darellon:
Thanks for all the replies. Could i maybe use a magnetic switch or an accelerometer - something like this: https://www.sparkfun.com/products/9836 ? How accurate are these things?

A magnetic switch should work, though may not be quite as repeatable as a microswitch. An optical detector where the beam is broken is another possibility - but a little more trouble electrically compared to a microswitch.

An accelerometer would be useless. Acceleration does not measure distance or location. I can't even figure why you asked the question.

...R