Author Topic: Arduino Stepper Encoder programming question  (Read 143 times)

0 Members and 1 Guest are viewing this topic.

Offline bkukuk62

  • Contributor
  • Posts: 7
  • Country: us
Arduino Stepper Encoder programming question
« on: September 18, 2019, 07:15:53 pm »
The code below is supposed to rotate a stepper motor to match the encoder rotation but I have an if-else if-else if statement where the code uses both a library (Stepper.h) and literal pin settings for the encoder pinout and stepper pinout.
The first part of the if statement is supposed to look for a button push and rotate the stepper 5 full rotations otherwise do the first statement on this where the stepper motor matches the encoder.

This compiles but I am not sure if what I did is the best approach.

I would like any and all comments.
thanks,
bkukuk62

// Modified code for Arduino, Quadrature Optical Encoder, Stepper Motor 9-18-2019

 #include <Stepper.h>

  const int InputPinStart = 8;  //  Input pin 8 to start auto rotation of rotor

  const int stepsPerRevolution = 200;  // Number of steps per revolution for the Stepper Motor

 #define encoder_a 2    //encoder a = arduino pin 2
 #define encoder_b 3    //encoder b = arduino pin 3
 #define motor_step 4    //motor step = arduino pin 4
 #define motor_direction 5    //motor direction = arduino pin 5

Stepper myStepper(stepsPerRevolution, 2, 3, 4, 5);

int stepCount = 0; //  number of steps the motor has taken
int val = 0;  // variable for reading input pin 8

volatile long motor_position, encoder;

void setup ()
{
    //set up the various outputs
    pinMode(motor_step, OUTPUT);
    pinMode(motor_direction, OUTPUT);
    // then the encoder inputs
    pinMode(encoder_a, INPUT);
    pinMode(encoder_b, INPUT);
    digitalWrite(encoder_a, HIGH);
    digitalWrite(encoder_b, HIGH);
    // encoder pin on interrupt 0 (pin 2)
    attachInterrupt(0, encoderPinChangeA, CHANGE);
    // encoder pin on interrupt 1 (pin 3)
    attachInterrupt(1, encoderPinChangeB, CHANGE);
    encoder = 0;
    pinMode (InputPinStart, INPUT);  //  Declare pushbutton as input to start rotation
}

void encoderPinChangeA()
{
    if (digitalRead(encoder_a) == digitalRead(encoder_b))
    {
        encoder--;
    }
    else
    {
        encoder++;
    }
}

void encoderPinChangeB()
{
    if (digitalRead(encoder_a) != digitalRead(encoder_b))
    {
        encoder--;
    }
    else
    {
        encoder++;
    }
}


void loop()
{
//do stuff dependent on encoder position here
//such as move a stepper motor to match encoder position
//if you want to make it 1:1 ensure the encoder res matches the motor res by dividing/multiplying
  int sensorReading = analogRead(A0);  //  Read the sensor value from potentiometer on pin A0
  int motorSpeed = map(sensorReading, 0, 1023, 0, 100);  //  Map sensor range from 0 to 100
  if (motorSpeed > 0) {
    myStepper.setSpeed(motorSpeed);
    // step 1/100 of a revolution:
    myStepper.step(stepsPerRevolution / 100);     
  }

  val = digitalRead(InputPinStart);
  if (InputPinStart == HIGH) {
    myStepper.step(stepsPerRevolution*5);  //  Turn stepper motor 5 full rotations     
    }
   
    else if (encoder > 0) {
        digitalWrite(motor_direction, HIGH);
        digitalWrite(motor_step, HIGH);
        digitalWrite(motor_step, LOW);
        _delay_us(200);
        motor_position++;
        encoder = 0;
    }
    else if (encoder < 0) {
        digitalWrite(motor_direction, LOW);
        digitalWrite(motor_step, HIGH);
        digitalWrite(motor_step, LOW);
        _delay_us(200);
        motor_position--;
        encoder = 0;
    }
}
 

Offline ledtester

  • Frequent Contributor
  • **
  • Posts: 534
  • Country: us
Re: Arduino Stepper Encoder programming question
« Reply #1 on: September 18, 2019, 08:53:07 pm »
(btw - you can use the code tag to format code blocks)

Is this perhaps a typo?
Code: [Select]
  const int InputPinStart = 8;  //  Input pin 8 to start auto rotation of rotor
  ...
  val = digitalRead(InputPinStart);
  if (InputPinStart == HIGH) {

You are reading the encoder in a non-blocking fashion, so one improvement might be to make the other control code non-blocking as well. Here are some pointers:

- non-blocking ADC reading:

https://www.gammon.com.au/adc

- non-blocking stepper motor control:

https://reprage.com/post/non-blocking-control-of-stepper-motors-on-arduino
 
The following users thanked this post: ChunkyPastaSauce

Offline bkukuk62

  • Contributor
  • Posts: 7
  • Country: us
Re: Arduino Stepper Encoder programming question
« Reply #2 on: September 18, 2019, 10:00:20 pm »
ledtester,
I think I have corrected the issues, can you review it again.  I removed the library portions.  I want the code to stop everything while the stepper is rotating 10 full rotations and resume afterward.
ledtester, thanks for helping me out on this.
-bkukuk62

// Modified code for Arduino, Quadrature Optical Encoder, Stepper Motor 9-17-2019

 const int PinStart = 8;  //  Input pin 8 to start auto rotation of rotor

 #define encoder_a 2    //encoder a = arduino pin 2
 #define encoder_b 3    //encoder b = arduino pin 3
 #define motor_step 4    //motor step = arduino pin 4
 #define motor_direction 5    //motor direction = arduino pin 5

volatile long motor_position, encoder;

void setup ()
{
    //set up the various outputs
    pinMode(motor_step, OUTPUT);
    pinMode(motor_direction, OUTPUT);
    // then the encoder inputs
    pinMode(encoder_a, INPUT);
    pinMode(encoder_b, INPUT);
    digitalWrite(encoder_a, HIGH);
    digitalWrite(encoder_b, HIGH);
    // encoder pin on interrupt 0 (pin 2)
    attachInterrupt(0, encoderPinChangeA, CHANGE);
    // encoder pin on interrupt 1 (pin 3)
    attachInterrupt(1, encoderPinChangeB, CHANGE);
    encoder = 0;
    pinMode (PinStart, OUTPUT);  //  Declare pushbutton as input to start rotation
}

void encoderPinChangeA()
{
    if (digitalRead(encoder_a) == digitalRead(encoder_b))
    {
        encoder--;
    }
    else
    {
        encoder++;
    }
}

void encoderPinChangeB()
{
    if (digitalRead(encoder_a) != digitalRead(encoder_b))
    {
        encoder--;
    }
    else
    {
        encoder++;
    }
}

void loop()
{
//if you want to make it 1:1 ensure the encoder res matches the motor res by dividing/multiplying

    if (PinStart == HIGH) {
      digitalWrite(motor_direction, HIGH);
      digitalWrite(motor_step, HIGH);
      _delay_us(200);
      digitalWrite(motor_step, LOW);
      _delay_us(200);
      for (int i = 0; i < 100; i++) {
        step(1000);
      }
   
    else (encoder > 0) {
        digitalWrite(motor_direction, HIGH);
        digitalWrite(motor_step, HIGH);
        digitalWrite(motor_step, LOW);
        _delay_us(200);
        motor_position++;
        encoder = 0;
    }

    else (encoder < 0) {
        digitalWrite(motor_direction, LOW);
        digitalWrite(motor_step, HIGH);
        digitalWrite(motor_step, LOW);
        _delay_us(200);
        motor_position--;
        encoder = 0;
    }
}
 

Offline ledtester

  • Frequent Contributor
  • **
  • Posts: 534
  • Country: us
Re: Arduino Stepper Encoder programming question
« Reply #3 on: September 18, 2019, 10:08:27 pm »
PinStart is a constant - it will always be 8. HIGH is another constant - it will always be 1. Therefore this test:

Code: [Select]
    if (PinStart == HIGH) {

will always fail.

Maybe you want:

Code: [Select]
  if (digitalRead(PinStart) == HIGH)


 

Offline bkukuk62

  • Contributor
  • Posts: 7
  • Country: us
Re: Arduino Stepper Encoder programming question
« Reply #4 on: September 18, 2019, 10:45:24 pm »
ledtester,
thanks for the review and comments.  I reworked it again and got it to compile.
Do you see anything else that I tripped up on?
Code: [Select]
// Modified code for Arduino, Quadrature Optical Encoder, Stepper Motor 9-18-2019


 #define encoder_a 2    //  encoder a = arduino pin 2
 #define encoder_b 3    //  encoder b = arduino pin 3
 #define motor_step 4    //  motor step = arduino pin 4
 #define motor_direction 5    //  motor direction = arduino pin 5
 #define PinStart 8  //  button to start auto rotation of rotor = arduino pin 8

volatile long motor_position, encoder;

void setup () {
    //set up the various outputs
    pinMode(motor_step, OUTPUT);
    pinMode(motor_direction, OUTPUT);
    // then the encoder inputs
    pinMode(encoder_a, INPUT);
    pinMode(encoder_b, INPUT);
    digitalWrite(encoder_a, HIGH);
    digitalWrite(encoder_b, HIGH);
    // encoder pin on interrupt 0 (pin 2)
    attachInterrupt(0, encoderPinChangeA, CHANGE);
    // encoder pin on interrupt 1 (pin 3)
    attachInterrupt(1, encoderPinChangeB, CHANGE);
    encoder = 0;
    pinMode (PinStart, OUTPUT);  //  Declare pushbutton as input to start rotation
}

void step(long stepDelay) {
    digitalWrite(motor_step, HIGH);
    _delay_us(200);
    digitalWrite(motor_step, LOW);
    _delay_us(200);
}


void encoderPinChangeA()
{
    if (digitalRead(encoder_a) == digitalRead(encoder_b))
    {
        encoder--;
    }
    else
    {
        encoder++;
    }
}

void encoderPinChangeB()
{
    if (digitalRead(encoder_a) != digitalRead(encoder_b))
    {
        encoder--;
    }
    else
    {
        encoder++;
    }
}

void loop() {
//if you want to make it 1:1 ensure the encoder res matches the motor res by dividing/multiplying

    if (digitalRead(PinStart) == HIGH) {
      for (int i = 0; i < 100; i++) {
        step(1000);
      }
    }
   
    else if (encoder > 0) {
        digitalWrite(motor_direction, HIGH);
        digitalWrite(motor_step, HIGH);
        digitalWrite(motor_step, LOW);
        _delay_us(200);
        motor_position++;
        encoder = 0;
    }

    else if (encoder < 0) {
        digitalWrite(motor_direction, LOW);
        digitalWrite(motor_step, HIGH);
        digitalWrite(motor_step, LOW);
        _delay_us(200);
        motor_position--;
        encoder = 0;
    }
}
 

Offline ledtester

  • Frequent Contributor
  • **
  • Posts: 534
  • Country: us
Re: Arduino Stepper Encoder programming question
« Reply #5 on: September 18, 2019, 10:56:35 pm »
ledtester,
thanks for the review and comments.  I reworked it again and got it to compile.
Do you see anything else that I tripped up on?

Getting help from an internet forum is going to work a lot better if you test your code first.

Test each individual part of it to see if it works the way you expect it to. Then you can come back and explain what you want it to do and what it is actually doing.
 

Offline bkukuk62

  • Contributor
  • Posts: 7
  • Country: us
Re: Arduino Stepper Encoder programming question
« Reply #6 on: September 18, 2019, 11:03:48 pm »
thanks,
testing tonight.

-bkukuk62
 

Offline FreddieChopin

  • Regular Contributor
  • *
  • Banned!
  • Posts: 99
  • Country: ua
Re: Arduino Stepper Encoder programming question
« Reply #7 on: September 22, 2019, 07:14:43 am »
You could use CppUTest library to unit test your code before trying it on actual hardware, it might be faster this way  :-+
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf