Arduino Forum

Using Arduino => Programming Questions => Topic started by: caorline on Mar 22, 2019, 09:07 pm

Title: Controlling stepper motor with hc-sr04 sensors & limit switches for linear stage
Post by: caorline on Mar 22, 2019, 09:07 pm
Hi Everybody-

I'm pretty new to arduino projects, currently working on a linear stage for an interactive sculpture for graduate school.

I have built an 8' linear stage powered by a Nema 23 stepper motor with driver that turns a 8' acme rod. Attached to the rod is a nut with a housing that travels back and forth on an aluminum track. I have successfully hooked up the motor, driver, and arduino and have achieved forward and backward movement as well as random movement (see videos).

Now, I need to install limit switches at both ends of the 8' to keep the nut driver (3-d printed truck that encases the nut and glides on the rail) from crashing. Additionally, my end goal is to have the movement based off human interaction, so that the truck moves towards a viewer that approaches.

The motor has 200 steps per rotation, I've calculated that is has 192000 rotations for the entire length of the acme rod.

I'm using an arduino uno with a proto screw shield.

This is my code for back and forth movement, works perfectly:

Code: [Select]
int PUL=7; //define Pulse pin
int DIR=6; //define Direction pin
int ENA=5; //define Enable Pin


void setup() {
  pinMode (PUL, OUTPUT);
  pinMode (DIR, OUTPUT);
  pinMode (ENA, OUTPUT);

}

void loop() {
  for (int i=0; i<24000; i++)    //Forward steps
  {
    digitalWrite(DIR,LOW);
    digitalWrite(ENA,HIGH);
    digitalWrite(PUL,HIGH);
    delayMicroseconds(400);
    digitalWrite(PUL,LOW);
    delayMicroseconds(400);
  }
  for (int i=0; i<24000; i++)   //Backward steps
  {
    digitalWrite(DIR,HIGH);
    digitalWrite(ENA,HIGH);
   digitalWrite(PUL,HIGH);
    delayMicroseconds(400);
    digitalWrite(PUL,LOW);
    delayMicroseconds(400);
  }
  
}


This is my code for random movement with limit switches. The back and forth functions but the limit switches aren't recognized.

Code: [Select]
int PUL=7; //define Pulse pin
int DIR=6; //define Direction pin
int ENA=5; //define Enable Pin
#define limitSwitch1 11 //define backward switch pin
#define limitSwitch2 12 //define forward switch pin

long randomNumber;

void setup() {

//start serial communication
Serial.begin(9600);

//send at start messages to the serial monitor
Serial.println("start a new sequence of random numbers");
  
  pinMode (PUL, OUTPUT);
  pinMode (DIR, OUTPUT);
  pinMode (ENA, OUTPUT);

}

void loop() {

 //assign random number to value
 randomNumber= random(0,192000);


  
  for (int i=0; i<randomNumber && digitalRead(limitSwitch1); i++)    //Forward steps
  {
    digitalWrite(DIR,LOW);
    digitalWrite(ENA,HIGH);
    digitalWrite(PUL,HIGH);
    delayMicroseconds(400);
    digitalWrite(PUL,LOW);
    delayMicroseconds(400);
  }
  for (int i=0; i<randomNumber && digitalRead(limitSwitch2); i++)   //Backward steps
  {
    digitalWrite(DIR,HIGH);
    digitalWrite(ENA,HIGH);
   digitalWrite(PUL,HIGH);
    delayMicroseconds(400);
    digitalWrite(PUL,LOW);
    delayMicroseconds(400);
  }
  
}



And finally, this is my code (so far!) for including ultrasonic sensors. I haven't tested this yet, but I'm pretty sure there are errors.

Code: [Select]
//HC-SR04 Ping distance sensor defining distance of tape measure travel

//steps per revolution=200


int PUL=7; //define Pulse pin
int DIR=6; //define Direction pin
int ENA=5; //define Enable Pin
int trigPin1=11; //sensor left
int echoPin1=10; //sensor left
int trigPin2=13; //sensor right
int echoPin2=12; //sensor right
long duration;
int distance;
int RightSensor;
int LeftSensor;



void setup() {
  Serial.begin(9600);
  pinMode(trigPin1,OUTPUT); //LeftSensor
  pinMode(echoPin1, INPUT); //LeftSensor
  pinMode(trigPin2, OUTPUT); //RightSensor
  pinMode(echoPin2, INPUT); //RightSensor
 
  pinMode (PUL, OUTPUT); //Pulse of stepper
  pinMode (DIR, OUTPUT); //Direction of stepper
  pinMode (ENA, OUTPUT); //Enable stepper
  digitalWrite (5, LOW); //set enable low
  digitalWrite (7, LOW); //set step low --is pulse the same as step?

}

void loop() {

//LeftSensor
 //clears the trigPin
digitalWrite(trigPin1, LOW);
delayMicroseconds(2);
//sets the trigPin on HIGH state for 5 micro sec
digitalWrite(trigPin1, HIGH);
delayMicroseconds(5);
digitalWrite(trigPin1, LOW);
//reads the echoPin, returns the sound wave travel time in microseconds
duration = pulseIn(echoPin1, HIGH);
distance = (duration/2) / 29.1; //other code says distance=duration*0.034/2
Serial.print ("in");
Serial.print (distance);
delay(1000);

//RightSensor
 //clears the trigPin
digitalWrite(trigPin2, LOW);
delayMicroseconds(2);
//sets the trigPin on HIGH state for 5 micro sec
digitalWrite(trigPin2, HIGH);
delayMicroseconds(5);
digitalWrite(trigPin2, LOW);
//reads the echoPin, returns the sound wave travel time in microseconds
duration = pulseIn(echoPin2, HIGH);
distance = (duration/2) / 29.1; //other code says distance=duration*0.034/2
Serial.print ("in");
Serial.print (distance);
delay(1000);


//travel of tape measure
for (int i=0; i<LeftSensor; i++)    //Move if left sensor reading
  {
    digitalWrite(DIR,LOW);
    digitalWrite(ENA,HIGH);
    digitalWrite(PUL,HIGH);
    delayMicroseconds(400);
    digitalWrite(PUL,LOW);
    delayMicroseconds(400);
  }
  for (int i=0; i<RightSensor; i++)   //Moves if right sensor moving
  {
    digitalWrite(DIR,HIGH);
    digitalWrite(ENA,HIGH);
   digitalWrite(PUL,HIGH);
    delayMicroseconds(400);
    digitalWrite(PUL,LOW);
    delayMicroseconds(400);
  }
  
}








So, I guess what I'm looking for is advice on how to combine all these codes. I realize that I have a lot more research to do into this subject, so any help with resources or code is greatly appreciated! I apologize in advance if I haven't followed formatting.
Thanks!
Title: Re: Controlling stepper motor with hc-sr04 sensors & limit switches for linear stage
Post by: Robin2 on Mar 22, 2019, 11:40 pm
Almost certainly you will need to eliminate all the delay()s and delayMicrosecond()s in order to achieve a responsive program. Also (equally certainly) FOR and WHILE loops must be eliminated unless the complete within a number of microseconds.

The functions delay() and delayMicroseconds() block the Arduino until they complete.
Have a look at how millis() is used to manage timing without blocking in Several Things at a Time (http://forum.arduino.cc/index.php?topic=223286.0).

And see Using millis() for timing. A beginners guide (http://forum.arduino.cc/index.php?topic=503368.0) if you need more explanation.


Also see the second example in this Simple Stepper Code (http://forum.arduino.cc/index.php?topic=277692.0). However it may make more sense to use the AccelStepper (http://www.airspayce.com/mikem/arduino/AccelStepper/) library


This Simple Merge Demo (http://forum.arduino.cc/index.php?topic=258240) may give you some ideas.

Before trying to merge the programs go through each of them carefully to make sure they are not trying to use the same resource - for example an I/O pin. If you find conflicts change something in one of the separate programs and make sure it still works with the change.

Also, merge A and B and get the combined program working before trying to merge C.

...R