Go Down

Topic: NEMA 17 direction issues (Read 364 times) previous topic - next topic

DF95

Aug 27, 2014, 11:52 am Last Edit: Aug 27, 2014, 12:11 pm by DF95 Reason: 1
Hi, I'm working on a project involving a platform moving along a threaded bar in both directions. The platform is restrained by two limit switches at the end of the assembly. The platform should first reach the interrupt limit switch(pin 2), the rotation direction should then switch to take the platform to the other limit switch(pin 5). During this process the number of steps equating to the platform travelling one length of the assembly is counted. Experiencing problems currently whereby the motor initially rotates in the reverse direction rather than the forward direction which I've coded for. Here is a copy of my code. I'm very new to coding so point out any obvious issues.
Thanks

Code: [Select]
const int stepsPerRevolution = 200;
const int pwmA = 3;
const int pwmB = 11;
const int brakeA = 9;
const int brakeB = 8;
const int dirA = 12;
const int dirB = 13;    
unsigned int REVcount = 0;
int delayLength = 1;
volatile int ISRcount = 0;
volatile int state = LOW;
int SW2 = 5;  


void setup()
{
pinMode(3, OUTPUT);
pinMode(11, OUTPUT);
pinMode(9, OUTPUT);
pinMode(8, OUTPUT);
digitalWrite(3, LOW);   //initially motor has zero motion, loop introduces first movement
digitalWrite(11, LOW);
digitalWrite(9, LOW);
digitalWrite(8, LOW);
pinMode(5, INPUT);
attachInterrupt(0, REV, CHANGE);
Serial.begin(9600);
}

void loop()
{
 if (ISRcount < 1)
 {
   enableMotor();
   motorFWD();       //if ISRcount is below 1, motor forward
   dissableMotor();
 }
 else
 {
   dissableMotor();          //if IRScount is above or equal to 1, dissable motor
 }
 
 
 int i = 0;
 int x = 0;
 if ((ISRcount == 1) && (Serial.available()>0))
 {
   int x = Serial.parseInt();
   for (i = 0; i < x; i++)                  //for statement to loop motorFWD until it reaches position x
   {
     enableMotor();
     motorFWD();
     dissableMotor();
   }
   Serial.print("Platform calibration complete, at position ");
   Serial.print(x);
   Serial.print("/");                  
   Serial.println(REVcount);
   ISRcount = 2;                   //increase in ISRcount to prevent looping and start dissableMotor
  }
 else
 {
   dissableMotor();
 }  
}


void REV()
{
 ISRcount = 1;
 while (digitalRead(5) == HIGH)   //Interrupt triggered by Switch 1 and ends when Switch 2 is no longer ON
 {
 enableMotor();    //Interrupt sequence, used to alter motion to REV to take platform to Switch 2.
 motorREV();       //The number of steps are counted for use in later possible operations
 REVcount++;
 dissableMotor();
 }
 if (digitalRead(5) == LOW)
 {
   detachInterrupt(0);    //when switch 5 is triggered, Interrupt ends
 }
}


void enableMotor()
{
 digitalWrite(3, HIGH);
 digitalWrite(11, HIGH);
}



void dissableMotor()
{
 digitalWrite(3, LOW);
 digitalWrite(11, LOW);
}



void motorFWD()
{
 digitalWrite(9, LOW);  //enable CHA
 digitalWrite(8, HIGH);  //disable CHB
 digitalWrite(12, HIGH);  //sets direction of CHA  
 analogWrite(3, 255);  //moves CHA  
 delay(delayLength);
 digitalWrite(9, HIGH);  //disable CHA
 digitalWrite(8, LOW);  //enable CHB
 digitalWrite(13, LOW);  //sets direction of CHB
 analogWrite(11, 255);  //moves CHB
 delay(delayLength);
 digitalWrite(9, LOW);  //enable CHA
 digitalWrite(8, HIGH);  //disable CHB
 digitalWrite(12, LOW);  //sets direction of CHA
 analogWrite(3, 255);  //moves CHA
 delay(delayLength);
 digitalWrite(9, HIGH);  //disable CHA
 digitalWrite(8, LOW);  //enable CHB
 digitalWrite(13, HIGH);  //sets direction of CHB
 analogWrite(11, 255);  //moves CHB
 delay(delayLength);
}



