I am using a potentiometer to control the speed and direction of a stepper motor. Stepper motor stops at Potentiometer middle point, CW when turn left and CCW when turn right.
The motor runs fine until I include the commented portion of code in the void loop area. The motor significantly slows down.
Code is given below. Your help will be appreciated.
#include <AccelStepper.h>
// Import the Liquid Crystal library
#include <LiquidCrystal.h>;
int potValue = 0;
//Initialise the LCD with the arduino. LiquidCrystal(rs, enable, d4, d5, d6, d7)
LiquidCrystal lcd(12, 11, 7, 6, 5, 4);
const byte stepPin = 3;
const byte dirPin = 2;
const byte enablePin = 8; // for CNC shield
//const byte potPin = A0;
AccelStepper stepper(AccelStepper::DRIVER, stepPin, dirPin);
void setup()
{
pinMode(A0, INPUT);
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
Serial.begin(9600);
lcd.begin(16,2);
lcd.print("Starting System");
delay(1000);
lcd.clear();
lcd.print("System On");
delay(1500);
lcd.clear();
Serial.begin(9600);
pinMode(enablePin, OUTPUT); // for CNC shield
digitalWrite(enablePin, LOW); // enable stepper(s)
stepper.setMaxSpeed(2000);
stepper.setAcceleration(100);
stepper.setSpeed(0);
}
void loop()
{
int potValue = analogRead(potValue);
if (potValue >= 487 && potValue <= 537) // ±25 hysteresis for center (0 speed)
{
stepper.setSpeed(0);
}
else if (potValue < 487)
{
stepper.setSpeed((487 - potValue) * 10); // your choice of multiplier
}
else if(potValue > 537)
{
stepper.setSpeed((537 - potValue) * 10); // your choice of multiplier
}
stepper.runSpeed();
//lcd.setCursor(0,0);
//lcd.print(" Stepper RPM ");
//
//
// potValue = analogRead(A0);
// Serial.println(potValue);
//
//lcd.setCursor(0,1);
//lcd.print(potValue);
//lcd.setCursor(4,1);
//lcd.print(" POT VALUE ");
//
//
// delay(50);
// lcd.clear();
}
welcome to the arduino-forum.
well done posting your code as a code-section in your first posting.
This is a general problem of the accelStepper-library.
The accelStepper-library has functions that require either that loop is running as fast as possible
or
only creating steps without beeing able to do other things in "parallel".
There is a very easy solution to this problem:
Using the MobaTools-library instead of the accelStepper-library.
The MobaTools create the step-pulses based on a timer-interrupt and this means your other code can be as slow as you want step-pulse-creation still works, because your other code is interrupted for a very short moment just at the correct time to create the step-pulse and then your other code goes on executing.
For a steppermotor receiving a step-pulse 1 millisecond too late is fatal. The stepper-motor will run chaotic or just vibrate without rotating.
If updating your display takes even 10 milliseconds longer this doesn't matter.
You can install the MobaTools with the library-manager of the Arduino-IDE.
The library includes a full documentation as a PDF-file.
The names of the functions are different so you have to lookup and learn the new function names after that using the MobaTools is a breeze.
Your code seem to rotate the steppermotor "infinitely" just changing speed and direction based on the potentiometer-position.
For this it will be sufficient to use the functions
myStepper.setRampLen(); // number of steps to accelerate deccelerate
myStepper.setSpeed();
myStepper.rotate(1); // for clockwise rotation
myStepper.rotate(-1); // for counterclockwise rotation
myStepper.stop();
I think you are not aware of that you have two different variables potValue;
You have one here
and a second here
This code works only by luck.
You should'nt name two different variables with the same name.
This gives extra-confusion.
for reading in an anlog inputpin
the name of the variable should have "Pin" it its name.
example
const byte potPin = A0;
then the variable-name itself explains what the purpose of the variable is.
When using the MobaTools setting up speed and direction looks like this
Not working code just showing the basic principle
const byte potPin = A0;
int potValue = analogRead(potPin);
int speed = 537 - potValue; // calculate speed and rotational direction + or -
if (speed < 0) {
direction = -1;
}
else {
direction = 1;
}
// abs(): get the pure number ALWAYS with positive sign
unsigned int speed10 = abs(speed) * 10;
myStepper.setSpeed(speed10);
myStepper.rotate(direction);
setSpeed always expects a positive number. Rotational direction is set by the sign inside the function rotate()
most things were already told. Have a look if this works better now:
#include <AccelStepper.h>
// Import the Liquid Crystal library
#include <LiquidCrystal.h>
int potValue = 0;
//Initialise the LCD with the arduino. LiquidCrystal(rs, enable, d4, d5, d6, d7)
LiquidCrystal lcd(12, 11, 7, 6, 5, 4);
const byte stepPin = 3;
const byte dirPin = 2;
const byte enablePin = 8; // for CNC shield
const byte potPin = A0; // use constants for your pin assignment
AccelStepper stepper(AccelStepper::DRIVER, stepPin, dirPin);
void setup()
{
pinMode(potPin, INPUT);
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
Serial.begin(9600);
lcd.begin(16, 2); // why again?!?
lcd.print("Starting System");
delay(1000);
lcd.clear();
lcd.print("System On");
delay(1500);
lcd.clear();
lcd.print(" Stepper RPM "); // only written once
//Serial.begin(9600); // why again?!?
pinMode(enablePin, OUTPUT); // for CNC shield
digitalWrite(enablePin, LOW); // enable stepper(s)
stepper.setMaxSpeed(2000);
stepper.setAcceleration(100);
stepper.setSpeed(0);
}
void loop()
{
potValue = analogRead(potPin); // you want to read the potPin not the potvalue !
if (potValue >= 487 && potValue <= 537) // ±25 hysteresis for center (0 speed)
{
stepper.setSpeed(0);
}
else if (potValue < 487)
{
stepper.setSpeed((487 - potValue) * 10); // your choice of multiplier
}
else if (potValue > 537)
{
stepper.setSpeed((537 - potValue) * 10); // your choice of multiplier
}
stepper.runSpeed();
static int previousPotValue = 0; // to store the old value - use the static keyword for this local variable
if (previousPotValue != potValue) {
previousPotValue = potValue;
//potValue = analogRead(A0); // why do you want to read a new value?
Serial.println(potValue);
lcd.setCursor(0, 1);
lcd.print(potValue);
lcd.print(" "); // overwrite existing characters of previous iteration
lcd.setCursor(4, 1);
lcd.print(" POT VALUE");
}
}
basically it will only update the LCD when the value has changed.
But all this will not generally solve the problem. If the stepper is to be stepping while the LCD is updated there will be a break in step generation. It will not generally slow down, but there will be a small jerk while the LCD is updated, because the step is delayed.
I think you will do better with a stepper library which drives the steps from a timer interrupt and the stepper should step during an lcd update. MobaTools does this, but you appear to be having issues using it. Perhaps you could try FastAccelStepper which is available through the Library Manager and will use the similar syntax as AccelStepper.
You can also try using the hd44780.h library for the lcd. It is significantly faster than the basic library.
I would also put the analog read of the potentiometer on a millis() timer (maybe every 100 ms) rather than every pass through loop. You can not adjust it that fast, and I think the readings can slow the loop.
Thanks @cattledog for your suggestions. I will give it a go. Is it possible to put your suggestions in a sketch if you have bandwidth. I am not too confident in the code
my conclusion is:
You want a complete and working demo-code for your
"potentiometer controls speed"-application.
Well - it is very unlikely that somebody will take the time and effort to write down a complete demo-code. Especcially if the user seems to be unwilling to learn.
This would end up in a behaviour of
OK thank you now I want this modification
OK thank you now I want this modification
OK thank you now I want this modification
...
"1000. OK thank you now I want this modification
As soon as you start posting in the style as described below answers are rushing in:
take any demo-code that you think might be a starting point
post this working demo-code as a code-section
do some small modifications to this demo-code towards your needs and post this modificated code as a code-section too
describe what the modifcated code-version is doing and how this behaviour is different from what you want to have as code-behaviour
ask specific questions to whatever detail you do not understand
Sounds like to much effort?
If you are looking for quick success, splitting wood really leads to quick success.