Help with delay/millis without influencing the framerate


#1

Hi i am trying to make some text pop up each letter at a time by using a string while my framerate is at 60 however i can not use delay() because it would influence the framerate. How can i do this without using delay?

p.s i have tried to use millis() but i can not find an example i can use


#2

yes, use millis() to make a timer


#3

Thank you for the code. I will see if i can use it


#4

i just made a delux version:
revision acc next post @neilcsmith

// timer variables
long startT, stopT=5000;
boolean diagT = true;
int typT = 1;  // 0 OFF, 1 ONESHOT, 2 CONTI

void setup() {
  //size(500, 500);
  println("operation:\nrestart oneshot timer key [t]\nconti timer key [c]\ntimer OFF key [q]\ndelta key [+] or [-]\nprinting key [p]");
  theTime("first start");
}

void theTime(String info) {
  if ( diagT ) println(info+"_time_"+year()+"-"+month()+"-"+day()+" "+hour()+":"+minute()+":"+second());
}

void myTimer() {
  boolean doit = false;
  if ( millis() > startT + stopT ) {
    if ( typT == 1 ) {                             // ONE SHOT
      theTime("_oneshot");
      doit = true;
      typT = 0;                                    // timer OFF
    } else if ( typT == 2) {                       // CONTI
      // https://discourse.processing.org/t/help-with-delay-millis-without-influencing-the-framerate/8153/5
      // startT = millis();                           // auto restart
      startT += stopT;
      theTime("_conti");
      doit = true;
    }
    if ( doit ) {
      if ( diagT ) println("+ + what else you need me to do now?");
      //____________________________________________ your code
    }
  }
}

void draw() {
  background(200,200,0);  
  myTimer();
}

void keyPressed() {
  if ( key == 't' ) {                       // manual restart ONESHOT timer
    typT = 1;
    startT = millis();
    theTime("_start");
  }
  if ( key == 'c' ) {                       // manual change to CONTI timer
    typT = 2;
    startT = millis();
    theTime("_start");
  }
  if ( key == 'q' ) {                       // manual change to timer OFF
    typT = 0;
    if ( diagT ) println("timer OFF");
  }
  if ( key == 'p' ) {                       // enable disable diag printing
    diagT = ! diagT;
    println("printing "+diagT);
  }
  if ( key == '+' ) {                       // increase
    if      ( stopT <  1000 )    stopT +=  100;
    else if ( stopT >= 1000 )    stopT += 1000;
    println("set "+stopT);
  }
  if ( key == '-' ) {                       // decrease
    if      ( stopT >  1000 )    stopT -= 1000;
    else if ( stopT <= 1000 )    stopT -= 100;
    else if ( stopT <     0 )    stopT =  10;    
    println("set "+stopT);
  }
}

and also a “nano” version:

// v01 https://discourse.processing.org/t/help-with-delay-millis-without-influencing-the-framerate/8153
// v02 change from 
//          startT = millis();                           // auto restart
// to:      startT += stopT;
// thanks to @neilcsmith
// https://discourse.processing.org/t/inaccurate-time-intervals-for-a-metronome/2463/10
// v03 also change use nano instead millis

// timer variables
long startT=0, msec = 1000000L, stopT=(long) 5000*msec;  // 5 sec
boolean diagT = true;
int typT = 2;  // 0 OFF, 1 ONESHOT, 2 CONTI
// user variables
int usercounter = 0;

void setup() {
  size(200, 200);
  frameRate(120);
  println("operation:\nrestart oneshot timer key [t]\nconti timer key [c]\ntimer OFF key [q]\ndelta key [+] or [-]\nprinting key [p]");
  startT = System.nanoTime();
  theTime("first start");
  fill(0,0,200);
}

void theTime(String info) {
  if ( diagT ) println(info+"_time_"+year()+"-"+month()+"-"+day()+" "+hour()+":"+minute()+":"+second());
}

void myTimer() {
  boolean doit = false;
//  if ( millis() > startT + stopT ) {

  if ( System.nanoTime() > startT + stopT ) {
    if ( typT == 1 ) {                             // ONE SHOT
      theTime("_oneshot");
      doit = true;
      typT = 0;                                    // timer OFF
    } else if ( typT == 2) {                       // CONTI
      // https://discourse.processing.org/t/help-with-delay-millis-without-influencing-the-framerate/8153/5
      // startT = millis();                           // auto restart
      startT += stopT;
      theTime("_conti");
      doit = true;
    }
    if ( doit ) {
      // println("+ + what else you need me to do now?");
      //____________________________________________ your code
      usercounter++;
    }
  }
}

void draw() {
  background(200,200,0);  
  myTimer();
  if ( diagT ) text(nf(frameRate,1,1)+" FPS; dT "+stopT/msec+" msec; T: "+typT,5,height-10);  //
  if ( diagT ) text(usercounter,width/2,height/2);   
}

void keyPressed() {
  if ( key == 't' ) {                       // manual restart ONESHOT timer
    typT = 1;
    startT = System.nanoTime();
    theTime("_start");
  }
  if ( key == 'c' ) {                       // manual change to CONTI timer
    typT = 2;
    startT = System.nanoTime();
    theTime("_start");
  }
  if ( key == 'q' ) {                       // manual change to timer OFF
    typT = 0;
    if ( diagT ) println("timer OFF");
  }
  if ( key == 'p' ) {                       // enable disable diag printing
    diagT = ! diagT;
    println("printing "+diagT);
  }
  if ( key == '+' ) {                       // increase
    if      ( stopT <  1000*msec )    stopT +=  100*msec;
    else if ( stopT >= 1000*msec )    stopT += 1000*msec;
    println("set "+stopT/msec);
  }
  if ( key == '-' ) {                       // decrease
    if      ( stopT >  1000*msec )    stopT -= 1000*msec;
    else if ( stopT <= 1000*msec )    stopT -=  100*msec;
    if      ( stopT <     0 )         stopT  =  0;    
    println("set "+stopT/msec);
  }
}


#5

You might also want to have a look at Inaccurate time intervals for a Metronome

The code looks good apart from the auto restart with startT = millis() - this will accumulate errors, although may be what you want - fixed rate or fixed delay?


#6

and just i looked up your

System.nanoTime()


is actually not very clear for me.

i come from the arduino side and have made some ?multi tasking? time scheduler? structures there
and learned also that the call “millis” takes too long,
so the basic loop i just made only by counters ( revolving job1=1001; job2=1002;…)
and used millis and check serial as rare as possible.

for this timing critical things in processing i not yet have a feeling, even i work mostly
on my 40euro computer Raspberry PI with 1GB ram for cpu+gpu
so i should learn the hard way.

ok: as long have println’s in draw and not use noSmooth(); in setup,
i think it is all not that critical.


#7

I prefer using nanoTime() as it’s a more accurate clock. On Windows for example the millis() clock can have a coarse resolution (only changes value every 16ms). The call to nanoTime() is computationally more expensive, but on a desktop computer (including the Pi!) it’s really not worth being concerned about compared to everything else Processing is doing.