Do..while loop control problem

Hi,

I'm new to Arduino so pardon the daft questions...

I'm having problems with do..while loops in a control program, part shown below:

//timing loop
void loop() {
do
{
// RA slew w
acc = acc + accrate;
digitalWrite(radir, HIGH);
digitalWrite(rastep, HIGH);
delayMicroseconds(pulselength);
digitalWrite(rastep, LOW);
delayMicroseconds(ra / acc);
}while (digitalRead(wpin)==HIGH);

} //end loop

I'm trying to send a timing pulse to 'rastep' pin that will increase in frequency (to accelerate a stepper driver) when 'wpin' is high.

I have used the serial monitor and even when 'wpin' is definately pulled low (monitor reports '0') the loop still operates and 'acc' gets bigger in 'accrate' increments.

I've done a lot of VBA programming but this is my first time in c.

Anyone know why this is happening - I'm very stuck?

Thanks,

Theo

I have used the serial monitor and even when 'wpin' is definately pulled low (monitor reports '0') the loop still operates and 'acc' gets bigger in 'accrate' increments.

This is where code snippets don't cut it. If you are not using the internal pullup resistor (or external resistor in pullup configuration), you have a floating pin condition. We can't see whether you are using the internal one, and you haven't described your hardware configuration.

We also can't see how acc, accrate, pulseLength, etc. are defined.

     digitalWrite(radir, HIGH);

Why is this in the loop? Do it once, not every iteration of the loop.

Hi,

I have external 100k pulldown resistors between pins 4,5,6,7 and a switches from to 5v pin to pull them HIGH. when pulled low and showing '0' on serial monitor, the do.. while loops still seem to act.

the 'direction' control pins for the driver are not ideal to reset every loop but each one acts in differnt directions so needs to specify it each time a different button is pressed.

The program is for a telescope controller, which slews at accelerating speed when a slew button is pressed (epin, wpin etc.), otherwise it should decelerate to normal speed again when nothing is pressed and continue to move in west direction only. I know there are some other problems still to sort out but at the moment I'm just confused why the do..while loops are acting when they shouldn't.

Here's the whole thing then, hope its clearer (the serial prints are just in for debugging):

Thanks very much for any help.

//scope

long ra = 46895; // normal motor tracking rate
float acc = 1;
float dacc = 1;
int pulselength = 5;
float accrate = 0.1;

int npin = 4;
int spin = 5;
int epin = 6;
int wpin = 7;
//int gnpin = 4;
//int gspin = 5;
//int gepin = 6;
//int gwpin = 7;
int rastep = 8;
int radir = 9;
int decstep = 10;
int decdir = 11;
int raenable = 12;
int decenable = 13;

//tracking rate = 21.317hz = 0.0469 sec
// with 5us pulse 1x RA = 46895us
//int rate = 1023; //set max slew rate to 1x = 5v INPUT, 0-1 ohms
//motor will accelerate upto max slew rate if <1000. if >1000 will use 2x rate for move and guide


void setup() {
 Serial.begin(9600);

//N
//pinMode(0,INPUT);
//S
//pinMode(1,INPUT);
//E
//pinMode(2,INPUT);
//W
//pinMode(3,INPUT);

// guide N
pinMode(4,INPUT);
//S
pinMode(5,INPUT);
//E
pinMode(6,INPUT);
//W
pinMode(7,INPUT);

//step RA
pinMode(8,OUTPUT);
//dir RA
pinMode(9,OUTPUT);

//step dec
pinMode(10,OUTPUT);
//dir dec
pinMode(11,OUTPUT);

//enable ra
pinMode(12,OUTPUT);
//enable dec
pinMode(13,OUTPUT);

digitalWrite(radir, HIGH); //set fwd on RA
digitalWrite(raenable, HIGH); //enable ra
digitalWrite(decenable, HIGH); //enable dec


}




//timing loop
void loop() {
  
 // int pot = analogRead(0);
 // if (pot < 1000)
 //  {
 //     acc = acc + accrate;
  //  }
  
Serial.print(ra);
Serial.print("  ;  ");
Serial.print(acc);
Serial.print("  ;  ");
Serial.print(dacc);
Serial.print("  ;  ");
Serial.print(digitalRead(wpin));
Serial.print(digitalRead(epin));
Serial.print(digitalRead(spin));
Serial.print(digitalRead(npin));
  Serial.println();
  
 

   do
   {
      // RA slew w
      acc = acc + accrate;
     digitalWrite(radir, HIGH);
     digitalWrite(rastep, HIGH);   
     delayMicroseconds(pulselength);
     digitalWrite(rastep, LOW);  
     delayMicroseconds(ra / acc);
   }while (digitalRead(wpin)==HIGH);
    
     
    do
    {
      // RA slew e
      acc = acc + accrate;
     digitalWrite(radir, LOW); //reverse direction
     digitalWrite(rastep, HIGH);   
     delayMicroseconds(pulselength);
     digitalWrite(rastep, LOW);  
     delayMicroseconds(ra / acc);
    }while (digitalRead(epin)==HIGH);
    
   do
   {
   //dec slew n
   dacc = dacc + accrate;
     digitalWrite(decdir, HIGH);
     digitalWrite(decstep, HIGH);   
     delayMicroseconds(pulselength);
     digitalWrite(decstep, LOW);  
     delayMicroseconds(ra / dacc);
     }while (digitalRead(npin)==HIGH);
   
  do
  {
   //dec slew s
   dacc = dacc + accrate;
     digitalWrite(decdir, LOW);
     digitalWrite(decstep, HIGH);   
     delayMicroseconds(pulselength);
     digitalWrite(decstep, LOW);  
     delayMicroseconds(ra / dacc);
     }while (digitalRead(spin)==HIGH);
  
    
    if (acc > 1) //bring down slew rate if nothing pressed
    {
     acc = acc -accrate;
    }
    else
    {
      acc=1;
    }
   
    // RA pulse
    digitalWrite(rastep, HIGH);   
    delayMicroseconds(pulselength);
    digitalWrite(rastep, LOW);  
    delayMicroseconds(ra / acc); //range of acc=1 to 500
    
    //dec pulse if dacc>1
    if (dacc > 1)
    {
      dacc=dacc-accrate;
   
    digitalWrite(decstep, HIGH);   
    delayMicroseconds(pulselength);
    digitalWrite(decstep, LOW);  
    delayMicroseconds(ra / dacc); //range of dacc=1 to 500
 }
      else
      {
        dacc = 1;
      }

if (acc > 500)
{
  acc = 500;
}

if (dacc > 500)
{
  dacc = 500;
}






}   //end loop

Moderator edit: Added Code box.

the serial prints are just in for debugging

So, you know how to use Serial for debugging. Add more debug statements inside one while loop. If the hardware (switch) is working, and behaving as expected, the Serial output will show that.

Once the while loop ends, shouldn't you set the appropriate enable pin LOW?

The problem is you are using a do-while loop instead of a while loop. the body of a do-while loop is always run at least once. You only want it to run when the button is depressed, so you need to rewrite it as

   while  (digitalRead(wpin)==HIGH)
   {
      // RA slew w
      acc = acc + accrate;
     digitalWrite(radir, HIGH);
     digitalWrite(rastep, HIGH);   
     delayMicroseconds(pulselength);
     digitalWrite(rastep, LOW); 
     delayMicroseconds(ra / acc);
   }

Also I think for even acceleration you should change the second delay to

     delayMicroseconds(ra / acc - pulselength);

and you need some test to limit the value of acc so it doesn't get too large.

yeah, while loop will probably work fine.

That's great, thanks. I didn't know a do..while ran though once. That was the problem.

Theo