I need to rotate a stepper motor at very low rpm in either direction using two push buttons hooked up to D4 and D5 of Arduino Nano. The motor should rotate as long as either button is pressed.
A simple way is to read the status of the buttons in the main loop, set the direction and execute the function to run the motor.
You may take a look at MobaTools, it uses interrupts to drive stepper motors. I have been using it in some of my own projects with success.
(The developer is an active member of this forum (mostly german section))
void loop()
{
readSelectorSwitch(); // Read Selector Switch and prepare data for display
displayData(); // Update data on LCD
//################## STRIP SETTING #############
reading = digitalRead(FWDpin);
debounce();
if (reading == LOW) ///// FWD button pressed
{
digitalWrite(dirPin, !Clockwise); // Change direction to forward
jogMoveStrip();
}
reading = digitalRead(REVpin);
debounce();
if (reading == LOW) ///// REV button pressed
{
digitalWrite(dirPin, Clockwise); // Change direction to reverse
jogMoveStrip();
}
//############## STRIP SETTING END ############
//%%%%%%%%%%%%% STRIP DETECTION %%%%%%%%%%%
if (digitalRead(stripPresentSensorPin) == LOW) // if strip present
{
digitalWrite(strokePausePin, LOW); // Do NOT pause stroke
}
else // if Strip NOT present
{
detectionDelay = analogRead(stripDetectionDelay);
detectionDelay = map(detectionDelay, 0, 1023, 2000, 10);
delay(detectionDelay);
if (digitalRead(stripPresentSensorPin) == HIGH) // recheck if Strip not present
{
digitalWrite(strokePausePin, HIGH); // PAUSE the stroke
}
}//%%%%%%%% STRIP DETECTION ENDS %%%%%%%%%%
}
void jogMoveStrip()
{
for(int x = 0; x < 20; x++)
{
digitalWrite(pulsePin, LOW);
delayMicroseconds(5);
digitalWrite(pulsePin, HIGH);
delayMicroseconds(5);
}
}
The FWD button is connected to D4 and REV button is connected to D5, with pullup resistors.
D2 and D3 are already in use. I tried to use PinChangeInterrupts for D4 & D5 but they offer only three mode RISING, FALLING and CHANGE whereas, I think it should do with LOW.
again, it seems redundant to read stripPresentSensorPin twice
and is the purpose of stripDetectionDelay simply to delay re-reading stripPresentSensorPin (again)?
presumably this would generate a pulse to step a motor every ~10usec. my experience is most stepper motors can't step faster than ~1msec.
Yes, they are 2 separate buttons. They are placed about 6" apart. Even if accidentally or purposely pressed simultaneously, nothing adverse will happen because the movement is very minor for the alignment of the strip before starting the main procedure.
Basically, the sensor is checking if the strip is stuck or not. If the strip is not present then it is stuck. However, in normal routine the strip is momentarily not present. That's why there is a need to reconfirm if the strip is really not present.
Agreed.
Earlier, I have been working with stepper. But now I am using an AC servo, the code is modified accordingly.
so these are intend to drive the thing either forward or backwards while being pressed, not just change direction. in other words, invoke jogMoveStrip()
shouldn't this be constantly checked within jogMoveStrip() ?
You CANNOT simply start issuing pulses at a very high rate. There is a thing called inertia. You must start at a low pulerate, and ramp up to the max speed over a reasonable period of time. AC servos, with proper PID settings, can react far better than a stepper motor (which will simply do nothing it you start issuing pulses at a high rate), but even AC servos need to be ramped up to speed. And you must also ramp down when stopping.
No. As I already mentioned earlier, these FWD and REV movement of the strip is required only once in the beginning to align the strip in proper initial position. After that the main procedure starts. The sensor checking is done within the main procedure.
Agreed without any argument.
Here, speed/acceleration of the motor is my secondary concern. They can be tuned later.
My primary concern is to turn the motor smoothly either forward or backwards (while the relevant button is pressed) within the main loop. The sensor checking portion of the code is actually causing delay.
Neither can the sensor checking be shifted to ISR because of "delay" involved, nor can the motor FWD or REV movement be shifted to ISR because PinChangeInt does not support LOW mode.
The "correct" way to generate step pulses with a timer is to set the timer interrupt to occur at TWICE the step rate, so you get an interrupt on BOTH edges of the step pulse, creating 50% duty cycle square wave step pulse stream. Even on an 8MHz Arduino this can easily handle at least a 10kHs step rate. You can then modulate the counter TOP value to control the step frequency. The ISR, with proper code and lookup tables, can then easily handle calculation of step timing, acceleration ramping, and counting steps. delay() is never required.
Does this "correct" way applies to manual movement of the motor? I mean the motor is to rotate as long as the button is press. (The servo is set at 4000 steps/revolution). The 20 steps is jogMoveStrip() is rotating only 1.8°
I would like to have some tips on this. Although, I have gone thru manual of the servo drive/motor but I could not get the idea of setting PID. Are there any 3rd party softwares which could sense the drive's settings and then allow auto/manual tuning?
PID tuning, especially for a high performance AC servo, is a whole science in itself. The smart way to go is buy a motor and drive that are pre-configured to operate together by the manufacturer. Otherwise, you'll never get it anywhere near optimum.
among other uses, PID is good for positioning by factoring in the speed along with the distance from a position to determine the controlling value (e.g. motor voltage) to reach the position with an acceptable amount of overshoot.
for example, for the same distance (proportional) from a target, moving slowly (derivative of distance) may result is a positive (kpP - kdD) control voltage while moving fast may result in a negative control voltage, actively braking the motor.
of course the control voltage has limits and may only become < limit at some distance (and speed) from a target slowing the motor
the integral part of PID may have been necessary with analog systems where some error was necessary to maintain a motor voltage at some speed even though the target speed error (P) and acceleration (D) are zero. digital systems can be different
Because he has no choice. He's using AC servos, and PID is built into the motor controller. AC servos is a very odd choice for a very low-speed, obviously non-critical, system. What he describes is an ideal application for stepper motors.