I am trying to do a project whereby I am trying to maintain a fixed distance of an object for a fixed amount of time. This project makes use of the ultrasonic sensor, hence the use of a distance condition.
I want to print a Serial text only once under a if condition while continually printing the timer. Is there any way that a certain condition (e.g. for loop, if loop?) can be set up within the if condition to make it such that the serial text only print once? I know it will continue printing as the condition is met and that it is also within a while(1) loop, thus it will be constantly printed out.
Below is the void function which will be called into the main " void loop()".
The text that I want to print only once are --> Serial.println("Maintain Posture"); , Serial.println("Time:"); , Serial.println("Adjust Position"); and Serial.println("Timer Paused");.
void CountDownPlank()
{
while(1)
{
digitalWrite(trigPin, LOW); // send out an ultra sonic sound for 5 microseconds and measure the time it took for the sound to go from the trigpin to the echo pin
delayMicroseconds(5);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
unsigned long signalDurationPlank = pulseIn(echoPin, HIGH, 6000); // Timeout good for 100 cm.
int plankDist = signalDurationPlank / MicrosecondsPerRoundTripCM; //convert the time the signal took to travel to distance in cm
if (plankDist >= 10 && plankDist <= 40)
{
resume();
Serial.println("Maintain Posture");
Serial.println("Time:");
timerBT(); //void timerBT() displays the time here
lcd.setCursor(0, 0);
lcd.print("Maintain Posture");
lcd.setCursor(0, 1);
lcd.print("Time:");
timerLCD(); //void timerLCD() displays the time here
lcd.setCursor(11, 1);
lcd.write(3);
}
else // if outside of the above stated range of 10cm to 40cm, timer pauses as posture is improper
{
pause();
Serial.println("Adjust Position");
Serial.println("Timer Paused");
lcd.setCursor(0, 0);
lcd.print("Adjust Position");
lcd.setCursor(0, 1);
lcd.print("Timer Paused");
lcd.setCursor(15, 0);
lcd.write(2);
}
}
}
Here is the display of the serial monitor. As you can see, the texts are constantly printed out.
A good way to achieve printing under certain conditions is to declare a Variable like e.g. "printed" and initialize it with 0. Once you printed what you wanted you set the variable to 1 and you can only print if the condition is "printed == 0". After the whole process is done you reset the variable to 0 again.
Then use a boolean flag like oncePrintFlag = true, in setup.
Before doing the printing, check the flag. After one printing is done, set the flag to false.
static bool postureWasGood = false;
bool postureIsGood = plankDist >= 10 && plankDist <= 40;
if (postureIsGood != postureWasGood)
{
// Posture changed
postureWasGood = postureIsGood;
if (postureIsGood)
{
// Posture just changed from bad to good
resume();
Serial.println("Maintain Posture");
Serial.println("Time:");
timerBT();
}
else
{
// Posture just changed from good to bad
pause();
Serial.println("Adjust Position");
Serial.println("Timer Paused");
}
}
Hi there Mr Johnwasser, sorry for getting back to you this late. However, is there a way to solve the issue of the timer spamming as well? I have figured out a code to only print the texts once under "void CountDownPlank()" , but I still cannot seem to solve the issue of the timer spamming as seen from the GIF posted above.
void pause() //to pause timer when improper posture is met
{
if (TimerRunning)
{
TimeRemaining = TimeRemaining - (millis() - TimeStarted); //to calculate the time that was paused at
TimerRunning = false;
}
}
void resume1() //to resume timer from when it was paused
{
if (!TimerRunning)
{
TimeStarted = millis(); //to assign to timerCD function to allow calculation of time that waas last paused
TimerRunning = true;
}
}
int timerCD() //main function to determine the calculation of timer and display the time
{
unsigned long currentTime = millis(); //assigns variable to millis() which stores the time it starts when it is activated
long displayTime;
if (TimerRunning) //if timer is still running, continue on with the code
{
unsigned long elapsedTime = currentTime - TimeStarted; //variable assigned to keep track of time that has passed
if (elapsedTime < TimeRemaining) //if time that passed has not exceeded the initial time set, continue with the code
{
displayTime = TimeRemaining - elapsedTime; //calculation of the count down timer. Every second elapsed time increases, display time decreases.
}
else
{
displayTime = 0; //if time that has passed exceeded the initial time, it means that timer has ran out
}
}
else //if timer is not running, continue with code
{
displayTime = TimeRemaining; // Timer is paused. Show the remaining time
}
byte countdown_minute = ((displayTime / 1000) / 60) % 60; //To convert from miliseconds to seconds
byte countdown_sec = (displayTime / 1000) % 60; //To convert from miliseconds to seconds
lcd.setCursor(6, 1);
if (countdown_minute < 10) //to ensure proper display of numbers once tenth digit becomes single digit
{
Serial.print('0');
lcd.print('0');
}
Serial.print(countdown_minute);
lcd.print(countdown_minute);
Serial.print(":");
lcd.print(":");
if (countdown_sec < 10) //to ensure proper display of numbers once tenth digit becomes single digit
{
Serial.print('0');
lcd.print('0');
}
Serial.println(countdown_sec);
lcd.print(countdown_sec);
if (displayTime == 0) // Time has expired
{
pause();
TimeRemaining = 0; //To ensure that timer does not restart
CDTimerEnd = 1; //Flag state to show that timer has expired
digitalWrite(GREEN, LOW);
if (RingOnce == false) //Ensure that buzzer only ring once everytime time has expired since it is in a continuous loop
{
digitalWrite(GREEN, LOW);
RingOnce = true;
tone(buzzer, 1000);
digitalWrite(RED, HIGH);
delay(200);
noTone(buzzer); // Stop sound...
digitalWrite(RED, LOW);
delay(100);
tone(buzzer, 1000);
digitalWrite(RED, HIGH);
delay(200);
noTone(buzzer); // Stop sound...
digitalWrite(RED, LOW);
delay(100);
}
return CDTimerEnd; //Value to return to CountDownPlank function
}
return 0; //to allow function to continue processing, else code will stall as it does not know what values to return
}
void CountDownPlank()
{
int CDTimerEndState = 0; //variable to allow return value to be assigned
while (1)
{
digitalWrite(trigPin, LOW); // send out an ultra sonic sound for 5 microseconds and measure the time it took for the sound to go from the trigpin to the echo pin
delayMicroseconds(5);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
unsigned long signalDurationPlank = pulseIn(echoPin, HIGH, 6000);
int plankDist = signalDurationPlank / MicrosecondsPerRoundTripCM; //convert the time the signal took to travel to distance in cm
if (plankDist >= 10 && plankDist <= 40) //proper position has been met
{
resume1(); //resume function will be called here
PrintOnceCD2 = false;
if (PrintOnceCD1 == false) //to ensure that display texts will only print once every positional change
{
PrintOnceCD1 = true;
Serial.println("Time:");
}
lcd.setCursor(0, 0);
lcd.print("Maintain Posture");
lcd.setCursor(0, 1);
lcd.print("Time:");
lcd.setCursor(11, 1);
lcd.write(3);
CDTimerEndState = timerCD(); //void timerCD() displays the time here
digitalWrite(YELLOW, LOW);
digitalWrite(GREEN, HIGH);
}
else // if outside of the above stated range of 10cm to 40cm, timer pauses as posture is improper
{
pause();
PrintOnceCD1 = false;
if(PrintOnceCD2 == false) //to ensure that display texts will only print once every positional change
{
PrintOnceCD2 = true;
Serial.println("Adjust Position");
Serial.println("Timer Paused");
}
lcd.setCursor(0, 0);
lcd.print("Adjust Position");
lcd.setCursor(0, 1);
lcd.print("Timer Paused");
lcd.setCursor(15, 0);
lcd.print(" ");
delay(1000);
lcd.setCursor(0, 1);
lcd.print("Time:");
CDTimerEndState = timerCD();
lcd.setCursor(11,1);
lcd.write(2);
digitalWrite(YELLOW, HIGH);
digitalWrite(GREEN, LOW);
delay(1000);
}
if(CDTimerEndState == 1) //returned value is sent here
{
TimeRemaining = MINUTE; //reset timer value to original
RingOnce = false;
PrintOnceCD1 = false;
PrintOnceCD2 = false;
break; //To end off count down planking exercise
}
}
}