Si además quieres enviarnos un Artículo para el Blog y redes sociales, pulsa el siguiente botón:
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 😀
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.
Me gusta tu idea, yo tengo un mando de play pero es inalambrico, de esos que conectas el receptor a la play y el mando no lleva cables 😀 que luces soy 😛
Nada me gustaria usar ese protocolo tambien para controlar alguno de mis enjendros, pero temo que aun no tengo el enjendro adecuado ni los conocimientos.
Alguna idea sobre que podria fabricar para controlar un bichejo?
Podrias poner como lo has hecho y que robot controlas?
Asi para poder hacerlo los demas y ver como trabaja.
Gracias
Luison, podrías bajar el tamaño de la foto?
Interesante el código.
jaba_ruben, El conector que va a la play será el mismo digo yo no?? (aunque no halla cable por medio)
S2
Ranganok Schahzaman
Luison, podrías bajar el tamaño de la foto?
Interesante el código.
jaba_ruben, El conector que va a la play será el mismo digo yo no?? (aunque no halla cable por medio)
S2
Ranganok Schahzaman
He minimizado... como he podido 🙄
Ese código lo hice hace tiempo, está bien que a alguien le interese.
Si tienes dudas sobre algo, pregúntame.
Contestando a jaba_ruben, todavía no tengo nada completamente construido porque me faltan piezas que ya tengo compradas... Podrías manejar un coche fácilmente... yo lo voy a utlizar para manejar un bípedo, así que como verás las posibilidades son infinitas. Te pongo una fotito (ya que me lo pides) de cómo conecto el mando de la play... uso la placa de inicialización de Basicx-24... le he añadido un LM1805 para alimentar al mando ya que no sé la corriente que pide y paso de quemar mi Basicx. En la foto se ve también mi emisor de radio, para manejar las cosas a distancia:
Como también me pides código... te paso el código que tengo hecho para el manejo de mi bípedo, ésto es TOP-SECRET, pero como mis "enemigos" no leerán éste post... 😉
' pin 10 --> DATA
' pin 7 --> Clk
' pin 8 --> COMAND
' pin 9 --> ATT
Public Obuff(1 To 12) As Byte ' 3 Bytes
Public Ibuff(1 To 10) As Byte ' 1 Byte, el mínimo
public DATA1(1 To 8) As Byte ' Lo que iremos reciviendo del mando[1-2]
public DATA2(1 To 8) As Byte
public COMAND(1 To 8) As Byte ' Lo que mandaremos al mando
public ESTADO(1 To 3) As Byte ' Estado actual y lo que mandaré vía radio
Public ESTADO_PAS(1 To 3) As Byte ' Estado anterior para comparar con actual
Public b As Byte
Public Sub Main()
b=0
Call PutPin(11, bxInputPullup) ' Configura los pines ACK y DATA como entradas en modo pull-up, con lo que me ahorro poner resistencias
Call PutPin(10, bxInputPullup)
Call PutPin(7,1) ' Dejo el reloj arriba
Call PutPin(9,1)
Call OpenQueue(Ibuff, 10)
Call OpenQueue(Obuff, 12)
Call DefineCom3(0, 6, bx0000_1000) ' lógica no invertida, sin paridad y 8bits de datos, sólo salida
Call OpenCom(3, 9600, Ibuff, Obuff)
Call Lee_mando()
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 Radio()
Dim z As String*4
' Dim comp1 As String*3
' Dim comp2 As String*3
' Dim ESTADO_2(1 To 3) As Byte
z=CStr(DATA2(1))&CStr(DATA2(2))&CStr(DATA2(3))&CStr(DATA2(4))
' z="0010"
if(z="1111") Then
ESTADO(1)=0 ' Andar [Nada]
elseIf(z="1011") Then
ESTADO(1)=1 ' Marcha atrás [R2]
elseIf(z="1010") Then
ESTADO(1)=2 ' Precisión [R2+R1]
elseif(z="1110") Then
ESTADO(1)=3 ' correr [R1]
elseIf(z="0111") Then
ESTADO(1)=4 ' xxxxxx[L2]
elseif(z="1101") Then
ESTADO(1)=5 ' xxxxxx[L1]
elseif(z="1100") Then
ESTADO(1)=6 ' Mov. Lateral [L1+R1]
elseif(z="0011") Then
ESTADO(1)=7 ' xxxxxx[L2+R2]
elseif(z="1000") Then
ESTADO(1)=8 ' Concurso correr 1,5m [L1+R1+R2]
elseif(z="0000") Then
ESTADO(1)=9 ' Concurso combate [L1+L2+R1+R2]
else
Goto Nada
End If
Accion:
z=CStr(DATA2(5))&CStr(DATA2(6))&CStr(DATA2(7))&CStr(DATA2(8))
if(z="1101") Then
ESTADO(2)=1 ' Pulsada X valida acción
elseif(z="1110") Then
ESTADO(2)=2 ' Pulsada [] --> xxxxx
elseif(z="1011") Then
ESTADO(2)=3 ' Pulsada 0 --> xxxxx
elseif(z="0111") Then
ESTADO(2)=4 ' Pulsada / --> xxxxx
else
ESTADO(2)=0 ' Para robot
End If
Direccion:
z=CStr(DATA1(5))&CStr(DATA1(6))&CStr(DATA1(7))&CStr(DATA1(8))
if(z="1111") Then
ESTADO(3)=0 ' Null
elseIf(z="0111") Then
ESTADO(3)=1 ' N
elseif(z="0011") Then
ESTADO(3)=2 ' NE
elseIf(z="1011") Then
ESTADO(3)=3 ' E
elseif(z="1001") Then
ESTADO(3)=4 ' SE
elseIf(z="1101") Then
ESTADO(3)=5 ' S
elseif(z="1100") Then
ESTADO(3)=6 ' SO
elseIf(z="1110") Then
ESTADO(3)=7 ' O
elseif(z="0110") Then
ESTADO(3)=8 ' NO
else
ESTADO(3)=0 ' No debería de llegar
End If
If ((ESTADO(1)=ESTADO_PAS(1)) AND (ESTADO(2)=ESTADO_PAS(2)) AND (ESTADO(3)=ESTADO_PAS(3))) Then
Goto Nada
Else
ESTADO_PAS(1)=ESTADO(1)
ESTADO_PAS(2)=ESTADO(2)
ESTADO_PAS(3)=ESTADO(3)
b=0
End If
Envia:
Call PutPin(25,0)
Call PutQueue(Obuff,ESTADO,3)
Call PutPin(25,1)
Nada:
b=b+1
if((b>1) AND (b<4)) Then ' Para enviar 3 veces cada cambio en el mando
Call PutPin(25,0)
Call PutQueue(Obuff,ESTADO,3)
Call PutPin(25,1)
End If
End Sub
Public Sub Lee_mando ()
Dim i As Byte
Dim r As String*8
do
Call PutPin(26,0) ' Apaga la luz roja... Más que nada para ver cuanto tardamos en leer el mando... 😉
Delay(0.005) ' Este será el tiempo cada cuanto leeremos el mando
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(1) ' 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)
DATA1(i)=GetPin(10)
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<>"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)
DATA1(i)=GetPin(10)
Next
Sleep(1)
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
DATA2(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 Radio()
Fin:
Call PutPin(9,1)
loop
End Sub
Lo que aparece como "xxxxx" son los movimientos "destructivos" 😈