Nueva clase Chronopic
- From: Juan González <juan iearobotics com>
- To: "For Chronojump developers (english, spanish)" <chronojump-devel-list gnome org>
- Subject: Nueva clase Chronopic
- Date: Thu, 26 Jan 2006 21:08:07 +0100
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]