Thanks Thanks:  0
Needs Pictures Needs Pictures:  0
Picture(s) thanks Picture(s) thanks:  0
Page 1 of 11 123456 ... LastLast
Results 1 to 15 of 163
  1. #1
    Join Date
    Nov 2006
    Location
    Heidelberg, Victoria
    Age
    79
    Posts
    2,251

    Default Handling limit switches?

    I'm trying to build a basic camera slider, didn't have much success with an earlier post.

    I have all the hardware sorted, and 99% of the code for controlling an Arduino UNO. The sketch for the Arduino was written by Brian Schmalz, basically consisting of a left push button, a stop push button, a right push button and a speed control pot.

    The basic hardware consists of an aluminium track, a carriage, a nema17 stepper motor at one end and a return pulley at the other for the toothed belt.

    So far so good, where I'm struggling is code for limit switches at each end. The problem is once the limit switch is depressed and kept depressed, no other action can take place.

    What I'm trying to achieve is this. Once a limit switch is hit, tell the Arduino to stop the motor with no further movement in that direction, but allow motion in the opposite direction to take place when the appropriate pb is pressed.

    Brian's sketch is here, it's the last example using an Adafruit motor shield V2.

    http://www.schmalzhaus.com/EasyDrive...rExamples.html

    One of my thoughts was that as soon as the limit switch is hit, the motor stops and backs off the switch, allowing the reverse button to be pressed. I don't reckon this is the answer, and in fact I wouldn't know how to code that anyway.

    I'm hoping for some assistance, you blokes are supposed to be smart, meow.

    Ken

  2. # ADS
    Google Adsense Advertisement
    Join Date
    Always
    Location
    Advertising world
    Age
    2010
    Posts
    Many





     
  3. #2
    Join Date
    Jun 2010
    Location
    Canberra
    Posts
    769

    Default

    There's no mention of limit switches in that code, only direction and a stop switch. I'm going to guess you've wired the limit switches in parallel with the stop switch? There's a bunch of ways to skin that cat, but one would be to use two input pins for the limit switch and test their state in the main loop after the other switches. In that test, you'd allow the sign to be the correct value to move off the limit switch, or you'd leave it as zero (stopped).

  4. #3
    Join Date
    Nov 2006
    Location
    Heidelberg, Victoria
    Age
    79
    Posts
    2,251

    Default Limit switches

    Hi RustyArc.

    You are correct, limit switches were not figured into the sketch I pointed to, hence this inquiry.

    If you were able to write a simple bit of code to do as you suggest, I'd be extremely grateful.

    Ken

  5. #4
    Join Date
    Jun 2010
    Location
    Canberra
    Posts
    769

    Default

    So you'd define 2 more input pins:

    // Define our three input button pins and two limit switches
    #define LEFT_PIN 2
    #define STOP_PIN 3
    #define RIGHT_PIN 4
    #define LEFT_LIM_PIN 5
    #define RIGHT_LIM_PIN 6

    Then in the main loop you'd add two more tests - note this isn't the most efficient or elegant way to do it, but hopefully easier to understand:

    // If a switch is pushed down (low), set the sign value appropriately
    if (digitalRead(LEFT_PIN) == 0) {
    sign = 1;
    }
    if (digitalRead(RIGHT_PIN) == 0) {
    sign = -1;
    }
    if (digitalRead(STOP_PIN) == 0) {
    sign = 0;
    }
    if (digitalRead(LEFT_LIM_PIN) == 0) { // If we're sitting on the left limit switch...
    if (digitalRead(RIGHT_PIN) == 0) { // Allow the right button to move off the limit
    sign = -1;
    }
    else {
    sign = 0; // Otherwise stop the motor
    }
    }
    if (digitalRead(RIGHT_LIM_PIN) == 0) { // If we're sitting on the right limit switch...
    if (digitalRead(LEFT_PIN) == 0) { // Allow the left button to move off the limit
    sign = 1;
    }
    else {
    sign = 0; // Otherwise stop the motor
    }
    }

  6. #5
    Join Date
    Nov 2008
    Location
    somewhere
    Posts
    152

    Default

    umm rusty's code is pretty good, but it won't actually stop the motor until analog_read_counter gets down to 0. given your hitting a limit switch, you'd probably want the motor to stop straight away.

    I'd add a stepper1.setSpeed(sign); on a new line after every sign=0; in Rusty's code. alternatively add a analog_read_counter=0; line after every sign=0; that'll have the same effect.

    let me know if that isn't clear and i'll update rusty's code.

  7. #6
    Join Date
    Nov 2006
    Location
    Heidelberg, Victoria
    Age
    79
    Posts
    2,251

    Default Limit switch code

    RustyArc

    Thank you for taking the time to go through Brian Schmalz's sketch and incorporating into it, your code to handle limit switches.

    There are a few delays in his code as it stands, ie, it can take several rotations of the motor shaft before it stops or is reversed. This is something I have to overcome. One other problem is the speed pot. There doesn't appear to be a great variation in speed from full to crawl, and again it takes a second or so to respond. I'm not 100% sure the pot I'm using is linear.

    foobillious

    I dare not ask how you came up with that user name.

    Many thanks for your contribution, anything to pull the motor up sharply makes good sense. If you have time to rewrite the sketch to reflect your ideas, great.

    I'm using an Arduino UNO R3, an Adafruit terminal shield and an Adafruit motor shield V2, and having fun.

    Gentlemen, thank you both

    Ken

  8. #7
    Join Date
    Nov 2008
    Location
    somewhere
    Posts
    152

    Default

    the pot may be a log (logarithmic) pot, which could be making your life a little bit difficult, but personally I find even the linear ones hard to set accurately repeatedly. You could try investing in a 5 or 10 turn multiturn pot, which would give you a great deal more control, or you could switch to an optical encoder and control the speed more directly from within the Arduino.
    *edit* you could also just add another couple of buttons and use those to increase / decrease the speed.
    I'd concentrate on getting the rest of it working first, and then add that.

    The second or two to respond is because the loop function of the code (where all the work is being done below) has code in it that stops the speed pot being read every time it goes through the loop. this is because the AnalogRead function is fairly slow and would limit the speed your stepper motor can achieve. I'd experiment with changing the number it counts down from (default is 3000) to see if you can find an acceptable response / speed compromise. Try 1000 or 500 first. I've commented the relevant line of the code.

    the updated code for the entire sketch is below. As Rusty noted there are more elegant ways of handing the limit switch, but this should be fine until you get everything figured out. I recommend trying it with the limits set a long way off the physical stops, or by manually triggering the limits. Please note I don't have an Arduino with me right now, and I don't have a motor shield at all so I haven't tested this at all.

    *edit* thing to check - what pins are your limit switches actually hooked up to? make sure they match the number in the defines.

    Code:
    // Example6 code for Brian Schmalz's Easy Driver Example page
    // http://www.schmalzhaus.com/EasyDriver/EasyDriverExamples.html
    
    #include <AccelStepper.h>
    #include <Wire.h>
    #include <Adafruit_MotorShield.h>
    
    // Define the stepper and the pins it will use
    Adafruit_MotorShield AFMS = Adafruit_MotorShield();
    Adafruit_StepperMotor *motor1 = AFMS.getStepper(200, 1);
    
    
    // you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
    void forwardstep() { 
      motor1->onestep(FORWARD, SINGLE);
    }
    void backwardstep() { 
      motor1->onestep(BACKWARD, SINGLE);
    }
    
    AccelStepper stepper1(forwardstep, backwardstep); // use functions to step
    
    // Define our three input button pins
    #define  LEFT_PIN  2
    #define  STOP_PIN  3
    #define  RIGHT_PIN 4
    // and define our two Limit inputs
    #define LEFT_LIM_PIN 5
    #define RIGHT_LIM_PIN 6
    
    // Define our analog pot input pin
    #define  SPEED_PIN A0
    
    // Define our maximum and minimum speed in steps per second (scale pot to these)
    #define  MAX_SPEED 500
    #define  MIN_SPEED 0.1
    
    void setup() {
      AFMS.begin();
     
      // The only AccelStepper value we have to set here is the max speeed, which is higher than we'll ever go
      stepper1.setMaxSpeed(500.0);
     
      // Set up the three button inputs, with pullups
      pinMode(LEFT_PIN, INPUT_PULLUP);
      pinMode(STOP_PIN, INPUT_PULLUP);
      pinMode(RIGHT_PIN, INPUT_PULLUP);
    }
    
    void loop() {
      static float current_speed = 0.0;         // Holds current motor speed in steps/second
      static int analog_read_counter = 1000;    // Counts down to 0 to fire analog read
      static char sign = 0;                     // Holds -1, 1 or 0 to turn the motor on/off and control direction
      static int analog_value = 0;              // Holds raw analog value.
     
      // If a switch is pushed down (low), set the sign value appropriately
      if (digitalRead(LEFT_PIN) == 0) {
        sign = 1;
      }
      if (digitalRead(RIGHT_PIN) == 0) {   
        sign = -1;
      }
      if (digitalRead(STOP_PIN) == 0) {
        sign = 0;
      }
      // code from Rusty
      if (digitalRead(LEFT_LIM_PIN)==0) {  // if the left limit pin is hit
        if (digitalRead(RIGHT_PIN)==0) {   // allow the right button to move us off the limit
            sign=-1;
        }
        else {
            sign=0;                           // but otherwise we should stop the motor
            stepper1.setSpeed(sign);        // by setting the motor's speed to 0
        }
      }
      if (digitalRead(RIGHT_LIM_PIN)==0) { // if the right limit pin is hit
        if (digitalRead(LEFT_PIN)==0) {    // allow the left button to  move us off the limit
            sign=1;
        }
        else {
            sign=0;                            // but otherwise we should stop the motor
            stepper1.setSpeed(sign);        // by setting the motor's speed to 0
        }
      }
    
      // We only want to read the pot every so often (because it takes a long time we don't
      // want to do it every time through the main loop). 
      if (analog_read_counter > 0) {
        analog_read_counter--;
      }
      else {
        analog_read_counter = 3000;  //  <-- change this to a lower number (i.e 500 or 1000) to increase pot response
        // Now read the pot (from 0 to 1023)
        analog_value = analogRead(SPEED_PIN);
        // Give the stepper a chance to step if it needs to
        stepper1.runSpeed();
        //  And scale the pot's value from min to max speeds
        current_speed = sign * ((analog_value/1023.0) * (MAX_SPEED - MIN_SPEED)) + MIN_SPEED;
        // Update the stepper to run at this new speed
        stepper1.setSpeed(current_speed);
      }
    
      // This will run the stepper at a constant speed
      stepper1.runSpeed();
    }
    Last edited by foobillious; 4th February 2015 at 02:32 PM. Reason: forgot to add the comment to the number

  9. #8
    Join Date
    Nov 2006
    Location
    Heidelberg, Victoria
    Age
    79
    Posts
    2,251

    Default Limit switch code

    Foobillious
    Many, many thanks, have not wired in the limits yet
    Can't wait to get home and try the revised code out
    If you'd like to muck around, I can lend you a spare Arduino, Adafruit terminal shield and motor shield

    Ken

  10. #9
    Join Date
    Nov 2008
    Location
    somewhere
    Posts
    152

    Default

    thanks for the offer, but I've frankly got too many projects on as it is.

  11. #10
    Join Date
    Jun 2010
    Location
    Canberra
    Posts
    769

    Default

    Poo. I posted without checking how the code would turn out - I didn't realise it'd lose all its indenting.

    foobillious clearly knows the right way to do it, and I must say I hadn't noticed the direction only gets set as part of reading the pot and setting the speed. I also noticed you need to initialise the extra pins as inputs. I've moved the speed calc out of the analogue read so it happens on every iteration of the main loop, meaning it should catch stop and direction changes immediately.

    My code mods adding to
    foobillious's version (and note, untested, so there may be a bug or three somewhere):

    Code:
    // Example6 code for Brian Schmalz's Easy Driver Example page
    // http://www.schmalzhaus.com/EasyDriver/EasyDriverExamples.html
    
    #include <AccelStepper.h>
    #include <Wire.h>
    #include <Adafruit_MotorShield.h>
    
    // Define the stepper and the pins it will use
    Adafruit_MotorShield AFMS = Adafruit_MotorShield();
    Adafruit_StepperMotor *motor1 = AFMS.getStepper(200, 1);
    
    
    // you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
    void forwardstep() { 
      motor1->onestep(FORWARD, SINGLE);
    }
    void backwardstep() { 
      motor1->onestep(BACKWARD, SINGLE);
    }
    
    AccelStepper stepper1(forwardstep, backwardstep); // use functions to step
    
    // Define our three input button pins
    #define  LEFT_PIN  2
    #define  STOP_PIN  3
    #define  RIGHT_PIN 4
    // and define our two Limit inputs
    #define LEFT_LIM_PIN 5
    #define RIGHT_LIM_PIN 6
    
    // Define our analog pot input pin
    #define  SPEED_PIN A0
    
    // Define our maximum and minimum speed in steps per second (scale pot to these)
    #define  MAX_SPEED 500
    #define  MIN_SPEED 0.1
    
    void setup() {
      AFMS.begin();
     
      // The only AccelStepper value we have to set here is the max speeed, which is higher than we'll ever go
      stepper1.setMaxSpeed(500.0);
     
      // Set up the three button inputs & limit inputs with pullups
      pinMode(LEFT_PIN, INPUT_PULLUP);
      pinMode(STOP_PIN, INPUT_PULLUP);
      pinMode(RIGHT_PIN, INPUT_PULLUP);
      pinMode(LEFT_LIM_PIN, INPUT_PULLUP);
      pinMode(RIGHT_LIM_PIN, INPUT_PULLUP);
    }
    
    void loop() {
      static float current_speed = 0.0;         // Holds current motor speed in steps/second
      static int analog_read_counter = 1000;    // Counts down to 0 to fire analog read
      static char sign = 0;                     // Holds -1, 1 or 0 to turn the motor on/off and control direction
      static int analog_value = 0;              // Holds raw analog value.
     
      // If a switch is pushed down (low), set the sign value appropriately
      if (digitalRead(LEFT_PIN) == 0) {
        sign = 1;
      }
      if (digitalRead(RIGHT_PIN) == 0) {   
        sign = -1;
      }
      if (digitalRead(STOP_PIN) == 0) {
        sign = 0;
      }
      // code from Rusty
      if (digitalRead(LEFT_LIM_PIN)==0) {  // if the left limit pin is hit
        if (digitalRead(RIGHT_PIN)==0) {   // allow the right button to move us off the limit
            sign=-1;
        }
        else {
            sign=0;                           // but otherwise we should stop the motor
            stepper1.setSpeed(sign);        // by setting the motor's speed to 0
        }
      }
      if (digitalRead(RIGHT_LIM_PIN)==0) { // if the right limit pin is hit
        if (digitalRead(LEFT_PIN)==0) {    // allow the left button to  move us off the limit
            sign=1;
        }
        else {
            sign=0;                            // but otherwise we should stop the motor
            stepper1.setSpeed(sign);        // by setting the motor's speed to 0
        }
      }
    
      // Give the stepper a chance to step if it needs to
      stepper1.runSpeed();
      //  And scale the pot's value from min to max speeds
      current_speed = sign * ((analog_value/1023.0) * (MAX_SPEED - MIN_SPEED)) + MIN_SPEED;
      // Update the stepper to run at this new speed
      stepper1.setSpeed(current_speed);
      // This will run the stepper at a constant speed
      stepper1.runSpeed();
    
      // We only want to read the pot every so often (because it takes a long time we don't
      // want to do it every time through the main loop). 
      if (analog_read_counter > 0) {
        analog_read_counter--;
      }
      else {
        analog_read_counter = 3000;  //  <-- change this to a lower number (i.e 500 or 1000) to increase pot response
        // Now read the pot (from 0 to 1023)
        analog_value = analogRead(SPEED_PIN);
      }
    
      
    }

  12. #11
    Join Date
    Nov 2006
    Location
    Heidelberg, Victoria
    Age
    79
    Posts
    2,251

    Default Limit switch code

    Rusty & foob,

    You've done a great job with the limit switch code. I haven't had a chance to try it out yet, and will wait for the morning light.
    I'd like to send a copy to Brian Schmalz for his comment, if you agree.

    Rusty, why do you say the code is not exactly elegant, it makes sense to me? Are you saying there are better ways of doing it?

    Where can I learn to write my own code?, I'm well over the pension age and this old dog is eager to learn new tricks.

    Ken

  13. #12
    Join Date
    Jun 2010
    Location
    Canberra
    Posts
    769

    Default

    Quote Originally Posted by neksmerj View Post
    Rusty, why do you say the code is not exactly elegant, it makes sense to me? Are you saying there are better ways of doing it?
    If you look through the main loop, there's 5 button reads, and as many as 6 if a limit switch is triggered. This makes the code easy to read and understand, but we know only one of the three buttons should be pressed (multiple buttons at one time doesn't make sense). So as soon as you find one button pressed, you'd not bother checking the others.

    With the limit switches added, there's potentially more checks, but the code as it stands has redundancies.

    So for example, more efficient code would check the stop button first - if it's pressed, there's no point checking anything else (including the limits) as the motor will be stopped as a result.

    If, say, the left button is pressed, you'd jump to the limit checks without checking the right button. Then, when you test the limit inputs, you don't really need to check the corresponding button to see if it should be moving off the limit switch - the value of the "sign" variable will actually tell you that, as it's just been set in the previous button tests.

    All that said, there's no problem with inefficient code if it's easier to understand and debug.

    As for learning to code, there's excellent tutorials for the Arduino online.

  14. #13
    Join Date
    Nov 2008
    Location
    somewhere
    Posts
    152

    Default

    nice catch Rusty, I forgot about initialising the inputs. my bad.

    I've got no objections to you sending the code to the original author for comment, but all we have really done is add a few lines. He'll probably re-write before he posts anything on it. I would if it was me - what we've done detracts a bit from how easy the code is to understand.

    The best place to learn to code depends really on what you want to do. If your interested in incorporating smarts into electronics, like your doing with your current project, then the arduino platform is a pretty good starting point. Plus you already have one. Its been a very popular platform for a number of years, so there are lots of tutorials out there. Everything from absolute beginner projects (ye olde blinky LEDs) to much more complex tasks. The arduino code editor comes with a bunch of sample code too, which makes seeing how other people have done stuff pretty easy.

    Two starting points for tutorials would be the arduino site: http://www.arduino.cc/en/Tutorial/HomePage
    and the tronixstuff site: http://tronixstuff.com/tutorials/
    (please note, I haven't read either, so I cant really vouch for quality).

    You could start at the beginner ones and work your way through. That way you'll pick up some electronics knowledge along with the how to code stuff.

  15. #14
    Join Date
    Nov 2006
    Location
    Heidelberg, Victoria
    Age
    79
    Posts
    2,251

    Default Compiling problem

    Rusty and foob,

    There is a problem when compiling the amended sketch, and I don't know how to debug it.

    Below is a copy of the error report.

    This report would have more information with
    "Show verbose output during compilation"
    enabled in File > Preferences.
    Arduino: 1.0.6 (Windows 7), Board: "Arduino Uno"

    RustyArc_stepper:1: error: function definition does not declare parameters
    RustyArc_stepper:22: error: 'AccelStepper' does not name a type
    RustyArc_stepper.ino: In function 'void setup()':
    RustyArc_stepper:43: error: 'stepper1' was not declared in this scope
    RustyArc_stepper.ino: In function 'void loop()':
    RustyArc_stepper:76: error: 'stepper1' was not declared in this scope
    RustyArc_stepper:85: error: 'stepper1' was not declared in this scope
    RustyArc_stepper:90: error: 'stepper1' was not declared in this scope

    Ken

  16. #15
    Join Date
    Nov 2008
    Location
    somewhere
    Posts
    152

    Default

    Quote Originally Posted by neksmerj View Post
    Rusty and foob,

    There is a problem when compiling the amended sketch, and I don't know how to debug it.
    <snip>

    RustyArc_stepper:1: error: function definition does not declare parameters
    RustyArc_stepper:22: error: 'AccelStepper' does not name a type

    <snip>
    Ken
    Hi Ken,

    Just guessing at this point (got Arduino software downloading now to check)... Looks like you haven't got the AccelStepper library installed. It is a library most of those examples are based on. Instructions for doing so are in example 3. Or you can get the file here:
    http://www.airspayce.com/mikem/ardui...epper-1.45.zip

    Once you've downloaded that you'll then need to install it by unziping it to your arduino libraries folder. I've got some memory that there was a way to install it through the IDE as well. just can't remember what it is.

    I'll post again in a couple of minutes when the download has finished and I've installed it.

Page 1 of 11 123456 ... LastLast

Similar Threads

  1. Limit/home switches
    By warrick in forum CNC Machines
    Replies: 2
    Last Post: 7th July 2012, 08:11 PM
  2. Limit switches
    By Bob Willson in forum CNC Machines
    Replies: 0
    Last Post: 24th August 2011, 12:31 PM
  3. CNC Mill Limit Switches
    By electrosteam in forum METALWORK FORUM
    Replies: 8
    Last Post: 10th September 2010, 07:31 PM
  4. How to Wire Limit switches on Xylotex board.
    By Ch4iS in forum CNC Machines
    Replies: 19
    Last Post: 19th October 2008, 09:58 PM
  5. Xylotex & limit/home switches
    By John H in forum CNC Machines
    Replies: 3
    Last Post: 31st July 2008, 08:08 PM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •