EEVblog Electronics Community Forum
Products => Computers => Programming => Topic started by: bkukuk62 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;
}
}
-
(btw - you can use the code tag to format code blocks)
Is this perhaps a typo?
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 (https://www.gammon.com.au/adc)
- non-blocking stepper motor control:
https://reprage.com/post/non-blocking-control-of-stepper-motors-on-arduino (https://reprage.com/post/non-blocking-control-of-stepper-motors-on-arduino)
-
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;
}
}
-
PinStart is a constant - it will always be 8. HIGH is another constant - it will always be 1. Therefore this test:
if (PinStart == HIGH) {
will always fail.
Maybe you want:
if (digitalRead(PinStart) == HIGH)
-
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?
// 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;
}
}
-
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.
-
thanks,
testing tonight.
-bkukuk62
-
You could use CppUTest library to unit test your code before trying it on actual hardware, it might be faster this way :-+