Você está na página 1de 16

ConectandooJoystickdoPS2SemFioaoPIC16F877a

(Parte2)Desenvolvimento
Depois de algum tempo do primeiro post mostrando a
comunicao entre um controle sem fio de Playstation 2 e um
microcontrolador PIC e de vrios pedidos dos visitantes do blog,
estou retomando o assunto. Neste artigo estou utilizando o PIC
modelo PIC16F877a para a comunicao, mas o cdigo pode
facilmente ser migrado para outro microcontrolador da famlia PIC
deacordocomasnecessidadesdoseuprojeto.

Noprimeiropost,mostreiumpequenovdeocomofuncionamentodocircuitoproposto.Agoravamos

mostrarcomofazlo.

Nofoipossvelcarregaroplugin.

AntesdemaisnadavamosconhecerosdetalhesdeumjoystickutilizadopeloPlayStation2.

OJoystickdoPS2:
Bom, este controle fantstico dispensa maiores apresentaes a respeito de sua jogabilidade. Com
seus16botesdigitaiseseusdoisjoysticksanalgicos,podeserasoluoperfeitaedebaixocusto
paramuitosprojetosnasreasdamecatrnica.

ExistemaindanomercadodiversoscontrolescompatveisMadeinChinaquebarateiamaindamais
nosso projeto e funcionam perfeitamente. No posso afirmar que todos os modelos disponveis
funcionemcomestemtodo,entretanto,todosasqueeutesteifuncionaramepartindodopressuposto
dequeelesfuncionamnoconsole,devemtambmfuncionaraqui.

Como citei a pouco, este circuito funciona tanto com o controle com fio quanto com o sem fio. J
encontreinainternetartigosfeitosparacontrolescomfioqnofuncionamcomcontrolessemfio.Este
artigofoibaseadosnestesemodificadoparaoperartambmcomoscontrolessemfio.Omudaentre
elesotempoentreasduasleiturasdocontrole.Seotempoforgrande,ocontrolesemfioperdea
comunicaoenovolta.
Comoocontrolesemfiodmuitomaisliberdadeaoprojeto,almdesermuitomaislegal,voubasear
todooartigoneles.Casoqueirautilizarumcontrolecomfio,bastafazlo.

APinagemdoconector
OconectordoJoystickdoPS2possuinovepinosconformeafiguraabaixo.Nelaobservamosopadro
decoresutilizadopeloscontrolescomfiooriginaisdaSony,casoseucontrolepossuacoresdiferentes,
guiesepeloconector,claro,antesdecortarosfios!rs

DescriodosPinosdoconectormachodoJoystickdoPlayStation2
Pino
Descrio
Corpadro
1
Data(dados)
Marrom
2
Command(Comandos)
Laranja
3
Vibrationmotorpower(Vibrao)
Cinza
4
GND(Terra)
Preto
5
Power(Alimentao3,3Vcc5Vcc)
Vermelho
6
Att(Ateno)
Amarelo
7
Clock(Pulsosdesincronismo)
Azul
8
NoUtilizado
Branco
9
Acknoledge(Reconhecimento)
Verde

1Data:

SinalenviadodocontroleparaoPlaystation.

EsteEstesinalumatransmissoserialde8bitssincronizadocomosinaldopinodeclockporbanda
dedescida.EstesinalcontmarespostaaosinalCommand.

Este pino uma sada em coletor aberto e necessita de um resistor de pullup (1 110k). Esta
resistncia necessria porque o controle s pode conectar este pino terra, ento ela se faz
necessriaparagarantironvellgico1.

2Command:

