Fixing (DualShock 3) Bluetooth Lag
-
OK. I will make this brief.
I think I have a fix which reduces a lot of Bluetooth input lag (latency). I have only tested this with a PS3 DualShock 3 controller, on a Raspberry Pi 3. I am using Retropie v4.1, but I must add that this is not entirely stock as Retroarch was updated and I have installed then uninstalled the ps3controller packages. However I believe this will work on Pi 3's with the PS3 controller, and possibly other controllers as well.To summarise, I have identified two actual sources of input lag which affect the PS3 controller, and possibly others. A) Coexistence of Bluetooth and Wifi, B) Whether the bluetooth controller is in master or slave mode.
Now the details.
To begin. I have set up the PS3 Controller for bluetooth play using the 8bitdo guide, which my understanding is the default bluetooth option in 4.1: https://github.com/retropie/retropie-setup/wiki/Setting-up-an-8bitdo-Bluetooth-controller . The controller is set to use udev and the firmware hack is off (I don't think either of these matter though). When the controller is plugged in directly to the USB port, there is no noticeable input lag delay (Yes my TV is tuned to game mode and Retroarch is not using any filters/mods. I am using SNES and Genesis emulators). However when using bluetooth, there is a VERY noticeable input lag making the characters in game feel sluggish and sticky.
While input lag can be felt subjectively during play, it's also possible to get a more objective measure by pinging the bluetooth device itself(We will be using the console for this fix). The address of the Bluetooth device can be found somewhere in the bluetooth menu, but to get it in the console type (Without the $)
$ hcitool con
You should see something like
Connections:
> ACL AA:BB:CC:DD:EE:FF handle 11 state 1 lm MASTERWhere one of the address AA:BB:CC:DD:EE:FF shown is your (PS3) bluetooth controller. Now, to test the connection to this device type
$ sudo l2ping AA:BB:CC:DD:EE:FF
Replacing AA:BB:CC:DD:EE:FF with your devices address. You should see output like
Ping: AA:BB:CC:DD:EE:FF from 00:11:22:33:44:55 (data size 44) ...
4 bytes from AA:BB:CC:DD:EE:FF id 0 time 53.73ms
4 bytes from AA:BB:CC:DD:EE:FF id 1 time 54.29ms
4 bytes from AA:BB:CC:DD:EE:FF id 2 time 16.00ms
4 bytes from AA:BB:CC:DD:EE:FF id 3 time 53.73msThese are round trip ping times, so I presume the actual input lag/latency is around half of this. This is a very noticeable amount of lag during gameplay. Now, an immediate improvement can be obtained by
A) Turning off Wifi
In console, type the following command (warning this will disable wifi until txpower is turned back on AND the Pi is rebooted) to disable the transmission power of the Pi3's onboard wifi (this also reduces temperatures slightly I have found)
$ sudo iwconfig wlan0 txpower off
Wifi is now off. Testing it with "sudo l2ping AA:BB:CC:DD:EE:FF" reveals (for me anyway), a ~20ms ping time improvement, translating into a 10ms reduction in input lag/latency.
4 bytes from AA:BB:CC:DD:EE:FF id 0 time 13.70ms
4 bytes from AA:BB:CC:DD:EE:FF id 1 time 36.19ms
4 bytes from AA:BB:CC:DD:EE:FF id 2 time 34.83ms
4 bytes from AA:BB:CC:DD:EE:FF id 3 time 36.08ms(Note: Wifi is now permanently off until the command "sudo iwconfig wlan0 txpower on" is run and the Pi rebooted. I realise this may not be an option for everyone, but the reality is that bluetooth and WiFi do interfere.)
This is good. Even at this stage, we have perhaps ~18ms of input lag from bluetooth -- just over half a frame. This improves gameplay considerably, but there is still some noticeable input lag, which affects many platformers. But we can do better. Notice that 13ms ping round trip time which occasionally appears, suggesting that a ~7-8ms input lag time is in fact possible. And this is achievable if the PS3 controller is set from being the MASTER in the bluetooth connection to the SLAVE instead. This seems to switch the refresh/polling/delay time rate to the lowest possible bluetooth setting of ~6ms.
B) Switching bluetooth connection to slave mode
To achieve this run the command
$ sudo hcitool sr AA:BB:CC:DD:EE:FF slave
replacing AA:BB:CC:DD:EE:FF with the PS3's address. This (I think) switches things so that the Pi is the Master and ping times are considerably reduced. Testing it with "sudo l2ping AA:BB:CC:DD:EE:FF" reveals (for me anyway) a relatively consistent ~12ms round trip ping time, suggesting a potential ~6ms input lag/latency delay over bluetooth
4 bytes from AA:BB:CC:DD:EE:FF id 0 time 13.81ms
4 bytes from AA:BB:CC:DD:EE:FF id 1 time 11.28ms
4 bytes from AA:BB:CC:DD:EE:FF id 2 time 12.32ms
4 bytes from AA:BB:CC:DD:EE:FF id 3 time 12.29ms
4 bytes from AA:BB:CC:DD:EE:FF id 4 time 12.27ms
4 bytes from AA:BB:CC:DD:EE:FF id 5 time 12.14ms
4 bytes from AA:BB:CC:DD:EE:FF id 6 time 12.36ms
4 bytes from AA:BB:CC:DD:EE:FF id 7 time 12.26ms
4 bytes from AA:BB:CC:DD:EE:FF id 8 time 12.27ms
4 bytes from AA:BB:CC:DD:EE:FF id 9 time 12.14ms
4 bytes from AA:BB:CC:DD:EE:FF id 10 time 28.64ms
4 bytes from AA:BB:CC:DD:EE:FF id 11 time 18.44ms
4 bytes from AA:BB:CC:DD:EE:FF id 12 time 12.30ms
4 bytes from AA:BB:CC:DD:EE:FF id 13 time 12.28ms
4 bytes from AA:BB:CC:DD:EE:FF id 14 time 12.11msAt this point, play over bluetooth is (for me) indistinguishable from play over direct USB connection on the Raspbery Pi 3. As proof, I can now obtain the emeralds in the Sonic 3 special stages over bluetooth with a PS3 controller. Previously this was practically infeasible.
I note finally that while this works, I believe it may cause more rapid draining of the Dualshock 3's (or other Bluetooth controller's) battery. Perhaps a drain of 3 times the speed or more. I'm not able to test this.
Anyway TL;DR Bluetooth fix.
In a console
- Turn off wifi with $ sudo iwconfig wlan0 txpower off
- Find controller bluetooth address AA:BB:CC:DD:EE:FF with $ hcitool con
- Switch controller from master to slave mode with $ sudo hcitool sr AA:BB:CC:DD:EE:FF slave (This must be done every time the controller is reconnected)
*) Test connection speed with $sudo l2ping AA:BB:CC:DD:EE:FF (optional)
People will need to test this on other Pis and with other controllers, but I believe these fixes will work. I am not sure how this will affect battery life or (potentially) Pi antenna life. I am not an expert on bluetooth, or even a novice, so caution may be needed when implementing this in practice. If people test this and find it useful, I think I will trying coming up with a script/menu item for these fixes in emulation station to give people the option of trying this fix without having to go into the console.
Anyway hopefully this is useful, and people can report back other tests in this thread.
-
I use 8bitDO FC30 bluetooth controllers. I'll do this same test and see what happens on my end. I'm quite excited by this prospect!
-
Try to use l2ping to determine ping times to the controller before and after each fix. The lag itself might be different for each controller. Also, I'm not sure if this works for devices with their own bluetooth dongles.
-
In my config, I already have wlan0 turned off when the system boots. My avg default ping times are ~36 seconds. I disabled Wlan tx for adapter 0(onboard) and wlan1 (Tenda Pico) No change in latency when I disable wlan0 or wlan1 tx.
When I try to change the role, I receive an error "Switch role request failed: input/output error
-
@batesman What is the output of
$ hcitool con
The connection may already be in slave mode. You could try switching to master mode instead to see if that changes anything. sudo hcitool sr AA:BB:CC:DD:EE:FF master
By the way, are you using the onboard wifi for the controller, or some kind of bluetooth dongle?
Also, are you running "sudo" before the switch role command?
-
The output of hcitool is ACL <Mac address of controller> handle 12 State 1 in MASTER AUTH ENCRYPT
I am using onboard bluetooth and a Tenda wifi dongle. I am running sudo before the role switch command. I edited my rc.local file to include "ifconfig wlan0 down" so that the onboard wifi isn't operational.
I am receiving the input / output error when I try to switch roles to master or slave.
-
@batesman It looks like that, by default, the FC30 requests (or demands) more parameters in its bluetooth connection. Specifically authentication and encryption. Strange since I would have presumed both would lead to more input lag.
I suspect there might be a way of getting the controller to relinquish its demands and revert to slave mode somehow. Probably using hcitool, which has a large amount of (sadly very undocumented) tools and methods for changing bluetooth connections.
What is the output of $hcitool info AA:BB:CC:DD:EE:FF.
For the PS3 controller, this is
BD Address: AA:BB:CC:DD:EE:FF
OUI Company: ALPS Co,. Ltd. (00-06-F7)
Device Name: PLAYSTATION(R)3 Controller
LMP Version: 2.0 (0x3) LMP Subversion: 0x131f
Manufacturer: Cambridge Silicon Radio (10)
Features: 0xfc 0x07 0x82 0x7e 0x08 0x18 0x00 0x80
<encryption> <slot offset> <timing accuracy> <role switch>
<hold mode> <sniff mode> <park state> <RSSI> <channel quality>
<paging scheme> <broadcast encrypt> <EDR ACL 2 Mbps>
<EDR ACL 3 Mbps> <enhanced iscan> <interlaced iscan>
<interlaced pscan> <inquiry with RSSI> <AFH cap. slave>
<AFH cap. master> <AFH class. master> <extended features>So encryption is there, but the Dualshock 3 is not requesting it. What is the equivalent feature set of the FC30?
-
BD Address: <Mac address>
Device name: 8bitDO FC30 Pro
LMP Version 3.0 (0x5) LMP Subversion 0xc
Manufacturer: RDA Microelectronics (97)
Features page 0: 0xff 0xff 0x8d 0xf8 0x98 0x1f 0x79 0x83<3-slot packets> <5 slot-packets> <encryption> <slot offset>
<timing accuracy> < role switch> <hold mode> <sniff mode>
<park state> <RSSI> <channel quality> <sco link>
<HV2 packets> <HV3 packets> <u-law log> <A-law log>
<CVSD> <power control> <transparent SCO> <broadcast encrypt>
<enhanced iscan> <interlaced iscan> <interlaced pscan> <inquiry with RSSI>
<extended SCO> <AFH cap. slave> <AFH class. slave> <3-slot EDR ACL>
<5-slot EDR ACL> <sniff subrating> <pause encryption>
<AFH cap. aster> <AFH class.master> <extended inquiry>
<simple pairing> <encapsulated PDU> <err.data report> <non -flush flag>
<LSTO> <inquiry TX power> <extended features>Features page 1: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
Features page 2: 0xff 0xa7 0xff 0xff 0x00 0x65 0x07 0x01 -
This is a great article. Thanks for posting!
-
ARoxdale,
Thank you so much for this thread. Great detailed instructions, no fluff, no filler. So many other threads which discuss the BT lag problem quickly devolve into a conversation about TV picture modes and 16-foot USB controller extensions. THIS is what I have been looking for. I have yet to try your method, but based on your results I am VERY hopeful. As you point out, so many games are all but unplayable when experiencing this lag.
To me it is well worth the effort of manually running Linux commands to rid myself of this pesky lag, but at the same time I would ask you to please consider following through on your script idea. And if you do come up with a script that can become an automated part of the boot sequence, please share it.
Thanks again, and good luck! I'll be watching this thread intently.
-Dave -
@batesman Sorry about the delay.
It looks like the FC30 is using a more updated version of the Bluetooth Link management profile. I'm guessing that the authentication and encryption paramethers are interfering with the basic switch role command, but this is only a guess.
Can you try running the following command
$ sudo hciconfig -a hci0 noauth noencrypt
Then, turn the FC30 off and on again. Check if it works(If not you'll have to reset the pi), then run the commands
$ hcitool con
$ sudo hcitool sr AA:BB:CC:DD:EE:FF slave
And finally another l2ping command
@EVEGames I will try to come up with a script file, but it will be very hacky. My intention is to get in contact with the Bluez team on their mailing list to see if they can shed light on a more stable way forward here.
I think it may be possible to adjust the settings of the pi's bluetooth hci0 controller, either by modifying the file /etc/bluetooth/main.conf or the config/settings files in /var/lib/bluetooth/AA:BB:CC:DD:EE:FF . These changes would be permentant, and if implemented in the distribution (I would not recommend doing this without consulting the Bluez team) would change the settings for all RetroPies.
This is all speculation, and really I'm not sure exactly why any of this is really working. But we can but fail.
(Edit: Corrected commands to include hcitool sr command)
-
Haven't forgotten about this, just haven't had the time. I hope to get to it later this evening.
-
So I ran hciconfig noauth noencrypt, rebooted the fc30 and tested. Everything still works, however when I run hcitool con afterward it still shows in MASTER AUTH ENCRYPT state. L2ping times were ~36 with spikes up to 80. After running the hciconfig command I still cannot switch roles.
-
Im also using a NES30 8Bitdo controller and since I wasnt able to change the BT mode, just like batesman, I wanted to try to turn wifi off. That did not change anything, and the problem is, now I cant turn it on again:
"Error for wireless requess "Set Tx Power (8B27) : GET Failed on device wlan0: input/output error"Edit: Nevermind, for some reason its working now. (Even without restarting the Pi)
-
I've been in some contact with the Bluez team, but no luck so far on a more permanent solution though I do have some ideas.
@batesman @snckrz I tried to get a PS4 controller working to see if it could reproduce this FC30 problem. It has most of the same connection paramaters, however (un)fortunately it allows role switching.
Can you try running the following commands and then checking their results using $hcitool con and $sudo l2ping as before
Firstly can you run
$ sudo hcitool enc AA:BB:CC:DD:EE:FF off
$ sudo hcitool sr AA:BB:CC:DD:EE:FF slaveThen test with hcitool con and l2ping. If this one doesn't work, try
$ sudo hciconfig -a hci0 lm accept,master
$ sudo hciconfig -a hci0 lp rswitch,sniff,holdThen turn off and reconnect the controllers. After this second step, try a few earlier commands as well.
You could also try just
$ sudo hciconfig -a hci0 lp hold
in the above.You could also try
Let me know how things go. I'll keep looking into things.
-
@ARoxdale said in Fixing (DualShock 3) Bluetooth Lag:
I've been in some contact with the Bluez team, but no luck so far on a more permanent solution though I do have some ideas.
@batesman @snckrz I tried to get a PS4 controller working to see if it could reproduce this FC30 problem. It has most of the same connection paramaters, however (un)fortunately it allows role switching.
Can you try running the following commands and then checking their results using $hcitool con and $sudo l2ping as before
Firstly can you run
$ sudo hcitool enc AA:BB:CC:DD:EE:FF off
$ sudo hcitool sr AA:BB:CC:DD:EE:FF slaveThen test with hcitool con and l2ping. If this one doesn't work, try
$ sudo hciconfig -a hci0 lm accept,master
$ sudo hciconfig -a hci0 lp rswitch,sniff,holdThen turn off and reconnect the controllers. After this second step, try a few earlier commands as well.
You could also try just
$ sudo hciconfig -a hci0 lp hold
in the above.You could also try
Let me know how things go. I'll keep looking into things.
Just to be clear, when you say "reconnect" do you mean disconnect and re-pair or just power off power on?
-
@ARoxdale Hey! I tried all your commands, reconnect and even repaired the controller, but it still connects in "MASTER AUTH ENCRYPT" mode, with a ping from 78-85ms.
But thanks for looking into this! -
@batesman I meant just to power off and power back on.
@snckrz Sorry these commands don't work for the FC30s. It's a pity.
I attempted to ask on the Bluez mailing list, but there hasn't been much response yet.
http://www.spinics.net/lists/linux-bluetooth/msg69611.htmlI'm not longer certain of my original assessment. The switch from master to slave may be a red herring, or maybe the FC30s simply don't accept a role change. I don't know enough about all this. I can report that the PS4 controller I have (which appears to eb a newer firmware model) did accept a role change, but only after encryption was deactivated. Once there, it gives an erratic set of ping times, which can be as low as ~4ms, but spikes to 20-40ms at times. Also, in this mode, similar spikes occure with the PS3 controller. Bluetooth is complicated I suppose.
-
A brief update. I've had no luck in finding a fix, but I do have a better tool to measure actual controller latency with.
With the controller off, run the following command
$sudo btmon -SThen turn the controller on. You should see a lot of output about the initial connection between the controller and the pie. This differs from controller to controller.
After that, you should see a long stream of text similar to the following. (You may need to hold down a button or waggle a stick to see these)ACL Data RX: Handle 12 flags 0x02 dlen 54 [hci0] 5.571498
Channel: 65 len 50 [PSM 0 mode 0] {chan 0}
a1 01 00 00 00 00 00 80 86 7d 7f 00 00 00 00 00 .........}......
00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 05 ................
16 ff d0 00 00 33 3c 77 01 c0 01 fc 02 02 01 86 .....3<w........
01 ee ..The part you're actually interested in here is the [hci0] 5.571498. This gives the time in seconds after btmon was started when the data packet from the controller was received by the pi (I think).
For my PS3 controller, before the role switch to slave, these times increase unsteadily in intervals of about 30ms (0.03s). That's about 2 frames at 60fps. Once the role is switched to slave, the packets begin to arrive at steadier intervals of a consistent 11ms. I believe the PS3 controller is sending a packet every 11ms so I presume this is the maximum input lag as a result, presuming no computation delays within the controller itself. 1 frame is 1/60 of a second or about 16.67ms, so this is a major improvement.
The PS4 controller I have is a more interesting case.
By default, even when in slave mode, the PS4 controller seems to be sending packets of data every ~1.3ms . Even when switched to slave mode, this remains consistent. The ping times improve, but role switch seems to have no effect on the actual rate at which the device is sending packets of data. I think the PS4 controller should produce almost minimal input lag by default. Can anyone confirm this? (Edit: I should add. The PS4 controller tends to introduce a lot of "noise" which cause the PS3 controller to expierience quasi-regular lags.)I'm curious as to what the delay times are for the FC30 controllers. Canyou try running btmon -S for your controllers also. Also, btmon does report more useful information about the connection setup, but I don't know how to use this yet. The Bluez team may know more.
-
Damn good stuff, @ARoxdale .
So it sounds like the role switch to slave yields a measurable improvement. From your original thread, you give the command: sudo hcitool sr AA:BB:CC:DD:EE:FF slave , of course, filling in the variables per your instructions. And you say that the command needs to be executed every time the controller is re-connected. I take it that means, every time the Pi is shut down and turned back on? If so, I know there are "runbefore" options available at boot time, seems that command could simply be added there? But the question is, does the device's address change from boot to boot?
I'm without a PS3 controller temporarily to test this out myself...
Contributions to the project are always appreciated, so if you would like to support us with a donation you can do so here.
Hosting provided by Mythic-Beasts. See the Hosting Information page for more information.