The Countdown Timer in Android studio skips some of the seconds within the time interval - countdowntimer

I read about the problem a day ago where the problem occurs with people but when it comes to the final second. I kept noticing in my timer that the as it counts down it sometimes skips a second, some suggested changing the interval from 1000ms to 500ms others said make it 900. And there are those who suggested making your own Timer.
My timer is a bit big as it contains two smaller timers within it, that count down individual minutes within the total time and I activate an animation during those times. So basically I am asking what approach should I take to for a time critical counter that is 100% accurate?
This is my code:
private void startTimer() {
Log.println(Log.ASSERT, "CHECK","Entered startTimer() method");
millisInFuture = mTimeLeftInMillis;
mCountDownTimer = new CountDownTimer(mTimeLeftInMillis, 900) {
#Override
public void onTick(long millisUntilFinished) {
mTimeLeftInMillis = millisUntilFinished;
updateCountDownText();
millisPassed = millisInFuture - mTimeLeftInMillis;
progress = (int) (millisPassed * 100 / millisInFuture);
pb.setProgress(progress);
pb2.setProgress(0);
pb3.setProgress(0);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Key: 60 sec
if (millisInFuture == 480000) {
if (millisPassed <= 60000 || (millisPassed > 180000 && millisPassed <= 240000) || (millisPassed > 300000 && millisPassed <= 360000 || (millisPassed > 420000 && millisPassed <= 480000))) {
// Animation animation = AnimationUtils.loadAnimation(tool1mode1.this, R.anim.fade_in);
// stepupimage.setAnimation(animation);
Log.println(Log.ASSERT,"CHECK","Check that the first if statement of key 60 is entered");
statusIfUp();
time_of_stage = (millisInFuture - millisPassed) % 60000;
progress2 = (int) (time_of_stage*100 / 60000);
Log.println(Log.VERBOSE,"CHECK","TIME OF STAGE = "+time_of_stage);
Log.println(Log.VERBOSE,"CHECK","progress2= "+progress2);
pb2.setProgress(progress2);
updateStageUpCount();
upArrowAnimation();
setflowrate();
}
}
#Override
public void onFinish() {
Toast.makeText(tool1mode1.this, "Done", Toast.LENGTH_SHORT).show();
avd2.stop(); avd3.stop();
try {
pb.setProgress(100); pb2.setProgress(0); pb3.setProgress(0);
stage_timer.setVisibility(View.INVISIBLE);
stage_timer.setVisibility(View.INVISIBLE);
progressBar.setVisibility(View.INVISIBLE);
progressBar2.setVisibility(View.INVISIBLE);
progressBar.setProgress(0);
progressBar2.setProgress(0);
progressBar.setTranslationY(60);
progressBar2.setTranslationY(60);
flow.setTranslationY(60);
animation1.cancel(); animation2.cancel();
//Vibration
if (Build.VERSION.SDK_INT >= 26) {
((Vibrator) getSystemService(VIBRATOR_SERVICE)).vibrate(VibrationEffect.createOneShot(150, VibrationEffect.DEFAULT_AMPLITUDE));
} else {
((Vibrator) getSystemService(VIBRATOR_SERVICE)).vibrate(VibrationEffect.createWaveform(new long[]{150}, new int[]{VibrationEffect.EFFECT_CLICK}, -1));
}
}
catch (NullPointerException e) {
e.printStackTrace();
}
}
}.start();
}
So to summarize: I have a big timer and two small timers that count certain intervals within the larger timer. Now the CountDownTimer class that is provided by Android skips a second or two at times during the count down. I want to fix this problem and don't know how, I would have just rolled with it but unfortunately the one I'm making the app for requires it to be 100% accurate as the application is time critical.
Note: pb, pb2, pb3, are progress bars of the timers (1st is the big one, 2nd and 3rd alternate for the second timer)

Related

TIM2 module not ticking at 1us in STM8S103F3 controller

I created a program on STM8S103F3 to generate a delay in rage of micro seconds using TIM2 module, but the timer is not ticking as expected and when I tried to call 5 sec delay using it, it is giving around 3 sec delay. I'm using 16MHz HSI oscillator and timer pre-scalar is set to 16. please see my code below. Please help me to figure out what is wrong with my code.
void clock_setup(void)
{
CLK_DeInit();
CLK_HSECmd(DISABLE);
CLK_LSICmd(DISABLE);
CLK_HSICmd(ENABLE);
while(CLK_GetFlagStatus(CLK_FLAG_HSIRDY) == FALSE);
CLK_ClockSwitchCmd(ENABLE);
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);
CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO, CLK_SOURCE_HSI,
DISABLE, CLK_CURRENTCLOCKSTATE_ENABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_SPI, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_I2C, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_ADC, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_AWU, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_UART1, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER1, DISABLE);
CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER2, DISABLE);
}
void delay_us(uint16_t us)
{
volatile uint16_t temp;
TIM2_DeInit();
TIM2_TimeBaseInit(TIM2_PRESCALER_16, 2000); //Prescalar value 8,Timer clock 2MHz
TIM2_Cmd(ENABLE);
do{
temp = TIM2_GetCounter();
}while(temp < us);
TIM2_ClearFlag(TIM2_FLAG_UPDATE);
TIM2_Cmd(DISABLE);
}
void delay_ms(uint16_t ms)
{
while(ms--)
{
//delay_us(1000);
delay_us(1000);
}
}
It is better to use a 10us time base to round the delays. Well in order to achive a 10us timebase, if you use 16MHz master clock and you prescale TIM2 by 16, then you get a 1 us increment time, right? But we want TIM2 to overflow to generate an event named 16us event. Since we know that the timer will increment every 1us, if we use a reload value 65536 - 10 = 65526, this will give us a 10us overflow hence, 10us time base. If we are ok until here in delay code we'll just check the TIM2 update flag to know whther it has overflowed or not. See the example code snippet below.
// Set up it once since our time base is a fixed 10us
void setupTIM2(){
TIM2_DeInit();
TIM2_TimeBaseInit(TIM2_PRESCALER_16, 65526); //Prescalar value 16,Timer clock 1MHz
}
void delay_us(uint16_t us)
{
volatile uint16_t temp;
TIM2_Cmd(ENABLE);
const uint16_t count = us / 10; //Get the required counts for 10us time base
// Loop until the temp reaches the required count value
do{
while(TIM2_GetFlagStatus(TIM2_FLAG_UPDATE) == RESET); //Wait for the TIM2 to overflow
TIM2_ClearFlag(TIM2_FLAG_UPDATE); // Clear the overflow flag
temp++;
} while(temp < count);
TIM2_Cmd(DISABLE);
}
void delay_ms(uint16_t ms)
{
while(ms--)
{
//delay_us(1000);
delay_us(1000);
}
}
void main(void){
...
setupTIM2();
...
delay_ms(5000);
}

sleep using java.time.Duration

I work in java8 and would like to use class java.time.Duration to set up sleep time.
As I understand Duration is composed via seconds and nanoseconds.
So waiting Duration time is should be equivalent to waiting:
java.util.concurrent.TimeUnit.SECONDS.sleep(long);
java.util.concurrent.TimeUnit.NANOSECONDS.sleep(long);
Is my understating is correct?
The TimeUnit.sleep functionality only provides millisecond granularity for sleeping. It forwards to Thread.sleep and the nanoseconds are ignored.
public static void sleep(long millis, int nanos)
throws InterruptedException {
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
millis++;
}
sleep(millis);
}
If you want something more reliable have a look at LockSupport.parkNanos. You should be able to get something like 50us granularity on your sleep on Linux.
https://hazelcast.com/blog/locksupport-parknanos-under-the-hood-and-the-curious-case-of-parking/

Save output in processing every X seconds

Hi I'm using processing and want to know if there is a way I can automatically save my output every X amount of seconds?
Any help would be great!
You are looking for saveFrame() method.
Inside your draw() method, you can save a screenshot of your visual output.
void draw() {
// YOUR CODE
...
// Saves each frame as screenshot-000001.png, screenshot-000002.png, etc.
saveFrame("screenshot-######.png");
}
More info: https://processing.org/reference/saveFrame_.html
And for take screenshot every X seconds:
int lastTime = 0;
void draw(){
// YOUR CODE
...
// 1000 in milisecs, that's 1 sec
if( millis() - lastTime >= 1000){
saveFrame("screenshot-######.png");
lastTime = millis();
}
}

Possible Memory Leak Arduino?

This is code to run automated blinds. However, it appears that there is some memory leak going on inside of loop as my program will not run. I am using XOBXOB to input data. Look below for where it really breaks.
void loop()
{
Serial.println("loop");
// New XOB request every 4 seconds (if previous response has been received)
if (lastResponseReceived && (abs(millis() - lastRequestTime) > 4*1000)) {
// if the connection has dropped, reconnect
while (!XOB.connected()) XOB.connect();
// Reset timer and response flags. Then, request "XOB" contents
lastResponseReceived = false;
lastRequestTime = millis();
Serial.println("requesting xob");
//enter name of XOB
XOB.requestXOB("XOB");
Serial.println("XOB requested!");
}
// Load response a character at a time when it is available.
// If loadStreamedResponse returns true, a completed response has been received
// Get the "switch" message from the XOB and turn the LED on/off
// NOTE: The message contents are returned with quotes. So, include them
// in the comparison statement.
// Serial.println("LSR: ");
// Serial.print(XOB.loadStreamedResponse());
This is where the loop does not run. It seems that the stream of data from XOBXOB cannot be stored and therefore loadStreamedResponse returns false.
if (!lastResponseReceived && XOB.loadStreamedResponse()) {
Serial.println("requesting reponse");
lastResponseReceived = true;
Serial.println("Get Xob Messages");
//Gets the string from value.
String str_value = XOB.getMessage("value");
Serial.println(str_value);
//Gets the string from switch
String str_switch = XOB.getMessage("switch");
Serial.println(str_switch);
String str_text = XOB.getMessage("text");
Serial.println(str_text);
//If time is not set, get the time from text xob.
if(time_set == false) {
Serial.println("setting time");
// insert code to parse time and set it from the text xob.
time_set = true;
}
// parse the hour from value and convert to minute for wake hour
String string_hour = str_value.substring(1,3);
int wake_hour = string_hour.toInt();
//Serial.println(wake_hour);
// parse minute from value and convert to int for wake minute
String string_minute = str_value.substring(3,5);
int wake_minute = string_minute.toInt();
// Serial.println(wake_minute);
// compare wake_minute and wake_hour with current time
// convert both to minutes for comparison
int wake_time = wake_minute + (60 * wake_hour);
int current_time = 738; //minute() + (hour() * 60);
Serial.println("checking wake condtions");
// rise up blinds slowly if the wake time is + or - 1 minute and if the blinds are closed.
if((wake_time == current_time || wake_time == (current_time - 1) || wake_time == (current_time + 1))
&& blinds_open == false ) {
Serial.println("Natural Wakeup");
rollup_blinds_slow();
blinds_open = true; // blinds should be open now.
}
// Check for opening up blinds condition. Blinds must be closed, to open them
Serial.println("Checking Open Condition");
if (str_switch.equalsIgnoreCase("\"ON\"") && blinds_open == false) {
Serial.println("Blinds Up");
rollup_blinds_fast();
blinds_open = true;
Serial.println(blinds_open);
}
Serial.println("Check closing condition");
// Check for closing blinds condition. Blinds must be closed, to open them
if (str_switch.equalsIgnoreCase("\"OFF\"") && blinds_open == true) {
Serial.println("Blinds down");
rolldown_blinds_fast();
blinds_open = false;
}
}

Android java development time of acceleration to

How can I calculate the time of acceleration to 100kmh?
Well, I registered a location listener when the !location.hasSpeed() is true store the time of location into a variable. When the speed is reach of the given speed in this case 100km/h (27.77 m/s) I substract from the spped of location and the result I divide by 1000.
Here is the "pseudo code"
#Override
public void onLocationChanged(Location currentLoc) {
// when stop reseted, when start reset again
if (isAccelerationLoggingStarted) {
if (currentLoc.hasSpeed() && currentLoc.getSpeed() > 0.0) {
// dismiss the time between reset to start to move
startAccelerationToTime = (double) currentLoc.getTime();
}
}
if (!currentLoc.hasSpeed()) {
isAccelerationLoggingStarted = true;
startAccelerationToTime = (double) currentLoc.getTime();
acceleration100 = 0.0;
}
if (isAccelerationLoggingStarted) {
if (currentLoc.getSpeed() >= 27.77) {
acceleration100 = (currentLoc.getTime() - startAccelerationToTime) / 1000;
isAccelerationLoggingStarted = false;
}
}
}
The main problem i see here, is that whenever the device is moving, startAccelerationToTime is reset. (The first if only checks whether there's movement; it doesn't check whether there's already a start time recorded.
I don't see where isAccelerationLoggingStarted is needed at all -- the speed, and the variables themselves, can be cleaned up a bit to make it clear what the next step should be.
Your pseudocode probably ought to look something like:
if speed is 0
clear start time
else if no start time yet
start time = current time
clear acceleration time
else if no acceleration time yet, and if speed >= 100 mph
acceleration time = current time - start time
In Java, that'd look like...
long startTime = 0;
double accelerationTime = 0.0;
#Override
public void onLocationChanged(Location currentLoc) {
// when stopped (or so slow we might as well be), reset start time
if (!currentLoc.hasSpeed() || currentLoc.getSpeed() < 0.005) {
startTime = 0;
}
// We're moving, but is there a start time yet?
// if not, set it and clear the acceleration time
else if (startTime == 0) {
startTime = currentLoc.getTime();
accelerationTime = 0.0;
}
// There's a start time, but are we going over 100 km/h?
// if so, and we don't have an acceleration time yet, set it
else if (accelerationTime == 0.0 && currentLoc.getSpeed() >= 27.77) {
accelerationTime = (double)(currentLoc.getTime() - startTime) / 1000.0;
}
}
Now, i'm not sure exactly how location listeners work, or how often they notify you when you're moving. So this may only semi work. In particular, onLocationChanged might not get called when you're not moving; you may need to request an update (perhaps via a "reset" button or something) or set certain params in order to trigger the stuff that happens when speed == 0.

Resources