Expresate

Si además quieres enviarnos un Artículo para el Blog y redes sociales, pulsa el siguiente botón:

Avisos
Vaciar todo

Código completo control mando Playstation

57 Respuestas
7 Usuarios
0 Reactions
34.6 K Visitas
luison
Respuestas: 495
Topic starter
(@luison)
Reputable Member
Registrado: hace 18 años

Bueno, hace casi dos días que empecé a programar en Basic, así que seguramente el código se pueda depurar bastante:
Creo que para controlar cualquier tipo de robot lo más indicado es un mando de play (por su sencillez de protocolo y por todos los botones que trae).
Hace dos días programé por primera vez en Basic y conseguí con todo éxito controlar servos mediante el SC32.
Ayer, como me aburría me fuí a comprar un mando de play guarripeich, después de una hora de cola para el cajero (de reloj) pagué mis 9,90 por el mando que es transparente (así es más "geek").
Una vez en casa me leí unos pequeños tutoriales de protocolo del mando de play (que están en éste mismo foro). Conecté el mando usando unas pequeñas piezas de plástico MUY comunes... no sé describirlos, pero es la hembra de las piezas metálicas que se usan para conectar cosas fácilmente en una placa... venga, subo foto que ni yo me entero 😀
dsc00287ca2fz0

Como iva diciendo la hembra de esas piezas se puede conectar "fácilmente" al mando, tan sólo apretar un poco (soy de Bilbao así que puede que sea un mucho 😉 ) y queda fijado bastante fuerte, luego tirando se pueden volver a quitar y así no rompemos el mando, sin comprar cable alargador ni nada 🙂 El mando lo alimenté con la propia fuente que trae mi estupendo-fantástico Basicx-24 y tampoco utilicé resistencia alguna. No conecté el cable de 9V ya que es para la vibración que no uso, y tampoco el cable ACK... jejej como veréis en el código hay trapicheo para solventar éste "problema".
En resumidas cuentas conecto directamente ATT, DATA, COMAND, CLK, VCC yGND.
Bueno, sin más dilación os pongo el código.

' pin 10 --> DATA
' pin 7 --> Clk
' pin 8 --> COMAND
' pin 9 --> ATT
Public Ibuff(1 To 10) As Byte
Public Obuff(1 To 60) As Byte
public DATA1(1 To 8) As Byte
public DATA2(1 To 8) As Byte
public DATA3(1 To 8) As Byte
public COMAND(1 To 8) As Byte

Public Sub Main()
Call PutPin(10, bxInputPullup) '' Configura el pin DATA como entradas en modo pull-up, con lo que me ahorro poner resistencias
Call PutPin(7,1) ' Dejo el reloj arriba
Call PutPin(9,1) ' Dejo la atención arriba NOTA: mientras está activa (abajo) el mando se bloquea
Call OpenQueue(Ibuff, 10)
Call OpenQueue(Obuff, 60)
Call OpenCom(1, 19200, Ibuff, Obuff)
Call Lee_mando()

End Sub

Public Sub Serial () ' Envía chorrazo enorme de datos, MUY poco eficiente, pero para verlo nosotros "bonito" en la pantalla está bien, si quieres usar un radio modem, por Dios COMPRIME! No puedes perder casi el 25% de la RAM en ésto. O sí 😉
Call PutQueuestr(Obuff, CStr(DATA1(1))&CStr(DATA1(2))&CStr(DATA1(3))&CStr(DATA1(4))&CStr(DATA1(5))&CStr(DATA1(6))
&CStr(DATA1(7))&CStr(DATA1(8))&Chr(13)&"Botones1:"&CStr(DATA2(1))&CStr(DATA2(2))
&CStr(DATA2(3))&CStr(DATA2(4))&CStr(DATA2(5))&CStr(DATA2(6))&CStr(DATA2(7))&CStr(DATA2(8))
&Chr(13)&"Botones2:"&CStr(DATA3(1))&CStr(DATA3(2))&CStr(DATA3(3))&CStr(DATA3(4))
&CStr(DATA3(5))&CStr(DATA3(6))&CStr(DATA3(7))&CStr(DATA3(8))&Chr(13)&Chr(10))
End Sub

Public Sub COM01()
COMAND(1)=1
COMAND(2)=0
COMAND(3)=0
COMAND(4)=0
COMAND(5)=0
COMAND(6)=0
COMAND(7)=0
COMAND(8)=0
End Sub

Public Sub COM42()
COMAND(1)=0
COMAND(2)=1
COMAND(3)=0
COMAND(4)=0
COMAND(5)=0
COMAND(6)=0
COMAND(7)=1
COMAND(8)=0
End Sub

Public Sub Lee_mando ()
Dim i As Byte
Dim r As String*8
do
Call PutPin(26,0) ' Enciende la luz verde... Más que nada para ver cuanto tardamos en leer el mando... 😉
Delay(3.0) ' Este será el tiempo cada cuanto leeremos el mando, lo ideal sería dejarlo en 0.1, pero para verlo por pantalla mejor así
Call PutPin(26,1)
Call PutPin(9,0) ' Llamada de atención
Call COM01() ' Comando de inicio
For i=1 To 8
Call PutPin(7,0) ' Bajo el reloj
If (COMAND(i)=0) Then ' Según COMAND se va introduciendo unos y ceros...
Call PutPin(8,0)
else
Call PutPin(8,1)
end if
Call PutPin(7,1) ' Subo el reloj
Next
Sleep(2) ' No detecto el ACK y así no uso interrupciones y me ahorro cableado :D.
Call COM42() ' Por contra, espero 4ms para asegurarme que el mando se ha enterado (se podría rebajar o incluso quitar) [Trapicheo 1]
For i=1 To 8
Call PutPin(7,0)
If (COMAND(i)=0) Then
Call PutPin(8,0)
else
Call PutPin(8,1)
end if
Call PutPin(7,1)
DATA1(i)=GetPin(10) ' Recojo el bit puesto por el mando
Next
r=CStr(DATA1(1))&CStr(DATA1(2))&CStr(DATA1(3))&CStr(DATA1(4))&CStr(DATA1(5))&CStr(DATA1(6))&CStr(DATA1(7))&CStr(DATA1(8))
If (r<>"10000010") then ' Miro si está en modo analógico o digital
goto Fin ' Sólo recogemos en un modo, ya que no necesitamos más precisión, si se usan los "Joysticks" el de la izquierda se
end if ' traducirá como las ocho direcciones del Pad y el de la derecha como el [],X,/,0 (lo hace el mando)
' No introduzco esperas (por lo del ACK) ya que hemos enredado un poco con operaciones y no hace falta...
For i=1 To 8
Call PutPin(7,0)
Call PutPin(7,1)
Sleep(1) ' Me aseguro con 2ms que el mando ha introducido ya bit (se podría eliminar)
DATA2(i)=GetPin(10)
Next
r=CStr(DATA2(1))&CStr(DATA2(2))&CStr(DATA2(3))&CStr(DATA2(4))&CStr(DATA2(5))&CStr(DATA2(6))&CStr(DATA2(7))&CStr(DATA2(8))
If (r<>"01011010") then ' Me aseguro de que todo vaya correctamente
goto Fin
end if

For i=1 To 8
Call PutPin(7,0)
Call PutPin(7,1)
DATA2(i)=GetPin(10)
Next
Sleep(2)
For i=1 To 8
Call PutPin(7,0)
Sleep(1) ' Ocurre un pequeño error si leo como antes, ya que el mando quita el bit nada más ver subir el reloj
DATA3(i)=GetPin(10) ' sólo en el último dato que se coja... no me voy a complicar y simplemente leo antes 😀 [Trapicheo 2]
Call PutPin(7,1) ' la espera de 2ms es para asegurarme que está el bit introducido
Next
call Serial()

Fin:
Call PutPin(9,1)

loop
End Sub

PS: Si éste código debería de ir en "proyectos" o en cualquier otra sección más generalista lo siento.

Responder
56 respuestas
luison
Respuestas: 495
Topic starter
(@luison)
Reputable Member
Registrado: hace 18 años

Hola de nuevo! he estado haciendo pruebitas con el mando, pero programandolo en c. He hecho unas especie de traduccion del código que dejaste y mirando la pág web, me ha costado, pero más o menos he conseguido entender el protocolo. Como no, el porbelma es que no me funciona el progerma, el probela principal es que no se como capturar bien el DATA. Os pongo a continuación el código que tengo hecho, de momento me da todo el rato el printf del final 0s, toy un poco hartita del cerito jeje. Bueno, si alguien le echa un poco paciencia y me puede ayudar le estría eternamente agradecida (por cierto, el mando va al puerto serie del ordenador para ver lo que nevía por el hyperterminal)
#include <16f876a>

#fuses HS,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT //ordenes para el programador
#use delay (clock=20000000) //Fosc=20Mhz
#use fast_io(b)
#use fast_io(C)
#use RS232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#define DATA PIN_B7
#define Clk PIN_B6
#define COMAND PIN_B5
#define ATT PIN_B4

static char Keypress;
static char Keypress_ant;
int8 Ibuff(10);
static int8 DATA1;
static int8 DATA2;
static int8 DATA3;
static int8 DATA4;
static int8 DATA5;
static int8 COMANDO;

int b=0;
static int8 i=0;
int r;
static int8 z;

void Serial(void);
void COM01(void);
void COM42(void);
void Lee_mando(void);
void Radio(void);
void Nada(void);

void main(void) {

disable_interrupts(global);
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);

port_b_pullups(TRUE);

output_high(CLK);
output_high(ATT);

Lee_mando();
}

void COM01(void)
{bit_set(COMANDO,0);
bit_clear(COMANDO,1);
bit_clear(COMANDO,2);
bit_clear(COMANDO,3);
bit_clear(COMANDO,4);
bit_clear(COMANDO,5);
bit_clear(COMANDO,6);
bit_clear(COMANDO,7);
}

void COM42(void)
{bit_clear(COMANDO,0);
bit_set(COMANDO,1);
bit_clear(COMANDO,2);
bit_clear(COMANDO,3);
bit_clear(COMANDO,4);
bit_clear(COMANDO,5);
bit_set(COMANDO,6);
bit_clear(COMANDO,7);
}

void Radio(void)
{
z=DATA1;

if(z==11110111)
{Keypress= 'w';
}
else{if(z==11111011)
{Keypress= 'd';
}
else{if(z==11111101)
{Keypress= 's';
}
else{if(z==11111110)
{Keypress= 'a';
}
else{
z=DATA2;

if (z==01111111)
{Keypress= 't';
}
else{if(z==10111111)
{Keypress= 'y';
}
else{if(z==11011111)
{Keypress= 'g';
}
else{if(z==11101111)
{Keypress= 'h';
}

else{Nada(); }

}
}
}
}
}
}
}
if(Keypress==Keypress_ant)
{Nada();
}
else
{Keypress_ant=Keypress;
b=0;
}

printf("%c",Keypress);
Nada();
}

void Nada (void)
{b=b+1;
if((b>=1)&(b<4))
{printf("%c",Keypress);
}
}

void Lee_mando(void)
{
while(1)
{delay_ms(5);
output_low(ATT);
COM01(); //bucle para el start
for(i=0;i<=7;i++)
{output_low(CLK);
if(bit_test(COMANDO,i)==0)
{output_low(COMAND);
}
else{output_high(COMAND);
}
output_high(CLK);
}
// printf("start");
delay_ms(5);
COM42(); //bucle para pedir datos
for(i=0;i<=7;i++)
{output_low(CLK);
if(bit_test(COMANDO,i)==0)
{output_low(COMAND);
}
else{output_high(COMAND);
}
output_high(CLK);
shift_right(DATA1,8,DATA); //para recoger modo a la vez que pedimos datos
}
delay_ms(5);
if (DATA1==0x41) //para ver que está en modo digital
{
for(i=0;i<=7;i++)
{output_low(CLK);
delay_ms(2);
if(input(DATA)==0)
{bit_clear(DATA1,i);
}
else{bit_set(DATA1,i);}
output_high(CLK);
}
delay_ms(5);
if(DATA1!=0x5A) //recibimos ahí va el dato del mando?
{output_high(ATT);
}

printf("/n va dato");

for(i=0;i<=7;i++) //si es que sí, recoger primer byte
{output_low(CLK);
if(input(DATA)==0)
{bit_clear(DATA1,i);
}
else{bit_set(DATA1,i);}
output_high(CLK);
}
// printf("/n%c",DATA1);
delay_ms(5);

for(i=0;i<=7;i++) //el segundo byte
{output_low(CLK);
if(input(DATA)==0)
{bit_clear(DATA2,i);
}
else{bit_set(DATA2,i);}
output_high(CLK);
}
delay_ms(5);
}

// else{
// output_high(ATT); //sino, cerrar comunicación
// }
Radio();
printf("/t%d",DATA1);

output_high(ATT);
}
}

Muchas gracias, y ayuda porfiiiiiiiiiiiiiiiiiiiiiii
Ésto ya es respuesta un pelín rebuscada:

