Bucle incremental con secuencia de valores ajustados

Iniciado por VladisMSX1, 11 Mayo 2012, 18:25 PM

0 Miembros y 1 Visitante están viendo este tema.

VladisMSX1

Buenas gente. Tengo un pequeño problema lógico que me está rompiendo el cráneo.

He creado una función que recibe una serie de datos (canal, valor de inicio, valor final, duración) y con un bucle anidado envía los datos a otra función. El bucle anidado está pensado para seguir un intervalo regular, el bucle interior se repite 25 veces en un segundo, y el exterior se repite en función del número de segundos que quiera que dure el envío, y ese dato en segundos es el que le envio a la función.

La gracia está en que el número de envíos por segundo tiene que ser constante, 25 por segundo, pero el rango de valores (valor final - valor de inicio) puede ser cualquiera. Eso significa que tengo que repetir valores o quitarlos para que ajuste a esos 25 valores por segundo, de manera escalonada y continua (no puedo eliminar los valores sobrantes de golpe al principio o al final).

La sucesión de datos, para que lo entendáis, es para subir o bajar la cantidad de luz que un dimmer le entrega a un foco. Envia el dato cada vez que el bucle interior cumple un ciclo a la función conectar.

Os copio la función para que veais el lio que he montado:


int rampa(int canal, int valor_a, int valor_b, int duracion)                 //Función de rampa para un canal
       {
       int i;
       if ((canal<1) || (canal>512) || (valor_a<0) || (valor_b>255) || (valor_b<valor_a) || (valor_b>255) || (duracion<1))
          {
          system("cls");
          cout<<"ERROR - Numero de canal o valor indicado fuera de rango\nPulsa cualquier tecla para continuar...";
          getch();
          return 1;
          }
       else
           {
           int i, j, k, cont, cont_b=0, intervalo, valores_segundo_sin, valores_segundo_fijo, resta, resta_cont;
           intervalo=valor_b-valor_a;                                           //Intervalo de valores de la rampa
           valores_segundo_sin=intervalo/duracion;                              //numero de valores por segundo sin reducir a 25/s
           valores_segundo_fijo=25;                                             //numero de valores por segundo fijos
           resta=valores_segundo_sin - valores_segundo_fijo;                    //numero de valores a eliminar en un segundo
           cont=valor_a;                                                        //asignamos al contador el valor de inicio
           resta_cont=valores_segundo_sin/valores_segundo_fijo;                   //Cada cuantos valores se elimina uno en un segundo
           //Positivamos los valores resta para poder trabajar con ellos
           if (resta_cont<0)
              {
              //Aqui la variacion de añadir o quitar IMPORTANTE
              resta=resta*(-1);
              }
           if (resta<0)
              {
              resta=resta*(-1);
              }
           
           //ARRAY DE VALORES DE CANALES
           char valores[526];
           for (k=0; k<526; k++)
              {
              valores[k]=0;
              }
           //ARRAY DE SECUENCIA
           char secuencia[1];
           
           for (j=0; j<duracion; j++)//Este bucle dura la cantidad de segundos que se han ordenado
               {
               for (i=0; i<25; i++)//Este bucle dura exactamente 1 segundo y contiene 25 repeticiones
                   {
                   valores[canal-1]=cont;
                   secuencia[0]=secuencia[0]+1;
                   cont++;
                   cont_b++;
                   if (cont_b==resta_cont)
                      {
                      cont++;
                      cont_b=0;
                      }
                   if (secuencia[0]==255)
                      {
                      secuencia[0]=0;
                      }
                   conectar(valores, secuencia);

                   Sleep(40); //Pausa en ms para que el bucle dure 1s (1000ms / 25= 40ms)
                   }
               }
           return 0;
           }
       };


Me da dos problemas principalmente. El primero es que no recorre todo el rango de valores que le pido. Si le digo que vaya de 0 a 255, solo llega a enviar un tercio de los valores.

El segundo problema es que no cumple la pausa de 40ms. O no está bien especificado. Porque tarda muuuuuuuuuuuuuuuuuuuuuucho mas de los segundos que le especifico.

¿Debería enfocarlo todo de otra manera? ¿Que hago mal?

Gracias por la ayuda  :D

david_BS

lo de la pausa podés hacerlo con Sleep obviamente o con un contador también.
lo de los valores no lo miré realmente

una idea que hice recién sobre el contador puede ser así:

#include <windows.h>
#include <stdio.h>
#pragma comment (lib, "winmm.lib")
int rampa(int canal, int valor_a, int valor_b, float duracion){


double b_time = timeGetTime();
double n_time = 0;

if ((canal<1) || (canal>512) || (valor_a<0) || (valor_b>255) ||
(valor_b<valor_a) || (valor_b>255) || (duracion<1.0))
   {
return -1;
   }

else
{

//n_time = timeGetTime();

unsigned int ciclos=0;

while( ((n_time-b_time)) <= 40){

ciclos++;
printf("diff: %f\n",((n_time-b_time)));
printf("b_time: %f\n",b_time);
printf("n_time: %f\n",n_time);
printf("ciclos: %d\n",ciclos);
printf("======================\n");

for(unsigned int i=0; i<25; i++){

n_time = timeGetTime();
}

n_time = timeGetTime();
}
}

return 0;
}

int main(){


if(!rampa(2,2,2,2)) {

printf("Salida..\n");
return 0;
}

printf("...............\n");
while(getchar()!='\n');
return 0;
}



VladisMSX1

Gracias por la idea, no es mala idea el timer que dices, toma el tiempo del sistema así que supongo que es más estable que el sleep, que hasta donde se es un contador.

Pero mi mayor problema es el de los valores. Es un puzzle de miedo, obtener la cantidad de paquetes que hay que sustraer o añadir en un segundo para que de 25/s es fácil. Eliminarlos o duplicarlos, una vez que sabes cuantos son, me está volviendo loco. No se que hago mal pero he probado con varios planteamientos, jugando con los bucles y las operaciones con los contadores, pero no me funciona. Lo que más se le ha acercado es el código que he copiado en el primer mensaje y solo consigo llegar a un tercio de los valores, la rampa dura muchísimo mas de lo que tendría que durar, y si lo intento con rangos de valores pequeños ya es para morirse de risa.

Me estoy volviendo loco con esto. Con lo feliz que era yo programando web... :(

Alguna idea para el tema de los valores?

VladisMSX1

He seguido dándole vueltas y he cambiado algunas cosas sobre los valores. He puesto un escape para que cuando alcanza el valor tope del rango salga y no se vuelva majara el bucle, y he conseguido que según la duración salte valores o los repita (fijándome en el progreso de valores[canal-1] en comparación con el de secuencia[0], que siempre es fijo).

Pero los valores que quita o añade al rango para ajustarlo siguen siendo muy pocos con lo que la rampa sigue durando una barbaridad.

Copio el código con los arreglos que he hecho hasta ahora:


int rampa(int canal, int valor_a, int valor_b, int duracion)                 //Función de rampa para un canal
       {
       int i;
       bool rampa_ascendente;
       if ((canal<1) || (canal>512) || (valor_a<0) || (valor_b>255) || (valor_b>255) || (duracion<1))
          {
          system("cls");
          cout<<"ERROR - Numero de canal o valor indicado fuera de rango\nPulsa cualquier tecla para continuar...";
          getch();
          return 1;
          }
       else
           {
           int i, j, k, cont, cont_b, intervalo, valores_segundo_sin, valores_segundo_fijo, resta, resta_cont;
           if (valor_a<valor_b)                                                 //Intervalo de valores de la rampa
              {
              rampa_ascendente=true;                                            //Comprobamos si la rampa es ascendente o no
              intervalo=valor_b-valor_a;                                           
              }
           else
               {
               rampa_ascendente=false;
               intervalo=valor_a-valor_b;
               }
           
           valores_segundo_sin=intervalo / duracion;                            //numero de valores por segundo sin reducir a 25/s
           valores_segundo_fijo=25;                                             //numero de valores por segundo fijos
           resta=valores_segundo_sin - valores_segundo_fijo;                    //numero de valores a eliminar en un segundo
           cont=valor_a;                                                        //asignamos al contador el valor de inicio
           resta_cont=valores_segundo_fijo / resta;                             //Cada cuantos valores se elimina uno en un segundo
           //Positivamos los valores resta para poder trabajar con ellos
           if (resta_cont<0)
              {
              //Aqui la variacion de añadir o quitar IMPORTANTE
              resta_cont=resta_cont*(-1);
              }
           if (resta<0)
              {
              resta=resta*(-1);
              }
           
           //ARRAY DE VALORES DE CANALES
           char valores[526];
           for (k=0; k<526; k++)
              {
              valores[k]=0;
              }
           //ARRAY DE SECUENCIA
           char secuencia[1];
           secuencia[0]=0;
           
           //for (j=0; j<duracion; j++)//Este bucle dura la cantidad de segundos que se han ordenado
           j=0;
           cont=valor_a;
           cont_b=0;
           while ((j < duracion) || (cont != intervalo))
               {
               for (i=0; i<valores_segundo_fijo; i++)//Este bucle dura exactamente 1 segundo y contiene 25 repeticiones
                   {
                   if (cont!=intervalo)//Escape en caso de superar el valor final de la rampa
                      {i=valores_segundo_fijo;}
                   //Esta sería la secuencia de contadores y el envio para rampas ascendentes
                   if (rampa_ascendente==true)
                      {     
                       valores[canal-1]=cont;
                       secuencia[0]=secuencia[0]+1;
                       cont++;
                       cont_b++;
                       conectar(valores, secuencia);
                       if (cont_b==resta)
                          {
                          cont=cont++;
                          cont_b=0;
                          }
                       if (secuencia[0]==255)
                          {
                          secuencia[0]=0;
                          }
                       Sleep(10);
                       }
                   else
                   //Esta sería la secuencia de contadores y el envio para rampas descendentes
                       {
                       valores[canal-1]=cont;
                       secuencia[0]=secuencia[0]+1;
                       cont--;
                       cont_b++;
                       conectar(valores, secuencia);
                       if (cont_b==resta_cont)
                          {
                          cont--;
                          cont_b=0;
                          }
                       if (secuencia[0]==255)
                          {
                          secuencia[0]=0;
                          }
                       Sleep(10);
                       }                                             
                   }
               j++;
               }
           return 0;
           }
       };


Gracias por vuestro tiempo  ;D