void motorREV()
{
 digitalWrite(9, LOW);  //enable CHA
 digitalWrite(8, HIGH);  //disable CHB
 digitalWrite(12, HIGH);  //sets direction of CHA  
 analogWrite(3, 255);  //moves CHA  
 delay(delayLength);
 digitalWrite(9, HIGH);  //disable CHA
 digitalWrite(8, LOW);  //enable CHB
 digitalWrite(13, HIGH);  //sets direction of CHB
 analogWrite(11, 255);  //moves CHB
 delay(delayLength);
 digitalWrite(9, LOW);  //enable CHA
 digitalWrite(8, HIGH);  //disable CHB
 digitalWrite(12, LOW);  //sets direction of CHA
 analogWrite(3, 255);  //moves CHA
 delay(delayLength);
 digitalWrite(9, HIGH);  //disable CHA
 digitalWrite(8, LOW);  //enable CHB
 digitalWrite(13, LOW);  //sets direction of CHB
 analogWrite(11, 255);  //moves CHB
 delay(delayLength);  
}

DF95

I should mention I'm using the Arduino Uno with the Motor Shield with the motor powered by a 12V supply.

Robin2

You can't use ISRs like that. They should be very short - ideally something like

Code: [Select]
void rev() {
    limitSwitchTouched = true;
}


Then your other code notices that the variable is true and makes other stuff happen.

Why not use the AccelStepper library to handle all the tedious cr*p of sequencing the motor steps. Then it should be much easier to manage the direction.

The motor shield is a poor choice for driving stepper motors. A proper stepper motor driver board (such as the Pololu A4988) makes the code a lot simpler and allows the motor to be driven at a higher voltage for better performance. As you haven't posted details of your motor I don't claim that the A4988 is suitable - but there will be alternatives that are.

...R

DF95

Thanks for the reply, I'm using a bipolar NEMA 17 stepper motor with 2 control wires.
Other than the ones on the site you linked previously do you know of any good sites or links to learn the AccelStepper library?

MarkT

If you are only interested in the limit switch activating, use either RISING or FALLING
as the interrupt mode, having it as CHANGE will cause confusion as the switch
isn't debounced.

If the ISR responds to the event by overriding the direction to the safe direction
(rather than reversing it), it will be fool-proof and debouncing isn't so important.
[ I won't respond to messages, use the forum please ]

raschemmel

Are you sure you have the winding polarity correct to the driver ? Stepper motor direction is controlled by the drive sequence as it relates to the polarity. The direction is changed by changing the sequence. If you are experiencing  unexpected direction changes the sequence is probably wrong.
Read the datasheet for the L297 (page 4 I think) for the sequence patterns for steppers or google it.
Arduino UNOs, Pro-Minis, ATMega328, ATtiny85, LCDs, MCP4162, keypads,
DS18B20s,74c922,nRF24L01, RS232, SD card, RC fixed wing, quadcopter

Robin2


Thanks for the reply, I'm using a bipolar NEMA 17 stepper motor with 2 control wires.


Surely there are 4 power wires for the two coils? (Or maybe 6 wires if it is a hybrid motor).

Nema 17 defines the size of the front face of the motor and the position of the mounting holes. It has nothing to do with its electrical characteristics. The most important information from the control perspective is how much current the motor draws. Obviously the most important factor for you is whether it has enough torque for your application.

There are several examples on the Accelstepper website.

I agree with @MarkT's comment about limit switches and swapping the direction - but it must be done with a short ISR.

...R

raschemmel

Quote
I'm using a bipolar NEMA 17 stepper motor with 2 control wires.  

We're only talking about the motor itself, not the controller or wires going to the controller .
Stepper motor wires are called "windings", not control wires.
Either you didn't understand the question or there is something seriously wrong with your motor.
How many wires on the motor ?
Datasheet for the motor ?

Two wires is only one winding. . A stepper motor needs at least 4.
Arduino UNOs, Pro-Minis, ATMega328, ATtiny85, LCDs, MCP4162, keypads,
DS18B20s,74c922,nRF24L01, RS232, SD card, RC fixed wing, quadcopter

DF95

Thanks for the replies, the problem is sorted now as I am using a new unipolar motor.
I didn't mean to say 2 control wires, my mistake.

I haven't shortened the interrupt sequence however will remember to do so as well as consider using AccelStepper in future projects.

Go Up