Go Down

Topic: Stepper Motors with Watchdog Switches (Read 2451 times) previous topic - next topic

vonnied

I am currently designing a test rig that has two stepper motors in sync. I need them to have watchdog switches so if one stepper motor is stopped and doesn't complete the full revolution the system stops.

I have tried Switch/Case, if statements and if/else statements with no luck.

I had tried to write the code so when one switch was hit the steppers would step halfway through a revolution and then when the next witch was triggered it would step through the second half of the revolution.

After each full revolution I would like the LCD to also Display what iteration ( what revolution) it was on.

On top of all of this I would like to have the system running at 120 rpm with possibility of cranking it up to 600-800 rpm.

I am using a Arduino Uno and controlling the steppers with a ST-M5045 MircoStep Controller.

I would appreciate any insight. I would post code but do to trying multiple ways I have like 6 different files and none of them come close to working.

Thank you for any help!

Robin2

If you want help the first requirement is to post your code.

It would probably also be useful to post a wiring diagram - especially for the switches.

...R
Stepper Motor Basics
Two or three hours spent thinking and reading documentation solves most programming problems.

vonnied

OK I got my code to work the way I want but I have the Arduino writing PIN 9 HIGH and LOW in a For loop using a modulo.

Is there any way to have it write this faster or am I stuck with the speed of the processor on the Arduino?

MorganS

Modulo is slow because it uses a division operation. Can you post your updated code in [ code ] tags so we can see it?
"The problem is in the code you didn't post."

vonnied

Here you go, sorry about that!


Code: [Select]
// Include the library code:
#include <LiquidCrystal.h>

// Initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

// Constants won't change. They're used here to
// set pin numbers:
const int start_reset = 6;  // The start/reset button pin
const int         off = 7;  // The stop button pin
const int   hammer_WD = 10;  // The hammer watchdog
const int  trigger_WD = 13;  // The trigger watchdog

boolean boHammerWD;
boolean boTriggerWD;

// Variables will change:
int sensorPin = A0;
int sensorValue = 0;
int iteration;
int current_speed;
int hWD_state = LOW;              // the current reading from the hammer Watchdog pin
int last_hWD_state = LOW;   // the previous reading from the hammer Watchdog pin
int tWD_state = LOW;              // the current reading from the trigger Watchdog pin
int last_tWD_state = LOW;   // the previous reading from the trigger Watchdog pin

void setup() {
  pinMode (start_reset, INPUT);
  pinMode (off, INPUT);
  pinMode (hammer_WD, INPUT);
  pinMode (trigger_WD, INPUT);

  pinMode(8, OUTPUT); //Directional Pin
  pinMode(9, OUTPUT); //Step Pin
  digitalWrite(8, LOW);
  digitalWrite(9, LOW);

  // Set up the LCD:
  lcd.begin(16, 2);
  lcd.print("Iteration");

}

void loop() {
  iteration = 0;
  lcd.setCursor(0, 1);
  lcd.print(iteration);

  // Potentiometer
  sensorValue = analogRead(sensorPin);
  sensorValue = map(sensorValue, 0, 1023, 3600, 1);

  tWD_state = digitalRead(trigger_WD);
  hWD_state = digitalRead(hammer_WD);

  if (tWD_state != last_tWD_state)
  {
    boTriggerWD = true;
  }
  else {
    boTriggerWD = false;
  };

  if (hWD_state != last_hWD_state)
  {
    boHammerWD = true;
  }
  else {
    boHammerWD = false;
  };

  if (boTriggerWD) {
    iteration++;
    last_tWD_state = tWD_state;
    lcd.print(iteration);
    for (int x = 0; x <= 200; x++) {
      if (x % 2 == 0) {
        digitalWrite(9, HIGH);
        delayMicroseconds(sensorValue);
      }
      if (x % 2 == 1) {
        digitalWrite(9, LOW);
        delayMicroseconds(sensorValue);
      }
    }
  }
  if (boHammerWD) {
    last_hWD_state = hWD_state;
    lcd.print(iteration);
    digitalWrite(9, HIGH);
    digitalWrite(9, LOW);
    for (int x = 0; x <= 200; x++) {
      if (x % 2 == 0) {
        digitalWrite(9, HIGH);
        delayMicroseconds(sensorValue);
      }
      if (x % 2 == 1) {
        digitalWrite(9, LOW);
        delayMicroseconds(sensorValue);
      }
    }
  }
}

vonnied

I just replaced the second modulo on both if statements with else in hopes to speed up but no luck.

Code: [Select]
  if (boTriggerWD) {
    iteration++;
    last_tWD_state = tWD_state;
    lcd.print(iteration);
    for (int x = 0; x <= 200; x++) {
      if (x % 2 == 0) {
        digitalWrite(9, HIGH);
        delayMicroseconds(sensorValue);
      }
      else {
        digitalWrite(9, LOW);
        delayMicroseconds(sensorValue);
      }
    }
  }
  if (boHammerWD) {
    last_hWD_state = hWD_state;
    lcd.print(iteration);
    digitalWrite(9, HIGH);
    digitalWrite(9, LOW);
    for (int x = 0; x <= 200; x++) {
      if (x % 2 == 0) {
        digitalWrite(9, HIGH);
        delayMicroseconds(sensorValue);
      }
      else {
        digitalWrite(9, LOW);
        delayMicroseconds(sensorValue);
      }
    }
  }
}

vonnied

Would making an array 1x250 with alternating 1's and 0's and calling the column with a for loop to decide which if statement to run be faster than the modulo?

Robin2

Wouldn't this be a whole lot simpler
 
Code: [Select]
byte upDown = 0;
   for (int x = 0; x <= 200; x++) {
      if (upDown == 0) {
        digitalWrite(9, HIGH);
        delayMicroseconds(sensorValue);
        upDown = 1;
      }
      else {
        digitalWrite(9, LOW);
        delayMicroseconds(sensorValue);
        upDown = 0;
      }
    }


Also, why have you duplicate code. This should work just as well

Code: [Select]
   byte upDown = 0;
   for (int x = 0; x <= 200; x++) {
         digitalWrite(9, upDown);
        delayMicroseconds(sensorValue);
         upDown = ! upDown;
    }

It may also be wise to abandon delayMicroseconds() in favour of the using micros() or millis() as in the second example in this simple stepper code.

You probably should also abandon the use of FOR as that also blocks until it is complete.

That will make your code much more responsive

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

vonnied

Thank you I will try that out! I am new to this style coding and trying to make it more efficient.

vonnied

Wouldn't this be a whole lot simpler
  
Code: [Select]
byte upDown = 0;
   for (int x = 0; x <= 200; x++) {
      if (upDown == 0) {
        digitalWrite(9, HIGH);
        delayMicroseconds(sensorValue);
        upDown = 1;
      }
      else {
        digitalWrite(9, LOW);
        delayMicroseconds(sensorValue);
        upDown = 0;
      }
    }


Also, why have you duplicate code. This should work just as well

Code: [Select]
  byte upDown = 0;
   for (int x = 0; x <= 200; x++) {
         digitalWrite(9, upDown);
        delayMicroseconds(sensorValue);
         upDown = ! upDown;
    }

It may also be wise to abandon delayMicroseconds() in favour of the using micros() or millis() as in the second example in this simple stepper code.

You probably should also abandon the use of FOR as that also blocks until it is complete.

That will make your code much more responsive

...R
Thank you modifying your code solved my issue and now it runs like a charm!!!!

MarkT

Or the blindingly simple
Code: [Select]

    for (int x = 0; x <= 100; x++)
    {
      digitalWrite(9, HIGH);
      delayMicroseconds(sensorValue);
      digitalWrite(9, LOW);
      delayMicroseconds(sensorValue);
    }


But note the modulo wasn't the problem in the first place, the limiting
factor is that digitalWrite is very slow because its general enough to work
with any pin.

Direct port manipulation is often employed when speed really matters.

What actual step rates are you wanting to achieve?

You will need to deal with ramping up the speed to get to high stepping speeds,
a motor cannot accelerate infinitely fast.
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

Go Up