encoder trouble need help with changing millisBetweenSteps

Hello i am semi new to Arduino ,
Ive hacked a few sketches together in the past to use and encoder to control menus,speed and such.
But i am having an issue getting and encoder to adjust the speed of a stepper while running.
Ive dragged a bit of code from several sources including here but my copy and paste skills have faltered

Ive got the buttons working can switch DIR and SLEEP
without much hassle the Sleep seams to have a bit of jitter or is picky about setting some times but not much of an issue
my troubles are with getting the millsBetweenSteps to adjust for speed control of the step pin
if i tinker with the encoder section i can get it to increment a number from zero +or- and print to screen
i can print the current " unsigned long millisBetweenSteps = 25;" but cant adjust the ms to control step timing
this stepper only needs to run from 1 to 100 rpm approx but need to be easily adjustable.
so any links to the necessary steps to convert the steps to rpm would be appreciated too.

/*
Last Edit 09:27 GMT 2019/09/05
Final Fixes Added buttons work SLEEP still Glitchy
LCD Prints (millisBetweenSteps)  Starts at 25 encoder control works 

*/
#include <Arduino.h>
#include <Wire.h>
#include <LiquidCrystal_PCF8574.h>
#include <RotaryEncoder.h>
#include <Bounce2.h>
#include <BasicStepperDriver.h>


//switches
const int CWSwitchPin = 6;
const int CCWSwitchPin = 7;
const int SleepSwitchPin = 2;


// Rotary Encoder Module connections
#define ROTARYSTEPS 1
#define ROTARYMIN 0
#define ROTARYMAX 100
RotaryEncoder encoder(A2, A3);


// set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_PCF8574 lcd(0x27);


//Stepper1
const int STEP = 8;
const int DIR = 9;
const int SLEEP = 12;
#define MOTOR_STEPS 200
#define MICROSTEPS 4   //set externaly mo1,mo2,mo3 all set to high from arduino source 32micro
BasicStepperDriver Stepper1(MOTOR_STEPS, DIR, STEP, SLEEP);

// Instantiate a Bounce object
Bounce CWSwitch = Bounce();
Bounce CCWSwitch = Bounce();
Bounce SleepSwitch = Bounce();

unsigned long curMillis;
unsigned long prevStepMillis = 0;
unsigned long millisBetweenSteps = 0;
int lastPos = -1;

void setup() {
  pinMode(CWSwitchPin, INPUT_PULLUP);
  CWSwitch.attach(CWSwitchPin);
  CWSwitch.interval(25);
  pinMode(CCWSwitchPin, INPUT_PULLUP);
  CCWSwitch.attach(CCWSwitchPin);
  CCWSwitch.interval(25);
  pinMode(SleepSwitchPin, INPUT_PULLUP);
  SleepSwitch.attach(SleepSwitchPin);
  SleepSwitch.interval(10);

  pinMode(STEP, OUTPUT);
  pinMode(DIR, OUTPUT);
  pinMode(SLEEP, OUTPUT);

  digitalWrite(SLEEP, LOW);
  digitalWrite(DIR, HIGH);

  lcd.begin(16, 2); // initialize the lcd
  lcd.setBacklight(1);
  lcd.print("Step Delay In ms");
  encoder.setPosition(25 / ROTARYSTEPS);
} // End setup()
void loop() {
  curMillis = millis();
  readEndStops();
  actOnEndStops();
  sleepOnOff();

  encoder.tick();
  int newPos = encoder.getPosition() * ROTARYSTEPS;

  if (newPos < ROTARYMIN) {
    encoder.setPosition(ROTARYMIN / ROTARYSTEPS);
    newPos = ROTARYMIN;
  }// if
  else if (newPos > ROTARYMAX) {
    encoder.setPosition(ROTARYMAX / ROTARYSTEPS);
    newPos = ROTARYMAX;
  } // else if
  if (lastPos != newPos) {
    lastPos = newPos;
  } // if
  if (millisBetweenSteps != newPos) {
    millisBetweenSteps = newPos;
    lcd.setCursor(0, 1);
    lcd.print("Delay ms ");
    lcd.print(millisBetweenSteps);
    lcd.print(" ");
  } // if
}
void readEndStops() {
  CWSwitch.update();
  int CWState = CWSwitch.read();
  CCWSwitch.update();
  int CCWState = CCWSwitch.read();

  if ((CWState == HIGH && (digitalRead(DIR) == HIGH)) && (CCWState == HIGH && (digitalRead(DIR) == LOW))) {
    singleStep();
  }
}
void actOnEndStops() {
  CWSwitch.update();
  int CWState = CWSwitch.read();
  CCWSwitch.update();
  int CCWState = CCWSwitch.read();

  if (CWState == LOW && (digitalRead(DIR) == HIGH)) {
    digitalWrite(DIR, LOW);
    singleStep();
  }
  if (CCWState == LOW && (digitalRead(DIR) == LOW )) {
    digitalWrite(DIR, HIGH);
    singleStep();
  }
}
void singleStep() {
  if (curMillis - prevStepMillis >= millisBetweenSteps) {
    prevStepMillis = curMillis;
    digitalWrite(STEP, HIGH);
    digitalWrite(STEP, LOW);
  }
}
void sleepOnOff() {
  SleepSwitch.update();
  int SleepState = SleepSwitch.read();

  if (SleepState == LOW) {
    if (digitalRead(SLEEP) == LOW) {
      digitalWrite(SLEEP, HIGH);
    }
    else if (digitalRead(SLEEP) == HIGH) {
      digitalWrite(SLEEP, LOW);
    }
  }
}

im reading this post : How to read an encoder and control a stepper motor without delay() - Programming Questions - Arduino Forum

i think im confused ,,, nope i am def a bit confused.

i think i need to assign some memory to hold the millisBetweenSteps and get the info from the encoder to compare it to?
then reassign the mem to the updated ??

im dyslexic takes a bit to read and understand but partial explanations make it more confusing.

I think you'd have better luck if you gave your variables better names so your code reads better

#include <Arduino.h>
#include <Wire.h>
#include <LiquidCrystal_PCF8574.h>
#include <RotaryEncoder.h>
#include <Bounce2.h>
#include <BasicStepperDriver.h>

/*
  //switches
  #define Switch1 6    //CwSw end stop switch
  #define Switch2 7    //CcwSw  end stop switch
  #define Switch3 2    // Sleep enable disable encoder switch
*/
const int CWSwitchPin = 6;
const int CCWSwitchPin = 7;
const int SleepPin = 2;

// Rotary Encoder Module connections
RotaryEncoder encoder(3, 4);

// set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_PCF8574 lcd(0x27);


//Stepper1
#define STEP 8
#define DIR  9
#define SLEEP 12
#define MOTOR_STEPS 200
#define MICROSTEPS 4   //set externaly mo1,mo2,mo3 all set to high from arduino source

BasicStepperDriver Stepper1(MOTOR_STEPS, DIR, STEP, SLEEP);
/*
  // Instantiate a Bounce object
  Bounce debouncer1 = Bounce();
  Bounce debouncer2 = Bounce();
  Bounce debouncer3 = Bounce();
*/
Bounce CWSwitch = Bounce();
Bounce CCWSwitch = Bounce();
Bounce SleepSwitch = Bounce();

unsigned long curMillis;
unsigned long prevStepMillis = 0;
unsigned long millisBetweenSteps = 25; // milliseconds between steps

void setup()                 ////////////////////////////////////////////////////////////////////////////////////
{
  pinMode(CWSwitchPin, INPUT_PULLUP);
  CWSwitch.attach(CWSwitchPin);
  CWSwitch.interval(25);
  pinMode(CCWSwtichPin, INPUT_PULLUP);
  CCWSwitch.attach(CCWSwitchPin);
  CCWSwitch.interval(25);
  pinMode(SleepSwitchPin, INPUT_PULLUP);
  SleepSwitch.attach(SleepSwitchPin);
  SleepSwitch.interval(25);

  pinMode(STEP, OUTPUT);
  pinMode(DIR, OUTPUT);
  pinMode(SLEEP, OUTPUT);

  digitalWrite(SLEEP, LOW);
  digitalWrite(DIR, HIGH);

  lcd.begin(16, 2); // initialize the lcd
  lcd.setBacklight(1);
  lcd.print("Stepper1 Speed ");
}


void loop()               /////////////////////////////////////////////////////////////////////////////////////////////
{
  curMillis = millis();
  encoderSpeedset();
  readEndStops();
  actOnEndStops();
  sleepOnOff();
}

void encoderSpeedset() {
  encoder.tick();

  unsigned long newmillisBetweenSteps;
  unsigned long oldmillisBetweenSteps;

  oldmillisBetweenSteps = millisBetweenSteps;
  newmillisBetweenSteps = encoder.getPosition();
  if (newmillisBetweenSteps != oldmillisBetweenSteps) {
    millisBetweenSteps = newmillisBetweenSteps;
    lcd.setCursor(0, 1);
    lcd.print("Speed ms ");
    lcd.print(millisBetweenSteps);
    lcd.print(" ");
  }
}

void readEndStops() {

  CWSwitch.update();
  int CWState = CWSwitch.read();
  CCWSwitch.update();
  int CCWState = CCWSwitch.read();

  if ((CWState == HIGH && (digitalRead(DIR) == HIGH)) && (CCWState == HIGH && (digitalRead(DIR) == LOW))) {
    singleStep();
  }
}

void actOnEndStops() {

  CWSwitch.update();
  int CWState = CWSwitch.read();
  CCWSwitch.update();
  int CCWState = CCWSwitch.read();

  if (CWState == LOW && (digitalRead(DIR) == HIGH)) {
    digitalWrite(DIR, LOW);
    singleStep();
  }
  if (CCWState == LOW && (digitalRead(DIR) == LOW )) {
    digitalWrite(DIR, HIGH);
    singleStep();
  }
}

void singleStep() {

  //  int millisBetweenSteps;
  if (curMillis - prevStepMillis >= millisBetweenSteps) {
    prevStepMillis = curMillis;
    digitalWrite(STEP, HIGH);
    digitalWrite(STEP, LOW);
  }
}                                  //End code for motor direction switching Cw and CCW from switches 1 and 2


void sleepOnOff() {                // Begin code for enable disable stepper motor state from encoder switch 3

  SleepSwitch.update();
  int SleepState = SleepSwitch.read();

  if (SleepState == LOW) {
    if (digitalRead(SLEEP) == LOW)) {
      digitalWrite(SLEEP, HIGH);
    }
    else {
      digitalWrite(SLEEP, LOW);
    }
  }
}

The basic issue was that you were never changing the 'millisBetweenSteps' variable (and you make it local, not global).

It is also confusing to have variables with 'millis' in the name when they are measuring encoder position and have nothing to do with time. If you truly want to measure speed, you will have to record the time of your encoder position reading and then do some basic math to calculate how far you have moved over the last time interval.

This does not make any sense

newmillisBetweenSteps = encoder.getPosition();

As well as making code easier to read the use of meaningful variable names makes the logic clearer for the programmer.

I presume that encoder.getPosition() returns a number that signifies the number of steps the encoder has made.

The name millisBetweenSteps sounds as if it has something to do with the speed of a stepper motor. I have used that variable name in my Simple Stepper Code

If you want to change the time-interval for the stepper motor using an encoder that you turn by hand then you need to calculate the change in the encoder position and use that to increase or decrease the value of millisbetweenSteps.

...R

yes robin 2 i jacked some of your code cause it sorta worked. :slight_smile:
it incremented .

im trying to control the speed of a stepper motor with the step pin that is controled by (millisBetweenSteps)
i can name it ramdom stuff
but new and old were easy to read. and im new to millis.

i cut and pasted from wrong sketch above i have two open most of the time make changes new changes work goes int working code.
ive been plugging stuff into the working code to see what bounces. or errors.
im not getting errors to often
Buttons do what they are supposed to do, tested with leds.
i have steppers but not the 8825s yet (slow boat) so i cant test if stepper works
im trying to get lcd to post the changes from encoder get a sense of whats happening.
it will post current millis :slight_smile: it will increment from 0 depending on what i stuff in.

im learning new stuff :slight_smile: im an old dog. and dyslexic

below is what compiles. with a few ideas //in to test later
i know the encoder read is all buggered up its all i could find.
and no where near what it was when i started, i misplaced the source i pulled from.
this morning ive been reading https://www.baldengineer.com/arduino-millis-examples.html
and his tuts on blink without delays
trying to get a hold on the concepts and implementing for encoders reads and changing what i need changed.

Bih64 Thankyou "I think you'd have better luck if you gave your variables better names so your code reads better"

i had to c/p your changes to ide to compare, im starting to get a start to understanding
most of the examples i pull from arnt very informative on spelling out changes for multiple instances and i just copy whats there add a digit and run with it.

when i grab code i have to space things out and add tags to under stand a bit .
i get code

#;kdfgjvkdj
#2xfvtgifbi
#iyujgbtrimyj[bm
#kfjhy[pyigb

and make it look
//////////////////////////////////////////
#define // sets pin

#define // //if things get to close they get confusing

#define
//////////////////////////////////////////////////////////////////
// letters and numbers dont get flipped or reversed just to much data in one byte

most human brains and eyes visually only process 6 to 8 characters at any given time while the eyes move over the text
Dyslexic can visually process 11 to unk value / pages at one time , but the brain is still stuck with 6 to 8.
that causes Error!!!!!!!!!!!!!!!!!!!!!!! i started understanding how to read in the 7th grade.

a wiring schematic or a blue print though is like candy in the hands of toddlers, just gobbled down

so thank you for the help.

OGP:
im trying to control the speed of a stepper motor with the step pin that is controled by (millisBetweenSteps)
i can name it ramdom stuff

"millisBetweenSteps" is a good name for the interval between stepper motor movements.

My comment was intended to convey that what you get from encoder.getPosition(); is not a number of milliseconds.

Are you saying that the program in Reply #4 is the one you are working on, and not the one in your Original Post? It could do with a bit of tidying up. For example you have a reference to BasicStepperDriver but you don't use it at all. I haven't checked for other stuff. Also, please use the AutoFormat tool. It makes code very much easier to read.

...R

I cleaned up the code in the posts,
auto format cool. didnt know that was there. i spread the lines out when im tinkering with stuff so i can read it.

i changed a few things like blh64 showed
al-tho a Swtich vs Switch got me confused was going bonkers till i plugged the code into a spellcheck

pinMode(CCWSwtichPin, INPUT_PULLUP);

i changed the encoder read to a copy of Rotory_with_limits but its not compiling as written in my code above

the code runs fine in demo but i get definition errors when i try to compile the code after plugging it into mine above

Robin2:
"millisBetweenSteps" is a good name for the interval between stepper motor movements.

My comment was intended to convey that what you get from encoder.getPosition(); is not a number of milliseconds.

i did get that,
the encoder read section was totally buggered i was frustrated and started plugging random ints in to keep from punching the screen.
then posted here

Will this work to change (millisBetweenSteps) and print to screen
i cant run it as the error baffles me and i cant get the compile completed.

but by itself it compiles and changes millisBetweenSteps on the screen at least

#include <Arduino.h>
#include <Wire.h>
#include <LiquidCrystal_PCF8574.h>
#include <RotaryEncoder.h>

#define ROTARYSTEPS 1
#define ROTARYMIN 0
#define ROTARYMAX 100
RotaryEncoder encoder(A2, A3);
unsigned long millisBetweenSteps = 0;
int lastPos = -1;

// set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_PCF8574 lcd(0x27);

void setup() {
  Serial.begin(57600);
  Serial.println("LimitedRotator example for the RotaryEncoder library.");
  lcd.begin(16, 2); // initialize the lcd
  lcd.setBacklight(1);
  lcd.print("Step Delay In ms");


  encoder.setPosition(25 / ROTARYSTEPS);                                           // start with the value of 25.

} // setup()

void loop() {

  encoder.tick();
  int newPos = encoder.getPosition() * ROTARYSTEPS;               // get the current physical position and calc the logical position

  if (newPos < ROTARYMIN) {
    encoder.setPosition(ROTARYMIN / ROTARYSTEPS);
    newPos = ROTARYMIN;

  } else if (newPos > ROTARYMAX) {
    encoder.setPosition(ROTARYMAX / ROTARYSTEPS);
    newPos = ROTARYMAX;
  } // else if


  if (lastPos != newPos) {
    lastPos = newPos;
  } // if

  if (millisBetweenSteps != newPos) {
    millisBetweenSteps = newPos;
    lcd.setCursor(0, 1);
    lcd.print("Delay ms ");
    lcd.print(millisBetweenSteps);
  } // if
} // loop ()

OGP:
Will this work to change (millisBetweenSteps) and print to screen
i cant run it as the error baffles me and i cant get the compile completed.

but by itself it compiles and changes millisBetweenSteps on the screen at least

I don't understand the parts that I have highlighted - one says it doesn't and the other says it does.

If you are getting a compiler error message please post it.

...R

The lower code by its self compiled, i grabbed it from stepper with limits in the library added print to lcd and millisBetweenSteps. It compiled and printed milisBetweenSteps to lcd and incremented as expected.

I incerted the code into my original code and got compile errors.
As stated earlier iv got to spread things out a bit to read the code better.

My compile error was. } // setup. Was missing
I started from the top work my way down.
Fixed it.
Now my SLEEP. Is not working.
Led at pin12. Blinks at reset. shows power
digitalWrite(SLEEP, LOW) gets set and it goes off.
But button no longer triggers state change?
Was some minor issues with not setting properly befor with what appeared to be bounce when pushing button. Ive tried jumper with wire from(5) direct to ground without changes as well.

When you need help you always need to post the complete program that is causing the problem. Otherwise it is impossible to make sense of comments. You are living with this all the time. I look in occasionally for 2 or 3 minutes.

...R

Ive been updating to first post code

ive been time and date stamping updates on top most post.

i fixed code in top post ,, it apears to be working but i dont have dvr8825 yet to test output.

i have shop away from house to test with oscope

going to test output of step pin to see output and determin if stepper functions.
wil post results.

OGP:
Ive been updating to first post code

Please please please don't do that.

It's important to be able to look back over the succession of changes. Also it makes a nonsense of any comments that were already written that related to the earlier version of the code.

It should be possible for someone to read the Thread from top to bottom and see it evolve.

Can you please reinstate the original code in the Original Post and post the new program in your next Reply?

...R

heres is where im at still not working.

But your code from Simple stepper is broken as well. i cant adjust the (millisBetweenSteps)

i write 200 in and i get a pulse of 5.8us with a leading edge to leading edge spacing of 22.00us
so ruffly 15us gap
i write 2000 to (millisBetweenSteps = 2000;
i get a 5.750 to 5.8us pulse with a leding edge to leading edge puls spacing of 22.00us or ruflly 15us between pulses

i write 20000 to (millisBetweenSteps = 20000;
i get a 5.750 to 5.8us pulse with a leding edge to leading edge puls spacing of 22.00us or ruflly 15us between pulses

so eiterr my uno only has one speed or the millisBetweensteps isnt getting used the way its writen

// testing a stepper motor with a Pololu A4988 driver board or equivalent

// this version uses millis() to manage timing rather than delay()
// and the movement is determined by a pair of momentary push switches
// press one and it turns CW, press the other and it turns CCW
//edit by OGP runs continuously until it hits endstops changes direction goes till endstop forever

byte directionPin = 5;
byte stepPin = 6;

byte buttonCWpin = 3;
byte buttonCCWpin = 4;

boolean buttonCWpressed = false;
boolean buttonCCWpressed = false;

//const int ledPin = 13;

unsigned long curMillis;
unsigned long prevStepMillis = 0;
int millisBetweenSteps = 2000; // milliseconds

void setup() {

  pinMode(directionPin, OUTPUT);
  pinMode(stepPin, OUTPUT);
  pinMode(buttonCWpin, INPUT_PULLUP);
  pinMode(buttonCCWpin, INPUT_PULLUP);

}

void loop() {
  curMillis = millis();
  readButtonAndStep();
  actOnButtons();
}

void readButtonAndStep() {

  buttonCCWpressed = false;
  buttonCWpressed = false;

  if (digitalRead(buttonCWpin) == LOW) {
    buttonCWpressed = true;
  }
  if (digitalRead(buttonCCWpin) == LOW) {
    buttonCCWpressed = true;
  }
}

void actOnButtons() {

  if ((buttonCWpressed == false) && (buttonCCWpressed == false)) {
    singleStep();
  }
  if (buttonCWpressed == true) {
    digitalWrite(directionPin, LOW);

  }
  if (buttonCCWpressed == true) {
    digitalWrite(directionPin, HIGH);

  }
}

void singleStep() {
  if (curMillis - prevStepMillis >= millisBetweenSteps);
  {
    digitalWrite(stepPin, HIGH);
    digitalWrite(stepPin, LOW);
    prevStepMillis = curMillis;
  }
}

in trying to understand why my code is not working as expected iv gone back to one of the sources,

Robin2 simple stepper program.
ive modded it to run continuously with endstop switches to change the direction of the stepper motor

now this works as it will trigger a pulse at the step pin, but it wont change the time between pulses as stated in
millisBetweenSteps;
ive changed it from 200, 2000 and 20000.
the pulse with was 5.8us on average with a duration between leading edges of 22.1us

any ideas on why it fails to change the step interval??

// testing a stepper motor with a Pololu A4988 driver board or equivalent

// this version uses millis() to manage timing rather than delay()
// and the movement is determined by a pair of momentary push switches
// press one and it turns CW, press the other and it turns CCW
//edit by OGP runs continuously until it hits endstops changes direction goes till endstop forever

byte directionPin = 5;
byte stepPin = 6;

byte buttonCWpin = 3;
byte buttonCCWpin = 4;

boolean buttonCWpressed = false;
boolean buttonCCWpressed = false;

//const int ledPin = 13;

unsigned long currentMillis;
unsigned long previousMillis;
unsigned long millisBetweenSteps = 2000; // milliseconds

void setup() {

  pinMode(directionPin, OUTPUT);
  pinMode(stepPin, OUTPUT);
  pinMode(buttonCWpin, INPUT_PULLUP);
  pinMode(buttonCCWpin, INPUT_PULLUP);

}

void loop() {
  readButtonAndStep();
  actOnButtons();
}

void readButtonAndStep() {

  buttonCCWpressed = false;
  buttonCWpressed = false;

  if (digitalRead(buttonCWpin) == LOW) {
    buttonCWpressed = true;
  }
  if (digitalRead(buttonCCWpin) == LOW) {
    buttonCCWpressed = true;
  }
}
void actOnButtons() {

  if (buttonCWpressed == true) {
    digitalWrite(directionPin, LOW);
  }
  if (buttonCCWpressed == true) {
    digitalWrite(directionPin, HIGH);
  }
  if ((buttonCWpressed == false) && (buttonCCWpressed == false)) { 
    singleStep();
  }
}
void singleStep() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > millisBetweenSteps);
  {
    digitalWrite(stepPin, HIGH);
    digitalWrite(stepPin, LOW);
    previousMillis = currentMillis;
  }
}
if (currentMillis - previousMillis > millisBetweenSteps);

Remove the semicolon ; from the end of this line.

You have fallen into trap #13

The full Tips and Traps document is well worth reading.

Would this also be better for setting the STEP pin to cycle on then off again

Int stepState = LOW;
}//
Void singleStep() {
Unsigned long curMillis = millis();
If (curMillis - prevStepMillis > millisBetweenSteps) {
If (stepState == LOW)
stepState = HIGH;
else
stepState = LOW;
digitalWrite(STEP, stepState);

OR THIS??

void singleStep() {
if (curMillis - prevStepMillis > millisBetweenSteps) {
if (digitalRead(STEP, LOW)
digitalWrite(STEP, HIGH);
else
digitalWrite(STEP, LOW);
prevStepMillis = curMillis;

}
}

I see no reason to change from your code which is essentially the same as Robin2's Simple Stepper Program example.

void singleStep() {
  if (curMillis - prevStepMillis >= millisBetweenSteps);
  {
    digitalWrite(stepPin, HIGH);
    digitalWrite(stepPin, LOW);
    prevStepMillis = curMillis;
  }
}