¿Cómo has conectado el cable del que te vienen los datos??
Yo en mi Basicx24 lo configuraba como pull-up y así me evitaba resistencia que ES NECESARIA... con tu PIC haces también eso? Creo que no suelen dejar... Si no has puesto la resistencia de Pull-up (que no es más que una resistencia de 22K Aprox. a Vcc en la propia línea, no te irá... creo que hay más líneas que lo necesitan...

Responder
deirdre
Respuestas: 18
(@deirdre)
Active Member
Registrado: hace 17 años

Hola, ante todo gracias por responder siempre con tanta rapidez. Según la forma de programar si que he activado las pull-up, porque con la instrucción:
port_b_pullups(TRUE);
se activan, asi que en principio no debería necesitar nada más. Tengo conectado data, clock,att y command a I/Os del puerto B. Igual lo que está mal es que no debo activar todas las pull-up del puerto b?solo algunas?
El reloj que uso para el micro es de 20MHz, no se si eso también puede influir.
Espero haber respondido bien 😉

Responder
luison
Respuestas: 495
Topic starter
(@luison)
Reputable Member
Registrado: hace 18 años

No, no creo que sea problema de tu reloj... sólo DATA (y ACK que no usamos) deben tener la resistencia de Pull-up (según se ve en el esquema electrónico de la página que te pasé...). Si eso, vete probando poco a poco. Por ejemplo: cuando bajes la línea ATT, debería de "bloquearse" el mando de play si todo está bien, ésto lo comprobarás fácil si pulsas el botón "analog" (ese del centro). Generalmente, cuando analog es pulsado el mando cambia de modo (como habrás podido leer) y se ve porque enciende/apaga un led... si ATT está a nivel bajo NO lo hará... así por lo menos sabrás que estás "empezando" correctamente. Luego comprueba que cuando tú estás introduciendo el comando42 el mando te estará respondiendo a la vez... comprueba que eso hace bien, si no lo hace, entonces no prosigas e intenta averiguar el porqué...
Si crees que realmente vas muy rápido (por tu reloj) introduce un delay de 1ms entre cada cambio de reloj...

Comprueba que shift_right(DATA1,8,DATA) hace lo que debe, osea, que va metiendo los bits recogidos en orden por cada vuelta del bucle for (que yo diría que no, pero es que yo no programo en C para PIC's) y luego manda tú directamente DATA1, los 8 bits sin cambiar nada para ver qué tal vas.

Responder
deirdre
Respuestas: 18
(@deirdre)
Active Member
Registrado: hace 17 años

Creo que el probelma es que no leo bien el DATA, o puede ser incluso que no esté mandando bien el COMMAND, aunque eso creo que lo hago bien, porque el led rojo se paga/enciende cuando le doy al analog. Para mandar/recibir a la vez hago lo siguiente:
COM42(); //bucle para pedir datos
for(i=0;i<=7;i++)
{output_low(CLK);
if(bit_test(COMANDO,i)==0)
{output_low(COMAND);
}
else{output_high(COMAND);
}
if(input(DATA)==0)
{bit_clear(DATA1,i);
}
else{bit_set(DATA1,i);} //para recoger modo a la vez que pedimos datos
output_high(CLK);
}

He rpobado a cambiar el bajar el CLK a otras posiciones, pero nada. Seguiré intentando a ver

Responder
luison
Respuestas: 495
Topic starter
(@luison)
Reputable Member
Registrado: hace 18 años

Creo que el probelma es que no leo bien el DATA, o puede ser incluso que no esté mandando bien el COMMAND, aunque eso creo que lo hago bien, porque el led rojo se paga/enciende cuando le doy al analog. Para mandar/recibir a la vez hago lo siguiente:
COM42(); //bucle para pedir datos
for(i=0;i<=7;i++)
{output_low(CLK);
if(bit_test(COMANDO,i)==0)
{output_low(COMAND);
}
else{output_high(COMAND);
}
if(input(DATA)==0)
{bit_clear(DATA1,i);
}
else{bit_set(DATA1,i);} //para recoger modo a la vez que pedimos datos
output_high(CLK);
}

He rpobado a cambiar el bajar el CLK a otras posiciones, pero nada. Seguiré intentando a ver

Mandar parece que lo haces bien... pero como te dije haz paso a paso. Haz un programita que tan sólo baje el ATT y lo deje abajo, si realmente hace lo que debe el mando se bloquearía... mira que la alimentación del mando y de tu PIC tengan LA MISMA TIERRA, y si tienes polímetro mira si realmente ATT lo bajas a tierra también... paso a paso.

Responder
Página 6 / 12
Compartir: