help jumping out of a do loop

Hello,

Can you please help me to jump out of a do loop. I'm sure its something very simple, but just can't work this out.

I'm trying to use a do loop and millis to keep a brushless motor running for 20 seconds and then drop to idle. I've spent ages looking the do loop examples because I thought thats where my problem was; now I'm thinking its possibly a problem with the roll over of the millis value and how these need to be handled.

My problem function is "void MotorRun()" in the attached version 22 code "while ((currentMillis - motorStartTime) >= motorTime);" I want it to jump out when the value hits 20036, but it just keeps on running.

The line of code marked version 20 jumps out of the loop; but after the first loop and not 20 seconds after.

I've included this function below and the full sketch. I'm new to this kind of thing; sorry if its not very well written.

many thanks

Dave

// based on SweepNoDelay example from SoftRcPulseOut examples
//
// by RC Navy (http://p.loussouarn.free.fr/arduino/arduino.html>)
// This sketch can work with ATtiny and Arduino UNO, MEGA, etc...
// This example code is in the public domain.

#include <SoftRcPulseOut.h>
#include <Rcul.h>

SoftRcPulseOut ESC;  // create servo object to control a servo
// a maximum of eight servo objects can be created

const int ESC_PIN = 3;     // 0 is pin 5 on ATtiny85 chip and P0 on digispark USB board
// use output 3 for testing on UNO board
const int LED = 13;          //  output 1 is P1 on digispark USB board & onboard LED or pin 6 on Ttiny85 chip -
//  use pin 13 on UNO for built in LED

const int BUTTON = 2;  // assign button to input 2 (pin P4 on digispark board or pin 7 on ATtiny chip

unsigned long motorStartTime = 0;    //  time in millis that the motor started
unsigned long motorDuration = 0;  // length of time motor has been running in milliseconds
unsigned long motorTime = 20000;  // length of motor run in milliseconds
unsigned long currentMillis = millis();

#define REFRESH_PERIOD_MS 20

#define NOW


#define UP_DIRECTION      +1
#define DOWN_DIRECTION    -1

#define ESC_MIN           20
#define ESC_MAX           160

int ESC_pos = ESC_MIN;    // variable to store the servo position

int step = UP_DIRECTION;

void setup()
{
  ESC.attach(ESC_PIN);  // attaches the servo on pin defined by SERVO_PIN to the servo object
  ESC.write(ESC_pos);

  pinMode(LED, OUTPUT);
  pinMode(BUTTON, INPUT);
  digitalWrite(BUTTON, LOW);   //  set button to low or zero volts

  delay(1000);                // wait 1 seconds before doing anything
  digitalWrite(LED, HIGH);      //  put the onboard LED on
  delay(3000);               // wait for 3 seconds
  digitalWrite(LED, LOW);      //  turn the LED off


  Serial.begin(9600); // initialize serial port hardware

}

void loop()
{

  Wait();   //  jump to the function that waits for the button to be pressed

  // eventually put a delay in here to deley starting the motor

  //  MotorStartt();   //  jump to the function that starts the motor

  MotorRun();   //  jump to the function that keeps the motor on for the duration


  idle();   //  return to idle after power run



}


//  ##############################
//  ###  functions below here  ###
//  ##############################

//  $$$$$$$$$$$$$$$$$$$$$$$$$
// $$  this loop outputs low throttle until a button is pressed
void Wait() {
  Serial.println("waiting for button press");          // removed spaces to save memory
  while (digitalRead(BUTTON) == LOW) //  this loop keeps the ESC at idle until a button is pressed
  {
    if (SoftRcPulseOut::refresh())    // refresh() returns 1 every 20ms (after pulse update)
    {
      // We arrive here every 20ms
      ESC_pos == ESC_MIN;
      ESC.write(ESC_pos);
    }
  }   //  Exit the loop when the button is pressed and then continute onto the power cycle
}
//  $$$$$$$$$$$$$$$$$$$$$$$$


//  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5
void MotorStart()   //  this is based on the digispark example knob sketch
{
  //  val = analogRead(POT_PIN);           // reads the value of the potentiometer (value between 0 and 1023)
  //  val = map(val, 0, 1023, 0, 179);     // scale it to use it with the servo (value between 0 and 180)

  for (int ESC_pos = ESC_pos ; ESC_pos <= 180; ESC_pos += 1)  {


    Serial.print("ESC position = ");           //  changed text to save memory
    Serial.println(ESC_pos);          // removed spaces to save memory

    ESC.write(ESC_pos);                  // sets the servo position according to the scaled value
    delay(REFRESH_PERIOD_MS);            // waits for the servo to get there
    SoftRcPulseOut::refresh(NOW);        // generates the servo pulse Now
  }
}
//  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


//  *************************************************
//  ***  this needs to hold the power on for the desired motor run time
void MotorRun()   //  this is based on the digispark example knob sketch
{
  Serial.println("now in motor run mode");
  unsigned long motorStartTime = millis();
  Serial.print("motor started at  ");
  Serial.println(motorStartTime);

  //  while (1) //  think I need to change this to a doo loop; drop out when motor timer goes above the run time
  // if ((unsigned long)(currentMillis - motorStart) <= motorTime);


  do
  {
    ESC.write(ESC_MAX);                  // sets the servo position according to the scaled value
    delay(REFRESH_PERIOD_MS);            // waits for the servo to get there
    SoftRcPulseOut::refresh(NOW);        // generates the servo pulse Now

    unsigned long currentMillis = millis();
    unsigned long motorDuration = currentMillis - motorStartTime;

    //  just output some stuff to serial monitor for testing only
    Serial.print("motor started at ");
    Serial.print(motorStartTime);
    Serial.print("   current millis ");
    Serial.print(currentMillis);
    Serial.print("   motor run secs = ");
    Serial.print(motorTime);
    Serial.print("  ESC posn = ");           //  changed text to save memory
    Serial.print(ESC_MAX);          // removed spaces to save memory
    Serial.print("  motor been on: ");
    Serial.println(motorDuration);
    // Serial.print("   ");
    // Serial.println(motorTime - motorDuration);
    // Serial.print(" still to go");
    // Serial.println((currentMillis - motorStartTime) );
    //  return;    // trying to jump out of the loop, sure this is not the right way.....

    // } while (motorDuration > motorTime);  // from version 20 -  jumps out of the loop ok but after the first cycle; need it to jump out after 20 seconds
    // } while ((currentMillis - motorStartTime)> motorTime);  //  from version 21 - motor starts up ok but dusn't jump out of the do loop after 20 seconds
  } while ((currentMillis - motorStartTime) >=  motorTime); //  from version 22 - motor starts up ok but dusn't jump out of the do loop after 20 seconds
  //  while ((currentMillis - motorStart) >=  motorTime); from version 19


  //  return;  // trying to jump out of the loop, sure this is not the right way.....
}
//  **************************************************




//  $$$$$$$$$$$$$$$$$$$$$$$$$
// $$  this loop outputs low throttle until a button is pressed
void idle() {
  Serial.println("return to idle after power run");          // removed spaces to save memory
  while (1)   //digitalRead(BUTTON) == LOW) //  this loop keeps the ESC at idle until a button is pressed
  {
    if (SoftRcPulseOut::refresh())    // refresh() returns 1 every 20ms (after pulse update)
    {
      // We arrive here every 20ms
      ESC_pos == ESC_MIN;
      ESC.write(ESC_pos);
    }
  }   //  Exit the loop when the button is pressed and then continute onto the power cycle
}
//  $$$$$$$$$$$$$$$$$$$$$$$$



// @@@@@@@@@@@ this loop sweeps the servo
void Sweep() {
  while (1)   //  this loop is here to keep power cycle going; at this point its just the seep loop
  {
    // this loop is the normal sweep without delay loop from the example program
    if (SoftRcPulseOut::refresh())    // refresh() returns 1 every 20ms (after pulse update)
    {
      // We arrive here every 20ms
      ESC_pos += step;
      if (ESC_pos >= ESC_MAX) step = DOWN_DIRECTION; //180 degrees reached -> Change direction
      if (ESC_pos <= ESC_MIN) step = UP_DIRECTION;  //  0 degrees reached -> Change direction
      ESC.write(ESC_pos);
    }
  }
}
//  @@@@@@@@@@@@@@@@@@@@@

Your problem is you declared a local variable called 'currentMillis' in your do loop. That is not the same as the global variable 'currentMillis'. The conditional on your do loop is evaluating the global variable 'currentMillis' which never changes. You did the same thing with the 'motorDuration' variable.

Thank you for looking at my code. I would have never worked this out on my own.

Think I need to learn more about local & global variables :slight_smile:

Cheers

Dave

beenie:
Thank you for looking at my code. I would have never worked this out on my own.

Think I need to learn more about local & global variables :slight_smile:

Cheers

Dave

Common problem. Just remember local variable scope is limited to the code between the curly brackets!

All working fine now :slight_smile:

Its all so easy when you know what your doing; i've so much to learn.

Thank you for pointing me in the right direction

Dave