I have the below code that i have been working on that will count the steps of each motor and stop when they all return back to zero, based on a raito of their speed.
I can get this working quite fine when the millis between steps are set to like 200ms+ all motor stop when they all are at zero again, but when they are down towards 10,20& 30ms it never works and it appers that the millis between steps time are wrong, when i print the steps count of all motors they are the same except motor 3 it is 2 steps out, therefore making the motors contiunally run and never stop.
unsigned long curMillis1;
unsigned long prevStepMillis1 = 0;
unsigned long millisBetweenSteps1 = 20; // milliseconds
int stepperMotor1StepCount = 0;
int stepperMotor1Rotation = 0;
unsigned long curMillis2;
unsigned long prevStepMillis2 = 0;
unsigned long millisBetweenSteps2 = 10; // milliseconds
int stepperMotor2StepCount = 0;
int stepperMotor2Rotation = 0;
unsigned long curMillis3;
unsigned long prevStepMillis3 = 0;
unsigned long millisBetweenSteps3 = 40; // milliseconds
int stepperMotor3StepCount = 0;
int stepperMotor3Rotation = 0;
int startToDraw =0 ;
void setup() {
Serial.begin(9600);
}
void loop() {
curMillis1 = millis();
curMillis2 = millis();
curMillis3 = millis();
stopAllAtZero();
// stops motors Once all hit zero
if(startToDraw == 0){
StepperMotorControl();
}
}
void stopAllAtZero() {
// when all motors return back to step 0 at the same time print the below message
if (stepperMotor1StepCount == 0 && stepperMotor2StepCount == 0 && stepperMotor3StepCount == 0 && curMillis1 > 2000)
{
Serial.print("all Axis equal zero");
startToDraw = 1;
}
}
void StepperMotorControl() {
if (curMillis1 - prevStepMillis1 >= millisBetweenSteps1) {
prevStepMillis1 = curMillis1;
//Serial.print("steps1:");
//Serial.println(stepperMotor1StepCount);
Serial.println("stepperMotor1Rotation");
Serial.println(stepperMotor1Rotation);
stepperMotor1StepCount++;
}
if (stepperMotor1StepCount == 199) {
stepperMotor1StepCount = 0;
stepperMotor1Rotation++;
}
if (curMillis2 - prevStepMillis2 >= millisBetweenSteps2) {
prevStepMillis2 = curMillis2;
//Serial.print("steps2:");
//Serial.println(stepperMotor2StepCount);
Serial.println("stepperMotor2Rotation");
Serial.println(stepperMotor2Rotation);
stepperMotor2StepCount++;
}
if (stepperMotor2StepCount == 199) {
stepperMotor2StepCount = 0;
stepperMotor2Rotation++;
}
if (curMillis3 - prevStepMillis3 >= millisBetweenSteps3) {
prevStepMillis3 = curMillis3;
//Serial.print("steps3:");
//Serial.println(stepperMotor3StepCount);
Serial.println("stepperMotor3Rotation");
Serial.println(stepperMotor3Rotation);
stepperMotor3StepCount++;
}
if (stepperMotor3StepCount == 199) {
stepperMotor3StepCount = 0;
stepperMotor3Rotation++;
}
}
What am i missing here that's making the millis be incorrect?
If you are going to be printing out position information 100 times a second (every 10 milliseconds) you should definitely change your baud rate from 9600 (about 1000 character per second) to 115200 (about 11,000 characters per second). I think that might actually fix your problem.
TheMemberFormerlyKnownAsAWOL: Serial.begin(9600)The 1970s called; they want their bitrate back.
Nope! I'm still using that bit rate!
Bails:
if (stepperMotor3StepCount == 199) {
Try to get into the habit of using greater-than (or less-than) in these kinds of comparisons. Things like millis() can skip one and then your processor locks up for 49 days waiting for the exact number to come around again. You might change your code in the future to count in steps of 2 and then this comparison will never become true.
This is also an example of a "magic number". You might change one stepper to a different number of steps (maybe through micro-stepping, so there is no change in the hardware) so which ones of the "199" do you change? Can you be sure you got all of them?
Give every number like this a name. Like stepper1StepsPerRev or something that makes sense to you. Then use that name everywhere.
You have not actually explained the purpose of this code. Whenever you have three variables, it suggests that you have two too many. Your initialization failure has already been pointed out; there is no guarantee that all three variables will have different values. On the other hand, a 1ms error is irrelevant. I think you should create one class for each motor, that does whatever it does for that motor, e.g.,
class MyMotor : public WhateverYourStepperMotorClassIs {
protected:
long StepTime;
long Count;
long Interval;
bool clockwise = true;
public:
bool takeAStep()
{
if(Count <= 0)
return false;
if(millis() < StepTime + Interval)
return false;
oneStep();
StepTime = mlllis() + Interval;
Count--;
return true;
} // takeAStep
void setNext(long c)
{
StepTime = millis();
if(c < 0)
{
clockwise = false;
Count = -c;
}
else
{
clockwise = true;
Count = c;
}
} // setNext
MyMotor(long dt)
{
StepTime = millis();
Count = 0;
Interval = dt;
}
protected:
void oneStep()
{
//...call your motor superclass using "clockwise" to determine what the
//...direction parameter is.
}
}; // class Motor
MyMotor motor1(20); // motor1 needs 20ms interstep time
MyMotor motor2(30); // motor2 needs 30ms interstep time
MyMotor motor3(20); // motor3 needs 20ms interstep time
void loop()
{
bool any = false;
any |= motor1.takeAStep();
any |= motor2.takeAStep();
any |= motor3.takeAStep();
if(!any)
{
// ... do things that compute future steps, if any are needed
// ...for example, the result might be
// motor1.setNext(-5); // 5 steps CCW
// motor2.setNext(14); // 14 steps CW
// ...note that motor3 dpes not get a value in this example computation,
// and will not move
}
} // loop
I wrote this off the top of my head, but if it is not the precise truth, it is closer than the overly-complex code you wrote. Never think of using multiple global variables when class instances can solve the problem trivially. In fact, try to ignore the concept of global variables, except in a few rare cases, such as for class variables that represent the objects you are controlling. In this example, the only three global variables are for the three motors. There are no other global variables to maintain state.
I need to learn a bit more about classes to fully understand these and to utilise in my code.
Besides my formatting issues, would the Baud rate and the amount of information i want to print actually effect the rest of the code with regards to the millis between steps?
Bails:
Besides my formatting issues, would the Baud rate and the amount of information i want to print actually effect the rest of the code with regards to the millis between steps?