Nueva clase Chronopic



Hola,

  Ya Tengo una primera versión de la nueva clase Chronopic, que accede
al puerto serie utlizando las librerías de mono.

  Adjunto el código (Chronopic.cs) y un programa de pruebas para mostrar
el tiempo de vuelo (muy similar al chronojump-mini).

  Xavi, pruébalo y si te funciona bien adapta el Chronojump-mini a la
nueva clase. Así te familiarizas con la nueva interfaz. Han cambiado
algunas cosillas.

  No he implementado control de errores, de manera que si se le pasa un
puerto serie erróneo, la clase peta.

  Lo he probado todo con el cable usb-serie


  Para compilar:

$ gmcs test-saltos.mono.cs chronopic.cs
 

-- 
Juan González Gómez
juan iearobotics com
www.iearobotics.com
--------------------------------------------------------------
- Yo también quiero una Europa libre de Patentes de Software -
--------------------------------------------------------------
 EuropeSwPatentFree - http://EuropeSwPatentFree.hispalinux.es 
--------------------------------------------------------------

/**********************************************/
/* chronopic.cs        Juan Gonzalez Gomez.   */
/*--------------------------------------------*/
/* Licencia GPL                               */
/**********************************************/

using System;
using System.IO.Ports;
using System.Threading;

public class Chronopic {

   //****************************
   //  TIPOS PUBLICOS
   //****************************
   public enum ErrorType
   {
     Ok = 0,        //-- OK. No hay error
     Timeout = 1,   //-- Error por Timeout
     Invalid = 2,   //-- Error por recibir caracter invalido
   }
   
   //-- Estado de la plataforma
   public enum Plataforma : int
   {
     ON = 1,
     OFF = 0,
     UNKNOW = -1,
   }

   //******************************
   //  CONSTRUCTORES Y DESTRUCTORES
   //******************************
  
   //-- Constructor
   public Chronopic(SerialPort sp)
   {
     //-- Comprobar si puerto serie ya estaba abierto
     if (sp != null)
			if (sp.IsOpen)
				sp.Close();
  
     //-- Abrir puerto serie
     sp.Open();
     
     //-- Configurar timeout por defecto
     sp.ReadTimeout = DefaultTimeout;
     
     //-- Guardar el puerto serie
     this.sp = sp;
     
     //-- Vaciar buffer
     this.flush();
   }

   //-- Destructor
   ~Chronopic()
   {
     //-- Cerrar puerto serie
     sp.Close();
   }

   //***************************************
   //  METODOS PUBLICOS
   //***************************************
   
   //--------------------------------------------------
   //-- Leer un evento en Chronopic
   //-- Devuelve:
   //--   * timestamp : Marca de tiempo
   //--   * plataforma: Nuevo estado de la plataforma
   //--------------------------------------------------
   public bool Read_event(out double timestamp, 
                          out Plataforma plataforma)
   {
     double t;
     
     //-- Trama de Evento
     byte[] trama = new byte[5];
     bool ok;
     
     //-- Esperar a que llegue la trama o que se
     //-- produzca un timeout
     ok = Read_cambio(trama);
     
     //-- Si hay timeout o errores
     if (ok==false) {
       plataforma = Plataforma.UNKNOW;
       timestamp = 0.0;
       return false;
     }
     
     //-- Comprobar que el estado transmitido en la trama es correcto
     //-- El estado de la plataforma solo puede tener los valores 0,1
     if (trama[1]!=0 && trama[1]!=1) {
       //-- Trama erronea
       plataforma = Plataforma.UNKNOW;
       timestamp = 0.0;
       return false;
     }
     
     //-- Actualizar el estado
     if (trama[1]==0)
       plataforma = Plataforma.OFF;
     else 
       plataforma = Plataforma.ON;
       
     //-- Obtener el tiempo
     t = (double)((trama[2]*65536 + trama[3]*256 + trama[4])*8)/1000;
     
     timestamp = t;
     
     return true;
   }   
   
   //----------------------------------------
   //-- Obtener el estado de la plataforma
   //----------------------------------------
   public bool Read_platform(out Plataforma plataforma)
   {
     //-- Crear la trama
     byte[] trama = {(byte)Trama.Estado};
     byte[] respuesta = new byte[2];
     int n;
     int count;
     bool status;
    
     //-- Enviar la trama por el puerto serie
     sp.Write(trama,0,1);
     
     //-- Esperar a que llegue la respuesta
     //-- Se espera hasta que en el buffer se tengan el numero de bytes
     //-- esperados para la trama. (para esta trama 2). Si hay un 
     //-- timeout se aborta
     count=0;
     do {
       n = sp.Read(respuesta,count,2-count);
       count+=n;
     } while (count<2 && n!=-1);
    
     //-- Comprobar la respuesta recibida
		 switch(count) {
       case 2 : //-- Datos listos
         if (respuesta[0]==(byte)Trama.REstado) {
           switch (respuesta[1]) {
             case 0: 
               plataforma = Plataforma.OFF;
               this.error=ErrorType.Ok;
               status=true;
               break;      
             case 1: 
               plataforma = Plataforma.ON;
               this.error=ErrorType.Ok;
               status=true;
               break;      
             default:
               plataforma = Plataforma.UNKNOW;
               this.error=ErrorType.Invalid;
               status=false;
               break;
           }
		     }
		     else {  //-- Recibida respuesta invalida
           plataforma = Plataforma.UNKNOW;
		       this.error=ErrorType.Invalid;
		       status=false;
		      
		       //-- Esperar un tiempo y vaciar buffer
		       Thread.Sleep(ErrorTimeout);
		       this.flush();
		     }
		     break;
       default : //-- Timeout (u otro error desconocido)
         status=false;
         plataforma = Plataforma.UNKNOW;
	       this.error=ErrorType.Timeout;
	    	 break;
     }
     
     return status;
   }

   /****************************/
   /* PROPIEDADES              */
   /****************************/
   public ErrorType Error 
   {
     get {
       return this.error;
     }
   }

   //***************************************
   //  METODOS PRIVADOS
   //***************************************
   //-- Esperar a recibir una trama de cambio de estado
   private bool Read_cambio(byte[] respuesta)
   {
     //-- Crear la trama
     int n;
     int count;
     bool status;
    
     //-- Esperar a que llegue la respuesta
     //-- Se espera hasta que en el buffer se tengan el numero de bytes
     //-- esperados para la trama. (En el caso de id son 4). Si hay un 
     //-- timeout se aborta
     count=0;
     do {
       n = sp.Read(respuesta,count,5-count);
       count+=n;
     } while (count<5 && n!=-1);
    
     //-- Comprobar la respuesta recibida
     switch(count) {
       case 5 : //-- Datos listos
         if (respuesta[0]==(byte)Trama.Evento) {  //-- Trama de evento
           this.error=ErrorType.Ok;
           status=true;
         }
         else {  //-- Recibida trama invalida
           this.error=ErrorType.Invalid;
           status=false;
          
           //-- Esperar un tiempo y vaciar buffer
           Thread.Sleep(ErrorTimeout);
           this.flush();
         }
         break;
       default : //-- Timeout (u otro error desconocido)
         status=false;
         this.error=ErrorType.Timeout;
         break;
     }
      
    return status;
  }
   
   //-- Vaciar buffer de entrada
   //-- De momento se hace leyendo muchos datos y descartando
   private void flush()
   {
     byte[] buffer = new byte[256];
    
     sp.Read(buffer,0,256);
   }
  
  /**********************************/
  /* TIPOS PRIVADOS                 */
  /**********************************/
  //-- Identificacion de las tramas
  private enum Trama
  {
    Evento =  'X',  //-- Trama de evento
    Estado =  'E',  //-- Trama de solicitud de estado
    REstado = 'E',  //-- Trama de respuesta de estado
  }
  
