Advertisement
Guest User

SpaceMouse-compatible code for space mushroom

a guest
Feb 13th, 2023
2,743
0
Never
4
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.40 KB | Source Code | 0 0
  1. // This code makes your Arduino act as a 3DConnexion SpaceMouse (32u4-based board required).
  2. // To make this work you also need to set the USB Vendor ID and Product ID to values matching a real 3DConnexion device.
  3. // You can do this by editing appropriate entries in the boards.txt file in your Arduino installation.
  4. // Example values: vid=0x256f, pid=0xc631 (SpaceMouse Pro Wireless (cabled))
  5. // Then install the 3DxWare software from 3DConnexion on your computer and you can use you Arduino device in software like Fusion 360 as it it were a real SpaceMouse.
  6.  
  7. #include "HID.h"
  8.  
  9. #define DOF 6
  10. // ports of analog input for joysticks
  11. int port[DOF] = {A6, A2, A1, A0, A3, A7};
  12. int origin[DOF]; // initial sensor values
  13.  
  14.  
  15. // conversion matrix from sensor input to rigid motion
  16. int coeff[DOF][DOF] = {
  17. { 0, 0, 0, 10, 10, -20}, // TX
  18. { -3, -3, -3, 0, 0, 0}, // TZ
  19. { 0, 0, 0, -17, 17, 0}, // TY
  20. { 3, 3, -6, 0, 0, 0}, // RX
  21. { 0, 0, 0, 3, 3, 3}, // RZ
  22. {6, -6, 0, 0, 0, 0}, // RY
  23. };
  24.  
  25. int maxValues[2][DOF] = {
  26. {3000, 4000, 4000, 4000, 3000, 4500},//Positive Direction
  27. {3000, 4000, 1500, 4000, 3000, 4500} //Negative Direction
  28. };
  29. static const uint8_t _hidReportDescriptor[] PROGMEM = {
  30. 0x05, 0x01, // Usage Page (Generic Desktop)
  31. 0x09, 0x08, // 0x08: Usage (Multi-Axis)
  32. 0xa1, 0x01, // Collection (Application)
  33. 0xa1, 0x00, // Collection (Physical)
  34. 0x85, 0x01, // Report ID
  35. 0x16, 0x00, 0x80, //logical minimum (-500)
  36. 0x26, 0xff, 0x7f, //logical maximum (500)
  37. 0x36, 0x00, 0x80, //Physical Minimum (-32768)
  38. 0x46, 0xff, 0x7f, //Physical Maximum (32767)
  39. 0x09, 0x30, // Usage (X)
  40. 0x09, 0x31, // Usage (Y)
  41. 0x09, 0x32, // Usage (Z)
  42. 0x75, 0x10, // Report Size (16)
  43. 0x95, 0x03, // Report Count (3)
  44. 0x81, 0x02, // Input (variable,absolute)
  45. 0xC0, // End Collection
  46. 0xa1, 0x00, // Collection (Physical)
  47. 0x85, 0x02, // Report ID
  48. 0x16, 0x00, 0x80, //logical minimum (-500)
  49. 0x26, 0xff, 0x7f, //logical maximum (500)
  50. 0x36, 0x00, 0x80, //Physical Minimum (-32768)
  51. 0x46, 0xff, 0x7f, //Physical Maximum (32767)
  52. 0x09, 0x33, // Usage (RX)
  53. 0x09, 0x34, // Usage (RY)
  54. 0x09, 0x35, // Usage (RZ)
  55. 0x75, 0x10, // Report Size (16)
  56. 0x95, 0x03, // Report Count (3)
  57. 0x81, 0x02, // Input (variable,absolute)
  58. 0xC0, // End Collection
  59.  
  60. 0xa1, 0x00, // Collection (Physical)
  61. 0x85, 0x03, // Report ID
  62. 0x15, 0x00, // Logical Minimum (0)
  63. 0x25, 0x01, // Logical Maximum (1)
  64. 0x75, 0x01, // Report Size (1)
  65. 0x95, 32, // Report Count (24)
  66. 0x05, 0x09, // Usage Page (Button)
  67. 0x19, 1, // Usage Minimum (Button #1)
  68. 0x29, 32, // Usage Maximum (Button #24)
  69. 0x81, 0x02, // Input (variable,absolute)
  70. 0xC0,
  71. 0xC0
  72. };
  73.  
  74. void setup() {
  75. static HIDSubDescriptor node(_hidReportDescriptor, sizeof(_hidReportDescriptor));
  76. HID().AppendDescriptor(&node);
  77. delay(300);
  78. for (int i = 0; i < DOF; i++) {
  79. origin[i] = analogRead(port[i]);
  80. }
  81. }
  82.  
  83. void send_command(int16_t x, int16_t y, int16_t z, int16_t rx, int16_t ry, int16_t rz) {
  84. uint8_t trans[6] = { x & 0xFF, x >> 8, y & 0xFF, y >> 8, z & 0xFF, z >> 8 };
  85. HID().SendReport(1, trans, 6);
  86. uint8_t rot[6] = { rx & 0xFF, rx >> 8, ry & 0xFF, ry >> 8, rz & 0xFF, rz >> 8 };
  87. HID().SendReport(2, rot, 6);
  88. }
  89.  
  90. void loop() {
  91. int sv[DOF]; // sensor value
  92. int mv[DOF]; // motion vector
  93. int moveFlag = false;
  94.  
  95. for (int i = 0; i < DOF; i++) {
  96. sv[i] = analogRead(port[i]) - origin[i];
  97. }
  98.  
  99. for (int i = 0; i < DOF; i++) {
  100. mv[i] = 0;
  101. for (int j = 0; j < DOF; j++) {
  102. mv[i] += coeff[i][j] * sv[j];
  103. }
  104.  
  105.  
  106. //Rescale to max value range
  107. if (mv[i] > 0) {
  108. mv[i] = (mv[i]) / (maxValues[0][i]/127);
  109. }
  110. else {
  111. mv[i] = (mv[i]) / (maxValues[1][i]/127);
  112. }
  113. if(mv[i] > 127) {
  114. mv[i] = 127;
  115. }
  116. else if(mv[i] < -128) {
  117. mv[i] = -128;
  118. }
  119. }
  120. //IDK if I wired it wrong, but I needed to invert and mess with a lot of the axes.
  121. send_command(-mv[0], -mv[1], -mv[2], -mv[3], -mv[4], -mv[5]);
  122. }
Advertisement
Comments
  • Maderuelo1
    2 years
    # text 0.05 KB | 0 0
    1. Esta lleno de errores, seguro que funciona bien ?
    2.  
  • Thommy3512
    2 years
    # text 0.29 KB | 0 0
    1. Hey ! It works very well, you did a great job !
    2. DO you know how to add buttons ? I've seen that you stated it in 'hidReportDescriptor' but they aren't sent to the computer. I tried to add some code in 'send_command' function but I think I'm missing something cause it didin't work.
    3.  
    4. Have a nive day
  • 8fold
    1 year
    Comment was deleted
  • 8fold
    1 year
    # text 0.39 KB | 0 0
    1. If you made this and are having some difficulty, you may need to switch the axis (Y and X) around. I followed the initial tutorial, and found that the axis on the joystick 1 at the 2 o'clock position was wrong, and the X and Y needed to be switched. There's a more reliable code remixed from this on the top of the thingiverse comments, which added in a deadzone as well.
    2.  
    3. https://pastebin.com/erhTgRBH
Add Comment
Please, Sign In to add comment
Advertisement