Driving a stepper motor with ISR. Issues explained in comment.

justconmac:
Also BLH, that does work, however I need to stay latched in that speed after button is pressed. Think I have an idea how to approach that. What is confusing to me is how the ISR relates to the main loop. I always thought ISR were for breaking out of something, resetting if you will.

ISR is independent of the main loop, i.e., it will happen when it is time to happen...unless interrupts are disabled.

justconmac:
Also BLH, that does work, however I need to stay latched in that speed after button is pressed. Think I have an idea how to approach that. What is confusing to me is how the ISR relates to the main loop. I always thought ISR were for breaking out of something, resetting if you will.

I thought the whole point was to change the RPM when you pressed a button? I do not understand what you mean by staying latched in that speed?

blh64:
I thought the whole point was to change the RPM when you pressed a button? I do not understand what you mean by staying latched in that speed?

I wonder if your program returns to a default position when a button is released?

...R

Robin2:
I wonder if your program returns to a default position when a button is released?

…R

I suppose it does. I guess I was thinking more of reading a POT than buttons with voltage dividers that go back to some default value when released. Easily fixed (assuming no button = large analogRead() value)

#include <LiquidCrystal.h>

/*
   Hardware specs

   stepper motors, 200 steps per revolution
   will always run at 1/8 step selection on controllers, gives 1600 steps per revolution,  hard wire these
   maximum input signal frequency is 500,000 Hz


   Desired functionality

   direction control (CW/CCW) for each bank of (3) steppers
   speed control for each bank of (3) steppers
   rotation count for each bank of (3) steppers
   Stop, go, pause, reset counters
   all of the above functionality but for (ALL) 12 motors on single box at the same time.
   minimum 0.1 rev/min (between 0 and 20 rpm.. above 20 rpm, increment 1 rpm)  maximum 90 rev/min

*/

// Variable definitions ***********************************************************


float desired_rpm_bank1 = 2.5; // 8 rpm is max speed

int rpm_bank1 = (int) desired_rpm_bank1;

const int mot_steps_per_rev = 200; // steps/revolution  (CHECK THIS ON MOTOR DATASHEET)
const int microstep_scaler = 8; // half step  (MUST MAKE MS1 INACTIVE (low/open) AND MS2 ACTIVE (high/5v))  (both active high in relaity, no step scaling.
const int steps_per_rev = mot_steps_per_rev * microstep_scaler;
const int sec_per_min = 60;
const int clk_pulses_per_step = 2;

float clock_freq = (desired_rpm_bank1*clk_pulses_per_step*steps_per_rev / sec_per_min) * 100; // Hz      max pwm frequency  = clock frequency/2
const int prescaler = 1;
unsigned int match_register = (16000000 / (prescaler*clock_freq)) - 1;

float clock_counter_bank1 = 0;
float step_counter_bank1 = 0;
int revolution_counter_bank1 = 0;
float clock_pulse_per_state_change_bank1 = 0;

float clock_pulse_per_rev_bank1 = 0;

int bank1_state = 0;

float currentRPM, prevRPM;
volatile bool report_flag = false;

// End Variable definitions ******************************************************

// Lcd setup
//LiquidCrystal lcd(8, 13, 9, 4, 5, 6, 7); // REMOVE ONE
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);  // REMOVE ONE

// Start Setup ********************************************************************
void setup()
{
  // calculate number of clock pulses to change state (do this in a function only once until pause or stop happens)
  clock_pulse_per_state_change_bank1 = (1 / ((desired_rpm_bank1 * steps_per_rev * clk_pulses_per_step) / (sec_per_min))) * clock_freq;

  // calculates how many clock pulses per one revolution (for counter)
  clock_pulse_per_rev_bank1 = (sec_per_min * clock_freq) / desired_rpm_bank1;


  // Internal timer interrupt******************************************************

  cli();//stop interrupts

  //set timer1 interrupt
  TCCR1A = 0;// set entire TCCR1A register to 0                         //I'M STARTING TO UNDERSTAND THESE TIMER INTERRUPTS
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;//initialize counter value to 0
  // set compare match register for 1hz increments
  OCR1A = match_register;// = (16*10^6) / (1*4800) - 1 (must be <65536)
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS10 and CS12 bits for 1 prescaler
  TCCR1B |= (0 << CS12) | (1 << CS10);
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);

  sei();//allow interrupts

  //End interrupt setup ***********************************************************

  pinMode(2, OUTPUT); // clock output 1       ORANGE
  pinMode(3, OUTPUT); // direction output 1   BLUE
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);
  pinMode(A0, INPUT);  // input from shield buttons (resistor ladder)
  pinMode(A1, OUTPUT);
  pinMode(A2, OUTPUT);
  pinMode(A3, OUTPUT);
  pinMode(A4, OUTPUT);
  pinMode(A5, OUTPUT);

  Serial.begin(250000); // begin sereal communication    (can we use this with shield?)


  // begin lcd and print
  lcd.begin(16, 2); // start the library
  //lcd.setCursor(3,0); // set cursor to line 0, column 3
  //lcd.print("message 1"); // print message, 1st char in line 0, col 4

  digitalWrite(3, HIGH); // direction 1 (high = CW) DO NOT RUN REVERSE
  digitalWrite(10, HIGH); // backlight on
}
// End setup **********************************************************************

// Start loop *********************************************************************
void loop()
{
  int reading = analogRead(A0);

  if ( reading < 50 ) {
    currentRPM = 2.5;
  }
  else if ( reading < 100 ) {
    currentRPM = 3.0;
  }
  else if ( reading < 150) {
    currentRPM = 4.5;
  }
  else if ( reading < 300) {
    currentRPM = 6.0;
  }
  else {
    // no button pressed, do nothing
  }

  if ( currentRPM != prevRPM ) {
    // update speed
    clock_freq = (currentRPM * clk_pulses_per_step * steps_per_rev / sec_per_min) * 100; // Hz      max pwm frequency  = clock frequency/2
    match_register = (16000000 / (prescaler * clock_freq)) - 1;
    OCR1A = match_register;// = (16*10^6) / (1*4800) - 1 (must be <65536)
    desired_rpm_bank1 = currentRPM;
  }
  prevRPM = currentRPM;

  if ( report_flag ) {
    Serial.println(revolution_counter_bank1);
    lcd.setCursor(0, 0); // set cursor to line 0, column 3
    lcd.print("Count: "); // print message, 1st char in line 0, col 4
    lcd.setCursor(10, 0); // set cursor to line 0, column 3
    lcd.print(revolution_counter_bank1);
    lcd.setCursor(0, 1); // set cursor to line 0, column 3
    lcd.print("RPM: ");
    lcd.setCursor(5, 1); // set cursor to line 0, column 3
    lcd.print( desired_rpm_bank1);
    lcd.setCursor(11, 1);
    lcd.print(clock_counter_bank1);
    report_flag = false;
  }


}
// End loop ***********************************************************************


//Start timer1 interrupt function 5000 Hz **********************************************
ISR(TIMER1_COMPA_vect)                            //MAIN PROGRAM. THIS IS WHERE I'D LIKE THE OPTION OF FOUR DIFFERENT IF STATEMENTS ALLOWING US TO ENTER 4 DIFFERENT RPM STATES
{
  clock_counter_bank1++;

  if (clock_counter_bank1 >= 100)                   //THIS WOULD BE ACHIEVED BY USING THIS MAIN CODE AND A DIFFERENT RPM FOR EACH ONE WITHIN THE 4 IF STATEMENTS
  {
    clock_counter_bank1 = 0;
    step_counter_bank1 = step_counter_bank1 + 18.6; //"2"= 10 RPM. "1" = 5 RPM. "0.5" = 2.5 RPM. "18.6" = 93 RPM.
    if (bank1_state == 0)
    {
      bank1_state = 1;
      digitalWrite(2, HIGH);
    }
    else
    {
      bank1_state = 0;
      digitalWrite(2, LOW);
    }

    if (step_counter_bank1 > steps_per_rev)
    {
      step_counter_bank1 = 0;
      revolution_counter_bank1++;
      report_flag = true;
    }

  }
  /*
    if(step_counter_bank1 <= steps_per_rev_bank1) // count up until one revolution has happened.
      {
        clock_counter_bank1++;
      }
      else // one revolution has occured
        {
          clock_counter_bank1 = 0;
          revolution_counter_bank1++;
          prev_clock_counter_bank1 = clock_counter_bank1;
          //Serial.print(revolution_counter_bank3);
          //Serial.print("  ");
          //Serial.println(millis());
        }

    if(clock_counter_bank1 >= prev_clock_counter_bank1+clock_pulse_per_state_change_bank1)  // if current clock counter is greater than prev clock counter plus clck pulse per stste change, then state change.
      {
        prev_clock_counter_bank1 = clock_counter_bank1;


      }

  */
}
//End timer1 interrupt function 5000 Hz ************************************************

Hello all,

I’ve previously posted about this issue and received help for which I am grateful to all those who helped and I hope I doted good karma to all.

Note: Using LCD shield with analog buttons as my input for different RPM’s I’d like to be able to enter when pushed.

Note: I added the “isrSet” value to try to accomplish what I’m asking.

I’ve inherited this code that’s driving a few stepper motors and my main problem (mostly from a lack of in depth understanding of the ISR) is that the program immediately begins without any input from my input’s. They are currently just separated by a few if statements. It seems like the ISR is immediately counting without me allowing it to (from my inputs). Now I know ISR is something that’s purpose is to stop the main code to execute and that it is suppose to execute when it hits that OCR1A value.

Program Goal: The goal is to have the program not do anything, no execution until I input the desired RPM of the analog0 buttons.

Any information is greatly appreciated.

Is it even possible to do what I’m asking while using the ISR?

gas_stepper_driver1.2.ino (7.62 KB)

== for comparison

//if (isrSet = true)
if (isrSet == true)

OP’s code

#include <LiquidCrystal.h>

/*
   Hardware specs

   stepper motors, 200 steps per revolution
   will always run at 1/8 step selection on controllers, gives 1600 steps per revolution,  hard wire these
   maximum input signal frequency is 500,000 Hz


   Desired functionality

   direction control (CW/CCW) for each bank of (3) steppers
   speed control for each bank of (3) steppers
   rotation count for each bank of (3) steppers
   Stop, go, pause, reset counters
   all of the above functionality but for (ALL) 12 motors on single box at the same time.
   minimum 0.1 rev/min (between 0 and 20 rpm.. above 20 rpm, increment 1 rpm)  maximum 90 rev/min

*/

// Variable definitions ***********************************************************


float desired_rpm_bank1;

int rpm_bank1 = (int) desired_rpm_bank1;

const int mot_steps_per_rev = 200; // steps/revolution  (CHECK THIS ON MOTOR DATASHEET)
const int microstep_scaler = 8; // half step  (MUST MAKE MS1 INACTIVE (low/open) AND MS2 ACTIVE (high/5v))  (both active high in relaity, no step scaling.
const int steps_per_rev = mot_steps_per_rev * microstep_scaler;
const int sec_per_min = 60;
const int clk_pulses_per_step = 2;

float clock_freq = (desired_rpm_bank1*clk_pulses_per_step*steps_per_rev / sec_per_min) * 100; // Hz      max pwm frequency  = clock frequency/2
const int prescaler = 1;
unsigned int match_register = (16000000 / (prescaler*clock_freq)) - 1;

float clock_counter_bank1 = 0;
float step_counter_bank1 = 0;
int revolution_counter_bank1 = 0;
float clock_pulse_per_state_change_bank1 = 0;

float clock_pulse_per_rev_bank1 = 0;

int bank1_state = 0;
int isrSet;

float currentRPM, prevRPM;
volatile bool report_flag = false;

// End Variable definitions ******************************************************

// Lcd setup
//LiquidCrystal lcd(8, 13, 9, 4, 5, 6, 7); // REMOVE ONE
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);  // REMOVE ONE

// Start Setup ********************************************************************
void setup()
{
  // calculate number of clock pulses to change state (do this in a function only once until pause or stop happens)
  clock_pulse_per_state_change_bank1 = (1 / ((desired_rpm_bank1 * steps_per_rev * clk_pulses_per_step) / (sec_per_min))) * clock_freq;

  // calculates how many clock pulses per one revolution (for counter)
  clock_pulse_per_rev_bank1 = (sec_per_min * clock_freq) / desired_rpm_bank1;


  // Internal timer interrupt******************************************************

  cli();//stop interrupts

  //set timer1 interrupt
  TCCR1A = 0;// set entire TCCR1A register to 0                         //I'M STARTING TO UNDERSTAND THESE TIMER INTERRUPTS
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;//initialize counter value to 0
  // set compare match register for 1hz increments
  OCR1A = match_register;// = (16*10^6) / (1*4800) - 1 (must be <65536)
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS10 and CS12 bits for 1 prescaler
  TCCR1B |= (0 << CS12) | (1 << CS10);
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);

  sei();//allow interrupts

  //End interrupt setup ***********************************************************

  pinMode(2, OUTPUT); // clock output 1       ORANGE
  pinMode(3, OUTPUT); // direction output 1   BLUE
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);
  pinMode(A0, INPUT);  // input from shield buttons (resistor ladder)
  pinMode(A1, OUTPUT);
  pinMode(A2, OUTPUT);
  pinMode(A3, OUTPUT);
  pinMode(A4, OUTPUT);
  pinMode(A5, OUTPUT);

  Serial.begin(250000); // begin sereal communication    (can we use this with shield?)


  // begin lcd and print
  lcd.begin(16, 2); // start the library
  //lcd.setCursor(3,0); // set cursor to line 0, column 3
  //lcd.print("message 1"); // print message, 1st char in line 0, col 4

  digitalWrite(3, HIGH); // direction 1 (high = CW) DO NOT RUN REVERSE
  digitalWrite(10, HIGH); // backlight on
}
// End setup **********************************************************************

// Start loop *********************************************************************
void loop()
{
  
  //Right
  if ( analogRead(0) < 50 ) {
    currentRPM = 2.5;
    isrSet = true;
  }
  //Up
  else if ( analogRead(0) < 250 ) {
    currentRPM = 3.0;
  }
  //Down
  else if ( analogRead(0) < 450) {
    currentRPM = 4.5;
  }
  //Select
  else if ( analogRead(0) < 850) {
    currentRPM = 50.0;                //was 93
  }
  else {
    // no button pressed, do nothing
  }

  if ( currentRPM != prevRPM && analogRead(0) < 850 ) {
    // update speed
    clock_freq = (currentRPM * clk_pulses_per_step * steps_per_rev / sec_per_min) * 100; // Hz      max pwm frequency  = clock frequency/2
    match_register = (16000000 / (prescaler * clock_freq)) - 1;
    OCR1A = match_register;// = (16*10^6) / (1*4800) - 1 (must be <65536)
    desired_rpm_bank1 = currentRPM;
  }
  prevRPM = currentRPM;

  if ( report_flag ) {
    lcd.setCursor(0, 0); // set cursor to line 0, column 3
    lcd.print("Count: "); // print message, 1st char in line 0, col 4
    lcd.setCursor(10, 0); // set cursor to line 0, column 3
    lcd.print(revolution_counter_bank1);
    lcd.setCursor(0, 1); // set cursor to line 0, column 3
    lcd.print("RPM: ");
    lcd.setCursor(5, 1); // set cursor to line 0, column 3
    lcd.print( desired_rpm_bank1);
    lcd.setCursor(11, 1);
    lcd.print(clock_counter_bank1);
    report_flag = false;
  }


}
// End loop ***********************************************************************


//Start timer1 interrupt function 5000 Hz **********************************************
ISR(TIMER1_COMPA_vect)                            //MAIN PROGRAM. THIS IS WHERE I'D LIKE THE OPTION OF FOUR DIFFERENT IF STATEMENTS ALLOWING US TO ENTER 4 DIFFERENT RPM STATES
{
  if (isrSet = true)
  {
  clock_counter_bank1++;

  if (clock_counter_bank1 >= 100)                   //THIS WOULD BE ACHIEVED BY USING THIS MAIN CODE AND A DIFFERENT RPM FOR EACH ONE WITHIN THE 4 IF STATEMENTS
  {
    clock_counter_bank1 = 0;
    step_counter_bank1 = step_counter_bank1 + 4; //"2"= 10 RPM. "1" = 5 RPM. "0.5" = 2.5 RPM. "18.6" = 93 RPM. //Appears to be part of reason why the program executes with no button selected
    if (bank1_state == 0)
    {
      bank1_state = 1;
      digitalWrite(2, HIGH);
    }
    else
    {
      bank1_state = 0;
      digitalWrite(2, LOW);
    }

    if (step_counter_bank1 > steps_per_rev)
    {
      step_counter_bank1 = 0;
      revolution_counter_bank1++;
      report_flag = true;
      isrSet = false;
    }
  }
  }
  /*
    if(step_counter_bank1 <= steps_per_rev_bank1) // count up until one revolution has happened.
      {
        clock_counter_bank1++;
      }
      else // one revolution has occured
        {
          clock_counter_bank1 = 0;
          revolution_counter_bank1++;
          prev_clock_counter_bank1 = clock_counter_bank1;
          //Serial.print(revolution_counter_bank3);
          //Serial.print("  ");
          //Serial.println(millis());
        }

    if(clock_counter_bank1 >= prev_clock_counter_bank1+clock_pulse_per_state_change_bank1)  // if current clock counter is greater than prev clock counter plus clck pulse per stste change, then state change.
      {
        prev_clock_counter_bank1 = clock_counter_bank1;


      }

  */
}
//End timer1 interrupt function 5000 Hz ************************************************

justconmac:
I've previously posted about this issue and received help

In the other Thread you were already told not to split things over several Threads and the Moderator had to merge your earlier Threads. Why are you now starting a new Thread about the same project?

Click Report to Moderator and ask to have this merged with your other Thread.

That way we will have all the project info in one place.

...R

  1. isrSet needs to be a volatile bool
  2. revolution_counter_bank1 needs to be volatile
  3. Why is clock_counter_bank1 a float if you are just using it as a counter?
  4. clock_counter_bank1 need to be delcared as volatile
  5. Any multi-byte variables shared between an ISR and main loop processing should only be accessed from the main loop with interrupts disabled.

Duplicate topics merged again

STOP CREATING NEW TOPICS FOR THE SAME THING

All I did was exactly what Robin2 asked me to do.

justconmac:
All I did was exactly what Robin2 asked me to do.

Remind me, please, what did I ask?

...R

You asked me to notify moderator to merge, apologies Robin2 I see now moderators issue was with me creating a second topic in the first place not the act of notifying.

justconmac:
You asked me to notify moderator to merge, apologies Robin2 I see now moderators issue was with me creating a second topic in the first place not the act of notifying.

That's why I was confused by your comment in Reply #29

...R

So I know it’s been awhile and the program (again I inherited it and am just trying to understand/tweek it) is working, however it does not seem to be adjusting to the speeds I want, specifically 93 RPM. I can’t get it to match that speed, any more thoughts???

Thanks for any help and I’ll reattach the program.

gas_stepper_driver1.2.ino (7.59 KB)

justconmac:
Thanks for any help and I'll reattach the program.

It makes it very much easier for people to help you if you include your program in your Post - as was done on your behalf in Reply #25

See How to get the best out of the Forum

Am I correct to assume there has not been a single change to the program since the version that appeared in Reply #25?

however it does not seem to be adjusting to the speeds I want, specifically 93 RPM. I can't get it to match that speed, any more

Specifically what have you done in order to get it to run at 93 RPM. And by the way it is easier to if speed is measured in RPS (1.55) because all of the code works in seconds or millsecs or microsecs.

...R

The program was slightly altered from the suggestion in #25, I’m now able to start PWM upon selecting a button.

So far I’m able to adjust speed only by skipping the steps. The “currentRPM” is part of a math function that is suppose to calculate OCR1A, which as it was explained to me is what the counter will count to thus giving is a duty cycle and the ability to change speed. This does not seem to be the case.

I almost might be better off starting from scratch at this point.

Here is the updated program in line.

#include <LiquidCrystal.h>

/*
   Hardware specs

   stepper motors, 200 steps per revolution
   will always run at 1/8 step selection on controllers, gives 1600 steps per revolution,  hard wire these
   maximum input signal frequency is 500,000 Hz


   Desired functionality

   direction control (CW/CCW) for each bank of (3) steppers
   speed control for each bank of (3) steppers
   rotation count for each bank of (3) steppers
   Stop, go, pause, reset counters
   all of the above functionality but for (ALL) 12 motors on single box at the same time.
   minimum 0.1 rev/min (between 0 and 20 rpm.. above 20 rpm, increment 1 rpm)  maximum 90 rev/min

*/

// Variable definitions ***********************************************************


float desired_rpm_bank1;

int rpm_bank1 = (int) desired_rpm_bank1;

const int mot_steps_per_rev = 200; // steps/revolution  (CHECK THIS ON MOTOR DATASHEET)
const int microstep_scaler = 8; // half step  (MUST MAKE MS1 INACTIVE (low/open) AND MS2 ACTIVE (high/5v))  (both active high in relaity, no step scaling.
const int steps_per_rev = mot_steps_per_rev * microstep_scaler;
const int sec_per_min = 60;
const int clk_pulses_per_step = 2;

float clock_freq = (desired_rpm_bank1*clk_pulses_per_step*steps_per_rev / sec_per_min) * 100; // Hz      max pwm frequency  = clock frequency/2
const int prescaler = 1;
unsigned int match_register = (16000000 / (prescaler*clock_freq)) - 1;

float clock_counter_bank1 = 0;
float step_counter_bank1 = 0;
int revolution_counter_bank1 = 0;
float clock_pulse_per_state_change_bank1 = 0;

float clock_pulse_per_rev_bank1 = 0;

int bank1_state = 0;
int isrSet;

float currentRPM, prevRPM;
volatile bool report_flag = false;

// End Variable definitions ******************************************************

// Lcd setup
//LiquidCrystal lcd(8, 13, 9, 4, 5, 6, 7); // REMOVE ONE
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);  // REMOVE ONE

// Start Setup ********************************************************************
void setup()
{
  // calculate number of clock pulses to change state (do this in a function only once until pause or stop happens)
  clock_pulse_per_state_change_bank1 = (1 / ((desired_rpm_bank1 * steps_per_rev * clk_pulses_per_step) / (sec_per_min))) * clock_freq;

  // calculates how many clock pulses per one revolution (for counter)
  clock_pulse_per_rev_bank1 = (sec_per_min * clock_freq) / desired_rpm_bank1;


  // Internal timer interrupt******************************************************

  cli();//stop interrupts

  //set timer1 interrupt
  TCCR1A = 0;// set entire TCCR1A register to 0                         //I'M STARTING TO UNDERSTAND THESE TIMER INTERRUPTS
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;//initialize counter value to 0
  // set compare match register for 1hz increments
  OCR1A = match_register;// = (16*10^6) / (1*4800) - 1 (must be <65536)
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS10 and CS12 bits for 1 prescaler
  TCCR1B |= (0 << CS12) | (1 << CS10);
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);

  sei();//allow interrupts

  //End interrupt setup ***********************************************************

  pinMode(2, OUTPUT); // clock output 1       ORANGE
  pinMode(3, OUTPUT); // direction output 1   BLUE
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);
  pinMode(A0, INPUT);  // input from shield buttons (resistor ladder)
  pinMode(A1, OUTPUT);
  pinMode(A2, OUTPUT);
  pinMode(A3, OUTPUT);
  pinMode(A4, OUTPUT);
  pinMode(A5, OUTPUT);

  Serial.begin(250000); // begin sereal communication    (can we use this with shield?)


  // begin lcd and print
  lcd.begin(16, 2); // start the library
  //lcd.setCursor(3,0); // set cursor to line 0, column 3
  //lcd.print("message 1"); // print message, 1st char in line 0, col 4

  digitalWrite(3, HIGH); // direction 1 (high = CW) DO NOT RUN REVERSE
  digitalWrite(10, HIGH); // backlight on
}
// End setup **********************************************************************

// Start loop *********************************************************************
void loop()
{
  
  //Right
  if ( analogRead(0) < 50 ) {
    currentRPM = 2.5;
    isrSet = true;
  }
  //Up
  else if ( analogRead(0) < 250 ) {
    currentRPM = 3.0;
    isrSet = true;
  }
  //Down
  else if ( analogRead(0) < 450) {
    currentRPM = 4.5;
    isrSet = true;
  }
  //Select
  else if ( analogRead(0) < 850) {                                //Idealy the "currentRPM" would be adjusting the OCR1A to change the pwm but it does not appear to do so
    currentRPM = 93;                
    isrSet = true;
  }
  else {
    // no button pressed, do nothing
  }

  if ( currentRPM != prevRPM && analogRead(0) < 850 ) {
    // update speed
    clock_freq = (currentRPM * clk_pulses_per_step * steps_per_rev / sec_per_min) * 100; // Hz      max pwm frequency  = clock frequency/2
    match_register = (16000000 / (prescaler * clock_freq)) - 1;
    OCR1A = match_register;// = (16*10^6) / (1*4800) - 1 (must be <65536)
    desired_rpm_bank1 = currentRPM;
  }
  prevRPM = currentRPM;

  if ( report_flag ) {
    lcd.setCursor(0, 0); // set cursor to line 0, column 3
    lcd.print("Count: "); // print message, 1st char in line 0, col 4
    lcd.setCursor(6, 0); // set cursor to line 0, column 3
    lcd.print(revolution_counter_bank1);
    lcd.setCursor(0, 1); // set cursor to line 0, column 3
    lcd.print("RPM: ");
    lcd.setCursor(5, 1); // set cursor to line 0, column 3
    lcd.print( desired_rpm_bank1);
    report_flag = false;
  }


}
// End loop ***********************************************************************


//Start timer1 interrupt function 5000 Hz **********************************************
ISR(TIMER1_COMPA_vect)                            //MAIN PROGRAM. THIS IS WHERE I'D LIKE THE OPTION OF FOUR DIFFERENT IF STATEMENTS ALLOWING US TO ENTER 4 DIFFERENT RPM STATES
{
  if (isrSet == true)
  {
  clock_counter_bank1++;

  if (clock_counter_bank1 >= 100)                   
  {
    clock_counter_bank1 = 0;
    step_counter_bank1 = step_counter_bank1 + 10; //Manipulating the "10" or skipping steps is the only way so far I can change speed
    if (bank1_state == 0)
    {
      bank1_state = 1;
      digitalWrite(2, HIGH);
    }
    else
    {
      bank1_state = 0;
      digitalWrite(2, LOW);
    }

    if (step_counter_bank1 > steps_per_rev)
    {
      step_counter_bank1 = 0;
      revolution_counter_bank1++;
      report_flag = true;
      
    }
  }
  }

So far I'm able to adjust speed only by skipping the steps.

What does that mean?

it does not seem to be adjusting to the speeds I want, specifically 93 RPM. I can't get it to match that speed, any more thoughts???

Is this still correct? Why the big difference between the low values and the 93 rpm. Previous code was 6.5 at the top end.

If you leave out all the adjustment code, but just try to run the stepper at 93RPM using the math values for OCR1A at that speed, do you see that speed? What do your prints tell you is the value for OCR1A when you try to set 93 rpm with the buttons?

You were better with the previous version which only did one analogRead() before the conditional testing of the values

int reading = analogRead(A0);

I should have asked this obvious question when I read Reply #33. “Why bother using interrupts to produce the steps for a slow speed such as 93 RPM”

…R

I agree, I'd like to stay away from interrupts entirely if that is possible. Would that just entail me using a PWM library and that's basically it? Still only one output for CW/CWW and one output for PWM?

justconmac:
I agree, I'd like to stay away from interrupts entirely if that is possible. Would that just entail me using a PWM library and that's basically it? Still only one output for CW/CWW and one output for PWM?

PWM is not required for or relevant to stepper motors. It is for DC motors and dimming LEDs.

Just use millis() or micros() to generate step pulses at the appropriate interval. Have a look at the second example in this Simple Stepper Code

...R