Can anyone help me with Servo position limiting please?

Hi All,

I’m looking for some advice regarding some code for a servo-stepper project, I have found various bits of code online but… I’m struggling to finish the project as I’m lacking the understanding of how to implement the rest of the code to fulfill the project requirements.

The setup is a MEGA 2560, iHSV42 servo-stepper motor with integrated controller, 2 position digital switch to move the rig forwards and backwards, a potentiometer to adjust the speed, a limit switch to set the position and an LCD to output the speed and delay time.

When the rig powers up it moves towards the limit switch which should set the home position to 0 and then moves back near to the central position at a value of 5500.

I would like to keep the rig in the range of 0 to 12000 so when I press forward or backward the rig will stop before it goes past this point at either end?

I found this code from https://www.brainy-bits.com/homing-stepper-motor-at-startup/

void loop() {

// Enable movement of Stepper Motor using the Joystick

while (analogRead(x_pin) >= 0 && analogRead(x_pin) <= 100) {
if (steps > 0) { // To make sure the Stepper doesn’t go beyond the Home Position
digitalWrite(dir_pin, HIGH); // (HIGH = anti-clockwise / LOW = clockwise)
digitalWrite(step_pin, HIGH);
delay(1);
digitalWrite(step_pin, LOW);
delay(1);
steps–; // Decrease the number of steps taken
}
}

while (analogRead(x_pin) > 900 && analogRead(x_pin) <= 1024) {
if (steps < 650) { // Maximum steps the stepper can move away from the Home Position
digitalWrite(dir_pin, LOW);
digitalWrite(step_pin, HIGH);
delay(1);
digitalWrite(step_pin, LOW);
delay(1);
steps++; // Increase the number of steps taken
}
}
}

Lost on how how to implement this into the current code?

Also, I would like to output the position of the rig rather than the delay time to the LCD but if i try and display the value of x it just displays a static value of 5500 rather than the current position?

The code is as follows…

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
#define potmeterPin A0    //DEFINE POTENTIOMETER PIN
#define home_switch 8 // Pin 8.  connected to Home Switch (MicroSwitch)
LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line displ

String revision="1.3";          //==============ALTER THIS LINE FOR EACH CODE VERSION

const int dirPin  = 2;  
const int stepPin = 4;  
const int enPin   = 6;  

const int switchOne     = 10;   //switch input pins
const int switchTwo     = 11;

int p1buttonState = 0;         // current state of the button
int lastp1buttonState = 0;     // previous state of the button

int p2buttonState = 0;         // current state of the button
int lastp2buttonState = 0;     // previous state of the button
bool bPress = false;

bool isForward = false;   //boolean definition as false
bool isBackward = false;

int x;        // Used to set HOME position after Homing is completed
int sensorValue = digitalRead(home_switch);

//==========================================================================

void setup() {

Serial.begin(9600);   //serial start
pinMode( switchOne, INPUT_PULLUP);    //define inputs with pullups
pinMode( switchTwo, INPUT_PULLUP);

pinMode(stepPin,OUTPUT);     // Sets the two pins as Outputs
pinMode(dirPin,OUTPUT);

pinMode(enPin,OUTPUT);
digitalWrite(enPin,LOW);

pinMode(home_switch, INPUT_PULLUP);

lcd.init();                 // initialize the lcd
lcd.backlight();            // Turn on the blacklight and print a message.

//=====flash screen - Servo Tester and revision number

   lcd.setCursor(0,0);
   lcd.print("Servo Tester");
   lcd.setCursor(0,1);
   lcd.print("Version - ");
   lcd.print(revision);    //see variable to change on code upsuffix
  delay(1500);
 lcd.clear();

while (digitalRead(home_switch)) {  // Do this until the switch is activated   
 digitalWrite(dirPin, HIGH);      // (HIGH = anti-clockwise / LOW = clockwise)
 digitalWrite(stepPin, HIGH);
 delay(1);                       // Delay to slow down speed of Stepper
 digitalWrite(stepPin, LOW);
 delay(1);   
//  Serial.println("HOME");
}

while (!digitalRead(home_switch)) { // Do this until the switch is not activated
 digitalWrite(dirPin, LOW); 
 digitalWrite(stepPin, HIGH);
 delay(1);                       // More delay to slow even more while moving away from switch
 digitalWrite(stepPin, LOW);
 delay(1);
//  Serial.println("AWAY");  
}

x = 0;  // Reset position variable to zero

}
//===============================================================

void loop() {

int p = analogRead(potmeterPin);     //note pot value to varaible p
int delay_time = map(p,0,1023,100,1);   //map pot from 100 to 0 on FSD
isForward = false;     //boolean off
isBackward = false;    //boolean off

p1buttonState = digitalRead(switchOne);    //analogue read of switch inputs
p2buttonState = digitalRead(switchTwo);

if (p1ButtonPress()) {

 digitalWrite(dirPin,HIGH);    //write direction fwd

 delay(5);
}

 if (p2ButtonPress()) {

   digitalWrite(dirPin,LOW);   //change direction - backward

   delay(5);
 }
 if( isForward || isBackward ){

Serial.println(millis());

     for(x = 0; x < 5500; x++) {   //step loop, 12000 is full length of rig
     digitalWrite(stepPin,HIGH);
     delayMicroseconds(delay_time);
     digitalWrite(stepPin,LOW);
     delayMicroseconds(delay_time);

   }

Serial.println(millis());

 }

lcd.setCursor(0,0);       //set position of lcd start point line 1
lcd.print("Delay time - ");
lcd.print(delay_time);
lcd.setCursor(0,1);
lcd.print(((0.125*2)/delay_time)*10000);
lcd.print(" - mm/s");
Serial.println(delay_time);
}

//===============================================================

bool p1ButtonPress()
{
bool isPress = false;

if (p1buttonState != lastp1buttonState) {   // compare the p1buttonState to its previous 
 
 if (p1buttonState == LOW) { // if the current state is HIGH then the button went from off to on: 
   
   bPress = true;
   isPress = true;
   Serial.println("Forward");
 
 } else {
   
   Serial.println("off");    // if the current state is LOW then the button went from on to off:
   isForward = true;
 }
 
 delay(50);    // Delay a little bit to avoid bouncing
}

lastp1buttonState = p1buttonState;  // save the current state as the last state, for next time through the loop
return isPress;
}

//===============================================================

bool p2ButtonPress()
{
bool isPress = false;

if (p2buttonState != lastp2buttonState) { // compare the p1buttonState to its previous state
 
 if (p2buttonState == LOW) {  // if the state has changed, increment the counter
   // if the current state is HIGH then the button went from off to on:
   bPress = true;
   isPress = true;
   Serial.println("Backward");
 
 } else {
  
   Serial.println("off");    // if the current state is LOW then the button went from on to off:
   isBackward = true;
 }
 
 delay(50);    // Delay a little bit to avoid bouncing
}

lastp2buttonState = p2buttonState;     // save the current state as the last state, for next time through the loop
return isPress;

}

//===========================================================

Can anyone help me please? :o

To make it easy for people to help you please modify your post and use the code button </>
codeButton.png

so your code 
looks like this

and is easy to copy to a text editor. See How to use the Forum

Your code is too long for me to study quickly without copying to my text editor. The text editor shows line numbers, identifies matching brackets and allows me to search for things like all instances of a particular variable or function.

...R

Thank you Robin,

Have modified as requested...

Gav.

If you are not sure, use the Arduino Stepper motor library - servo is very different from what you have.
Then you can obtain the current position from the stepper object, use moveTo(position) etc.

Thank you DrDiettrich,

I’m not overly experienced as you may have guessed, I started off with a stepper motor for the project and could not get the speed I required. I soon realised the stepper is great for slow precision work and the code was adapted from there…

I came across the iHSV42, how to use it to its potential is far from my understanding. Couldn’t really find anything online regarding the use of these motors I was under the impression it is a Servo-Stepper motor but again I am far from confident.

Will have a look into the Arduino Stepper motor library as you have advised.

Thanks again!

Gav.

@GavGil, please post a link to the datasheet for your "iHSV42 servo-stepper motor with integrated controller". If it takes step and direction signals then the standard Stepper library will not be suitable. You could use the AccelStepper library.

Or you could just write your own code. This Simple Stepper Code may give you some ideas.

...R
Stepper Motor Basics
[

Hi Robin,

The data sheet is here... Intergrated ac servo motor manual

Also the link to the website for the Motor... iHSV42-40-05-24 iHSV42

Was purchased from here... iHSV42-40-07-24 NEMA17

Thank you for your response!

Gav.

@Robin2 and yes your right I really need to start just writing my own code :slight_smile:

When the rig powers up it moves towards the limit switch which should set the home position to 0 and then moves back near to the central position at a value of 5500.
I would like to keep the rig in the range of 0 to 12000 so when I press forward or backward the rig will stop before it goes past this point at either end?

It's not quite clear to me what motion you desire with the buttons.

You begin at the middle of range (step count value = 5500). From this point, should backward take you back to 0 and forward to 11000? Then when you are at either of these two end positions, where do you want backwards and forwards to take you?

Alright Cattledog,

The buttons function fine, when the rig starts up the motor turns a ball screw to move a plate to the left until a limit switch is activated by the plate…

This is supposed to set the home point x = 0, once it has run through the start-up the motor then moves the plate away from the home point to 5500 to the right / almost center of the ball screw, 12000 being the total movement from left to right. I can press the < to move the rig to 0 and then > twice which moves the rig to 11000. So the rig moves between 3 points, 0 where the limit switch is located, 5500 almost center and 11000, 1000 off the opposite end of the rig.

Say I’m at 0 and i press < the plate attached to the ball screw can’t go any further and the motor cuts out and the alarm light flashes. Also if i press > when the plate is located at 11000 the motor again cuts out and the alarm flashes.

What I was trying to get the code to do is if i’m at the 0 point the < button will not let me move past 0 and if I’m at the 11000 point the > button will not let me go past this point.

Sorry if this seems a really long winded way to explain? If it makes any sense at all?

Gav.

What I was trying to get the code to do is if i’m at the 0 point the < button will not let me move past 0 and if I’m at the 11000 point the > button will not let me go past this point.

You will need to keep track of the x count and make the moves + or - from that point.
The button routines should check the x count value, and not enable a forward move if the count == 11000 or a backwards move if the count == 0.

Do not reset x = 0 to start all moves . This code needs revision to consider the actual position and whether the step count adds or subtracts.

if( isForward || isBackward ){
 for(x = 0; x < 5500; x++)

Thank you Cattledog,

I will contemplate your response...

Gav.