  /*********************************************************************/
  /* CONSTANTES PRIVADAS                                               */
  /*********************************************************************/
  private const int DefaultTimeout = 100;  //-- En ms 
  private const int ErrorTimeout   = 500;  //-- En ms
  
  //------------------------------
  //   Propiedades privadas
  //------------------------------
  //-- Puerto serie donde esta conectada la Chronopic
  private SerialPort sp;
  //-- Ultimo error que se ha producido
  private ErrorType error = ErrorType.Ok;
 
}
/***********************************************************/
/* test-saltos.mono    Juan Gonzalez Gomez. Febrero 2005   */
/*---------------------------------------------------------*/
/* Medir el tiempo de vuelo de los saltos                  */
/* Licencia GPL                                            */
/***********************************************************/

using System;
using System.IO.Ports;

class Test {
  
  //-- Estado del automata
  enum Automata {
    ON,
    OFF
  }
  
  /**********************/
  /* PROGRAMA PRINCIPAL */
  /**********************/
  public static void Main()
  {
    Chronopic.Plataforma estado_plataforma;
    Automata estado_automata;  
    SerialPort sp;
    double timestamp;
    double toff;
    bool ok;
    
    //-- Crear puerto serie		
		sp = new SerialPort("/dev/ttyUSB0");
    
    //-- Abrir puerto serie. Si ocurre algun error
    //-- Se lanzara una excepcion
    try {
      sp.Open();
    } catch (Exception e){
       Console.WriteLine("Error al abrir puerto serie");
       Console.WriteLine(e);
       Environment.Exit(1);
    }
    
    //-- Crear objeto chronopic, para acceder al chronopic
    Chronopic cp = new Chronopic(sp);
    
    //-- Obtener el estado inicial de la plataforma
    ok=cp.Read_platform(out estado_plataforma);
    if (!ok) {
      //-- Si hay error terminar
      Console.WriteLine("Error: {0}",cp.Error);
      System.Environment.Exit(-1);
    }
    Console.WriteLine("Plataforma: {0}",estado_plataforma);
    
    //-- Establecer el estado inicial del automata
    if (estado_plataforma==Chronopic.Plataforma.ON) 
      estado_automata=Automata.ON;
    else {
      Console.WriteLine("Suba a la plataforma para realizar el salto");
      
      //-- Esperar a que llegue una trama con el estado de la plataforma
      //-- igual a ON. Esto indica que el usuario se ha subido
      do {
        ok = cp.Read_event(out timestamp, out estado_plataforma);
      } while (!ok);
      
      //-- Se han subido a la plataforma
      estado_automata = Automata.ON;
    }
    
    Console.WriteLine("");
    Console.WriteLine("Puede saltar cuando quiera");
    Console.WriteLine("Pulse control-c para finalizar la sesion");
    Console.WriteLine("-----------------------------------------"); 
    
    while(true) {
      //-- Esperar a que llegue una trama
      do {
        ok = cp.Read_event(out timestamp, out estado_plataforma);
      } while (ok==false);
       
      //-- Segun el estado del automata
      switch(estado_automata) {
      
        case Automata.OFF: //-- Usuario estaba en el aire
        
          //-- Si ha aterrizado
          if (estado_plataforma==Chronopic.Plataforma.ON) {
          
            //-- Pasar al estado ON
            estado_automata=Automata.ON;
            
            //-- Registrar tiempo de vuelo
            toff = timestamp;
            
            //-- Imprimir informacion
            Console.WriteLine("Tiempo de vuelo: {0:f1} ms",toff);
          }
          break;
          
        case Automata.ON: //-- Usuario estaba en la plataforma
        
          //-- Si ahora esta en el aire...
          if (estado_plataforma==Chronopic.Plataforma.OFF) {
            
            //-- Pasar al estado OFF
            estado_automata=Automata.OFF;
          }
          break;
      } 
    } 
  }
}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]