Using Timers instead of delays

My program is reading serial from my transmission controller to display on a Seetron OLED display. The program looks at the serial buffer from controller to display the gear number and auto or manual mode. Animations were created with 3 segments of characters that scroll between 1 to 2 gear, 2 to 3, and 3 to 4 and back. I used delays in my first program, but when I would scroll the Mode “A” to “M” ofcoarse it would stop the loop and wait for the delays before scrolling the gear to the correct position which takes too long. I really want them to scroll at the same time which leads me to this post on Timers http://www.uchobby.com/index.php/2012/01/21/replacing-delay-in-arduino-sketches-istime-to-the-rescue/ .
I was not able to make the created characters scroll in my program when the trans is switching gears when I removed delays and based the program from the IsTime code.
Since the delays are gone from between the serial.writes I am having trouble figuring out exactly how to write the code so the sequence of the animating characters move from one to the other. Example, the serial serial sequence previously was:

 if (buttonPushCounter ==0 && currentgear == '2' && previousgear == '1') {
        Serial1.write("\x10\x40\x87") ;  // Animate through transitions...  Moveto, position 0x40, character in display buffer =1 to 2  \1
        delay(40);
        Serial1.write("\x10\x40\x88") ;//1 to 2  \2
        delay(40);
        Serial1.write("\x10\x40\x89") ;//1 to 2  \3
        delay(40);
        Serial1.write("\x10\x40\x32") ; // 2

Now, without the delays I can’t figure out how to Serial.write the next character and so on. The code is long so I’ve reduced it down to just the main functions and characters:

/*
  Modified Blink - Origanl is included with the Arduino IDE pacage.
 Turns on an LED on for one second, then off for one second, repeatedly.
 Uses IsTime() to control the scroll rahter then the delay() function.
 
 David Fowler, AKA uCHobby, http://www.uchobby.com 01/21/2012
 Cut and paste from this text file into a new Arduino skectch
 */

/*Modified the Timer Blink code for Serial OLED display using 3 chacters animated for scrolling affect between 1 to 2, 2 to 3, and 3 to 4 and vise versa. */

#define TRANSMODE_POSITION 0  
#define GEAR_POSITION      2
#define THROTTLE_POSITION  4
#define THROTTLE_POSITION_2  5
#define MPH_POSITION       7
#define MPH_POSITION2       8
#define MPH_POSITION3       9

int buttonPin = 26;
int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;       // variable for reading the pushbutton status
int lastButtonState = 0;     // previous state of the button

void setup() {                
  // initialize the digital pin as an output.
  // Pin 13 has an LED connected on most Arduino boards:
  Serial2.begin(19200);
  Serial1.begin(19200);
  Serial.begin(19200);


  pinMode(buttonPin, INPUT);  



  Serial1.write("\x1b\x44\x37\x80\x82\x96\x92\x82\x82\x82\x97") ;  // 135 1-2.1
  Serial1.write("\x1b\x64\x30\x80\x91\x8B\x89\x91\x81\x81\x9B") ;  // 136 1-2.2
  Serial1.write("\x1b\x64\x31\x80\x98\x85\x84\x88\x90\x80\x9D") ;  // 137 1-2.3

  Serial1.write("\x1b\x64\x32\x80\x93\x84\x80\x80\x91\x92\x87") ;  // 138 2-3.1
  Serial1.write("\x1b\x64\x33\x80\x99\x92\x80\x90\x88\x89\x93") ;  // 139 2-3.2
  Serial1.write("\x1b\x64\x34\x80\x9C\x89\x90\x88\x84\x84\x99") ;  // 140 2-3.3

  Serial1.write("\x1b\x64\x35\x80\x87\x80\x81\x80\x90\x84\x83") ;  // 141 3-4.1
  Serial1.write("\x1b\x64\x36\x80\x93\x90\x90\x90\x98\x92\x91") ;  // 142 3-4.2
  Serial1.write("\x1b\x44\x36\x80\x89\x98\x88\x88\x9C\x89\x88") ;  // 134 3-4.3

}

unsigned long scrollTimeMark=0;  //a millisecond time stamp used by the IsTime() function. initialize to 0
unsigned long int scrollTimeInterval=800;  //How many milliseconds we want for the scroll cycle. 1000mS is 1 second.
unsigned long scroll2TimeMark=0;  //a millisecond time stamp used by the IsTime() function. initialize to 0
unsigned long int scroll2TimeInterval=800;  //How many milliseconds we want for the scroll cycle. 1000mS is 1 second.
unsigned long scroll3TimeMark=0;  //a millisecond time stamp used by the IsTime() function. initialize to 0
unsigned long int scroll3TimeInterval=800;  //How many milliseconds we want for the scroll cycle. 1000mS is 1 second.
unsigned long scroll4TimeMark=0;  //a millisecond time stamp used by the IsTime() function. initialize to 0
unsigned long int scroll4TimeInterval=800;  //How many milliseconds we want for the scroll cycle. 1000mS is 1 second.

void loop() {

  char buffer [15];
  char currentchar;
  char previousgear;
  char previousmode;
  char previousbutton;
  int  currentlinelength;
  int previouslinelength;
  char currentgear;  
  char currentmode;

  currentgear = '\0';
  previousgear = '\0';

  while (1) {
    currentlinelength = 0;
    currentchar = '\0';

    while (currentchar != 0x0d) {
      if (Serial2.available()) {
        currentchar = Serial2.read();
        if (currentchar != 0x0d) {
          buffer[ currentlinelength++ ] = currentchar;

        }  
      }            
    }
    buttonState = digitalRead(buttonPin);
    if (buttonState != lastButtonState) {
      if (buttonState == HIGH) {
        buttonPushCounter++;
        Serial.println (buttonPushCounter);


      }

      if (buttonPushCounter > 1)
        buttonPushCounter =0;

    }

    lastButtonState = buttonState;
    if ((buffer [ GEAR_POSITION ] == '1') ||
      (buffer [ GEAR_POSITION ] == '2') ||
      (buffer [ GEAR_POSITION ] == '3') ||
      (buffer [ GEAR_POSITION ] == '4')) {

      if ((buttonPushCounter ==0  && previousgear == '\0') ||
        (buttonPushCounter ==0  && previousbutton !=0 )) {
        previousgear = buffer [ GEAR_POSITION ];

        //Print "1" at line (0)
        Serial1.write ("\x03\x02\x02\x02\x14");
        Serial1.write("\x10\x40\x31");
      }
      currentgear = buffer [ GEAR_POSITION ]; 
      Serial1.write ("\x03\x02\x02\x02\x14"); //reset font size\bigger font\bigger font\bigger font\font type

//----------------------------------------------------------------------------------------------------------------------------------
//    Below is the issue. The IF statement works, but I can't figure how to add the next Serial1.write, and the next, and the next.........
//-----------------------------------------------------------------------------------------------------------------------------------
      if(buttonPushCounter ==0 && currentgear == '2' && previousgear == '1' && IsTime(&scrollTimeMark,scrollTimeInterval)) {  //Is it time to scroll next character?
        Serial1.write("\x10\x40\x87") ; // ------> I need to figure out how to call the next animation character after this one runs to its timer point.
        //Serial1.write("\x10\x40\x88") ; //This is first scroll animation character //scroll2TimeMark,scroll2TimeInterval
        // Serial1.write("\x10\x40\x89") ;  //scroll2TimeMark,scroll2TimeInterval
        // Serial1.write("\x10\x40\x32") ; //scroll4TimeMark,scroll4TimeInterval

      }

      previousgear = buffer [ GEAR_POSITION ];  



      //We can do anything here! The above code takes a tiny fraction of a second each pass though loop. Uses nearly no 
      //processor resource.
    }
  }
}



//**********************************************************
//IsTime() function - David Fowler, AKA uCHobby, http://www.uchobby.com 01/21/2012

#define TIMECTL_MAXTICKS  4294967295L
#define TIMECTL_INIT      0

int IsTime(unsigned long *timeMark, unsigned long timeInterval){
  unsigned long timeCurrent;
  unsigned long timeElapsed;
  int result=false;

  timeCurrent=millis();
  if(timeCurrent<*timeMark) {  //Rollover detected
    timeElapsed=(TIMECTL_MAXTICKS-*timeMark)+timeCurrent;  //elapsed=all the ticks to overflow + all the ticks since overflow
  }
  else {
    timeElapsed=timeCurrent-*timeMark;  
  }

  if(timeElapsed>=timeInterval) {
    *timeMark=timeCurrent;
    result=true;
  }
  return(result);  
}

Thanks for any help.

1) Write the first one. 2) Look at the clock 3) Is it time to write the next one? 4) If no, go and do something else and return to 2 5) If yes, write the next one 6) loop back to 2

Use a queue to keep the strings to write and when to write them. Each time thru the loop() check the next item in the queue to see if it is time to write to the serial port. Queue entries could be a struct with two elements, a pointer to the string to write and an unsigned long to time to write.

Try this:

unsigned long startTime = millis();
unsigned long myDelay = 1000; // 1 second. Change to whatever delay you want
int state = 1;
      if(buttonPushCounter ==0 && currentgear == '2' && previousgear == '1' ) {
      while(state < 5){
         switch (state){
           case 1:
              if (millis()-startTime >=myDelay){  //has time elapsed?
                      Serial1.write("\x10\x40\x87") ; //yes
                      startTime = millis();  //reset startTime for next output
                      state++; //go to next state
             }
             break;
           case 2:
              if (millis()-startTime >=myDelay){
                      Serial1.write("\x10\x40\x88") ;
                      startTime = millis();
                      state++;
              }
              break;
           case 3:
              if (millis()-startTime >=myDelay){
                      Serial1.write("\x10\x40\x89") ;
                      startTime = millis();
                      state++;
              }
              break;
           case 4:
              if (millis()-startTime >=myDelay){
                      Serial1.write("\x10\x40\x32") ;
                      startTime = millis();
                      state++;
              }
              break;
          default:  //you should never get here
            state = 1;  //reset to start, just in case!
            break;
         }
    }
}

I tried all this weekend to make these suggestions work with my novice experience with no luck. The above makes the sequence work at least. I will try to incorporate everything else with this. Thank you very much Henry=Best. :)

You don't say what you mean by animation BUT, changing the display/icon once every 10th of a second will do the job. Ensure that you do not use delays or any code which may take more than (approx) 1/50th of a second. Look at the blink without delay example and in the playground at FSM's (finite state machines). No path through loop() should make more than 1/50th of a second.

Mark