Timeslice con oscilador y contador

Buenos días… estuve trabajando con un proyecto de un electroestimulador temporizado con arduino. Estoy usando una arduino UNO para hacer un selector de tiempo en horas, minutos y segundos (cada uno con su respectivo pulsador). Ahora bien una vez seleccionado el tiempo de la sesion y puesto en marcha el temporizador debo generar unos pulsos con un periodo máximo de 5 segundos por lo que solamente he puesto el siguiente codigo:

   digitalWrite(Salida,HIGH);
    delay(2500); 
    digitalWrite(Salida,LOW);
    delay(2500);

Ahora con un potenciometro, una entrada analógica y la función map voy a el valor 2500 entre los 1023 del potenciometro en la entrada.

Pero aquí el problema… No tuve en cuenta el detalle en que arduino no puede hacer dos cosas al mismo tiempo pero leyendo encontré esta técnica TIMESLICE. http://forum.arduino.cc/index.php?topic=257056.0

El código que hice hasta ahora esta asi:

#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#define I2C_ADDR    0x27
LiquidCrystal_I2C             lcd(I2C_ADDR,2, 1, 0, 4, 5, 6, 7);
unsigned long tiempo; //Variable para el control
unsigned long tiempo_max= 1000;
int Salida = 13;
int ahoras = 0;            //Variable a mostrar por LCD de las horas
int aminutos = 0;          //Variable a mostrar por LCD de los minutos
int asegundos = 0;         //Variable a mostrar por LCD de los segundos
int segundostotal = 0;     //Tiempo total
int pulStart = 7;            //Pulsador de arranque
int pulHora = 6;             //Pulsador de Horas
int pulMin = 5;             //Pulsador de Minutos
int pulSeg = 4;             //Pulsador de segundos
int varHora = 0;           //Variable para almacenar el valor del pulsador de horas
int varMin = 0;           //Variable para almacenar el valor del pulsador de minutos
int varSeg = 0;           //Variable para almacenar el valor del pulsador de segundos
int VAL = 0;

void setup()
{
  pinMode(pulHora, INPUT);     //Pin de pulsador de horas --> Entrada
  pinMode(pulMin, INPUT);     //Pin de pulsador de minutos --> Entrada
  pinMode(pulSeg, INPUT);     //Pin de pulsador de segundos --> Entrada
  pinMode(pulStart, INPUT);    //Pin de pulsador de arranque --> Entrada
  pinMode(Salida, OUTPUT);
  
  lcd.begin (16,2);    // Inicializar el display con 16 caraceres 2 lineas
  lcd.setBacklightPin(3,POSITIVE);
  lcd.setBacklight(HIGH);

  lcd.home ();                   // go home
  lcd.print("ELECTRO");
  lcd.setCursor ( 5, 1 );        // go to the 2nd line
  lcd.print("ESTIMULADOR");
  delay(3000);
  lcd.clear();
}

void loop()
{
  digitalWrite(Salida,LOW);
  varHora = digitalRead(pulHora);   //Leemos boton de horas
  varMin = digitalRead(pulMin);   //Leemos boton de minutos
  varSeg = digitalRead(pulSeg);   //Leemos boton de segundos

  if(varHora == HIGH)              //Si el boton ha sido pulsado, aumentamos las horas en una unidad
    {
      ahoras = ahoras + 1 ;
      delay(250);
    } 
      
    if(varMin == HIGH)            //Si el boton ha sido pulsado, aumentamos los minutos en una unidad
    {
      aminutos = aminutos + 1;
      if(aminutos == 60) 
      {
        aminutos = 0;
        ahoras = ahoras + 1;
      }
        delay(250);      
     } 
      
     if(varSeg == HIGH)            //Si el boton ha sido pulsado, aumentamos los segundos en una unidad
     {
       asegundos = asegundos + 1;
       if(asegundos == 60) 
       {
        asegundos = 0;
        aminutos = aminutos + 1;
       }
        delay(250);
      } 
            
  lcd.setCursor(0,0);
  lcd.print("Tiempo de Sesion");  //Muestra mensaje y las HH:MM:SS que vayamos aumentando
  lcd.setCursor(4,1);    


  if (ahoras < 10) lcd.print("0");    // Si las horas son menor que 10, pone un "0" delante.
  lcd.print(ahoras);                 // Sin este codigo, se muestra asi: H:M:S  (1:M:S)
  lcd.print(":");


  if (aminutos < 10) lcd.print("0");  // Si los minutos son menor que 10, pone un "0" delante.
  lcd.print(aminutos);               // Sin este codigo, se muestra asi: H:M:S  (H:1:S)


  lcd.print(":");
  if (asegundos < 10) lcd.print("0"); // Si los segundos son menor que 10, pone un "0" delante.
  lcd.print(asegundos);              // Sin este codigo, se muestra asi: H:M:S  (H:M:1)

 
  if(digitalRead(pulStart) == HIGH)
  {
    segundostotal = asegundos + (aminutos * 60) + (ahoras * 60 * 60);  //Convierte el tiempo elegido en segundos

    while (segundostotal > 0)
      {
        delay(1000);          //Descontamos en periodos de 1 segundo
        segundostotal--;    
  
        ahoras = ((segundostotal / 60)/ 60);   //Convertimos los segundos totales en horas
        aminutos = (segundostotal / 60) % 60;  //Convertimos los segundos totales en minutos
        asegundos = segundostotal % 60;        //Convertimos los segundos totales en periodos de 60 segundos

        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("Tiempo restante");        //Mostramos mensaje de tiempo restante

        lcd.setCursor(4,1);
        if (ahoras < 10) lcd.print("0");     // Si las horas son menor que 10, pone un "0" delante.
        lcd.print(ahoras);                   // Sin este codigo, se muestra asi: H:M:S  (1:M:S)
        lcd.print(":");


        if (aminutos < 10) lcd.print("0");   // Si los minutos son menor que 10, pone un "0" delante.
        lcd.print(aminutos);                 // Sin este codigo, se muestra asi: H:M:S  (H:1:S)


        lcd.print(":");
        if (asegundos < 10) lcd.print("0");  // si el valor de segundo esta por debajo de 9 (unidad) antepone un cero
        lcd.print(asegundos);                // Sin este codigo, se muestra asi: H:M:S  (H:M:1)
       
        oscilador();
        
        while(digitalRead(pulStart) == HIGH)
        {
          if(millis()-tiempo >= tiempo_max)
          {
            ahoras = 0;
            aminutos = 0;
            asegundos = 0;
            segundostotal = 0;
            lcd.clear();
            lcd.setCursor(5,0);
            lcd.print("RESET");
            delay(2000);
            goto salir;
          }
        }
        tiempo = millis();
          if (segundostotal == 0)            //Si finaliza el tiempo
          {                  
             {              
                  lcd.clear();
                  lcd.setCursor(5,0);
                  lcd.print("Sesion");
                  lcd.setCursor(3,1);
                  lcd.print("Finalizada");
                  delay(3000);
                  lcd.clear();
             }     
          }
      }
  }   
  salir:; 
}
  void oscilador()
  {
    digitalWrite(Salida,HIGH);
    delay(10); 
    digitalWrite(Salida,LOW);
    delay(10);
  }

Como verán uso un lcd con el módulo I2C, el pulsador de inicio al mantenerlo presionado sale del bucle while cuando esta contando y cuando se está seleccionando el tiempo resetea los valores a 0.

Intenté emular uno de los ejemplos encontrados de timeslice en donde se encendia leds en difenrentes tiempos pero el programa no funcionaba bien.

Asi como está descuenta solo 1 segundo cada 5 que el oscilador necesita como máximo.
Agradecería su ayuda por favor.

Eso lo escribí yo alla por el 2014 cuando venía con mi bagaje anterior.. ahora veo que lo mejor es usar máquinas de estados (descriptas en la sección Documentación)
Con una máquina de estados resuelves tu problema.

En tu caso TU ERROR es este:

 if(millis()-tiempo >= tiempo_max)
          {
            ahoras = 0;
            aminutos = 0;
            asegundos = 0;
            segundostotal = 0;
            lcd.clear();
            lcd.setCursor(5,0);
            lcd.print("RESET");
            delay(2000);
            goto salir;
          }

Si usas millis() no usas delay porque si tu dif millis()-tiempo ocurre durante este delay(2000) simplemente te quedas esperando 2 seg sin hacer nada.

Asi que una cosa es incomptabilible con la otra.

Mira el ejemplo (al comienzo de la sección) y puedes ver tmb el comentario en el post #14 que yo hago.

Estoy revisando la documentacion gracias, en cuanto al delay lo habia puesto para que en el diplay lcd se muestre ese mensaje por ese tiempo