SinalenviadodoPlaystationparaocontrole.
umatransmissoserialde8bits,tambmsincronizadocomopinodeclock.Eleserutilizadopara
estabelecer a comunicao entre o controle e o nosso pseudo console, solicitando as informaes
necessriasconformeveremoslogo.
3Vibrationmotorpower:
SinalenviadodoPlaystationparaocontrole.
Esta funo no est implementada neste artigo, mas atravs deste pino podemos fazer o controle
vibrar.Particularmenteaindanotesteiestafuno.
4GND:
Terminalderefernciaparaosdemaissinaisalmdaalimentaodocircuito.
5Power3,3V5V:
SinalenviadodoPlaystationparaocontrole.
Tensodealimentaodocontroleou,nonossocaso,dotransmissorsemfiodocontrole.Algumas
literaturas informam que os controles genricos sem fio s funcionam com 3,3V, nos meus testes
funcionaram com 5 V normalmente. As mesmas literaturas informam que os controles originais
funcionamcomqualquertensoentre3,3Ve5V.
6Att:
Sinalenviadodoconsoleparachamaraatenodocontrole.
Estesinalpermaneceemnvellgicobaixoduranteatransmisso.
7Clock(250kHz500kHz):
SinalenviadodoPlaystationparaocontrole.
UtilizadoparamantersincroniaentreoPlaystationeocontrole.

8Noutilizado.
9ACK(Acknoledge):
SinalenviadodocontroleparaoPlaystation.
Estesinaldeveirparanvellgicozero,porpelomenosumpulsodeclockdepoisdecadaumdos8
bits enviado e ATT mantida em nvel lgico zero. Se o Sinal de ACK no for para nvel lgico zero
dentrodecercade60uS,oPlaystationcomeaainteragircomoutrosdispositivos.
Paraonossoprojetonoprecisamosnospreocuparcomestesinal,vamosapenasignorlo.
Revisandonovamentenossoconector,verificamosqueseroutilizadosemnossoprojetoosseguintes
sinais:

Comunicao
DuranteoestudodossinaisencontreinositeCuriousinventorumaleituraemtemporealdossinaisde
transmisso realizada com um osciloscpio. Nela podemos observar exatamente como se combinam
todos os sinais. O texto informa que est uma leitura real entre um Playstation e uma Guitarra do
GuitarHero.

Fonte:Curiousinventor
Simplistamente,acomunicaoentreoPlaystationeocontroleocorredaseguintemaneira:
1. Oconsoleenviaumsinalparaidentificarseocontroleestconectado
2. Ocontrolerespondeaestesinaleacomunicaoestabelecida
3. Emseguidaoconsolesolicitaosdadosdocontrole
4. O controle, ento, envia o estado de todos os botes naquele momento e aguarda nova
solicitao.

Agora,commaisdetalhes,vamosvercomofuncionaestacomunicao:

QuandooPlaystationquerlerinformaesdeumcontrole,primeiramentesetaosinalATTpara
zeroeenviaocomandodeinicio(0x01)
O Controle ento responde com sua identificao: ( 0x41 = Digital 0x73=Analgico) Em nosso
projetoestevalornoserutilizado
Aomesmotempoemqueocontroleenviaestebytedeidentificao,oPlaystationestenviando
obyte(0x42)parasolicitardadosaocontrole
Em seguida o Playstation envia um byte nulo (0x00) enquanto o controle responde com o
byte(0x5A)indicandoqueiriniciaroenviodosdadosdosbotes
Nasequncia,soenviados6bytescomostatusdetodososbotes
Depoisdereceberestes6bytes,oPlaystationcolocaopinoATTem1paraqueocontrolepara
deenviardados
Acomunicaoentreemrepousoatquesejasolicitadonovopedidodedadosaocontrole.

Comisso,acomunicaoacontecerdaseguintemaneira:

Controleemmododigital:
Byte
01
02
03
04
05

Byte
Byte
Comando Dados
0x01
idle
0x42
0x41
0x00
0x5A Bit0
idle
Byte1 SLCT
idle
Byte2
L2

DescriodoBytedeDados

Bit1

Bit2

R2

L1

Bit3 Bit4 Bit5


Bit6
Bit7
STRT UP RGHT DOWN LEFT
R1
/\
O
X
[]

Controleemmodoanalgico(LEDligado):
Byte
01
02
03
04
05
06
07
08
09

Byte
Comando
0x01
0x42
0x00
Idle
idle
idle
idle
idle
idle

Byte
DescriodoBytedeDados
Dados
idle
0x73
0x5A Bit0 Bit1 Bit2 Bit3 Bit4 Bit5
Bit6
Bit7
Byte1 SLCT JOYR JOYL STRT UP RGHT DOWN LEFT
Byte2
L2
R2
L1
R1
/\
O
X
[]
Byte3 JoyAnalgicoDireito0x00=Esquerda0Xff=Direita
Byte4
JoyAnalgicoDireito0x00=UP0Xff=DOWN
Byte5 JoyAnalgicoEsquerdo0x00=Esquerda0Xff=Direita
Byte6
JoyAnalgicoEsquerdo0x00=UP0Xff=DOWN

Hardware:
Ohardwareparaesteprojetomuitosimples,sendocomposta,almdoprpriocontrole,de:
Um microcontrolador PIC16F877a. A escolha deste uC se deu apenas por ele estar disponvel
em meu laboratrio, mas o projeto pode ser facilmente adaptado para o modelo preferido de
cadaum

Umadaptadorouextensorparaoconectordocontrole.Issoparaocasodenosecortarocabo
originaldocontroleeutilizarosfiosdiretamente.Nocasodocontrolesemfio,possvelsoldar
umnovocabodiretamentedospinosdotransmissorsemfio,maseuprefiroutilizaroadaptador
epodersubstituirocontrolefacilmentecasoeleapresentealgumdefeito,almdoacabamento
ficar muito melhor. Eu comprei meu adaptador no site ChinesDeal Extreme, eles no cobram
freteparaoBrasileospreossomuitobaixos

Para este projeto, utilizei alguns LEDs para demonstrar o funcionamento do circuito, cada vez
que um boto pressionado, um led correspondente se acende. Em uma aplicao real, fica
livreaimaginaodoprojetista.
Aseguiroesquemaeletrnicodocircuito:

Software:
O software foi baseado no programa apresentado no site Robotizando. O original foi escrito para
apresentarosdadosemumaserialaserutilizadoporumoutrodispositivo.Estesitemuitobome
apresentadiversosoutrosartigosmuitointeressantes.
Fizamodificaonocdigooriginalparasecomunicarcomumcontrolesemfio(ooriginalnopermite
este uso). Alm disso, em aplicaes no to robustas como em robs pouco complexos, podemos
utilizar um nico uC para comunicao com o controle de Playstation ao mesmo tempo que com os
demaisperifricosdorob(motores,atuadores,etc).
//************************************************************************//
//
//PROJETOCOMUNICAOJOYSTICKPS2WIRELESSCOMPIC16F877A
//
//************************************************************************//
//Configurao
PIC//************************************************************************//
#include<16F877A.h>
#FUSESNOWDT//Semwatchdog
#FUSESHS//Cristalaltavelocidade
#FUSESPUT//Timerdealimentao
#FUSESNOPROTECT//Cdigodesprotegido
#FUSESNOBROWNOUT//Semresetdebrownout

#FUSESNOLVP//Programaoemaltavoltagem
#FUSESNOCPD//Semproteodememria
eeprom
#FUSESNOWRT
#usedelay(clock=20000000)//cristalde20Mhz
//Definiodosports
#byteporta=0x05
#byteportb=0x06
#byteportc=0x07
#byteportd=0x08
#byteporte=0x09
//************************************************************************//
//CONTROLEPLAYSTATION

//************************************************************************//
//DefiniodeI/Os

//************************************************************************//
#definecmdPIN_D6
#defineattPIN_D4
#defineclkPIN_D5
#definedadoPIN_D7
#defineLED_STATUSPIN_E0//Ledindicadordestatus
#definestartPIN_A1
#defineselectPIN_A0
#defineservo_x_lPIN_D0
#defineservo_y_lPIN_D1
#defineservo_x_rPIN_D2
#defineservo_y_rPIN_D3
#definesobePIN_B0
#definedescePIN_B1
#definedireitaPIN_B2
#defineesquerdaPIN_B3
#definetrianguloPIN_B4
#definebolinhaPIN_B5
#definequadradoPIN_B6
#definexisPIN_B7
#definel1PIN_C0
#definel2PIN_C1
#definel3PIN_C2
#definer1PIN_C3
#definer2PIN_C4
#definer3PIN_C5
//************************************************************************//
//DefiniodeparmetrosdecomunicaocomocontrolePS2
//************************************************************************//
//Temposemmicrosegundos(us)
#definetempoInicio20
#definetempoClk20
#definetempoEntreByte20

#definetempoEntreCiclo40//ms
//************************************************************************//
//VARIAVEISGERAIS

//************************************************************************//
intpsxDado[6]//Bufferdocontrole
intpsxDadoAnt[6]//Bufferdocontrole
int1psxMudou
//BotesdoControle
int1bt_select=0
int1bt_l3=0
int1bt_r3=0
int1bt_start=0
int1bt_sobe=0
int1bt_desce=0
int1bt_esquerda=0
int1bt_direita=0
int1bt_l1=0
int1bt_l2=0
int1bt_r1=0
int1bt_r2=0
int1bt_triangulo=0
int1bt_bolinha=0
int1bt_quadrado=0
int1bt_xis=0
intX_Left=0
intY_Left=0
intX_Right=0
intY_Right=0

intpsxCont//contadorgenrico
int1estado//estadodoled

//************************************************************************//
//CONSTRUESDASFUNES
//************************************************************************//
//************************************************************************//
//psxLeByteCapturaumbyte,enviadopelocontroleatravsdopinoDADO
//************************************************************************//
intpsxLeByte()
{
intaux=0
intc
for(c=0c<=7c++)//Passaportodososbitsdavarivel
psxByte
{
output_bit(clk,false)//baixaoclock,paraqueocontrole

//disponibilizeodadonopino"dado"
delay_us(tempoClk)
if(INPUT(dado)==1)
bit_clear(aux,c)
else
bit_set(aux,c)
output_bit(clk,true)//Sobeoclock
}
delay_us(tempoEntreByte)
return(aux)
}
//************************************************************************//
//psxGravaByteEscreveumbyte,enviadopelocontroleatravsdopinoCMD
//************************************************************************//
voidpsxGravaByte(intbyteDado)
{
intc
for(c=0c<=7c++)//PassaportodososbitsdavarivelpsxByte
{
//SobeoudesceopinodeacordocomcadabitdavarivelpsByte
//significaqueestamosenviandoocomando0x01hparaocontrole
if(bit_test(byteDado,c))
output_bit(cmd,true)
else
output_bit(cmd,false)
output_bit(clk,false)//depoisdesetaropino,mandaclock
//delay_us(tempoClk)
//aguardaumtempinho...
output_bit(clk,true)//upclock...NOTA:clock
}
output_bit(cmd,true)//upcomandoparasinalizar
delay_us(tempoEntreByte)//esperaumtempinhoentreumbytee
outro
}
//************************************************************************//
//psxCopiaDadocopiabufferatualparaanterior
//************************************************************************//
voidpsxCopiaDado()
{
inti
for(i=0i<6i++)
psxDadoAnt[i]=psxDado[i]
}
//*************************************************************************//
//psxComparaDadoComparaleituraanteriorcomaatual
//************************************************************************//

booleanpsxComparaDado()
{
intj
for(j=0j<6j++)
{
if(psxDadoAnt[j]!=psxDado[j])
return(1)
}
return(0)
}
//************************************************************************//
//psxAtualizaVariaveisconvertebufferdeleituraparavariaveis
discretas
//************************************************************************//
voidpsxAtualizaVariaveis()
{
if((psxDado[0]&1)==1)
bt_select=1
else
bt_select=0
if((psxDado[0]&2)==2)
bt_l3=1
else
bt_l3=0
if((psxDado[0]&4)==4)
bt_r3=1
else
bt_r3=0
if((psxDado[0]&8)==8)
bt_start=1
else
bt_start=0
if((psxDado[0]&16)==16)
bt_sobe=1
else
bt_sobe=0
if((psxDado[0]&32)==32)
bt_direita=1
else
bt_direita=0
if((psxDado[0]&64)==64)
bt_desce=1
else
bt_desce=0

if((psxDado[0]&128)==128)
bt_esquerda=1
else

bt_esquerda=0

if((psxDado[1]&1)==1)
bt_l2=1
else
bt_l2=0
if((psxDado[1]&2)==2)
bt_r2=1
else
bt_r2=0
if((psxDado[1]&4)==4)
bt_l1=1
else
bt_l1=0
if((psxDado[1]&8)==8)
bt_r1=1
else
bt_r1=0
if((psxDado[1]&16)==16)
bt_triangulo=1
else
bt_triangulo=0
if((psxDado[1]&32)==32)
bt_quadrado=1
else
bt_quadrado=0
if((psxDado[1]&64)==64)
bt_xis=1
else
bt_xis=0
if((psxDado[1]&128)==128)
bt_bolinha=1
else
bt_bolinha=0
x_right=psxDado[2]
y_right=psxDado[3]
x_Left=psxDado[4]
y_Left=psxDado[5]
}
//************************************************************************//
//psxLeControleExecutaaleituradocontroledeplaystation

//************************************************************************//
voidpsxLeControle()
{
intpsxByte=0

output_bit(cmd,true)//upcomando
output_bit(clk,true)//upclock
output_bit(att,false)//attemlowhabilitaojoystick
delay_us(tempoInicio)//aguardaocontroleentenderoattemlow
//Enviaoprimeirobyteparaocontrole0x01
psxByte=1
psxGravaByte(psxByte)
//Enviaosegundobyteparaocontrole0x42h
psxByte=66
psxGravaByte(psxByte)
//Enviaoterceirobyteparaocontrole0x00
psxByte=0
psxGravaByte(psxByte)
//Recuperaos6prximobytes
for(psxCont=0psxCont<6psxCont++)
psxDado[psxCont]=psxLeByte()
//Voltaoattparaalto...liberaocontroleindicandoqueelepode
//parardeenviardados
output_bit(att,true)
//Comparacomavarivelanterioreverificaseser
//necessrioatualizarasvariaveisdiscretas
if(psxComparaDado()==1)
{
psxAtualizaVariaveis()
psxMudou=true
}
else
psxMudou=false
psxCopiaDado()
}
//************************************************************************//
//atualizaSaidasAtualizaostatusdetodasassadasdoPIC
//************************************************************************//
voidatualizaSaidas()
{
output_bit(start,bt_start)
output_bit(select,bt_select)
output_bit(sobe,bt_sobe)
output_bit(desce,bt_desce)
output_bit(direita,bt_direita)
output_bit(esquerda,bt_esquerda)
output_bit(triangulo,bt_triangulo)
output_bit(bolinha,bt_bolinha)
output_bit(quadrado,bt_quadrado)
output_bit(xis,bt_xis)
output_bit(l1,bt_l1)

output_bit(l2,bt_l2)
output_bit(l3,bt_l3)
output_bit(r1,bt_r1)
output_bit(r2,bt_r2)
output_bit(r3,bt_r3)
}

//************************************************************************//
//PROGRAMA
PRINCIPAL//************************************************************************/
voidmain()
{
set_tris_a(0b00000100)
set_tris_b(0b00000000)
set_tris_c(0b00000000)
set_tris_d(0b00000001)
set_tris_e(0b00000000)
porta=0x00
portb=0x00
portc=0x00
portd=0x00
porte=0x00
while(1)
{

psxLeControle()
delay_ms(20)

estado=!estado
output_bit(LED_STATUS,estado)
atualizaSaidas()
}//Fimdolaoprincipal
}//Fimdoprograma

//************************************************************************//

Você também pode gostar