Turning a Stepper motor until an input detected and then turning the other way

Currently working on a project but having some trouble with one section of it. What I need to happen is on power up the arduino checks to see if their is any force on a force sensor if their is not it turns the stepper motor until it detects force at which point it should turn the opposite way a set amount of steps
Heres my code currently

//Defines Control Pins:
const int Button = 5;// the pin our push button is on
const int Vibrator = 11;     //pin 3 has PWM funtion
const int ForceSensor = A4; //pin A0 to read analog input

// defines Motor pins
#define stepPin 54
#define dirPin 55
const int dirPinX = 55; // this will pretty much be dictating rotation direction "clockwise/counterclockwise"
const int stepPinX = 54; // this pretty much dictates speed, reducing delays increases speed
const int enPinX = 38; // this enables or disables the motor

//Variables:
int value; //save analog value
int Position; // Creates Position Variable

void setup()
{
  pinMode(Button,INPUT_PULLUP); // Set the Button as an input
  pinMode(Vibrator, OUTPUT);  //Set pin 3 as 'feedback output' 
  Serial.begin(9600);       //Begin serial communication
// Declare All Stepper pins as Outputs
 pinMode(stepPinX, OUTPUT);
 pinMode(dirPinX, OUTPUT);
 pinMode(enPinX, OUTPUT);

 value = analogRead(ForceSensor);       //Read and save analog value from potentiometer
if (value < 100){
  homing();
}
 }


void homing ()
{
    value = analogRead(ForceSensor);       //Read and save analog value from potentiometer
        int digitalVal= digitalRead(ForceSensor);
    digitalWrite(dirPinX,HIGH); // Enables the motor to move in a particular direction by switching between HIGH and Low
  // Makes 200 pulses for making one full cycle rotation
  while (value < 100)
  {//This determines by how many degrees the stepper will move:3200steps is 360 degrees which means that 12.5 steps is 1.4 degrees, 1 degree = 8.929steps
    digitalWrite(stepPinX,HIGH); 
    delayMicroseconds(500);    // by changing this time delay between the steps we can change the rotation speed Higher Number= Lower Speed Lower Limit = 16 ms
    digitalWrite(stepPinX,LOW); 
    Position++;//Updates Position Variable
    delayMicroseconds(50); 
}
}


void loop() {
  
   // Get button event and act accordingly
   int b = checkButton();
   if (b == 2) doubleClickEvent();
   if (b == 3) holdEvent();

    value = analogRead(ForceSensor);       //Read and save analog value from potentiometer
   value = map(value, 0, 1023, 0, 255); //Map value 0-1023 to 0-255 (PWM)
   analogWrite(Vibrator, value);          //Send PWM value to vibrator

}

//=================================================
// Events to trigger




void doubleClickEvent() {
      int digitalVal= digitalRead(ForceSensor);
    digitalWrite(dirPinX,LOW); // Enables the motor to move in a particular direction by switching between HIGH and Low
  // Makes 200 pulses for making one full cycle rotation
  for(int x = 0; x < Position ; x++) {//Returns Motor To Position 0
    digitalWrite(stepPinX,HIGH); 
    delayMicroseconds(500);    // by changing this time delay between the steps we can change the rotation speed Higher Number= Lower Speed Lower Limit = 16 ms
    digitalWrite(stepPinX,LOW); 
    delayMicroseconds(50); 
}
 Position = 0; //Resets Position Variable to 0
}
void holdEvent() {
      int digitalVal= digitalRead(ForceSensor);
    digitalWrite(dirPinX,HIGH); // Enables the motor to move in a particular direction by switching between HIGH and Low
  // Makes 200 pulses for making one full cycle rotation
  for(int x = 0; x < 1; x++) {//This determines by how many degrees the stepper will move:3200steps is 360 degrees which means that 12.5 steps is 1.4 degrees, 1 degree = 8.929steps
    digitalWrite(stepPinX,HIGH); 
    delayMicroseconds(500);    // by changing this time delay between the steps we can change the rotation speed Higher Number= Lower Speed Lower Limit = 16 ms
    digitalWrite(stepPinX,LOW); 
    Position++;//Updates Position Variable
    delayMicroseconds(50); 
}
}

//=================================================
//  MULTI-CLICK:  One Button, Multiple Events

// Button timing variables
int debounce = 20;          // ms debounce period to prevent flickering when pressing or releasing the button
int DCgap = 150;            // max ms between clicks for a double click event
int holdTime = 151;        // ms hold period: how long to wait for press+hold event
int longHoldTime = 3000;    // ms long hold period: how long to wait for press+hold event

// Button variables
boolean buttonVal = HIGH;   // value read from button
boolean buttonLast = HIGH;  // buffered value of the button's previous state
boolean DCwaiting = false;  // whether we're waiting for a double click (down)
boolean DConUp = false;     // whether to register a double click on next release, or whether to wait and click
boolean singleOK = true;    // whether it's OK to do a single click
long downTime = -1;         // time the button was pressed down
long upTime = -1;           // time the button was released
boolean ignoreUp = false;   // whether to ignore the button release because the click+hold was triggered
boolean waitForUp = false;        // when held, whether to wait for the up event
boolean holdEventPast = false;    // whether or not the hold event happened already
boolean longHoldEventPast = false;// whether or not the long hold event happened already

int checkButton() {    
   int event = 0;
   buttonVal = digitalRead(Button);
   // Button pressed down
   if (buttonVal == LOW && buttonLast == HIGH && (millis() - upTime) > debounce)
   {
       downTime = millis();
       ignoreUp = false;
       waitForUp = false;
       singleOK = true;
       holdEventPast = false;
       if ((millis()-upTime) < DCgap && DConUp == false && DCwaiting == true)  DConUp = true;
       else  DConUp = false;
       DCwaiting = false;
   }
   // Button released
   else if (buttonVal == HIGH && buttonLast == LOW && (millis() - downTime) > debounce)
   {        
       if (not ignoreUp)
       {
           upTime = millis();
           if (DConUp == false) DCwaiting = true;
           else
           {
               event = 2;
               DConUp = false;
               DCwaiting = false;
               singleOK = false;
           }
       }
   }
   // Test for hold
   if (buttonVal == LOW && (millis() - downTime) >= holdTime) {
       // Trigger "normal" hold
       if (not holdEventPast)
       {
           event = 3;
           waitForUp = false;
           ignoreUp = true;
           DConUp = false;
           DCwaiting = false;
           //downTime = millis();
           holdEventPast = false;
           
       }

   }
   buttonLast = buttonVal;
   return event;
}

At the moment on power up if there is no force the motor does spin in the desired direction however once force is applied it does not stop
if their is force on the sensor on power up it functions correctly
Any ideas how to get this to work?
Thanks!

Does your force sensor have analog and digital output?
Are you aware you never use digitalVal?
Are you also aware the three local variables named digitalVal do not change each other?

Was this supposed to be on pin 3?

This while loop is an infinite loop. If you want it to stop, you need to update 'value' within the loop.

From what I can tell the force sensor does have both digital and analog outputs
I didnt notice that I never actually used digitalVal its left over from when I was messing around getting the motor to change speed based on the force so ill be sure to remove that thanks
Not quite sure what you meant by the 3 local variables not changing each other sorry still kinda new to some of this and yeah I changed the pin for the vibration motor forgot to change the comment so ill be sure to fix that thanks!

Ah okay didnt know that I had to update the value in the while loop thanks ill give that a shot!

1 Like

@skylord711
Are you using arduino Mega? or.....
If you are using arduino mega the pin A0 and 54 is the same. and so.........
. Look image.

have defined this pins twice...

// defines Motor pins
#define stepPin 54
#define dirPin 55
const int dirPinX = 55; // this will pretty much be dictating rotation direction "clockwise/counterclockwise"
const int stepPinX = 54; // this pretty much dictates speed, reducing delays increases speed

