Controller.ino 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. #include "I2Cdev.h"
  2. #include "MPU6050_6Axis_MotionApps20.h"
  3. #include <Wire.h>
  4. #include <WiFiUdp.h>
  5. #include <ESP8266WiFi.h>
  6. #include <EEPROM.h>
  7. #include <Adafruit_ADS1015.h>
  8. String WifiSSIDPrefix = "CrystalPoint";
  9. uint16_t BasestationPort = 2730;
  10. IPAddress BasestationIp = IPAddress(192, 168, 4, 1);
  11. Adafruit_ADS1115 ads;
  12. struct MPU6050Data{
  13. int yaw;
  14. int pitch;
  15. int roll;
  16. };
  17. struct JoystickData{
  18. int x;
  19. int y;
  20. char button;
  21. };
  22. struct SwitchData{
  23. char backSwitch;
  24. char magnetSwitch;
  25. };
  26. //mpu6050
  27. MPU6050 mpu;
  28. bool dmpReady = false; // set true if DMP init was successful
  29. uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU
  30. uint16_t packetSize; // expected DMP packet size (default is 42 bytes)
  31. uint16_t fifoCount; // count of all bytes currently in FIFO
  32. uint8_t fifoBuffer[64]; // FIFO storage buffer
  33. // orientation/motion vars
  34. Quaternion q; // [w, x, y, z] quaternion container
  35. VectorFloat gravity; // [x, y, z] gravity vector
  36. float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector
  37. volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high
  38. void dmpDataReady() {
  39. mpuInterrupt = true;
  40. }
  41. //Joystick offsets
  42. int joystickoffset_x, joystickoffset_y;
  43. //Data buffer for sensors
  44. struct MPU6050Data mpu6050data = {0};
  45. struct JoystickData joystickdata = {0};
  46. struct SwitchData switchdata = {0};
  47. //UDP server (receiving) setup
  48. unsigned int udpPort = 2730;
  49. byte packetBuffer[512]; //udp package buffer
  50. char sendBuffer[45];
  51. WiFiUDP Udp;
  52. void setup(void){
  53. Serial.begin(115200);
  54. Serial.println("Starting controller..");
  55. WiFi.mode(WIFI_STA);
  56. WiFi.disconnect();
  57. EEPROM.begin(512);
  58. delay(10);
  59. Udp.begin(udpPort);
  60. Wire.begin();
  61. //Magnetic sensor
  62. pinMode(13,INPUT);
  63. //clearEeprom();
  64. //connectLastBasestation();
  65. searchBasestation();
  66. delay(1000);
  67. ads.begin();
  68. joystickoffset_x = ads.readADC_SingleEnded(0);
  69. joystickoffset_y = ads.readADC_SingleEnded(1);
  70. mpu6050setup();
  71. }
  72. void mpu6050setup(){
  73. mpu.initialize();
  74. Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
  75. int devStatus = mpu.dmpInitialize();
  76. mpu.setXGyroOffset(62);
  77. mpu.setYGyroOffset(25);
  78. mpu.setZGyroOffset(-11);
  79. mpu.setXAccelOffset(-2030);
  80. mpu.setYAccelOffset(11);
  81. mpu.setZAccelOffset(2119); // 1688 factory default for my test chip
  82. if (devStatus == 0) {
  83. mpu.setDMPEnabled(true);
  84. attachInterrupt(15, dmpDataReady, RISING); //intrupt pin on pin 15
  85. mpuIntStatus = mpu.getIntStatus();
  86. dmpReady = true;
  87. packetSize = mpu.dmpGetFIFOPacketSize();
  88. } else {
  89. Serial.print(F("DMP Initialization failed (code "));
  90. Serial.print(devStatus);
  91. Serial.println(F(")"));
  92. }
  93. }
  94. u_long lasttime;
  95. int count;
  96. void loop(void){
  97. //wait for interupt from mpu6050, in the mean time pol udp server for new data
  98. while (!mpuInterrupt && fifoCount < packetSize) {
  99. //receiving rumble or shock data from basestation
  100. int noBytes = Udp.parsePacket();
  101. if ( noBytes ) {
  102. Serial.print(millis() / 1000);
  103. Serial.print(":Packet of ");
  104. Serial.print(noBytes);
  105. Serial.print(" received from ");
  106. Serial.print(Udp.remoteIP());
  107. Serial.print(":");
  108. Serial.println(Udp.remotePort());
  109. // We've received a packet, read the data from it
  110. Udp.read(packetBuffer,noBytes); // read the packet into the buffer
  111. // display the packet contents in HEX
  112. for (int i=1;i<=noBytes;i++){
  113. Serial.print(packetBuffer[i-1],HEX);
  114. if (i % 32 == 0){
  115. Serial.println();
  116. }
  117. else Serial.print(' ');
  118. }
  119. Serial.println();
  120. }
  121. delay(2);
  122. }
  123. //We are out of the while loop, so mpu interupt fired;
  124. readFifoMpu6050(&mpu6050data);
  125. readJoystick(&joystickdata);
  126. readSwitches(&switchdata);
  127. //Send new data
  128. joystickdata.button = 0;
  129. sendUdpMessage(&joystickdata, &mpu6050data, &switchdata);
  130. if(millis() - lasttime > 1000){
  131. printf("Samples per second: %d \n\r", count);
  132. count = 0;
  133. lasttime = millis();
  134. }else{
  135. count++;
  136. }
  137. }
  138. void readJoystick(struct JoystickData *joystickdata){
  139. joystickdata->x = ads.readADC_SingleEnded(1) - joystickoffset_x;
  140. delay(8);
  141. joystickdata->y = ads.readADC_SingleEnded(0) - joystickoffset_y;
  142. }
  143. void readFifoMpu6050(struct MPU6050Data *mpu6050data){
  144. // reset interrupt flag and get INT_STATUS byte
  145. mpuInterrupt = false;
  146. mpuIntStatus = mpu.getIntStatus();
  147. // get current FIFO count
  148. fifoCount = mpu.getFIFOCount();
  149. // check for overflow (this should never happen unless our code is too inefficient)
  150. if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
  151. // reset so we can continue cleanly
  152. mpu.resetFIFO();
  153. Serial.println(F("FIFO overflow!"));
  154. } else if (mpuIntStatus & 0x02){
  155. // wait for correct available data length, should be a VERY short wait
  156. while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
  157. // read a packet from FIFO
  158. mpu.getFIFOBytes(fifoBuffer, packetSize);
  159. // track FIFO count here in case there is > 1 packet available
  160. // (this lets us immediately read more without waiting for an interrupt)
  161. fifoCount -= packetSize;
  162. // get Euler angles in degrees
  163. mpu.dmpGetQuaternion(&q, fifoBuffer);
  164. mpu.dmpGetGravity(&gravity, &q);
  165. mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
  166. mpu6050data->yaw = ypr[0] * 18000/M_PI;
  167. mpu6050data->pitch = ypr[1] * 18000/M_PI;
  168. mpu6050data->roll = ypr[2] * 18000/M_PI;
  169. printf("ypr: %d | %d | %d \n\r", mpu6050data->yaw, mpu6050data->pitch, mpu6050data->roll);
  170. }
  171. }
  172. void readSwitches(struct SwitchData *switchdata){
  173. switchdata->magnetSwitch = !digitalRead(13);
  174. }
  175. void searchBasestation(void){
  176. Serial.print("Scanning for basestation ");
  177. for(int j = 0; j < 10; j++){
  178. int n = WiFi.scanNetworks();
  179. for (int i = 0; i < n; ++i){
  180. if(WiFi.SSID(i).startsWith(WifiSSIDPrefix)){ //We've found a basestation
  181. char WifiPassword[10];
  182. char WifiSSID[17];
  183. WiFi.SSID(i).toCharArray(WifiSSID, WiFi.SSID(i).length() + 1);
  184. calculateWiFiPassword(WiFi.SSID(i), WifiPassword);
  185. Serial.printf("Basestation found! SSID: %s", WifiSSID);
  186. Serial.printf("\nBasestation password: %s", WifiPassword);
  187. //Connect to the basestation
  188. WiFi.begin(WifiSSID, WifiPassword);
  189. while (WiFi.status() != WL_CONNECTED) {
  190. delay(500);
  191. Serial.print(".");
  192. }
  193. ///Writing data to eeprom
  194. writeEeprom(WifiSSID, WifiPassword);
  195. //Break out of the loop and stop scanning
  196. n = 254;
  197. j = 254;
  198. }
  199. }
  200. Serial.print(".");
  201. delay(1000);
  202. }
  203. }
  204. void connectLastBasestation(void){
  205. Serial.println("Reading information from EEPROM");
  206. char eepromWifiSSID[17];
  207. char eepromWifiPassword[10];
  208. //Read SSID
  209. for (int i = 0; i < 17; i++){
  210. eepromWifiSSID[i] = char(EEPROM.read(i));
  211. }
  212. eepromWifiSSID[17] = '\0';
  213. //Read Password
  214. for (int i = 0; i < 10; i++){
  215. eepromWifiPassword[i]= char(EEPROM.read(17+i));
  216. }
  217. eepromWifiPassword[10] = '\0';
  218. //Verify valid memory
  219. if(String(eepromWifiSSID).startsWith(WifiSSIDPrefix)){
  220. Serial.printf("Valid basestation information in eeprom found! \nEeprom SSID: %s \nEeprom Password: %s", eepromWifiSSID, eepromWifiPassword);
  221. //Connect to the basestation
  222. WiFi.begin(eepromWifiSSID, eepromWifiPassword);
  223. while (WiFi.status() != WL_CONNECTED) {
  224. delay(500);
  225. Serial.print(".");
  226. }
  227. }
  228. }
  229. void calculateWiFiPassword(String WifiSSID, char *WifiPassword)
  230. {
  231. String WifiStringPassword;
  232. for(char i=0; i < 17; i++){
  233. String s = String(WifiSSID[i], HEX);
  234. WifiStringPassword = s + WifiStringPassword;
  235. }
  236. for (int i=0; i < 10; i++)
  237. WifiPassword[i] = WifiStringPassword.charAt(i);
  238. WifiPassword[9] = '\0';
  239. }
  240. void sendUdpMessage(struct JoystickData *joystick, struct MPU6050Data *mpu6050data, struct SwitchData *switchdata){
  241. Udp.beginPacket(BasestationIp, BasestationPort);
  242. sprintf(sendBuffer, "%06d|%06d|%01d|", joystick->x, joystick->y, joystick->button);
  243. sprintf(sendBuffer, "%s%06d|%06d|%06d", sendBuffer, mpu6050data->yaw, mpu6050data->pitch, mpu6050data->roll);
  244. sprintf(sendBuffer, "%s%01d|%01d", sendBuffer, switchdata->backSwitch, switchdata->magnetSwitch);
  245. // Serial.printf("%s", sendBuffer);
  246. // Serial.println();
  247. Udp.write(sendBuffer);
  248. Udp.endPacket();
  249. }
  250. void writeEeprom(char *WifiSSID, char *WifiPassword){
  251. //Clean memory
  252. clearEeprom();
  253. //Write ssid
  254. for(int i = 0; i < 17; i++){
  255. EEPROM.write(i, WifiSSID[i]);
  256. }
  257. //Write password
  258. for(int i = 0; i < 10; i++){
  259. EEPROM.write(17+i, WifiPassword[i]);
  260. }
  261. EEPROM.commit();
  262. }
  263. void clearEeprom(){
  264. for (int i = 0; i < 30; i++) { EEPROM.write(i, 0); }
  265. }