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);
}
}
}
// @@@@@@@@@@@@@@@@@@@@@