Página 1 de 13

Software Captacion Datos (multi-Simuladores) + Arduino

Publicado: 15 Abr 2013 21:16
por Sito206
Hola a tod@s.

Estoy construyendo un software para captar, leer, recoger... todo los datos de los juegos de simulación de coches.

Por el momento llevo adelantado un poco, (empecé el viernes), y ya es compatible con 3 juegos (rFactor, rFactor2 y Live For Speed).

Os mostrare unas imágenes del software en cuestión.
[thumbnail]http://img42.imageshack.us/img42/8607/dsc2333v.jpg[/thumbnail]
Éste sería una captura (desde el móvil) con el rFactor de fondo, sé que los skin de los marcadores no son los mejores del mundo, pero quiero orientar este proyecto más a los Hardware que hay disponibles o que cada uno se puede hacer, en mi caso uso Arduino.

Esta sería la ventana principal, por ahora no está nada currada, iré cambiándola de aspecto sobre la marcha.
[thumbnail]http://img18.imageshack.us/img18/723/principaluix.jpg[/thumbnail]

La ventana de configuración de algunos parámetros, faltarían cosas como es obvio, pero como dije antes, sobre la marcha iría añadiendo más cosas.
[thumbnail]http://img20.imageshack.us/img20/818/configuracionj.jpg[/thumbnail]

Por último estaría el panel de mando, con el velocimetro, rpm, temperatura, etc...
[thumbnail]http://img191.imageshack.us/img191/2398 ... emando.jpg[/thumbnail]

Ahora estoy liado con el Dirt2/3 , pero lo dejaré para más adelante, ya que leer los paquetes de datos me está dando dolor de cabeza jaja, aún recuerdo cuando tuve el mismo problema con los paquetes de datos para scalextric.

Si alguien sabe algo sobre el tema de Dirt2/3 , y GTR que sé que este último usa la memoria compartida, no tengo problema por leer la memoria compartida, la cuestión es ( Con que nombre está guardado en la memoria compartida).

Acepto sugerencias y criticas constructivas :)

Un saludo, Alfonso.

Pincha para ir a la descarga InPutDataFisic V.0.0.0.4

Re: Construcción Software para todo los simuladores

Publicado: 16 Abr 2013 02:57
por Sito206
Bueno, parece que voy progresando...

Encontré las tramas del gtr2 en la memoria "MMF" de ahora en adelante.

Para los juegos de simbin, el nombre del MMF será el del juego entre el sombolo "$", para gtr2 en nuestro caso sería, $gtr2$ , esto no es del todo 100%, pero cuando lo pruebe en otros juegos de simbin lo confirmaré.

Ejemplo C#

Código: Seleccionar todo

MemoryMappedFile mmf = MemoryMappedFile.OpenExisting("$gtr2$");

Mañana explicaré más entendido la forma de obtener los datos , y cada cuantos byte hay que leer...etc..etc.

[thumbnail]http://img547.imageshack.us/img547/2739/datagtr2.jpg[/thumbnail]

Aquí podemos ver la marcha en la que estamos, esa trama se puede leer en el byte 88.

Bueno, mañana más y mejor.

Saludos, Alfonso.

Re: Construcción Software para todo los simuladores

Publicado: 17 Abr 2013 03:32
por Sito206
Hola :)

Ya añadí la mayoría de los datos , añadí también un juegos más, "Race 07".

Para usar un cuadro de mando, servos, led o cualquier otra forma de mostrar los datos por hardware os pongo un ejemplo en Arduino.

En mi caso este ejemplo lo hice con servos ( Los típicos de coches RC "Radio control" a 5V).

Código: Seleccionar todo

/*
Añadí toda las linea de comentario
el codigo lo explico para los que no entienden muy bien como "funciona" y que es cada "cosa", un buen codigo sin sus comentarios, no es un codigo completo ;)
Comentarios del codigo por : Alfonso carmona
*/
//Seccion de includes
#include <Servo.h>; //incluimos la libreria Servos.h

//Definimos las variables que vamos a utilizar de forma "Global"
int rpm; //variable tipo int
int Speed; //variable tipo int
Servo Speedserv; //variable de la clase Servo (obtiene las propiedades de la clase)
Servo Rpmserv; //variable de la clase Servo
Servo Aguaserv; //variable de la clase servo
Servo Oilserv; //variable de la clase servo
char comandos; // variable tipo char "caracter"
int serv = false; //variable tipo int, en otros lenguajes podriamos decir que seria una variable de tipo booleam ( true o false)
int PinFuel = 2;


//Funcion "setup", esta funcion es la que inicia las "opciones" de arduino, tales como los pines que queremos de "entrada", "salida", parametros a definir..etc..
void setup(){
Rpmserv.attach(3); //Le decimos que pin seleccionamos para el control
Speedserv.attach(9); //igual que el anterior
Aguaserv.attach(5); //igual que el anterior
Oilserv.attach(6); //igual que el anterior
pinMode(PinFuel, OUTPUT); //Ponemos el PinFuel "2" Como salida
Serial.begin(9600); //velocidad del puerto serie

}

//funcion "loop" de arduino, esta funcion se ejecuta continuamente , podemos decir que la funcion loop, es un "bucle infinito".
void loop()
{
  if(serv == false) // añadimos una sentencia "IF", solo se ejecuta una vez, ya que una vez entre en  "if", el valor de la variable "serv" pasara a ser "true"
  {
    //todo este codigo dentro del "if" es un teste de los componentes "cuadro de mando, servos, led...etc"
    digitalWrite(PinFuel, HIGH);//enciende el led
    delay(50);
    Rpmserv.write(175); //indicamo a la variable de clase "Servo" , con su metodo "write" que nos ponga el servo en la posicion ["175"(hablamos en grados)]
    delay(1); // con el metodo o funcion "delay()" le indicamos que para el proceso durante 1 milisegundo
    Speedserv.write(175); // al igual que la primera variable de la clase "Servo" indicamos con la funcion o metodo "write", que nos ponga el servo en la posicion ["175" (hablamos en grados)]
    delay(1); //otra vez ejecutamos la funcion o metodo "delay()"
    digitalWrite(PinFuel, LOW); //apaga el led
   
   serv = true;  //cambiamos el valor de la variable serv, a true
  } //cerramos la sentencia if
 
  while(Serial.available() > 0) // sentencia "while"( quiere decir "mientras"), en este caso, "mientras", Serial.available() no sea igual a "0" ( podriamos decir, que el while se ejecutara siempre que contenga datos
  {

    comandos = Serial.read(); // lee un caracter "char" y lo guarda en la variable comandos
    if (comandos == 'S' ) Read_Speed(); //sentencia "if", si la variable "comandos" es igual "==" a "S", ejecuta la funcion Read_Speed();
    if (comandos == 'R') Read_Rpm(); //sentencia "if", si la variable "comandos" es igual "==" a "R", ejecuta la funcion Read_Rpm();
    if (comandos == 'A') Read_Agua(); //sentencia "if", si la variable "comandos" es igual "==" a "A", ejecuta la funcion Read_Agua();
    if (comandos == 'O') Read_Oil(); //sentencia "if", si la variable "comandos" es igual "==" a "O", ejecuta la funcion Read_Oil();
    if (comandos == 'F') Read_Fuel(); //sentencia "if", si la variable "comandos" es igual "==" a "F", ejecuta la funcion Read_Fuel();
  //if (comandos == 'G') Read_Gear(); //sentencia "if", si la variable "comandos" es igual "==" a "G", ejecuta la funcion Read_Gear();
  } //fin de la sentencia "while"



} //fin de la funcion "loop"

void Read_Fuel()
{
 delay(2); //parada de 2 milesimas
int active = Serial.read() - 48; //lee del Serial

  if(active == 1) //en caso de que el valor sea igual a 1
  {
   digitalWrite(PinFuel, HIGH); //encendemos el led de reserva 
  }
  else //en caso contrario 
  {
  digitalWrite(PinFuel, LOW); //apagamos el led
  }

}//fin de la funcion Read_Fuel()

void Read_Speed() //funcion Read_Speed() esta funcion es la encargada de recoger los datos de "Speed",( la velocidad) y lo procesa
{
  delay(2); //delay de 2 milesimas
  int Speed100 = Serial.read() - 48; // lee el primer caracter "char"
  delay(2); //delay, ya lo explicamos, paramos el proceso durtante 2 milisegundo
  int Speed2 = Serial.read() - 48;// lee el segundo caracter "char"
  delay(2);//delay, ya lo explicamos, paramos el proceso durtante 2 milisegundo
  int Speed1 = Serial.read()- 48;// lee el tercer caracter "char"
  delay(2);//delay, ya lo explicamos, paramos el proceso durtante 2 milisegundo
  int Speed = 100*Speed100 + 10*Speed2 + Speed1; //hacemos un calculo con los datos recogidos, y los guardamos en la variable "Speed" 
  int cal2 = map(Speed, 0, 200, 170, 0); //funcion o metodo "map" los parametros para esta funcion o metodo son : map(Valor, Valor_minimo, valor_maximo, Servo_minimo, Servo_maximo), el resultado de dicha funcion o metodo, es calcular, en que posicion tiene que estar el "servo", calculando el "valor maximo que recibira" por el valor maximo del servo "175 grados en nuestro caso" para saber mas de esta funcion o metodo, busquen en la web de arduino
  Speedserv.write(cal2); // con la funcion o metodo write, añadimos el resultado que nos dio la funcion o metodo "map"( dando por resultado un valor de 0 a 170 grados)
} //fin de la funcion Read_Speed()

void Read_Rpm() //funcion Read_Rpm() esta funcion es la encargada de recoger los datos de "Rpm",( las Revoluciones por minutos) y lo procesa
{
  delay(2); //delay de 2 milesimas
  int Rpm1 = Serial.read() - 48; // lee el primer caracter "char"
  delay(2); //delay, ya lo explicamos, paramos el proceso durtante 2 milisegundo
  int Rpm2= Serial.read() - 48;// lee el segundo caracter "char"
  delay(2);//delay, ya lo explicamos, paramos el proceso durtante 2 milisegundo
  int Rpm3 = Serial.read()- 48;// lee el tercer caracter "char"
  delay(2);//delay, ya lo explicamos, paramos el proceso durtante 2 milisegundo
  int  Rpm = 1000*Rpm1 + 100*Rpm2 +10 Rpm3; //hacemos un calculo con los datos recogidos, y los guardamos en la variable "rpm" 
  int cal2 = map(Rpm, 0, 8000, 170, 0); //funcion o metodo "map" los parametros para esta funcion o metodo son : map(Valor, Valor_minimo, valor_maximo, Servo_minimo, Servo_maximo), el resultado de dicha funcion o metodo, es calcular, en que posicion tiene que estar el "servo", calculando el "valor maximo que recibira" por el valor maximo del servo "175 grados en nuestro caso" para saber mas de esta funcion o metodo, busquen en la web de arduino
  Rpmserv.write(cal2); // con la funcion o metodo write, añadimos el resultado que nos dio la funcion o metodo "map"( dando por resultado un valor de 0 a 170 grados)
} //fin de la funcion Read_Rpm()

void Read_Agua() //funcion Read_Agua() esta funcion es la encargada de recoger los datos de "Agua",( Temperatura ) y lo procesa
{
  delay(2); //delay de 2 milesimas
  int Agua1 = Serial.read() - 48; // lee el primer caracter "char"
  delay(2); //delay, ya lo explicamos, paramos el proceso durtante 2 milisegundo
  int Agua2= Serial.read() - 48;// lee el segundo caracter "char"
  delay(2);//delay, ya lo explicamos, paramos el proceso durtante 2 milisegundo
  int Agua3 = Serial.read()- 48;// lee el tercer caracter "char"
  delay(2);//delay, ya lo explicamos, paramos el proceso durtante 2 milisegundo
  int Agua = 100*Agua1 + 10*Agua2 + Agua3; //hacemos un calculo con los datos recogidos, y los guardamos en la variable "Agua" 
  int cal2 = map(Agua, 0, 130, 170, 0); //funcion o metodo "map" los parametros para esta funcion o metodo son : map(Valor, Valor_minimo, valor_maximo, Servo_minimo, Servo_maximo), el resultado de dicha funcion o metodo, es calcular, en que posicion tiene que estar el "servo", calculando el "valor maximo que recibira" por el valor maximo del servo "175 grados en nuestro caso" para saber mas de esta funcion o metodo, busquen en la web de arduino
  Aguaserv.write(cal2); // con la funcion o metodo write, añadimos el resultado que nos dio la funcion o metodo "map"( dando por resultado un valor de 0 a 170 grados)
} //fin de la funcion Read_Agua()

void Read_Oil() //funcion Read_Oil() esta funcion es la encargada de recoger los datos de "Oil",( Temperatura) y lo procesa
{
  delay(2); //delay de 2 milesimas
  int Oil1 = Serial.read() - 48; // lee el primer caracter "char"
  delay(2); //delay, ya lo explicamos, paramos el proceso durtante 2 milisegundo
  int Oil2= Serial.read() - 48;// lee el segundo caracter "char"
  delay(2);//delay, ya lo explicamos, paramos el proceso durtante 2 milisegundo
  int Oil3 = Serial.read()- 48;// lee el tercer caracter "char"
  delay(2);//delay, ya lo explicamos, paramos el proceso durtante 2 milisegundo
  int Oil = 100*Oil1 + 10*Oil2 + Oil3; //hacemos un calculo con los datos recogidos, y los guardamos en la variable "Oil" 
  int cal2 = map(Oil, 0, 130, 170, 0); //funcion o metodo "map" los parametros para esta funcion o metodo son : map(Valor, Valor_minimo, valor_maximo, Servo_minimo, Servo_maximo), el resultado de dicha funcion o metodo, es calcular, en que posicion tiene que estar el "servo", calculando el "valor maximo que recibira" por el valor maximo del servo "175 grados en nuestro caso" para saber mas de esta funcion o metodo, busquen en la web de arduino
  Oilserv.write(cal2); // con la funcion o metodo write, añadimos el resultado que nos dio la funcion o metodo "map"( dando por resultado un valor de 0 a 170 grados)
} //fin de la funcion Read_Oil()
Saludos, Alfonso.

Re: Construcción Software para todo los simuladores

Publicado: 17 Abr 2013 20:18
por Sito206
Hola a todos.

Hoy vengo de la mano de "Grid", no es un simulador, más bien un arcade, pero para gusto los colores, y mientras se pueda sacar "chicha" del juego lo incluyo :lengua:

Por el momento saqué la Velocidad, y la marcha, estoy intentando buscar la trama de las RPM, a ver si hoy doy con ella...Decir que cuanta con 150 paquetes , el 132 sería la marcha, y el 100 sería la velocidad, para sacar x,y,z será una locura :pillepalle: , pero algo se podrá hacer.

Ejemplo en c# (por si a alguien le interesa )

Código: Seleccionar todo

int received = Ventanas.socket.Receive(buffer); //Ventanas es una clase statica, en la cual guardo "datos" para acceder desde cualquier parte del código
                    if (received > 0) // sentencia de comparación "if" digamos que si hay datos, se cumple (received es mayor a 0)
                    {
                        
                        byte[] data = new byte[received]; //Creamos en un array de byte con el tamaño recibido 
                        Buffer.BlockCopy(buffer, 0, data, 0, received); //copiamos el buffer 
                        Velocidad = (float)((System.BitConverter.ToSingle(data, 100)) * 3.6); //cogemos nuestro paquete "100" de los almacenados en data y lo pasamos a float ( eso si lo multiplicamos por 3.6, ya que el valor devuelto está en metros / segundo)
                        Gear = (float)(System.BitConverter.ToSingle(data, 132)); //más de lo mismo pero con la marcha
                       

                    }

Bueno, ahora toca una imagen :

[thumbnail]http://img594.imageshack.us/img594/3594/dsc2335g.jpg[/thumbnail]

Y por ahora esto es todo, yo sigo con esto, una vez saque toda las tramas, el Dirt2, Dirt3 y demás juegos de la compañía Codemaster estarán incluidos de inmediato :P

Saludos, Alfonso.

Re: Construcción Software para todo los simuladores

Publicado: 17 Abr 2013 21:31
por RAYBACK
sito, grandisimo curro colega.... :aplausoup: :aplausoup: :aplausoup:
una pregunta:
¿es solo para arduino?
serviria para xrdisplay?

gracias un saludo.

Re: Construcción Software para todo los simuladores

Publicado: 17 Abr 2013 22:14
por Sito206
Hola RayBack.

No tendría ningún problema en crear una clase para el xrdisplay, solo me haría falta una cosa, saber las tramas que tendría que mandar al xrdisplay , si sabes en que lugar del foro están esos datos, lo añado sin problemas.

Un saludo :)

Re: Construcción Software para todo los simuladores

Publicado: 18 Abr 2013 14:49
por RAYBACK
pues sinceramente no tengo ni idea de como va, solo se donde esta el software que se hizo para el display pero como va, no se nada de nada
Esta muy bien poder utilizarlo para tantos juegos aunque algunos sean arcade y otros simuladores pero asi tener un rango mas amplio para el display.
Si alguien puede ayudar y decir como va pues....bien agradecido.
Un saludo.
Rayback

Re: Construcción Software para todo los simuladores

Publicado: 18 Abr 2013 15:41
por Sito206
Leí al respecto en el foro, pero no dicen claramente que forma utilizaron al final.
<displays izqda(4)><display central(1)><displays dcha(4)><estado leds(4)><estado grupos leds(2)><estado puntos(3)>

Por ejemplo:

08001pit27FFF00200

displays izda:

0800

display central:

1

displays dcha:

pit2

tira de leds:

7FFF -> 111111111111111 (los 15 leds encendidos)

grupos de leds:

0 -> 0000 y 0 -> 0000, apagados todos.

estado de los puntos

2->0010, 0->0000 y 0->0000. En el grupo de 4 de la izquierda está activo el tercer punto, con lo que quedaría 080.0

En el display aparecerá algo así (la firma de Ernesto):
Sí fuese éste lo haría sin problemas, si alguien lo puede confirmar, o el autor.

Eso sí, no sé si al autor le molestara que lo añada :scratchchin:

Si alguien me lo corrobora, hoy mismo lo añadiría

Saludos, Alfonso.

Re: Construcción Software para todo los simuladores

Publicado: 18 Abr 2013 15:45
por Vojvoda
Antes de tocar nada del display XR te recomiendo que le envies un mp o correo a Gaboni consultandoselo, entre otros proyectos está trabajando en integrar el GDXR a su aplicación original.

Re: Construcción Software para todo los simuladores

Publicado: 18 Abr 2013 15:56
por Sito206
Gracias Vojvada.

Ya le envíe un mp como me comentaste ya que el e-mail parece que no lo tiene ya.

A la espera de la respuesta de Gaboni, hoy iré al desguace a por un cuadro de mandos, de un civic a poder ser, para añadirlo junto con arduino.

Saludos, Alfonso.

Re: Construcción Software para todo los simuladores

Publicado: 18 Abr 2013 17:19
por Sito206
Bueno.

Estoy sacando aún las tramas de datos del Grid (Dirt2/Dirt3...Codemaster vamos).

Hice un programa para tal fin, si alguien quiere ayudar, cuelgo el programa para que pueda ayudar :wink:

[thumbnail]http://img209.imageshack.us/img209/8643/lectura.jpg[/thumbnail]

Los datos obtenidos hasta el momento son ( # -> Descripción)
8 -> Metros recorridos
20 -> Distancia hasta la meta
116 -> Solo marca cuando se acelera
120 -> Izquierda/derecha , los valores estaría comprendidos entre -1 y 1
124-> Solo marcha cuando se pulsa frenar ( estaría bien para encender unas luces de frenos... )
100 -> Velocidad en metros por segundo
132 -> Marcha actual ( la marcha atrás sería "9", y no como en otros juegos que daría un valor negativo "-1")

Un saludo, Alfonso.

Re: Construcción Software para todo los simuladores

Publicado: 18 Abr 2013 21:09
por Sito206
Bueno, parece ser que las RPM, no vienen en los datos , es una pena.

Saque estos datos en total.

Grid de codemaster, será lo mismo para sus otros juegos

0 -> Tiempo global
4-> Tiempo por vuelta
8-> Metros recorridos
12 -> Vueltas ( vueltas que hemos dado )
16-> Aún no lo sé
20-> Distancia de la meta
24-> Aún no lo sé
28-> Velocidad ( hay unos cuantos de la velocidad)
32-> Velocidad orientación
36 -> Aún no lo sé
40,44,48,52,46,60,64,68,72,76 -> Aún no lo sé, pero tiene que ver con la orientación o fuerza
80-> Izquierda derecha ( la fuerza )
84,88,92,96 -> Aún no lo sé
100 , 104, 108, 112 -> Velocidad
"Esto son referente a los controles"
116 -> Acelerador (0 mínimo , 1 máximo) flotante
120 -> Izquierda derecha ( valores "izquierda maximo 1", "derecha maximo -1", "centro 0" ) flotantes
124 -> Freno (0 mínimo, 1 máximo ) flotante
"fin de controles"
128-> neutro (1 neutro puesto, 0 neutro no puesto), para una luz de neutro va bien.
132-> marchas ( de 0 a 6, sería de Neutro a sexta, "9" sería marcha atrás)
136,140 -> Aún no lo sé


Esto es todo por el momento.

Saludos, Alfonso

Re: Construcción Software para todo los simuladores

Publicado: 19 Abr 2013 11:23
por Sito206
Hola.

Pensando un poco :scratchchin: , llegué a la conclusión de que lo mejor es que haga un programa algo más dinámico , a lo que hardware se refiere.

Mi idea es crear una carpeta Plugins, en la cual todos puedan hacer sus propias "dll", para los diferentes tipos de hardware, bien para arduino u otros, éste último lo haré yo.

Por el momento es solo una idea, pero hoy mismo la intentaré implementar, con ello conseguiremos que cada cual se pueda hacer sus "Dll" y hacer funcionar sus dispositivos sin tener que esperar a "terceros", ( a mi en este caso jajaja).

Cuando tenga algo prefijado, actualizaré el primer post con la información ( argumentos, funciones, etc ).

Un saludo, Alfonso.

Re: Construcción Software para todo los simuladores

Publicado: 19 Abr 2013 11:34
por Vojvoda
A mi me gustaría que este soft fuera similar al Simview/Simtools, yo lo uso bastante, utilizando de segundo monitor el portátil conectado por red.

Imagen

Re: Construcción Software para todo los simuladores

Publicado: 19 Abr 2013 18:10
por Kenzo
El que comenta Kiko también es buena idea, este que comoneto yo ahora también no seria mala idea y mas si puedes configurarlo como deseas.
Imagen
Imaganes Varias
También si se pudiera usar algún tipo de display algo más grande que el gdxr ya que por salida de vídeo consume muchos más recursos, seria la leche.

Muy buen trabajo

Re: Construcción Software para todo los simuladores

Publicado: 19 Abr 2013 19:16
por Sito206
Hola.

Vojvoda ya estoy trabajando en un visor externo "Cliente", para recibir los datos por lan.

[thumbnail]http://img405.imageshack.us/img405/9041/visorq.jpg[/thumbnail]

Lo dejado sin terminar que fui a comprar un cuadro de mandos :lengua:

Kenzo , eso es un plugins, ¿cierto?. ¿Dices de hacer otro?, ¿o añadir uno parecido al software?.

Unas imágenes del cuadro en cuestión ( De un volvo S40 )
[thumbnail]http://imageshack.us/a/img580/5856/dsc2337e.jpg[/thumbnail]

[thumbnail]http://imageshack.us/a/img4/2875/dsc2336d.jpg[/thumbnail]

Un saludo, Alfonso.

Re: Construcción Software para todo los simuladores

Publicado: 20 Abr 2013 02:44
por Sito206
Hola.

Voy avanzando en todo los campos jaja.

Dejo un vídeo de lo que estoy haciendo ahora mismo :disimulo:



Tengo que ir mañana a la tienda de electrónica, me faltan unos L293, y creo que ya :oks:

El código del ejemplo es muy simple "Arduino"

Código: Seleccionar todo

void setup()
{
  pinMode(4, OUTPUT);
  pinMode(2, OUTPUT);
}
void loop()
{
  digitalWrite(4, HIGH);
  for(int i =0; i<255;i++)
  {
  analogWrite(3, i);
  delay(50);
  }
  digitalWrite(4, LOW);
  digitalWrite(2, HIGH);
analogWrite(3, 255);
  delay(100);
  digitalWrite(2, LOW);
}
Saludos, Alfonso.

Re: Construcción Software para todo los simuladores

Publicado: 20 Abr 2013 15:43
por Kenzo
Sito206 escribió: Kenzo , eso es un plugins, ¿cierto?. ¿Dices de hacer otro?, ¿o añadir uno parecido al software?.
Plugin son todos claro., la idea ya sea por lan o por algún otro tipo de sistema es hacer lo como comentas por "sofware" incluso que se pudiera diseñar uno propiamente sus plantillas.
Es una sugerencia, esta claro que todo se puede hacer pero el trabajo es mucho.

Si a nivel gráfico quieres que te echen una mano y tal, no dudes en comentármelo, ayudar siempre es bueno.

Gracias por el trabajo :)

Re: Construcción Software para todo los simuladores

Publicado: 22 Abr 2013 01:22
por Sito206
Pues si, cada cual puede hacer su propia ventana para recoger los datos, cuando termine la que estoy haciendo e implemente las funciones, diré como paso los datos, y quien quiera se puede hacer la suya perfectamente. :wink:

Dejo un adelanto del cuadro , y dejo el código de arduino para el control.

Código: Seleccionar todo

/*
Añadí toda las linea de comentario
el codigo lo explico para los que no entienden muy bien como "funciona" y que es cada "cosa", un buen codigo sin sus comentarios, no es un codigo completo ;)
Comentarios del codigo por : Alfonso carmona
*/

int rpm; //variable tipo int
char comandos; // variable tipo char "caracter"
int velocidad_anterior = 0;

//Funcion "setup", esta funcion es la que inicia las "opciones" de arduino, tales como los pines que queremos de "entrada", "salida", parametros a definir..etc..
void setup(){
  pinMode(4, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT); 
Serial.begin(38400); //velocidad del puerto serie
digitalWrite(4, LOW);
digitalWrite(2, LOW);
digitalWrite(8, LOW);
digitalWrite(7, LOW);

}

//funcion "loop" de arduino, esta funcion se ejecuta continuamente , podemos decir que la funcion loop, es un "bucle infinito".
void loop()
{
 
  while(Serial.available() > 0) // sentencia "while"( quiere decir "mientras"), en este caso, "mientras", Serial.available() no sea igual a "0" ( podriamos decir, que el while se ejecutara siempre que contenga datos
  {

    comandos = Serial.read(); // lee un caracter "char" y lo guarda en la variable comandos
 if (comandos == 'S') Read_Speed(); //sentencia "if", si la variable "comandos" es igual "==" a "G", ejecuta la funcion Read_Gear();
  } //fin de la sentencia "while"



} //fin de la funcion "loop"



void Read_Speed() //funcion Read_Speed() esta funcion es la encargada de recoger los datos de "Speed",( la velocidad) y lo procesa
{
  delay(1); //delay de 2 milesimas
  int Speed100 = Serial.read() - 48; // lee el primer caracter "char"
  //delay(1); //delay, ya lo explicamos, paramos el proceso durtante 2 milisegundo
  int Speed2 = Serial.read() - 48;// lee el segundo caracter "char"
  //delay(1);//delay, ya lo explicamos, paramos el proceso durtante 2 milisegundo
  int Speed1 = Serial.read()- 48;// lee el tercer caracter "char"
  int Speed = 100*Speed100 + 10*Speed2 + Speed1; //hacemos un calculo con los datos recogidos, y los guardamos en la variable "Speed" 
 Control_Velocimetro(Speed);
} //fin de la funcion Read_Speed()

void Control_Velocimetro(int valor)
{
  if(valor > 0 && valor <= 40)
  {
    digitalWrite(2, LOW);
    digitalWrite(7, HIGH);
    analogWrite(10, 255);
    digitalWrite(8, LOW);
     digitalWrite(4, HIGH);
    analogWrite(3, map(valor, 0, 40, 0, 255));
  }

  if(valor >40 && valor <= 80)
  {
    digitalWrite(8 , LOW);
    digitalWrite(4, HIGH);
    digitalWrite(2, LOW);
    digitalWrite(7, HIGH);
    analogWrite(10, map(valor, 40, 80, 255, 0));
   
  }
  
if(valor >80 && valor <= 140)
{
digitalWrite(7, LOW);
digitalWrite(2, LOW);
digitalWrite(4, HIGH);
analogWrite(3, 255);
digitalWrite(8, HIGH);
analogWrite(10, map(valor, 80, 140, 0, 255));
}

if(valor >140 && valor <= 190)
{
  digitalWrite(2, LOW);
    digitalWrite(7, LOW);
  digitalWrite(8, HIGH);
  analogWrite(10, 255);
digitalWrite(4, HIGH);
analogWrite(3, map(valor, 140, 190, 255, 0));
}

if(valor >190 && valor <= 230)
{
  digitalWrite(4, LOW);
  digitalWrite(7, LOW);
  digitalWrite(8, HIGH);
   analogWrite(10, 255);
digitalWrite(2, HIGH);
analogWrite(3, map(valor, 190, 230, 0, 255));
}

if(valor >230 && valor <= 260)
{
  digitalWrite(4, LOW);
  digitalWrite(7, LOW);
  digitalWrite(2, HIGH);
digitalWrite(8, HIGH);
analogWrite(10, map(valor, 230, 260, 255, 130));

}
}




Saludos, Alfonso.

Re: Construcción Software para todo los simuladores

Publicado: 23 Abr 2013 00:30
por Sito206
Bueno..

Me voy a tener que pillar un arduino mega, ya que el actual que poseo, (arduino uno) se queda corto de salidas, y solo podría poner rpm y velocimetro.

Para mañana espero colgar ya el código para el "cliente" de lectura de datos, y terminar el mio claro jaja.

[thumbnail]http://img21.imageshack.us/img21/963/dsc2342k.jpg[/thumbnail]

Seguiré haciendo pruebas, por el momento parece un software estable, en unos días podré colgarlo.

Saludos, Alfonso.

Re: Construcción Software para todo los simuladores

Publicado: 25 Abr 2013 10:02
por mundocapi
Hola Sito206, yo dispongo de un arduino mega una placa lkm1638 y un display 1602
puedo hacer algo con esto?
ya que nunca supe como hacerlos funcionar?
Saludos

Re: Construcción Software para todo los simuladores

Publicado: 25 Abr 2013 22:13
por Sito206
Hola mundocapi.

Claro que puedes!, en internet mirando la conexión tanto al display como a la placa lkm1638, puedes montar lo que "quieras ", si no tienes mucha idea, pregunta y sin ningún problema te ayudo a montarlo.

En el tema "código" del arduino sería hacer las funciones de lecturas "general" (digamos que son las que leen los datos del software), y las "propias" ( las que hacen funcionar los componentes que usemos).

Fácil en principio.

Un saludo.

Re: Construcción Software para todo los simuladores

Publicado: 28 Abr 2013 09:28
por mundocapi
Por fin lo he podido hacer funcionar, aunque parece bastante simple, solo mide la velocidad y indica el cambio de marcha
La conexion es muy sencilla, como se muestra en esta imagen:

[img]http://2.bp.blogspot.com/-eVwgZju8N0U/U ... rduino.jpg[/img]

Enlace con el codigo arduino y pluing rfactor y rfactor2 http://www.mediafire.com/?dajj29ijk8bo5d8

El codigo es el siguiente:
#include <TM1638.h>

TM1638 module(8, 7, 9);

word leds [17] = {0, 256, 768, 1792, 3840, 7936, 16128, 32512, 65280, 1, 3, 7, 15, 31, 63, 127, 255};

String inputString = ""; // a string to hold incoming data
boolean stringComplete = false; // whether the string is complete
boolean affichage_speed;
boolean affichage_pneu;
boolean affichage_time;
int MillisStartBlink;
boolean blink_rpm;



struct Telemetrie
{
String Gear;
String Speed;
String RPM;
String RPM_Max;
String TPneu_Av_G;
String TPneu_Av_D;
String TPneu_Ar_G;
String TPneu_Ar_D;
String CurrentTime;
String LastTime;
};

typedef struct Telemetrie Telem;
Telem iTelemetrie;

void setup() {

Serial.begin(115200);
module.setupDisplay(true, 1);
module.clearDisplay();
inputString.reserve(200);
affichage_speed=true;
}

void loop()
{
// print the string when a newline arrives:
if (stringComplete) {

ParsingBuffer(inputString); // on decoupe la chaine de caractere en valeurs uniques

if (module.getButtons() == 0b00000001) // 1er bouton gauche affiche gear et speed
{
affichage_speed=true;
affichage_pneu=false;
affichage_time=false;
module.clearDisplay();
}
/* else if (module.getButtons() == 0b00000010) // 2nd bouton gauche affiche temperatures
{
affichage_speed=false;
affichage_pneu=true;
affichage_time=false;
module.clearDisplay();
}

else if (module.getButtons() == 0b000000100) // 3eme bouton gauche affiche temps
{
affichage_speed=false;
affichage_pneu=false;
affichage_time=true;
module.clearDisplay();
}*/

Affichage_LCD();

// clear the string:
inputString = "";
stringComplete = false;
}
}


void serialEvent() {
while (Serial.available()) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the inputString:
inputString += inChar;

// if the incoming character is a newline, set a flag
// so the main loop can do something about it:
if (inChar == '\n') {
stringComplete = true;
}
}
}

void ParsingBuffer(String Str_Parse)
{
//XX;XXX;XXXXX;XXXXX;XXX;XXX;XXX;XXX;XX:XX:XX;XX:XX:XX\n
//Gear;Speed;Rpm;RpmMax;TPneuAvG;TPneuAvD;TPneuArG;TPneuArD;CurrentLap;LastLap\n

int pos_n=0;

//on supprime le \n en fin de chaine
pos_n=Str_Parse.indexOf('\n');
Str_Parse = Str_Parse.substring(0,pos_n);

//Gear
pos_n=Str_Parse.indexOf(';');
String str_tmp = Str_Parse.substring(0,pos_n);

if (str_tmp == "-1") {iTelemetrie.Gear = "R";}
else if (str_tmp == "0") {iTelemetrie.Gear = "-";}
else if (str_tmp == "-2") {iTelemetrie.Gear = "";}
else {iTelemetrie.Gear = str_tmp;}

//On supprime les char de gear de la str de travail
Str_Parse = Str_Parse.substring(pos_n+1,Str_Parse.length());

//Speed
pos_n=Str_Parse.indexOf(';');
str_tmp = Str_Parse.substring(0,pos_n);
iTelemetrie.Speed = str_tmp;

//On supprime les char de gear de la str de travail
Str_Parse = Str_Parse.substring(pos_n+1,Str_Parse.length());

//RPM
pos_n=Str_Parse.indexOf(';');
str_tmp = Str_Parse.substring(0,pos_n);
iTelemetrie.RPM = str_tmp;

//On supprime les char de gear de la str de travail
Str_Parse = Str_Parse.substring(pos_n+1,Str_Parse.length());

//RPM_Max
pos_n=Str_Parse.indexOf(';');
str_tmp = Str_Parse.substring(0,pos_n);
iTelemetrie.RPM_Max = str_tmp;

//On supprime les char de gear de la str de travail
Str_Parse = Str_Parse.substring(pos_n+1,Str_Parse.length());

//Temp pneu av gauche
pos_n=Str_Parse.indexOf(';');
str_tmp = Str_Parse.substring(0,pos_n);
iTelemetrie.TPneu_Av_G = str_tmp;

//On supprime les char de gear de la str de travail
Str_Parse = Str_Parse.substring(pos_n+1,Str_Parse.length());

//Temp pneu av droit
pos_n=Str_Parse.indexOf(';');
str_tmp = Str_Parse.substring(0,pos_n);
iTelemetrie.TPneu_Av_D = str_tmp;

//On supprime les char de gear de la str de travail
Str_Parse = Str_Parse.substring(pos_n+1,Str_Parse.length());

//Temp pneu av droit
pos_n=Str_Parse.indexOf(';');
str_tmp = Str_Parse.substring(0,pos_n);
iTelemetrie.TPneu_Ar_G = str_tmp;

//On supprime les char de gear de la str de travail
Str_Parse = Str_Parse.substring(pos_n+1,Str_Parse.length());

//Temp pneu av droit
pos_n=Str_Parse.indexOf(';');
str_tmp = Str_Parse.substring(0,pos_n);
iTelemetrie.TPneu_Ar_D = str_tmp;

//On supprime les char de gear de la str de travail
Str_Parse = Str_Parse.substring(pos_n+1,Str_Parse.length());

//Current Time
pos_n=Str_Parse.indexOf(';');
str_tmp = Str_Parse.substring(0,pos_n);
iTelemetrie.CurrentTime= str_tmp;

//On supprime les char de gear de la str de travail
Str_Parse = Str_Parse.substring(pos_n+1,Str_Parse.length());

//Last Time
pos_n=Str_Parse.indexOf(';');
str_tmp = Str_Parse.substring(0,pos_n);
iTelemetrie.LastTime= str_tmp;
}


void Affichage_LCD ()
{
int NbLed;

if (affichage_speed==true)
{

module.setDisplayToString(" "+iTelemetrie.Gear+" ",0,0);

char carray_Speed[iTelemetrie.Speed.length() + 1]; //determine size of the array
iTelemetrie.Speed.toCharArray(carray_Speed, sizeof(carray_Speed)); //put readStringinto an array
int int_Speed = atoi(carray_Speed); //convert the array into an Integer

if (int_Speed < 10)
{
module.clearDisplayDigit(4,false);
module.clearDisplayDigit(5,false);
module.clearDisplayDigit(6,false);
module.setDisplayToString((String)int_Speed,0,7);
}
else
if (int_Speed < 100)
{
module.clearDisplayDigit(4,false);
module.clearDisplayDigit(5,false);
module.setDisplayToString((String)int_Speed,0,6);
}
else
{
module.clearDisplayDigit(4,false);
module.setDisplayToString((String)int_Speed,0,5);
}
}

if (affichage_pneu==true)
{
module.setDisplayToString(iTelemetrie.TPneu_Av_G+iTelemetrie.TPneu_Av_D+iTelemetrie.TPneu_Ar_G+iTelemetrie.TPneu_Ar_D,0b01010101);
}

if (affichage_time==true)
{
module.setDisplayToString("CL "+iTelemetrie.CurrentTime,0b00010100);
}

//Affichage en barre du RPM
// Transformation string en int
char carray_RPM[iTelemetrie.RPM.length() + 1]; //determine size of the array
iTelemetrie.RPM.toCharArray(carray_RPM, sizeof(carray_RPM)); //put readStringinto an array
int int_RPM = atoi(carray_RPM); //convert the array into an Integer

char carray_RPM_Max[iTelemetrie.RPM_Max.length() + 1]; //determine size of the array
iTelemetrie.RPM_Max.toCharArray(carray_RPM_Max, sizeof(carray_RPM_Max)); //put readStringinto an array
int int_RPM_Max = atoi(carray_RPM_Max); //convert the array into an Integer

if ((int_RPM > 0)) //&& (int_RPM_Max > int_RPM))
{
float rapport;

if (int_RPM > int_RPM_Max) { rapport=1;}
else
{ rapport= ((float)int_RPM / int_RPM_Max); }

rapport = rapport/(0.95);
NbLed = rapport*16;
}
else NbLed=0;

if (NbLed== 16 ) {
if ((millis() - MillisStartBlink) > 75){
if (blink_rpm== false)
{
module.setLEDs(leds[0x0000]);
blink_rpm= true;
}
else
{
module.setLEDs(leds[NbLed]);
blink_rpm= false;
}
MillisStartBlink = millis();
}
} else module.setLEDs(leds[NbLed]);
}
Un video del resultado:


Tengo varias preguntas:
Los leds suben progresivamente y parpadean a maximas revoluciones en color verde
Se podria hacer que los dos o tres ultimos cambiasen a rojo y a maximas revoluciones todos parpadeasen en rojo?

Los botones de la placa lkm1638 se podrian utilizar como botones del juego?

Y por ultimo y lo que mas me interesa es si se podria utilizar el softwar que estas desarrollando Imputdatafisic con el lkm1638 ya que me parece mucho mas completo

Saludos

Re: Construcción Software para todo los simuladores

Publicado: 28 Abr 2013 16:17
por Sito206
Hola, y enhorabuena :aplausoup:

Vamos por parte.

¿Se podría hacer que los dos o tres últimos cambiasen a rojo y a máximas revoluciones todos parpadeasen en rojo?

Si que se puede, no tengo dicho modulo, pero leyendo por internet encontré algo de información sobre su librería.
setLED()

Esta sentencia nos permite establecer el color de un diodo:
setLED(color, posicion)
Con 'color' controlamos el color que queremos mostrar, pondremos 'TM1638_COLOR_GREEN' para mostrar el diodo verde y 'TM1638_COLOR_RED' para mostrar el diodo rojo.
Para elegir que led es de cada color, usaremos 'pos', siendo un dato tipo byte, con valores válidos de '0' a '7'.
module.setLED(TM1638_COLOR_GREEN + TM1638_COLOR_RED, 3);
Este código en principio, enciende el led 3 y lo pone verde y rojo, pero en realidad, el rojo se come al color verde, por lo que solo se ve rojo.
TM1638_COLOR_GREEN y TM1638_COLOR_RED, en realidad son números, así que si no queremos tener que estar poniendo todo esto, si queremos que luzca rojo, podemos poner directamente un '1'1 y si queremos que luzca verde un '2'. module.setLED(TM1638_COLOR_GREEN , 3)
module.setLED(2,3)

setLEDs()

Esta sentencia hace lo mismo que el anterior, pero controlando a la vez el encendido/apagado y el color de todos los dios a la vez.
setLEDs(diodos)
El argumento 'diodos' es una palabra de 16 bits. Utiliza los 8 bits de mayor valor para encender o apagar el color verde, y los 8 de menos valor para el color rojo.
Ejemplo:
Si queremos encender de color rojo el diodo 1 el 3 y el 4, de verde el 2, el 6, el 7 y el 8, y dejar el 5 apagado, escribiríamos lo siguiente:
module.setLEDs(0b1110001000001101)






Analizamos el número:

8 bits de mayor valor (verde):

11100010
El primer bit (el de mayor valor) enciende el diodo 8 y el último deja sin verde el led1


8 bits de menos valor (rojo):

00001101 El primero deja sin rojo el diodo 8 y enciende de rojo el led1
El link Referencia librería TM1638/TM1640

¿Los botones de la placa lkm1638 se podrían utilizar como botones del juego?

También se puede, ya que lo que hace es leer el estado del botón, y arduino podría mandarlo al software para que lo interprete , siendo el botón "X", para entrar poner el limitador de velocidad por ejemplo.

¿se podría utilizar el software que estas desarrollando Imputdatafisic con el lkm1638 ya que me parece mucho mas completo?

Sí, se puede utilizar sin ningún problema, ya que el hardware principal o de comunicación es el arduino.

Solo tendrías que añadir este código a tu arduino.
char comandos; // variable tipo char "caracter"

void setup()
{
Serial.begin(115200); //velocidad del puerto serie
}

//funcion "loop" de arduino, esta funcion se ejecuta continuamente , podemos decir que la funcion loop, es un "bucle infinito".
void loop()
{
while(Serial.available() > 0) // sentencia "while"( quiere decir "mientras"), en este caso, "mientras", Serial.available() no sea igual a "0" ( podriamos decir, que el while se ejecutara siempre que contenga datos
{

comandos = Serial.read(); // lee un caracter "char" y lo guarda en la variable comandos
if (comandos == 'S') Read_Speed(); //sentencia "if", si la variable "comandos" es igual "==" a "G", ejecuta la funcion Read_Gear();
if (comandos == 'R') Read_Rpm();
} //fin de la sentencia "while"



} //fin de la funcion "loop"


void Read_Rpm()
{
delay(1);
int Rpm1000 = Serial.read() - 48; // lee el primer caracter "char"

int Rpm100 = Serial.read() - 48;// lee el segundo caracter "char"

int Rpm10 = Serial.read()- 48;// lee el tercer caracter "char"
int Rpm1 = Serial.read() -48;

int Rpm = 1000*Rpm1000 + 100*Rpm100 + 10*Rpm10 + Rpm1;

//Control_Rpm(Rpm); aquí iría tu función remplazando la mía "Control_Rpm"
}



void Read_Speed() //funcion Read_Speed() esta funcion es la encargada de recoger los datos de "Speed",( la velocidad) y lo procesa
{
delay(1); //delay de 2 milesimas
int Speed100 = Serial.read() - 48; // lee el primer caracter "char"
//delay(1); //delay, ya lo explicamos, paramos el proceso durtante 2 milisegundo
int Speed2 = Serial.read() - 48;// lee el segundo caracter "char"
//delay(1);//delay, ya lo explicamos, paramos el proceso durtante 2 milisegundo
int Speed1 = Serial.read()- 48;// lee el tercer caracter "char"
int Speed = 100*Speed100 + 10*Speed2 + Speed1; //hacemos un calculo con los datos recogidos, y los guardamos en la variable "Speed"
Control_Velocimetro(Speed); //aquí igual
} //fin de la funcion Read_Speed()
Solo tendrías que reemplazar las funciones Control_Velocimetro y Control_Rpm, por las funciones que tu estés usando.

Si tienes cualquier duda, me lo comunicas e intentaremos darle solución.

Saludos

Re: Construcción Software para todo los simuladores

Publicado: 28 Abr 2013 16:38
por Sito206
Perdón, se me olvido poner un ejemplo para el tema de los leds.
mundocapi escribió: Los leds suben progresivamente y parpadean a máximas revoluciones en color verde
Se podría hacer que los dos o tres últimos cambiasen a rojo y a máximas revoluciones todos parpadeasen en rojo?
Tu ejemplo sería éste para tu caso.

module.setLEDs(0b0001111111100000)

87654321 -> desde el led 8 al led 1
00011111 -> 0 Apagado 1 encendido , esto son los 8 primeros valores , para encender los verdes

87654321 -> Desde el led 8 al led 1
11100000 -> 0 Apagado 1 encendido, esto son los 8 valores restantes , para encender los rojos

Esto haría que todos los leds estén en verdes, menos los 3 últimos que estarían en rojo

Si aún así no lo terminas de entender, me lo dices y te lo explico por privado .

Un saludo