I have been having a hard time on this project. I have never used a stepper motor before. Here is the outline of the project. I am building a box to run on a clothesline left to right. The stepper motor will run to the right until the proximity sensor is met and held on for 1 second on the right side.( this it to prevent spiritic movement) Then the stepper will move to the left. Left sensor is made for a total of 1 second then the direction is changed to the right. when the right side sensor is made for 1 second the stepper motor changes direction and move to the left. ect... only ending when the battery dies. The stepper motor driver I am using is an L298N. sensor is a E18-D80NK. Below is the laughable code that I have been attempting to wright. I would be interested in a ramp up in speed due to the system working on a wheel system. This would prevent burnout but at this point I just want it to work. I would be grateful for any help you could provide. Thank you again.
int motorSpeed = 300; //RPM OF MOTOR
int RP; // right side prox
int RPTime; // time of right side prox
int RPDelay (500); // delay time before motor change
int LP; // left side prox
int LPTime; // time of right side prox
int LPDelay (10); // dealy time before motor change #define RPS 5 // pin for right side sensor #define LPS 1 // Pin for left side sensor
void setup() {
// nothing to do inside the setup
pinMode (RPS, INPUT_PULLUP); //setup for right sensor
pinMode (LPS, INPUT_PULLUP); //setup for left sensor
}
void loop() {
// read the sensor value:
RP =digitalRead(RPS); // check sensor
LP =digitalRead(LPS); // check sensor
if (LP == 0) {
LPTime = millis;
if (LPTime <= millis - LPDelay) {
myStepper.setSpeed(motorSpeed);
// step 1/100 of a revolution:
myStepper.step(stepsPerRevolution);}
}
if (RP == 0) {
myStepper.setSpeed(motorSpeed);
// step 1/100 of a revolution:
myStepper.step(-stepsPerRevolution);
Its just the one stepper motor. spins to the right until a sensor is made for 1 second thin spins to the left. until the left side sensor is made for one second.
Can you please post a copy of your circuit, a picture of a hand drawn circuit in jpg, png?
Hand drawn and photographed is perfectly acceptable.
Please include ALL hardware, power supplies, component names and pin labels.
The datasheet for that motor indicates current of 0.7 Amps and resistance of 4Ω, NOT suitable for L298. You need a "chopper" driver such as A4988.
Note: With a "chopper" driver you must set the current limiter to suit your motor (0.7 Amps).
This usage of millis() should use millis() with parentheses so you get the result of the call to the function, not the boring, constant, machine address of the name of the function:
It looks like there are other issues, but it is hard to read from your code formatting. Maybe try some of these:
Interesting. He shows the acceleration math that is used by the AccelStepper library, and the coordination between motors is done by sychronizing times of motion rather than the more industry-standard CNC way of using the Bresenham algorithm to keep the ratios of steps in sync, while doing acceleration on the most constrained axis. When using time instead of Bresenham, it is easy to get the motors out of coordination when their acceleration curves top out differently.
// By @iforce2d for https://www.youtube.com/watch?v=fHAO7SW-SZI
// Code from https://www.iforce2d.net/sketches/
// and https://www.iforce2d.net/sketches/stepperControl_iforce2d.zip
//
// For RAMPS 1.4
#define X_DIR_PIN 55
#define X_STEP_PIN 54
#define X_ENABLE_PIN 38
#define Y_DIR_PIN 61
#define Y_STEP_PIN 60
#define Y_ENABLE_PIN 56
#define Z_DIR_PIN 48
#define Z_STEP_PIN 46
#define Z_ENABLE_PIN 62
#define A_DIR_PIN 28
#define A_STEP_PIN 26
#define A_ENABLE_PIN 24
#define B_DIR_PIN 34
#define B_STEP_PIN 36
#define B_ENABLE_PIN 30
#define C_DIR_PIN 32
#define C_STEP_PIN 47
#define C_ENABLE_PIN 45
#define X_STEP_HIGH PORTF |= 0b00000001;
#define X_STEP_LOW PORTF &= ~0b00000001;
#define Y_STEP_HIGH PORTF |= 0b01000000;
#define Y_STEP_LOW PORTF &= ~0b01000000;
#define Z_STEP_HIGH PORTL |= 0b00001000;
#define Z_STEP_LOW PORTL &= ~0b00001000;
#define A_STEP_HIGH PORTA |= 0b00010000;
#define A_STEP_LOW PORTA &= ~0b00010000;
#define B_STEP_HIGH PORTC |= 0b00000010;
#define B_STEP_LOW PORTC &= ~0b00000010;
#define C_STEP_HIGH PORTL |= 0b00000100;
#define C_STEP_LOW PORTL &= ~0b00000100;
#define TIMER1_INTERRUPTS_ON TIMSK1 |= (1 << OCIE1A);
#define TIMER1_INTERRUPTS_OFF TIMSK1 &= ~(1 << OCIE1A);
struct stepperInfo {
// externally defined parameters
float acceleration;
volatile unsigned long minStepInterval; // ie. max speed, smaller is faster
void (*dirFunc)(int);
void (*stepFunc)();
// derived parameters
unsigned int c0; // step interval for first step, determines acceleration
long stepPosition; // current position of stepper (total of all movements taken so far)
// per movement variables (only changed once per movement)
volatile int dir; // current direction of movement, used to keep track of position
volatile unsigned int totalSteps; // number of steps requested for current movement
volatile bool movementDone = false; // true if the current movement has been completed (used by main program to wait for completion)
volatile unsigned int rampUpStepCount; // number of steps taken to reach either max speed, or half-way to the goal (will be zero until this number is known)
volatile unsigned long estStepsToSpeed; // estimated steps required to reach max speed
volatile unsigned long estTimeForMove; // estimated time (interrupt ticks) required to complete movement
volatile unsigned long rampUpStepTime;
volatile float speedScale; // used to slow down this motor to make coordinated movement with other motors
// per iteration variables (potentially changed every interrupt)
volatile unsigned int n; // index in acceleration curve, used to calculate next interval
volatile float d; // current interval length
volatile unsigned long di; // above variable truncated
volatile unsigned int stepCount; // number of steps completed in current movement
};
void xStep() {
X_STEP_HIGH
X_STEP_LOW
}
void xDir(int dir) {
digitalWrite(X_DIR_PIN, dir);
}
void yStep() {
Y_STEP_HIGH
Y_STEP_LOW
}
void yDir(int dir) {
digitalWrite(Y_DIR_PIN, dir);
}
void zStep() {
Z_STEP_HIGH
Z_STEP_LOW
}
void zDir(int dir) {
digitalWrite(Z_DIR_PIN, dir);
}
void aStep() {
A_STEP_HIGH
A_STEP_LOW
}
void aDir(int dir) {
digitalWrite(A_DIR_PIN, dir);
}
void bStep() {
B_STEP_HIGH
B_STEP_LOW
}
void bDir(int dir) {
digitalWrite(B_DIR_PIN, dir);
}
void cStep() {
C_STEP_HIGH
C_STEP_LOW
}
void cDir(int dir) {
digitalWrite(C_DIR_PIN, dir);
}
void resetStepperInfo( stepperInfo& si ) {
si.n = 0;
si.d = 0;
si.di = 0;
si.stepCount = 0;
si.rampUpStepCount = 0;
si.rampUpStepTime = 0;
si.totalSteps = 0;
si.stepPosition = 0;
si.movementDone = false;
}
#define NUM_STEPPERS 6
volatile stepperInfo steppers[NUM_STEPPERS];
void setup() {
pinMode(X_STEP_PIN, OUTPUT);
pinMode(X_DIR_PIN, OUTPUT);
pinMode(X_ENABLE_PIN, OUTPUT);
pinMode(Y_STEP_PIN, OUTPUT);
pinMode(Y_DIR_PIN, OUTPUT);
pinMode(Y_ENABLE_PIN, OUTPUT);
pinMode(Z_STEP_PIN, OUTPUT);
pinMode(Z_DIR_PIN, OUTPUT);
pinMode(Z_ENABLE_PIN, OUTPUT);
pinMode(A_STEP_PIN, OUTPUT);
pinMode(A_DIR_PIN, OUTPUT);
pinMode(A_ENABLE_PIN, OUTPUT);
pinMode(B_STEP_PIN, OUTPUT);
pinMode(B_DIR_PIN, OUTPUT);
pinMode(B_ENABLE_PIN, OUTPUT);
pinMode(C_STEP_PIN, OUTPUT);
pinMode(C_DIR_PIN, OUTPUT);
pinMode(C_ENABLE_PIN, OUTPUT);
digitalWrite(X_ENABLE_PIN, LOW);
digitalWrite(Y_ENABLE_PIN, LOW);
digitalWrite(Z_ENABLE_PIN, LOW);
digitalWrite(A_ENABLE_PIN, LOW);
digitalWrite(B_ENABLE_PIN, LOW);
digitalWrite(C_ENABLE_PIN, LOW);
noInterrupts();
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 1000; // compare value
TCCR1B |= (1 << WGM12); // CTC mode
TCCR1B |= ((1 << CS11) | (1 << CS10)); // 64 prescaler
interrupts();
steppers[0].dirFunc = bDir;
steppers[0].stepFunc = bStep;
steppers[0].acceleration = 1000;
steppers[0].minStepInterval = 50;
steppers[1].dirFunc = aDir;
steppers[1].stepFunc = aStep;
steppers[1].acceleration = 1000;
steppers[1].minStepInterval = 50;
steppers[2].dirFunc = cDir;
steppers[2].stepFunc = cStep;
steppers[2].acceleration = 1000;
steppers[2].minStepInterval = 50;
steppers[3].dirFunc = xDir;
steppers[3].stepFunc = xStep;
steppers[3].acceleration = 1000;
steppers[3].minStepInterval = 50;
steppers[4].dirFunc = yDir;
steppers[4].stepFunc = yStep;
steppers[4].acceleration = 1000;
steppers[4].minStepInterval = 50;
steppers[5].dirFunc = zDir;
steppers[5].stepFunc = zStep;
steppers[5].acceleration = 1000;
steppers[5].minStepInterval = 50;
}
void resetStepper(volatile stepperInfo& si) {
si.c0 = si.acceleration;
si.d = si.c0;
si.di = si.d;
si.stepCount = 0;
si.n = 0;
si.rampUpStepCount = 0;
si.movementDone = false;
si.speedScale = 1;
float a = si.minStepInterval / (float)si.c0;
a *= 0.676;
float m = ((a*a - 1) / (-2 * a));
float n = m * m;
si.estStepsToSpeed = n;
}
volatile byte remainingSteppersFlag = 0;
float getDurationOfAcceleration(volatile stepperInfo& s, unsigned int numSteps) {
float d = s.c0;
float totalDuration = 0;
for (unsigned int n = 1; n < numSteps; n++) {
d = d - (2 * d) / (4 * n + 1);
totalDuration += d;
}
return totalDuration;
}
void prepareMovement(int whichMotor, long steps) {
volatile stepperInfo& si = steppers[whichMotor];
si.dirFunc( steps < 0 ? HIGH : LOW );
si.dir = steps > 0 ? 1 : -1;
si.totalSteps = abs(steps);
resetStepper(si);
remainingSteppersFlag |= (1 << whichMotor);
unsigned long stepsAbs = abs(steps);
if ( (2 * si.estStepsToSpeed) < stepsAbs ) {
// there will be a period of time at full speed
unsigned long stepsAtFullSpeed = stepsAbs - 2 * si.estStepsToSpeed;
float accelDecelTime = getDurationOfAcceleration(si, si.estStepsToSpeed);
si.estTimeForMove = 2 * accelDecelTime + stepsAtFullSpeed * si.minStepInterval;
}
else {
// will not reach full speed before needing to slow down again
float accelDecelTime = getDurationOfAcceleration( si, stepsAbs / 2 );
si.estTimeForMove = 2 * accelDecelTime;
}
}
volatile byte nextStepperFlag = 0;
void setNextInterruptInterval() {
bool movementComplete = true;
unsigned long mind = 999999;
for (int i = 0; i < NUM_STEPPERS; i++) {
if ( ((1 << i) & remainingSteppersFlag) && steppers[i].di < mind ) {
mind = steppers[i].di;
}
}
nextStepperFlag = 0;
for (int i = 0; i < NUM_STEPPERS; i++) {
if ( ! steppers[i].movementDone )
movementComplete = false;
if ( ((1 << i) & remainingSteppersFlag) && steppers[i].di == mind )
nextStepperFlag |= (1 << i);
}
if ( remainingSteppersFlag == 0 ) {
TIMER1_INTERRUPTS_OFF
OCR1A = 65500;
}
OCR1A = mind;
}
ISR(TIMER1_COMPA_vect)
{
unsigned int tmpCtr = OCR1A;
OCR1A = 65500;
for (int i = 0; i < NUM_STEPPERS; i++) {
if ( ! ((1 << i) & remainingSteppersFlag) )
continue;
if ( ! (nextStepperFlag & (1 << i)) ) {
steppers[i].di -= tmpCtr;
continue;
}
volatile stepperInfo& s = steppers[i];
if ( s.stepCount < s.totalSteps ) {
s.stepFunc();
s.stepCount++;
s.stepPosition += s.dir;
if ( s.stepCount >= s.totalSteps ) {
s.movementDone = true;
remainingSteppersFlag &= ~(1 << i);
}
}
if ( s.rampUpStepCount == 0 ) {
s.n++;
s.d = s.d - (2 * s.d) / (4 * s.n + 1);
if ( s.d <= s.minStepInterval ) {
s.d = s.minStepInterval;
s.rampUpStepCount = s.stepCount;
}
if ( s.stepCount >= s.totalSteps / 2 ) {
s.rampUpStepCount = s.stepCount;
}
s.rampUpStepTime += s.d;
}
else if ( s.stepCount >= s.totalSteps - s.rampUpStepCount ) {
s.d = (s.d * (4 * s.n + 1)) / (4 * s.n + 1 - 2);
s.n--;
}
s.di = s.d * s.speedScale; // integer
}
setNextInterruptInterval();
TCNT1 = 0;
}
void runAndWait() {
adjustSpeedScales();
setNextInterruptInterval();
TIMER1_INTERRUPTS_ON
while ( remainingSteppersFlag );
remainingSteppersFlag = 0;
nextStepperFlag = 0;
}
void adjustSpeedScales() {
float maxTime = 0;
for (int i = 0; i < NUM_STEPPERS; i++) {
if ( ! ((1 << i) & remainingSteppersFlag) )
continue;
if ( steppers[i].estTimeForMove > maxTime )
maxTime = steppers[i].estTimeForMove;
}
if ( maxTime != 0 ) {
for (int i = 0; i < NUM_STEPPERS; i++) {
if ( ! ( (1 << i) & remainingSteppersFlag) )
continue;
steppers[i].speedScale = maxTime / steppers[i].estTimeForMove;
}
}
}
void loop() {
for (int i = 0; i < NUM_STEPPERS; i++) {
prepareMovement( i, 800 );
runAndWait();
}
prepareMovement( 0, 8000 );
prepareMovement( 1, 800 );
prepareMovement( 2, 2400 );
prepareMovement( 3, 800 );
prepareMovement( 4, 1600 );
prepareMovement( 5, 800 );
runAndWait();
delay(1000);
prepareMovement( 0, -8000 );
prepareMovement( 1, 1600 );
prepareMovement( 2, -2400 );
prepareMovement( 3, -800 );
prepareMovement( 4, 2400 );
prepareMovement( 5, -800 );
runAndWait();
while (true);
}
If you need acceleration, use AccelStepper or MobaTools.
I don't have your hardware or a clear understanding of the problem, but here's a simulation of a stepper bouncing between two simulated limit switches with acceleration: