Program works fine, but only with serial port enabled

Hello everyone,

I am new to programming and have a question. I wrote a program for some stepper motors, and it works just like it should, but only when serial port is enabled. If it disabled, the counter does not count like it should, and everything goes haywire. I would leave the serial port enabled, but it slows down all the motors involved.

Is there anyway to keep the motors rotating and the speed necessary and disable the serial port at the same time?

#include <AccelStepper.h>

AccelStepper spin1(AccelStepper::FULL4WIRE, 8,9,10,11);
AccelStepper spin2(AccelStepper::FULL4WIRE, 22,23,24,25);
AccelStepper swing(AccelStepper::FULL4WIRE, 4,5,6,7);





int x=1; 
int v;
int vold;
int dir;
int swingarmmove=50;
int analogReread=0;
int analog=0;
int t=0;
int remap=0;

void setup()
{  
   spin1.setMaxSpeed(900);
   spin1.setAcceleration(400.0);
   spin2.setMaxSpeed(900);
   spin2.setAcceleration(400.0); 
   swing.setMaxSpeed(1000);
   swing.setAcceleration(800);
   Serial.begin(9600);
}

void loop()
{ 
  
analogReread=analog;
analog=analogRead(A0);

Serial.println(analog);
if (analog<10)
{
analog=0;

}

 if (analog==0)
   { 
     if (analog<analogReread)
     {
       t++;
     }
   }


if (analog>11 && x==1)
{
  while(analog>11)
    {
      spin2.setSpeed(-1*analog*17);
      spin2.runSpeed();
      analog=0;	    
    } 

} 


if ( analog>11 && x==-1)
{
  while(analog>11)
    {
      spin1.setSpeed(-1*analog*17);
      spin1.runSpeed();
      analog=0;
    } 

} 
  
else if ( analog<11 && t>2 )
  
  {
    
    swing.runToNewPosition(swingarmmove);
    swingarmmove=-swingarmmove;
    t=0;   
    x=-x;
    
  }
  
}
int x=1; 
int v;

Nonsense names for global variables. Put aside your aversion to typing NOW!

  while(analog>11)
    {
      spin2.setSpeed(-1*analog*17);
      spin2.runSpeed();
      analog=0;	    
    }

More nonsense. There is NO excuse for bastardizing a while statement to make it into an if statement.

Hey, thanks for level headed constructive criticism and not deriding me for trying something for the first time

Are the non-descriptive intergers and loop bastardization what's causing it to work fine with Serial.begin?

@PaulS can sometimes sound a little rough - but he almost always has good advice. Take it.

I suspect if your program won't work if you comment out Serial.println(analog); it is because it is relying on the time that takes. As a temporary measure try adding a short delay(20); and see what happens. (And, yes, I know Serial.print() does not take 20 msecs)

It would be easier to manage the logic of your program if you group your IFs. For example

if (analog>11) {
    if (x ==1) {

    }
    else {

    }
}
else {
  // etc etc

}

...R

it is because it is relying on the time that takes.

Exactly. But, the question is "the time it takes to do what"?. The meaningless names do not make it clear what the program is doing, so it's nearly impossible to answer the original question.

You are asking for help, and you suspect that your counter isn't working. I'm not a mind reader. Would it not help, just a little, if the variable that you use to count, were called "counter", or something like that? :)

If you look up while(){} anywhere at all, it will tell you that it is for repetition. Having used something for a purpose that it was not intended, and finding that your program doesn't work, should not raise some kind of concern in your mind?

"Nonsense" may seem like a harsh word. What would you say if I asked you, "would you like an x"? Well, personally, I would say no. Tell me what it is first. :}

What would you say if I asked you, "would you like an x"?

Well, if you aren't happily married, the answer would be yes, an ex- would be a good idea.

Hey Robin, thanks for the reply

To be honest, I didnt even think of doing it like that, but I see how its more convenient and easier to read.

As for the delay, I tried setting it at all sorts of values from 20 to 1. At 20, the counter is inconsistent in picking up the motor stops to the point where it sometimes takes nearly 10 stops to rotate the swing stepper. At lower values it is inconsistent in the opposite direction, activating the swing stepper even at a single stop.

I thought it was the fact that the readings are innacurate around 0, so I dropped all values under 10 to 0 to avoid that, but it didnt seem to help. I was thinking of mapping analog input to a different set of values (internet suggests 0-255) but I don’t want that to affect the accuracy of the steppers following the DC motor that is the analog input.

Anyway, here is the cleaned up code. I could not think of a name for the x variable, which is used to switch motors, so I left it as such.

#include <AccelStepper.h>

AccelStepper spin1(AccelStepper::FULL4WIRE, 8,9,10,11);
AccelStepper spin2(AccelStepper::FULL4WIRE, 22,23,24,25);
AccelStepper swing(AccelStepper::FULL4WIRE, 4,5,6,7);





int x=1; 
int swingarmmove=50;
int analog=0;
int analogReread=0;
int t=0;
int remap=0;

void setup()
{  
   spin1.setMaxSpeed(900);
   spin1.setAcceleration(400.0);
   spin2.setMaxSpeed(900);
   spin2.setAcceleration(400.0); 
   swing.setMaxSpeed(1000);
   swing.setAcceleration(800);
   Serial.begin(9600);
}

void loop()
{ 
 delay(2); 
analogReread=analog;
analog=analogRead(A0);

if (analog<10)
{
analog=0;
}

if (analog==0 && analog<analogReread)
  {  
       t++;    
  }


if (analog>11)
{
  if (x==1)
  {
      spin2.setSpeed(-1*analog*17);
      spin2.runSpeed();
      analog=0;    
  } 


  else
  {
      spin1.setSpeed(-1*analog*17);
      spin1.runSpeed();
      analog=0;
  } 
}

if( analog<11 && t>2 )  
  {
    swing.runToNewPosition(swingarmmove);
    swingarmmove=-swingarmmove;
    t=0;   
    x=-x;    
  }
}

Anyway, here is the cleaned up code. I could not think of a name for the x variable, which is used to switch motors, so I left it as such.

So, motorToSwitch doesn’t make sense?

You can, and should, use long names. Ctrl-C, Ctrl-V really doesn’t car how long the name is, if typing a long name is challenging.

Casslex: I could not think of a name for the x variable, which is used to switch motors, so I left it as such.

motor?

#include <AccelStepper.h>

AccelStepper spin1(AccelStepper::FULL4WIRE, 8,9,10,11);
AccelStepper spin2(AccelStepper::FULL4WIRE, 22,23,24,25);
AccelStepper swing(AccelStepper::FULL4WIRE, 4,5,6,7);



int motorSwitcher=1;                   //motor switcher
int swingarmmove=50;
int analog=0;
int analogReread=0;
int counter=0;
int remap=0;

void setup()
{  
   spin1.setMaxSpeed(900);
   spin1.setAcceleration(400.0);
   spin2.setMaxSpeed(900);
   spin2.setAcceleration(400.0); 
   swing.setMaxSpeed(1000);
   swing.setAcceleration(800);
   //Serial.begin(9600);
}

void loop()
{ 
 delay(1);
analogReread=analog;
analog=analogRead(A0);

if (analog<10)
{
analog=0;
}

if (analog==0 && analog<analogReread)
  {  
       counter++;    
  }


if (analog>11)
{
  if (motorSwitcher==1)
  {
      spin2.setSpeed(-1*analog*17);
      spin2.runSpeed();	    
  } 

  else
  {
      spin1.setSpeed(-1*analog*17);
      spin1.runSpeed();
  } 
}

if( analog<11 && counter>2 )  
  {
    swing.runToNewPosition(swingarmmove);
    swingarmmove=-swingarmmove;
    counter=0;   
    motorSwitcher=-motorSwitcher;    
  }
  
}

Apparently the only time the counter works is when I have the monitor open and printing out analog input. The counter becomes somewhat inconsistent when I print out the counter, and completely useless when I gray out Serial.begin.

I tried throwing a capacitor in parallel with the DC motor to smooth out the signal, and I didn't really notice a difference. Another forum I stumbled unto said that the reason something works with a serial monitor open is because it somehow keeps the Arduino from resetting, and that a capacitor between the reset pin and the ground is the way to go, but in my case, it didn't seem to change anything either.

Two things that help us a lot are: adding comments to your code so we can try to follow your thought process and providing us with a schematic of your wiring.

An image of the actual wiring is also nice to see.

Another forum I stumbled unto said that the reason something works with a serial monitor open is because it somehow keeps the Arduino from resetting, and that a capacitor between the reset pin and the ground is the way to go, but in my case, it didn't seem to change anything either.

As has been said, the reason it "works" with the serial monitor open is that printing to the serial monitor takes time. When you stop printing to the serial monitor, then things speed up. Your method of counting, poor as it is, relies on that time being taken. You really must learn another way (like using millis() or micros()) of determining how much time has passed. Counting undefined amounts of time is NEVER going to work.

Your loop() seems very "busy". In other words, it repeats at a very high rate. It seems like you have some kind of feedback loop in mind, where actions are supposed to be influenced by that "analog" value. Feedback loops are a subject unto themselves, but one thing that can happen is instability. The commonplace analogy for this is over-reaction. Imagine a kind of Frankenstein. He can only react with big, slow, jerky motions. He leans forward, and starts to fall. Reacting, he bends back. It's too much, now he's falling backwards. So now he bends even farther forward. But it's too late.

So maybe you have a design problem, not a programming problem.

-Igor

PaulS:
You really must learn another way (like using millis() or micros()) of determining how much time has passed. Counting undefined amounts of time is NEVER going to work.

Does this mean, I should have the Arduino sample the signal for a while (25ms?) and then use the average to calculate the speed, instead of constantly sampling it?

aarg:
Imagine a kind of Frankenstein. He can only react with big, slow, jerky motions. He leans forward, and starts to fall. Reacting, he bends back. It’s too much, now he’s falling backwards. So now he bends even farther forward. But it’s too late.

-Igor

Thank you for dumbing it down for me a bit, excellent analogy. How would I go about making the loop less busy? Break it up into others?

I would leave the serial port enabled, but it slows down all the motors involved.

Do you have any actual basis for making this assertion ?

If you do what Paul suggests in the long run you'll get your answer and in the mean time you'll learn a better way to do something.

variable names matter a lot, especially once you start doing larger sketches....

michinyon: Do you have any actual basis for making this assertion ?

Only visual. The motors go from about 60 rpm to somewhere around 10-15 rpm.