Products > Programming
Arduino Stepper Encoder programming question
bkukuk62:
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;
}
}
ledtester:
(btw - you can use the code tag to format code blocks)
Is this perhaps a typo?
--- Code: --- const int InputPinStart = 8; // Input pin 8 to start auto rotation of rotor
...
val = digitalRead(InputPinStart);
if (InputPinStart == HIGH) {
--- End code ---
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
bkukuk62:
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;
}
}
ledtester:
PinStart is a constant - it will always be 8. HIGH is another constant - it will always be 1. Therefore this test:
--- Code: --- if (PinStart == HIGH) {
--- End code ---
will always fail.
Maybe you want:
--- Code: --- if (digitalRead(PinStart) == HIGH)
--- End code ---
bkukuk62:
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: ---// 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;
}
}
--- End code ---
Navigation
[0] Message Index
[#] Next page
Go to full version