Hello,
I'm new here, and I have a little project where I need to turn my stepper (28ByJ-48) 90° CW after pressing a button, than it has to stops, then turn 90°CCW after pushing the same button again.
I use a ULN2003 5V and Arduino Uno R3.
I already find a program to turn the motor CW and CCW with two buttons, but not with one.
Can someone help me please? thanks a lot!
Have a variable that records the direction the stepper should move to. This may be as simple as a boolean.
Partial pseudo-code:
bool direction_CW = true;
void setup () {
[...]
}
void loop () {
if (button_pressed) {
if (direction_CW) {
[Move stepper clockwise]
direction_CW = false;
}
else {
[Move stepper counter-clockwise]
direction_CW = true;
}
}
}
thanks for you fast answer !
after the void loop() I have now this:
That is written for 3 buttons (CW/CCW and STOP)
Like I said, i'm not verry used with this code.
with part do I have to replace with you code?
void loop()
{
stepVale = (SPR * goToAngle)/360 ;
//Robojax.com Stepper Push button Any Angle STPB-4
if(digitalRead(switchCCW) == LOW)
{
dirStatus =CCW;
count =0;
}else if(digitalRead(switchCW) == LOW)
{
dirStatus = CW;
count =0;
}
if(digitalRead(switchSTOP) == LOW)
{
dirStatus = STOP;
delay(200);
}
if(dirStatus ==CCW){
poleStep++;
count++;
if(count+correction_CCW <= stepVale)
{
driveStepper(poleStep);
}else{
driveStepper(8);
}
//full explannation at Arduino Course on Udemy.com see link above
}else if(dirStatus ==CW){
poleStep--;
count++;
if(count+correction_CW <=stepVale)
{
driveStepper(poleStep);
}else{
driveStepper(8);
}
}else{
driveStepper(8);
}
if(poleStep>7){
poleStep=0;
}
if(poleStep<0){
poleStep=7;
}
delay(speedFactor);
//Robojax.com Stepper Push button Any Angle STPB-4
}// loop
/*
* @brief moves motor to specific angle
* @param "angle" is integer representing the angle
* @return does not return anything
*
* www.Robojax.com code Ap1il 19 2020 at 01:22 in Ajax, Ontario, Canada
*/
void driveStepper(int c)
{
//Robojax.com Stepper Push button Any Angle STPB-4
digitalWrite(Pin1, pole1[c]);
digitalWrite(Pin2, pole2[c]);
digitalWrite(Pin3, pole3[c]);
digitalWrite(Pin4, pole4[c]);
if(c ==8)
{
digitalWrite(switchCW, HIGH);
digitalWrite(switchCCW, HIGH);
}
}//driveStepper ends here
None; your code already has a variable that keeps track of the direction ("dirStatus").
You'd have to revise this bit here:
if(digitalRead(switchCCW) == LOW)
{
dirStatus =CCW;
count =0;
}else if(digitalRead(switchCW) == LOW)
{
dirStatus = CW;
count =0;
}
You could do something like this instead:
if(digitalRead(switchCW) == LOW)
{
if (dirStatus == CW) {
dirStatus = CCW;
}
else {
dirStatus = CW;
}
count =0;
}
Neither your version nor my modification above allows for switch debouncing. I'd suggest including some way of debouncing your switch.
I'd also recommend reading up on the concept of a "finite state machine".
without debouncing the direction may be random.
I have managed to get the motor to work as it should, but I still have a bug that causes the motor to start rotating automatically after about 30 sec. If I then press the stop button, the program works randomly again.
int Pin1 = 8;//IN1 is connected to 8
int Pin2 = 9;//IN2 is connected to 9
int Pin3 = 10;//IN3 is connected to 10
int Pin4 = 11;//IN4 is connected to 11
int switchSTOP =2;//define input pin for STOP push button
int switchCW =3;//define input pin for CW push button
int switchCCW =4;//define input pin for CCW push button
bool direction_CW=true;
int speedFactor =1;//1=fastest, 2=slower or 3 more slower
long goToAngle = 360;
int correction_CW = 150;//watch video for details
int correction_CCW = 150;//watch video for details
const int CW =1;
const int CCW =2;
const int STOP =3;
int poleStep = 0;
long stepVale =0;
const int SPR=64*64;
int pole1[] ={0,0,0,0, 0,1,1,1, 0};//pole1, 8 step values
int pole2[] ={0,0,0,1, 1,1,0,0, 0};//pole2, 8 step values
int pole3[] ={0,1,1,1, 0,0,0,0, 0};//pole3, 8 step values
int pole4[] ={1,1,0,0, 0,0,0,1, 0};//pole4, 8 step values
int count=0;
int dirStatus = STOP;// stores direction status 3= stop (do not change)
void setup()
{
//Robojax.com Stepper Push button Any Angle STPB-4
Serial.begin(9600);
Serial.begin("Robojax Video for Stepper Motor STPB-2");
pinMode(Pin1, OUTPUT);//define pin for ULN2003 in1
pinMode(Pin2, OUTPUT);//define pin for ULN2003 in2
pinMode(Pin3, OUTPUT);//define pin for ULN2003 in3
pinMode(Pin4, OUTPUT);//define pin for ULN2003 in4
pinMode(switchSTOP,INPUT_PULLUP);
pinMode(switchCW,INPUT_PULLUP);
pinMode(switchCCW,INPUT_PULLUP);
}
void loop()
{
stepVale = (SPR * goToAngle)/360 ;
//Robojax.com Stepper Push button Any Angle STPB-4
if(digitalRead(switchCW) == LOW)
{
if (dirStatus == CW) {
dirStatus = CCW;
direction_CW = false;
}
else {
dirStatus = CW;
direction_CW=true;
}
count =0;
delay(200);
}
if(digitalRead(switchSTOP) == LOW)
{
dirStatus = STOP;
delay(200);
}
if(dirStatus ==CCW){
poleStep++;
count++;
if(count+correction_CCW <= stepVale)
{
driveStepper(poleStep);
}else{
driveStepper(8);
}
//full explannation at Arduino Course on Udemy.com see link above
}else if(dirStatus ==CW){
poleStep--;
count++;
if(count+correction_CW <=stepVale)
{
driveStepper(poleStep);
}else{
driveStepper(8);
}
}else{
driveStepper(8);
}
if(poleStep>7){
poleStep=0;
}
if(poleStep<0){
poleStep=7;
}
delay(speedFactor);
//Robojax.com Stepper Push button Any Angle STPB-4
}// loop
/*
* @brief moves motor to specific angle
* @param "angle" is integer representing the angle
* @return does not return anything
*
* www.Robojax.com code Ap1il 19 2020 at 01:22 in Ajax, Ontario, Canada
*/
void driveStepper(int c)
{
//Robojax.com Stepper Push button Any Angle STPB-4
digitalWrite(Pin1, pole1[c]);
digitalWrite(Pin2, pole2[c]);
digitalWrite(Pin3, pole3[c]);
digitalWrite(Pin4, pole4[c]);
if(c ==8)
{
digitalWrite(switchCW, HIGH);
digitalWrite(switchCCW, HIGH);
}
}//driveStepper ends here
this code reliably detects a button press
// simple button processing
const byte butPin = A1;
byte ledPin = 13;
byte butState;
enum { Off = HIGH, On = LOW };
// -----------------------------------------------------------------------------
void loop (void)
{
byte but = digitalRead (butPin);
if (butState != but) { // check that button state changed
butState = but;
delay (10); // debounce
if (LOW == but) // button pressed
digitalWrite (ledPin, ! digitalRead (ledPin));
}
}
// -----------------------------------------------------------------------------
void setup (void)
{
digitalWrite (ledPin, Off);
pinMode (ledPin, OUTPUT);
pinMode (butPin, INPUT_PULLUP);
butState = digitalRead (butPin);
}
comment
- don't see where
direction_CW
is used - direction could be +/- 1 and used to in/decrement your polestep instead of have separate CW/CCW routines
- could limit poleStep to 0-7 using the modulo operator, for example
poleStep = (poleStep + direction) % 8;
- could use an array for the pins, similar to your poleN variables, instead of separately writting to each pin
Well I'm almost there, if it weren't for the fact that the engine starts turning on its own after 30 seconds being not used... the CW and CCW works with 1 button...
anyone who can find that bug please?
That's not apparent from the code. It may be useful to have a look at your hardware setup. Could you post a schematic diagram and a clear photograph of how you've connected everything together?
int Pin1 = 8;//IN1 is connected to 8
int Pin2 = 9;//IN2 is connected to 9
int Pin3 = 10;//IN3 is connected to 10
int Pin4 = 11;//IN4 is connected to 11
int switchCWCCW =3;//define input pin for CW push button
bool direction_CW=true;
int speedFactor =1;//1=fastest, 2=slower or 3 more slower
long goToAngle = 90;
int correction_CW = 150;//watch video for details
int correction_CCW = 150;//watch video for details
const int CW =1;
const int CCW =2;
const int STOP =3;
int poleStep = 0;
long stepVale =0;
const int SPR=64*64;
int pole1[] ={0,0,0,0, 0,1,1,1, 0};//pole1, 8 step values
int pole2[] ={0,0,0,1, 1,1,0,0, 0};//pole2, 8 step values
int pole3[] ={0,1,1,1, 0,0,0,0, 0};//pole3, 8 step values
int pole4[] ={1,1,0,0, 0,0,0,1, 0};//pole4, 8 step values
int count=0;
int dirStatus = STOP;// stores direction status 3= stop (do not change)
void setup()
{
//Robojax.com Stepper Push button Any Angle STPB-4
Serial.begin(9600);
Serial.begin("Robojax Video for Stepper Motor STPB-2");
pinMode(Pin1, OUTPUT);//define pin for ULN2003 in1
pinMode(Pin2, OUTPUT);//define pin for ULN2003 in2
pinMode(Pin3, OUTPUT);//define pin for ULN2003 in3
pinMode(Pin4, OUTPUT);//define pin for ULN2003 in4
pinMode(switchCWCCW,INPUT_PULLUP);
}
void loop()
{
stepVale = (SPR * goToAngle)/360 ;
//Robojax.com Stepper Push button Any Angle STPB-4
if(digitalRead(switchCWCCW) == LOW)
{
if (dirStatus == CW) {
dirStatus = CCW;
direction_CW = false;
}
else {
dirStatus = CW;
direction_CW=true;
}
count =0;
delay(200);
}
if(dirStatus ==CCW){
poleStep++;
count++;
if(count+correction_CCW <= stepVale)
{
driveStepper(poleStep);
}else{
driveStepper(8);
}
}else if(dirStatus ==CW){
poleStep--;
count++;
if(count+correction_CW <=stepVale)
{
driveStepper(poleStep);
}else{
driveStepper(8);
}
}else{
driveStepper(8);
}
if(poleStep>7){
poleStep=0;
}
if(poleStep<0){
poleStep=7;
}
delay(speedFactor);
}// loop
void driveStepper(int c)
{
digitalWrite(Pin1, pole1[c]);
digitalWrite(Pin2, pole2[c]);
digitalWrite(Pin3, pole3[c]);
digitalWrite(Pin4, pole4[c]);
if(c ==8)
{
digitalWrite(switchCWCCW, HIGH);
}
}//driveStepper ends here
Thanks gcjr in advance,
do you have this hardware? Normally I think you should have the same error with this program. I'm afraid it's not the hardware but a writing bug
Why are you writing to your switch pin?
Btw, this doesn't explain the odd behavior after 30 seconds. This may be something simple like a bad connection in your wiring somewhere. Those DuPont style connectors tend to dislodge kind of easily.
Also, please remember what both @gcjr and me said about debouncing. It's relevant. Please give the code @gcjr provided a try.
It's something i copied of robojax (youtube).
As i told, i'm just new in this..
I can't write it myself, just copy and paste..
the self-starting of the engine always starts after 30 seconds. It would be a coincidence that a wire always comes loose just on that moment?
I would like to try gcjr's code, but I don't know where to paste it/replace my part..
// -----------------------------------------------------------------------------
void loop (void)
{
byte but = digitalRead (butPin);
if (butState != but) { // check that button state changed
butState = but;
delay (10); // debounce
if (LOW == but) // button pressed
digitalWrite (ledPin, ! digitalRead (ledPin));
}
}
// -----------------------------------------------------------------------------
void setup (void)
{
digitalWrite (ledPin, Off);
pinMode (ledPin, OUTPUT);
pinMode (butPin, INPUT_PULLUP);
butState = digitalRead (butPin);
}
Then you'll have to learn. The copy-paste method will always get you stuck.
Start by going through the code you have and attempting to understand what each line does. Then start modifying specific bits to change the program's behavior and see if you can accurately predict the effects of each modification.
To start with, I'd use a simpler program; e.g. an example that just blinks an LED. Then move up in complexity as your understanding improves.
I understand this, learning it myself until I can write such programs is not easy. Been working on it for a few days now and cutting and pasting works. I find this interesting, but it is only for 1 project. Unfortunately, spending weeks learning how to do this is not an option and my efforts and purchases so far are wasted.
Still, thanks for your time so far
I understand. Well, Arduino is relatively user-friendly, but not quite as user-friendly as assembling an IKEA Billy cupboard. I hope you find the willpower to persevere, or otherwise the peace of mind to come to grips with your sunk investment. Good luck either way!
hihi, If a professional like you doesn't find the bug in the program, I guess it's not that easy after all . That's already a reason why I won't delve into it further. I can still spend weeks on it without getting any results.
look this over
simplifies stepping
uses single button to sequence: stop, forward, stop, reverse
makes it easier to read/debug code
const byte PinStepper [] = { 8, 9, 10, 11 };
const byte switchSTOP =2;//define input pin for STOP push button
const byte switchCW =3;//define input pin for CW push button
const byte switchCCW =4;//define input pin for CCW push button
int speedFactor = 1;//1=fastest, 2=slower or 3 more slower
byte butState;
const int Npole = sizeof(PinStepper);
const byte pole [][8] = {
{ 0,0,0,0, 0,1,1,1 },
{ 0,0,0,1, 1,1,0,0 },
{ 0,1,1,1, 0,0,0,0 },
{ 1,1,0,0, 0,0,0,1 },
};
int state; // stop, forward, stop, reverse
int dir; // 1/0/-1
unsigned pos; // stepper sequence
// -----------------------------------------------------------------------------
void step (
unsigned c)
{
Serial.println (c);
for (int n = 0; n < Npole; n++)
digitalWrite (PinStepper [n], pole [n][c]);
}
// -----------------------------------------------------------------------------
void loop ()
{
// handle button
byte but = digitalRead(switchCW);
if (butState != but) {
butState = but;
delay (20);
if (LOW == but) {
switch (state) {
case 0:
state++;
dir = 1;
break;
case 1:
state++;
dir = 0;
break;
case 2:
state++;
dir = -1;
break;
case 3:
state = 0;
dir = 0;
break;
}
char s [90];
sprintf (s, " state %d, dir %2d", state, dir);
Serial.println (s);
}
}
// step
pos = (pos + dir) % 8;
step (pos);
delay (speedFactor);
}
// -----------------------------------------------------------------------------
void setup ()
{
Serial.begin (9600);
for (int n = 0; n < Npole; n++)
pinMode (PinStepper [n], OUTPUT);
pinMode (switchSTOP, INPUT_PULLUP);
pinMode (switchCW, INPUT_PULLUP);
pinMode (switchCCW, INPUT_PULLUP);
butState = digitalRead (switchCW);
}
Thank you! I'm trying to convert this to adjustable angle rotation and without a stop in between.