I am using a mega the comment says A0 but I changed that to A4

I gave that a go and it didnt work not sure if I did it right

void homing ()
{
  start:
        int digitalVal= digitalRead(ForceSensor);
    digitalWrite(dirPinX,HIGH); // Enables the motor to move in a particular direction by switching between HIGH and Low
  // Makes 200 pulses for making one full cycle rotation
  while (value < 100)
  {//This determines by how many degrees the stepper will move:3200steps is 360 degrees which means that 12.5 steps is 1.4 degrees, 1 degree = 8.929steps
    digitalWrite(stepPinX,HIGH); 
    delayMicroseconds(500);    // by changing this time delay between the steps we can change the rotation speed Higher Number= Lower Speed Lower Limit = 16 ms
    digitalWrite(stepPinX,LOW); 
    delayMicroseconds(50);
    value = digitalRead(ForceSensor); 
    digitalWrite (value);
}
    digitalWrite(dirPinX,HIGH); // Enables the motor to move in a particular direction by switching between HIGH and Low
  // Makes 200 pulses for making one full cycle rotation
  if (digitalVal < 100)
  {goto start;}
}

From reading your code it is unclear what you want to happen.

After it gets out of the while loop, value won't be <100 anymore and your goto won't do anything.

Maybe take a look at:

...and break homing() up into homeTowardsACertainForce() and backOffFromCertainForce().

Managed to work out a solution there's still some discrepancies in the code but all in all does what I need thanks to everyone for their advice!
Im attaching the code incase anyone needs it for anything similar its not perfect but it works

//Defines Control Pins:
const int Button = 5;         //pin 5 is push button
const int Vibrator = 11;     //pin 1 has PWM funtion
const int ForceSensor = A4; //pin A4 to read analog input

// defines Motor pins
#define stepPin 54
#define dirPin 55
const int dirPinX = 55; // this will pretty much be dictating rotation direction "clockwise/counterclockwise"
const int stepPinX = 54; // this pretty much dictates speed, reducing delays increases speed
const int enPinX = 38; // this enables or disables the motor

//Variables:
int value; //save analog value
int Position; // Creates Position Variable

void setup()
{
  pinMode(Button,INPUT_PULLUP); // Set the Button as an input
  pinMode(Vibrator, OUTPUT);  //Set pin 3 as 'feedback output' 
  Serial.begin(9600);       //Begin serial communication
// Declare All Stepper pins as Outputs
 pinMode(stepPinX, OUTPUT);
 pinMode(dirPinX, OUTPUT);
 pinMode(enPinX, OUTPUT);

 value = analogRead(ForceSensor);       //Read and save analog value from potentiometer
if (value < 100){
  homing();
  value = digitalRead(ForceSensor);
}
 }

void homing() {
    int digitalVal = 0;
    while (true) {
        // Check if there is no input from ForceSensor
        if (digitalRead(ForceSensor) == LOW) {
            digitalWrite(dirPinX, HIGH); // Set direction to HIGH
            digitalWrite(stepPinX, HIGH);
            delayMicroseconds(500);
            digitalWrite(stepPinX, LOW);
            delayMicroseconds(50);
        } else {
            // If input detected, turn in LOW direction for 3200 steps
            digitalWrite(dirPinX, LOW); // Set direction to LOW
            for (int i = 0; i < 3200; i++) {
                digitalWrite(stepPinX, HIGH);
                delayMicroseconds(500);
                digitalWrite(stepPinX, LOW);
                delayMicroseconds(50);
            }
            // Exit the homing function
            return;
        }
    }
}


void loop() {
  
   // Get button event and act accordingly
   int b = checkButton();
   if (b == 2) doubleClickEvent();
   if (b == 3) holdEvent();

    value = analogRead(ForceSensor);       //Read and save analog value from potentiometer
   value = map(value, 0, 1023, 0, 255); //Map value 0-1023 to 0-255 (PWM)
   analogWrite(Vibrator, value);          //Send PWM value to vibrator

}

//=================================================
// Events to trigger




void doubleClickEvent() {
      int digitalVal= digitalRead(ForceSensor);
    digitalWrite(dirPinX,LOW); // Enables the motor to move in a particular direction by switching between HIGH and Low
  // Makes 200 pulses for making one full cycle rotation
  for(int x = 0; x < Position ; x++) {//Returns Motor To Position 0
    digitalWrite(stepPinX,HIGH); 
    delayMicroseconds(500);    // by changing this time delay between the steps we can change the rotation speed Higher Number= Lower Speed Lower Limit = 16 ms
    digitalWrite(stepPinX,LOW); 
    delayMicroseconds(50); 
}
 Position = 0; //Resets Position Variable to 0
}
void holdEvent() {
      int digitalVal= digitalRead(ForceSensor);
    digitalWrite(dirPinX,HIGH); // Enables the motor to move in a particular direction by switching between HIGH and Low
  // Makes 200 pulses for making one full cycle rotation
  for(int x = 0; x < 1; x++) {//This determines by how many degrees the stepper will move:3200steps is 360 degrees which means that 12.5 steps is 1.4 degrees, 1 degree = 8.929steps
    digitalWrite(stepPinX,HIGH); 
    delayMicroseconds(500);    // by changing this time delay between the steps we can change the rotation speed Higher Number= Lower Speed Lower Limit = 16 ms
    digitalWrite(stepPinX,LOW); 
    Position++;//Updates Position Variable
    delayMicroseconds(50); 
}
}

//=================================================
//  MULTI-CLICK:  One Button, Multiple Events

// Button timing variables
int debounce = 20;          // ms debounce period to prevent flickering when pressing or releasing the button
int DCgap = 150;            // max ms between clicks for a double click event
int holdTime = 151;        // ms hold period: how long to wait for press+hold event
int longHoldTime = 3000;    // ms long hold period: how long to wait for press+hold event

// Button variables
boolean buttonVal = HIGH;   // value read from button
boolean buttonLast = HIGH;  // buffered value of the button's previous state
boolean DCwaiting = false;  // whether we're waiting for a double click (down)
boolean DConUp = false;     // whether to register a double click on next release, or whether to wait and click
boolean singleOK = true;    // whether it's OK to do a single click
long downTime = -1;         // time the button was pressed down
long upTime = -1;           // time the button was released
boolean ignoreUp = false;   // whether to ignore the button release because the click+hold was triggered
boolean waitForUp = false;        // when held, whether to wait for the up event
boolean holdEventPast = false;    // whether or not the hold event happened already
boolean longHoldEventPast = false;// whether or not the long hold event happened already

int checkButton() {    
   int event = 0;
   buttonVal = digitalRead(Button);
   // Button pressed down
   if (buttonVal == LOW && buttonLast == HIGH && (millis() - upTime) > debounce)
   {
       downTime = millis();
       ignoreUp = false;
       waitForUp = false;
       singleOK = true;
       holdEventPast = false;
       if ((millis()-upTime) < DCgap && DConUp == false && DCwaiting == true)  DConUp = true;
       else  DConUp = false;
       DCwaiting = false;
   }
   // Button released
   else if (buttonVal == HIGH && buttonLast == LOW && (millis() - downTime) > debounce)
   {        
       if (not ignoreUp)
       {
           upTime = millis();
           if (DConUp == false) DCwaiting = true;
           else
           {
               event = 2;
               DConUp = false;
               DCwaiting = false;
               singleOK = false;
           }
       }
   }
   // Test for hold
   if (buttonVal == LOW && (millis() - downTime) >= holdTime) {
       // Trigger "normal" hold
       if (not holdEventPast)
       {
           event = 3;
           waitForUp = false;
           ignoreUp = true;
           DConUp = false;
           DCwaiting = false;
           //downTime = millis();
           holdEventPast = false;
           
       }

   }
   buttonLast = buttonVal;
   return event;
}

Hey thanks for the advice ive managed to work out a solution ill look at that link though and see if i can make any improvement thanks!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.