-
Notifications
You must be signed in to change notification settings - Fork 198
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Gyroscope/Accelerometer Status #18
Comments
I've found with my weird racing tactic in a charging Joy-Con grip (having it connected over Bluetooth and then quickly switching to USB/UART) that input packets send additional data which looks to be gyro/accelerometer data, so it's mostly an issue of enabling the IMU. |
Again, forgive my ignorance. Are the packets you're seeing doing the enabling being sent by bluetooth before the switch, or by USB/UART after the switch. Do you have a dump of those packets? Would love to have a look at them |
I believe @shinyquagsire23 is referring to connecting the JoyCons to the switch over bluetooth, and then quickly connecting over USB, which let's you poll for gyroscope data / rumble; More testing is definitely needed to get a better understanding though. |
Found the commands to enable IMU data over input packets,
First line is what you'd send via charging grip or to a Pro Controller over USB, second is just what is sent over UART. |
Have you tried this over BT? |
An update on this would be awesome. I'm desperate to get that data over bluetooth. Not sure how much work needs to be done but we could close out this issue hopefully. Unrelated - is it correct that the Joy Cons communicate over Bluetooth even if they're in the Switch after an initial pairing? |
Joycon only use bluetooth when it's detached from the console. if it's attached to the console it uses physical serial communication instead. |
@claymullis This is the command to enable the IMU: https://github.com/riking/joycon/blob/master/prog4/joycon/bluetooth.go#L102 |
So you've managed. It looks great and so smooth! Are you planning to support up/down, left/right, forward/backwards movement also? |
@wormyrocks Great job! I have been waiting for someone to get that working in Unity beyond just the buttons as was easy to do previously. I also had analog sticks working in the editor but not on deployment. |
@CTCaer Yes - the equations I am using now give position and rotation - but right now my gyro data does not work well enough to look good when visualized. I saw that you did some digging into the gyroscope calibration values, that will be really helpful as I was mostly guessing when I did the initial integration. @sniejadlik This is literally my first Unity project, so I don't know how to handle flow control at all. Since the Joy-Con pushes IMU packets every 15ms and has a sizable FIFO buffer, if it is polled any slower than it produces data the buffer will quickly saturate, leading to a lag time of a few seconds between movement and response. So the demo looks nice, but when it is implemented in a project with a locked frame rate it totally chokes. Once that is fixed and my gyro data gets a little more accurate I will publish the code! If you want to integrate before then, the information used is all here. For Unity integration I used the HIDapi libraries from here. @CTCaer any suggestions on the best steps to take would be to prevent the buffer from saturating? My first instinct is just to rewrite my code to keep hid_reads in their own thread, and try to keep them as regular as possible at 15ms. The trouble then is that I suspect I will run into synchronization issues if I want to send rumble data or other subcommands after the polling thread begins. |
@wormyrocks good to know. I actually can't build anything right now as I was using my coworkers joycons the last time I was experimenting with this. I'm planning on buying a pair now just to experiment now that it looks like the integration is starting to work. As far as timing is concerned, is the issue that Unity is not giving you a consistent interval to poll with? Are you just trying it on the Update command? You could try creating a coroutine possibly and tie the timer to the Time.deltaTime in order to get an accurate time stamp. Not sure if that helps but just trying to think through possible issues with request functions tied to Unity's framerate. |
@wormyrocks Hmm.. 2nd use bit masking/operations and matrices to optimize the big math functions. 3rd is to have a global timer that you can check and correct the time your packet came to the expected time. The best way is to use the packet timer (2nd byte after the x30 id). Actually switch, uses this packet timer. Every 1 increment is 5ms. So you will see +3 in your packets. After reaching a good optimization you can then go to a delta of 5ms (instead of 15ms), by parsing all 3 acc/gyro samples in the packet. EDIT: |
@CTCaer I am looking at your updated IMU documentation. Can you explain how you arrived at the conclusion that the gyroscope scaling coefficient is 13371dps? I understand that that value is found in the SPI calibration memory location - but, according to the IMU datasheet, the maximum range is only 2000dps. I have been trying to figure out how the sample gyroscope readings provided in table 4.5 in the datasheet - table 4.5 - are supposed to be interpreted, to get some clue as to how to process the data found from the Joy-Con gyroscope. However, the obvious solution (sample * 245 / 32768) does not yield the corresponding value. I must be missing something here. Interestingly, when I test your equation for the gyroscope vector component, it gives me something very very close to the number of rotations per second, rather than degrees per second. In my Unity implementation, if I monitor a running sum of dt * gyro * 0.000204f and rotate the Joy-Con one full revolution in that axis, my sum is very close to 1. so I think your answer may just be in the wrong units. I am still not sure where the math in the datasheet came from. Nor the magic numbers in the implementation I originally used |
@wormyrocks First of all, I will update the whole thing, and I hope that you will help us add every other equation (angles, etc). Let's see now why Switch uses these number instead of 2000dps and 8G. Acc But, Switch uses a ±8192 mG (0.25mG/LSB) sensitivity for some reason. Maybe because it's a power of 2? We also see that the datasheet has the correct values for mG, for Joy-Con it's 0.244 mG/LSB. Gyro So what are these strange values from the calibration data and also from the datasheet? STMicroelectronics: 61+15%=70. Or ±2294dps. So what about the 13371 from Nintendo? First, let's convert it to mdps/digit. I don't know where the magic numbers came from that function there, but I assume with some calculations we can find out. Anyway, I hope that we now cleared up the mist. |
@wormyrocks Also I have another question: It seems that some axes are inversed in Gyroscope too:
Which one is correct? |
for the gyroscope, I get the same axes as you show in the diagram except that the Z-axis on the left Joy-Con is reversed. here is the eqn I used to get consistent axes of rotation on both Joy-Cons:
where i=0 : x, i=1: y, i=2: z. Interestingly, I get that the gyroscope coefficients are different on the left and right Joy-Cons. at least for my own set of Joy-Cons it looks like the left Joy-Con uses the STM default multiplier and the right Joy-Con uses the Nintendo coefficient for higher dynamic range. so, I am now normalizing to give degrees with the following equation:
also this documentation is fantastic. thanks for putting in all this effort |
You are welcome. Hmm. About the gyroscope coefficients, it's strange. Did you calibrated them? Now I'm trying to finalize the origin position SPI calibration. |
BTW, I ordered an LSM6DS3 developer kit which I might use to analyze the raw data coming from the IMU. let me know if you have any requests for any sort of data dumped from there. command outputs, calibration data, etc. I'll probably just use the Arduino library and look at the raw data output. If any of the Joy-Con subcommands let us send commands directly to the accel/gyro, it would be really cool to try and enable pedometer mode or motion sensor mode. Then people could use a Joy-Con + Raspberry Pi W, for instance, to build a security system or something similar. |
There are some commands, x41/x42/x43. Also, I hope for the temperature here. |
So I have double checked the gyro coefficients on the left and right Joy-Cons and I am pretty sure that the actual range is +- 2000 dps. I've rewritten my Unity library to poll with threading and numerically integrate with dt=5ms, and checking the timestamps on the input report I can actually be sure that I am processing every single packet sent by the Joy-Con. With this method I actually get a completely accurate rotation value (both Joy-Cons are the same) if I use the multiplier 0.061f rather than 0.07344f. Perhaps our Joy-Cons are calibrated differently from each other? |
No no, there is no problem with your calculations. They are correct. As I described before, we do this to avoid saturation when the values are out of range. The article I linked explained this:
So, basically this means the following:
About Nintendo use: First of all, for your usage case, forget what nintendo uses. You are not currently trying to connect the Joy-Cons to a Switch emulator, of which you are the jcpad plugin developer. A fun experiment to calculate the real sensitivity value for your room temperature: |
@wormyrocks
This is almost exactly what Switch is doing. My god, the whole back and forth in functions is tiring... I'm really curious what it does for acc.. |
That seems extremely suspicious, especially as the calibration values are uint16 and |
This maybe an outcome from IDA. And yes, like what you proposed, I made this to my toolkit:
So the outcome is rotations/s. To get dps:
OR
The funny thing is that it works and produces a coeff for each axis based on the origin position. So basically to calibrate we don't do (axis - origin) * sens_coeff. So, the coeff produced if the origin position is center (0x0000) it's 0,00019445*360=0,070f OK. I have to rework the sensor notes now! EDIT: |
Also another thing that I forgot. But we don't care about this I think. EDIT: |
And last but not least ACC:
Note: (1/magic)*4 = (1 / 16384) * 4 = 0.000244f! Oh, I'm so happy now EDIT: |
Last note and reference usable code: Code (for ±8G, ±2000dps):
EDIT: |
@wormyrocks EDIT: |
New development: You can now completely control the IMU. Every writable register and you can read all registers. Check here for more. |
Frickin awesome. |
I'll leave that here: |
Outstanding work to everyone that worked on this. Thanks. |
Anyone know how joycon orientation(rotation) matrix and rotation vector is derived or computed on the switch HID module? |
I saw that you managed to get the data from the SPI for accelerometer/gyroscope.
Is this something you've only been able to capture directly from the SPI?
I think it's been established that the joycons don't send accelerometer and gyroscope information without some sort of command being sent to the joycon. Is this accurate?
If so, is there any speculation as to what the command is currently or how to discover it?
disclaimer: I've seen this question asked a lot in other issues but I'm a bit of an outsider to all of the low-level reverse engineering skills this project requires. Please forgive any misunderstandings.
The text was updated successfully, but these errors were encountered: