I am trying to pulse a stepper motor driver between HIGH and LOW signals every millisecond for 6 seconds, and am having trouble accomplishing this. I tried the blink without delay sketch and i got the stepper motor to move but too slow for what i need. I have also tried AnalogWrite() on the PWM pins, this gets the stepper motor to move but too slowly even at max hertz.
Hoping i can get some input here:
const int solenoid = 10; //Output to solenoid relay
const int Step = 9; //Stepper motor driver pulse signal
const int step_dir = 8; //Low=CW High=CCW direction output to step driver
const int button = 7; //start button and Cylinder switch
const int cylswitch = 6; //cylinder switch
const int stepdirection = 5; //input for direction of stepper motor
int cylstate;
int buttonstate; //state of button high/low input from start button
int dirstate; //state of stepper direction high/low input from directional switch
int stepstate; //state of stepper motor pulse
int solstate; //state of solenoid high/low
long previousmillis = 0;
long interval = 1;
void setup() {
pinMode(button, INPUT_PULLUP);
pinMode(stepdirection, INPUT_PULLUP);
pinMode(cylswitch, INPUT_PULLUP);
pinMode(solenoid,OUTPUT);
pinMode(step_dir,OUTPUT);
pinMode(Step,OUTPUT);
digitalWrite(step_dir,LOW);
digitalWrite(Step,LOW);
}
void loop() {
stepstate=digitalRead(stepdirection);
buttonstate=digitalRead(button);
cylstate=digitalRead(cylswitch);
if (stepstate==HIGH){
dirstate=HIGH;} //when switch is on direction is CCW
else{
dirstate=LOW;} //when switch is off direction is CW
if (buttonstate==HIGH){
solstate=HIGH;}//start button is pressed strobe is clamped activating cylswitch input
else{
solstate=LOW;} //start button is not pressed strobe is released
//Having trouble here
if((buttonstate==HIGH) && (cylstate==LOW)){
unsigned long currentmillis=millis();
if (currentmillis-previousmillis>interval){ //when air cylinder switch and start buttons are active turn on stepper motor for 6 seconds.
previousmillis=currentmillis;
if (stepstate == LOW) {
stepstate = HIGH;}
else {
stepstate = LOW;}
digitalWrite(Step,stepstate);}
}
digitalWrite(solenoid,solstate);
digitalWrite(step_dir,dirstate);
}
If you want to time things to millisecond accuracy, use microseconds. There's 1000 microseconds in a millisecond.
You don't need to be using balanced on- and off-times for the stepper. Most stepper drivers only require the pulse to be on for 1 microsecond. So switch it on, delayMicroseconds(1) and then turn it off right away.
i get it to work using that technique (see code), but how do i time it so it only runs for 6 seconds?
const int solenoid = 10; //Output to solenoid relay
const int Step = 9; //Stepper motor driver pulse signal
const int step_dir = 8; //Low=CW High=CCW direction output to step driver
const int button = 7; //start button and Cylinder switch
const int cylswitch = 6; //cylinder switch
const int stepdirection = 5; //input for direction of stepper motor
int cylstate;
int buttonstate; //state of button high/low input from start button
int dirstate; //state of stepper direction high/low input from directional switch
int stepstate; //state of stepper motor pulse
int solstate; //state of solenoid high/low
long previousmillis = 0;
long interval = 6000;
void setup() {
pinMode(button, INPUT_PULLUP);
pinMode(stepdirection, INPUT_PULLUP);
pinMode(cylswitch, INPUT_PULLUP);
pinMode(solenoid,OUTPUT);
pinMode(step_dir,OUTPUT);
pinMode(Step,OUTPUT);
digitalWrite(step_dir,LOW);
digitalWrite(Step,LOW);
}
void loop() {
stepstate=digitalRead(stepdirection);
buttonstate=digitalRead(button);
cylstate=digitalRead(cylswitch);
if (stepstate==HIGH){
dirstate=HIGH;} //when switch is on direction is CCW
else{
dirstate=LOW;} //when switch is off direction is CW
if (buttonstate==HIGH){
solstate=HIGH;}//start button is pressed strobe is clamped activating cylswitch input
else{
solstate=LOW;} //start button is not pressed strobe is released
if((buttonstate==HIGH) && (cylstate==LOW)){
digitalWrite(Step,HIGH);;
delayMicroseconds(1);
digitalWrite(Step,LOW);;
delayMicroseconds(1);}
digitalWrite(solenoid,solstate);
digitalWrite(step_dir,dirstate);
}
tried adjusting the code following those samples you provided and still nothing happens. Not sure the issue.
const int solenoid = 10; //Output to solenoid relay
const int Step = 9; //Stepper motor driver pulse signal
const int step_dir = 8; //Low=CW High=CCW direction output to step driver
const int button = 7; //start button and Cylinder switch
const int cylswitch = 6; //cylinder switch
const int stepdirection = 5; //input for direction of stepper motor
int cylstate;
int buttonstate; //state of button high/low input from start button
int dirstate; //state of stepper direction high/low input from directional switch
int stepstate; //state of stepper motor pulse
int solstate; //state of solenoid high/low
long previousmillis = 0;
long interval = 6000;
void setup() {
pinMode(button, INPUT_PULLUP);
pinMode(stepdirection, INPUT_PULLUP);
pinMode(cylswitch, INPUT_PULLUP);
pinMode(solenoid,OUTPUT);
pinMode(step_dir,OUTPUT);
pinMode(Step,OUTPUT);
digitalWrite(step_dir,LOW);
digitalWrite(Step,LOW);
}
void loop() {
stepstate=digitalRead(stepdirection);
buttonstate=digitalRead(button);
cylstate=digitalRead(cylswitch);
if (stepstate==HIGH){
dirstate=HIGH;} //when switch is on direction is CCW
else{
dirstate=LOW;} //when switch is off direction is CW
if (buttonstate==HIGH){
solstate=HIGH;}//start button is pressed strobe is clamped activating cylswitch input
else{
solstate=LOW;} //start button is not pressed strobe is released
if((buttonstate==HIGH) && (cylstate==LOW)){
unsigned long currentmillis=millis();
if (currentmillis-previousmillis>interval){ //when air cylinder switch and start buttons are active turn on stepper motor for 6 seconds.
previousmillis=currentmillis;
if (digitalRead(Step)==LOW){
digitalWrite(Step,HIGH);;
delayMicroseconds(1);
digitalWrite(Step,LOW);;
delayMicroseconds(1);}}}
digitalWrite(solenoid,solstate);
digitalWrite(step_dir,dirstate);
}
Your code is hard to read with multiple } on some lines. Run the auto-format tool in Arduino to fix that.
The second delayMicroseconds() is not necessary.
Your timing is still using milliseconds, so you can't step any faster than one step per millisecond.
Normally you want a stepper motor to run to a certain position. To do that, you count the number of steps and stop when the required distance has been completed. If it has to run for a period of time, then you need an additional "interval" to keep track of that. The way it's written now ,it will only take one step each 6 seconds.
It looks like you're using buttons or switches to set the direction and start/stop. Think about the states the system can be in - waiting for a start, running forwards, etc. What happens if the direction switch is switched during the 6 seconds? Does it run the remaining time in reverse or should it remember the direction it was originally commanded and keep moving in that direction? Does it start a new 6 seconds?
I'm very much a noob, but I had a similar challenge.
Perhaps someone can verify this but i might try reading the micros() at the point you want the 6 seconds to start then let 6 seconds elapse.
currentmicros = micros(); //record current time as currentmicors
delaytime = currentmicros + 6000 ;//add 6 seconds to the currentmicros and call it delaytime
when micros and delaytime are equal 6 seconds have passed.
Everyone has been helpful with my challenges, so I hope I have helped with yours.
Put the code that is to be executed repeatedly in a function.
Create a boolean variable initially set to false and call the action function only when the boolean is true
Set the boolean to true when the start conditions become true not when they are true
Save the start time for the 6 second period at that time
Each time through loop() if the boolean is true and the 6 second period has not elapsed call the action function
When the period has elapsed or some exit condition()s become true set the boolean to false to stop the action
ultratec:
I'm very much a noob, but I had a similar challenge.
Perhaps someone can verify this but i might try reading the micros() at the point you want the 6 seconds to start then let 6 seconds elapse.
currentmicros = micros(); //record current time as currentmicors
delaytime = currentmicros + 6000 ;//add 6 seconds to the currentmicros and call it delaytime
when micros and delaytime are equal 6 seconds have passed.
Everyone has been helpful with my challenges, so I hope I have helped with yours.
There are one million microseconds in a second, not one thousand.
ultratec:
currentmicros = micros(); //record current time as currentmicors
delaytime = currentmicros + 6000 ;//add 6 (milli)seconds to the currentmicros and call it delaytime
Nice thanks for the feedback. I got my code to work by setting a Boolean variable in a timer loop which is pretty effective. However, this only works the first time the start button is pressed. When the start button is pressed a second time nothing happens. If i reset the board twice it works again for the first button press. Is there any way to adjust the code so the last two if loops are activated every time the start button is pressed?
const int solenoid = 10; //Output to solenoid relay
const int Step = 9; //output Stepper motor driver pulse signal
const int step_dir = 8; //output Low=CW High=CCW direction output to step driver
const int button = 7; //input for start button
const int cylswitch = 6; //input cylinder switch
const int stepdirection = 5; //input for direction of stepper motor
int cylstate; //state of solenoid and cylinders it actuates
int buttonstate; //7 state of button high/low input from start button
int dirstate; //5 state of stepper direction high/low input from directional switch
int stepstate; //state of stepper motor pulse
int solstate; //6 state of solenoid high/low
unsigned long overallstarttime;
unsigned long previousmicros; //time tracking variable
unsigned long Timeinterval = 6000000; //overall time interval to run step motor
unsigned long stepinterval = 1; //time per step om motor
unsigned long currenttime;
boolean stepping = true; //statement to control overall time of step motor running
void setup() {
pinMode(button, INPUT_PULLUP);
pinMode(stepdirection, INPUT_PULLUP);
pinMode(cylswitch, INPUT_PULLUP);
pinMode(solenoid, OUTPUT);
pinMode(step_dir, OUTPUT);
pinMode(Step, OUTPUT);
digitalWrite(step_dir, LOW);
digitalWrite(Step, LOW);
overallstarttime = micros();
previousmicros = overallstarttime;
}
void loop() {
//Read states of inputs
dirstate = digitalRead(stepdirection);
buttonstate = digitalRead(button);
cylstate = digitalRead(cylswitch);
//start button is pressed strobe is clamped activating cylswitch input to LOW
if (buttonstate == HIGH) {
solstate = HIGH;
}//start button is not pressed strobe is released
else {
solstate = LOW;
}
//when air cylinder switch and start buttons are active turn on stepper motor with 1 microsencond step time
if ((buttonstate == HIGH) && (cylstate == LOW)) {
currenttime = micros();
if (currenttime - previousmicros > stepinterval && stepping) {
digitalWrite(Step, !digitalRead(Step));
previousmicros = previousmicros + stepinterval;
}
//track 6s time interval for stepper motor to run
if (currenttime - overallstarttime >= Timeinterval && stepping) {
stepping = false;
}
}
//write output states
digitalWrite(Step, stepstate);
digitalWrite(solenoid, solstate);
digitalWrite(step_dir, dirstate);
}
const byte outPin = 3;
unsigned long currentTime;
unsigned long longPeriodStart;
unsigned long shortPeriodStart;
unsigned long longPeriod = 6000000; //6 seconds in microseconds
unsigned long shortPeriod = 1000; //1 millisecond in microseconds
boolean pulsing = true;
void setup()
{
Serial.begin(115200);
pinMode(outPin, OUTPUT);
currentTime = micros();
longPeriodStart = currentTime;
shortPeriodStart = currentTime;
}
void loop()
{
currentTime = micros();
if (currentTime - longPeriodStart >= longPeriod)
{
Serial.println("toggle");
pulsing = !pulsing;
longPeriodStart = currentTime;
shortPeriodStart = currentTime;
}
if (pulsing)
{
output();
}
}
void output()
{
if (currentTime - shortPeriodStart >= shortPeriod)
{
digitalWrite(outPin, !digitalRead(outPin));
shortPeriodStart = currentTime;
}
}
As written the code toggles between producing pulses for 6 seconds and not producing pulses for 6 seconds. To start producing pulses set the pulsing boolean to true for the required period, perhaps as a result of user input.
const int solenoid = 10; //Output to solenoid relay
const int Step = 9; //output Stepper motor driver pulse signal
const int step_dir = 8; //output Low=CW High=CCW direction output to step driver
const int button = 7; //input for start button
const int cylswitch = 6; //input cylinder switch
const int stepdirection = 5; //input for direction of stepper motor
int cylstate; //state of solenoid and cylinders it actuates
int buttonstate; //7 state of button high/low input from start button
int dirstate; //5 state of stepper direction high/low input from directional switch
int stepstate; //state of stepper motor pulse
int solstate; //6 state of solenoid high/low
unsigned long overallstarttime;
unsigned long previousmicros; //time tracking variable
unsigned long Timeinterval = 6000000; //overall time interval to run step motor
unsigned long stepinterval = 1; //time per step om motor
unsigned long currenttime;
boolean stepping = true; //statement to control overall time of step motor running
void setup() {
pinMode(button, INPUT_PULLUP);
pinMode(stepdirection, INPUT_PULLUP);
pinMode(cylswitch, INPUT_PULLUP);
pinMode(solenoid, OUTPUT);
pinMode(step_dir, OUTPUT);
pinMode(Step, OUTPUT);
digitalWrite(step_dir, LOW);
digitalWrite(Step, LOW);
overallstarttime = micros();
previousmicros = overallstarttime;
}
void loop() {
//Read states of inputs
dirstate = digitalRead(stepdirection);
buttonstate = digitalRead(button);
cylstate = digitalRead(cylswitch);
//start button is pressed strobe is clamped activating cylswitch input to LOW
if (buttonstate == HIGH) {
solstate = HIGH;
}//start button is not pressed strobe is released
else {
solstate = LOW;
}
//when air cylinder switch and start buttons are active turn on stepper motor with 1 microsencond step time
if ((buttonstate == HIGH) && (cylstate == LOW)) {
currenttime = micros();
if (currenttime - previousmicros > stepinterval && stepping) {
digitalWrite(Step, !digitalRead(Step));
previousmicros = previousmicros + stepinterval;
}
//track 6s time interval for stepper motor to run
if (currenttime - overallstarttime >= Timeinterval && stepping) {
stepping = false;
}
}
//change state of stepping when start button is released after 6 second cycle completed
if (buttonstate == LOW && stepping == false) {
stepping = true;
}
//write output states
digitalWrite(Step, stepstate);
digitalWrite(solenoid, solstate);
digitalWrite(step_dir, dirstate);
}