Hello to Everybody and Best Wishes for the New Year.
I would like a bit (or a lot) of help please. I am trying to operate a stepper motor, via an Easydriver board, based on 2 analog inputs. These inputs are the 'Command' or 'Set Point' and the other is a 'Feedback' signal that changes in response to the stepper motor moving a sensor over a variable number of rotations, basically a closed loop system. The stepper actually rotates a threaded rod that moves a nut up and down then in turn rotates the sensor, this part I cannot change as it is already fitted.
The idea is that you adjust the command signal and the stepper will move until both signals are the same values (for this I have used percentage as an output value because the ranges of the 2 inputs are different and can be any values). For this I want the stepper to slow down when it is close to the command value before it stops and then when a new command signal is input it accelerates the stepper up to a given speed until it is close then slows then stops again. Both the command and feedback signals in the real world are actually 4-20mA but I will sort that out in the future once I get the stepper to operate as I plan.
I have written some code for a T3.6 that appears to operate, in as much as the stepper runs at a constant speed and changes direction based on whether the command signal is higher or lower that the feedback signal. My problem, and there may be many I suspect, is I cannot get the stepper to slow properly or speed up in both directions.
My coding, below, is far from perfect and I appear to have gotten lost in the numerous 'if' statements, is there another way?. This code will eventually become part of a larger program should I get this part to work properly.
I have tried AccelStepper and TeensyStep libraries but both seem to want to be given a number of steps for it to move to rather than based on a second input. There may be others out there that will do just what I want but I haven't found them yet, still looking.
Any guidance would be appreciated.
Chris
I would like a bit (or a lot) of help please. I am trying to operate a stepper motor, via an Easydriver board, based on 2 analog inputs. These inputs are the 'Command' or 'Set Point' and the other is a 'Feedback' signal that changes in response to the stepper motor moving a sensor over a variable number of rotations, basically a closed loop system. The stepper actually rotates a threaded rod that moves a nut up and down then in turn rotates the sensor, this part I cannot change as it is already fitted.
The idea is that you adjust the command signal and the stepper will move until both signals are the same values (for this I have used percentage as an output value because the ranges of the 2 inputs are different and can be any values). For this I want the stepper to slow down when it is close to the command value before it stops and then when a new command signal is input it accelerates the stepper up to a given speed until it is close then slows then stops again. Both the command and feedback signals in the real world are actually 4-20mA but I will sort that out in the future once I get the stepper to operate as I plan.
I have written some code for a T3.6 that appears to operate, in as much as the stepper runs at a constant speed and changes direction based on whether the command signal is higher or lower that the feedback signal. My problem, and there may be many I suspect, is I cannot get the stepper to slow properly or speed up in both directions.
My coding, below, is far from perfect and I appear to have gotten lost in the numerous 'if' statements, is there another way?. This code will eventually become part of a larger program should I get this part to work properly.
Code:
#include <ResponsiveAnalogRead.h>
// Stepper motor is connected to Easydriver board
byte directionPin = 34;
byte stepPin = 33;
// Initial Stepper Pulse and Duty cycle
int pulseWidthMicros = 40; // microseconds Pulse length
int microsbetweenSteps = 80; // microseconds Duty Cycle width
// Pins for ADC
const int Feedback = A9; // 10K Pot connected to 3.3V & AGND
const int Command = A8; // 10K Pot connected to 3.3V & AGND
// Real values to introduce differeing datums and ranges as would be in real life.
int MINA = 932;
int MAXA = 3203;
int COML = 400;
int COMH = 3845;
// Other variables
double Output, Output1;
float Ad = 0.0; // Command Signal Range MAXA-MINA
float Cd = 0.0; // Feedback Signal Range COMH-COML
// Initialise ADC to pins
ResponsiveAnalogRead value1(Command, true);
ResponsiveAnalogRead value2(Feedback, true);
void setup() {
analogReadResolution(12); // Set ADC resolutions to 12 bits
Serial.begin(115200);
delay(2000);
//Set-up Pins for Stepper Motor
pinMode(directionPin, OUTPUT);
pinMode(stepPin, OUTPUT);
// Set-up ADC pins for input
pinMode(Command, INPUT);
pinMode(Feedback, INPUT);
// Calculate Signal ranges
Ad = (MAXA - MINA) / 100; // example 3203-932= 2270/100=22.7 bits/%
Cd = (COMH - COML) / 100; // example 3845-400= 3445/100=34.45 bits/%
}
int value3;
int value4;
float value5 = 0.0;
float value6 = 0.0;
float lastvalue = 0.0;
void loop() {
value1.update(); // Take ADC Reading Command
value2.update(); // Take ADC Reading Feedback
value3 = value1.getValue(); // Retrieve actual value
value4 = value2.getValue(); // Retrieve actual value
value5 = value3 / Ad; // This is incorrect, calculates % of ADC ouput but
value6 = value4 / Cd; // doesn't take datum value into account.
// Check if Command is bigger than Feedback signal to set stepper direction
if (value5 > value6) {
digitalWriteFast(directionPin, HIGH);
}
else
{
digitalWriteFast(directionPin, LOW);
}
// Check if micro's between pulses is less than 1999 to operate stepper or stop
if (microsbetweenSteps < 1999) {
digitalWriteFast(stepPin, HIGH);
delayMicroseconds(pulseWidthMicros); // this line is probably unnecessary
digitalWriteFast(stepPin, LOW);
delayMicroseconds(microsbetweenSteps);
}
// Check if command signal is higher than the feedback signal
if (value5 > value6) {
Output1 = value5 - value6;
Output = 100 - Output1; // Output is inverted from Output1
// This is where I check if the Output is between 98 & 100% so I can slow/quicken the stepper down
if (Output > 98 && Output < 100) {
// Then decide which direction the signal is going and act
if (lastvalue < value6) {
microsbetweenSteps = microsbetweenSteps - 1; // Speed up
if (microsbetweenSteps < 100) {
microsbetweenSteps = 100; // prevent duty cycle being to short
}
}
else
{
microsbetweenSteps = microsbetweenSteps + 1; // Slow Down
if (microsbetweenSteps > 5000) {
microsbetweenSteps = 5000;
}
}
}
else
{
microsbetweenSteps = 100; // When outside 98% - 100% run Stepper quickish
}
}
// The section below is based on the above section
// Is Feedback > Command signal
if (value6 > value5) {
Output1 = value6 - value5;
Output = 100 - Output1;
if (Output > 98 && Output < 100) {
if (lastvalue < value6) {
microsbetweenSteps = microsbetweenSteps - 100;
if (microsbetweenSteps < 100) {
microsbetweenSteps = 100;
}
}
else
{
microsbetweenSteps = microsbetweenSteps + 100;
if (microsbetweenSteps > 5000) {
microsbetweenSteps = 5000;
}
}
}
else
{
microsbetweenSteps = 100;
}
}
// Print out values
Serial.print("Command = ");
Serial.print(value3);
Serial.print(" Feedback = ");
Serial.print(value4);
Serial.print(" Command2 = ");
Serial.print(value5);
Serial.print(" Feedback = ");
Serial.println(value6);
Serial.print(" Output = ");
Serial.print(Output);
Serial.print(" Output1 = ");
Serial.print(Output1);
Serial.print(" Micro's = ");
Serial.println(microsbetweenSteps);
Serial.println();
Serial.print("Last Value = ");
Serial.println(lastvalue);
lastvalue = value6; // take previous value for checking signal direction
delay(2);
}
I have tried AccelStepper and TeensyStep libraries but both seem to want to be given a number of steps for it to move to rather than based on a second input. There may be others out there that will do just what I want but I haven't found them yet, still looking.
Any guidance would be appreciated.
Chris