Controller.ino 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. #include "I2Cdev.h"
  2. #include "MPU6050.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. int16_t ax, ay, az;
  29. int16_t gx, gy, gz;
  30. double ax_scaled, ay_scaled, az_scaled;
  31. double gx_scaled, gy_scaled, gz_scaled;
  32. double roll, pitch, yaw;
  33. double gx_off, gy_off, gz_off;
  34. double gyro_scale = 131.0;
  35. double accel_scale = 16384.0;
  36. //Joystick offsets
  37. int joystickoffset_x, joystickoffset_y;
  38. //rumble
  39. boolean rumbleActivated;
  40. u_long rumbleDuration;
  41. //Data buffer for sensors
  42. struct MPU6050Data mpu6050data = {0};
  43. struct JoystickData joystickdata = {0};
  44. struct SwitchData switchdata = {0};
  45. //UDP server (receiving) setup
  46. unsigned int udpPort = 2730;
  47. byte packetBuffer[68]; //udp package buffer
  48. char sendBuffer[68];
  49. WiFiUDP Udp;
  50. //Button pressed counter
  51. boolean isCounting = false;
  52. u_long startCountingTime;
  53. void setup(void){
  54. Serial.begin(115200);
  55. Serial.println("Starting controller..");
  56. WiFi.mode(WIFI_STA);
  57. EEPROM.begin(512);
  58. delay(10);
  59. Wire.begin(13,14);
  60. //Magnetic sensor
  61. pinMode(5,INPUT);
  62. //Joystick button
  63. pinMode(12,INPUT);
  64. //back button
  65. pinMode(0,INPUT);
  66. //Rumble motor
  67. pinMode(15, OUTPUT);
  68. //clearEeprom();
  69. connectLastBasestation();
  70. //searchBasestation();
  71. delay(200);
  72. Udp.begin(udpPort);
  73. ads.begin();
  74. joystickoffset_x = ads.readADC_SingleEnded(0, 1);
  75. joystickoffset_y = ads.readADC_SingleEnded(1, 1);
  76. delay(200);
  77. mpu6050setup();
  78. }
  79. void mpu6050setup(){
  80. mpu.initialize();
  81. Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
  82. calibrate();
  83. }
  84. void calibrate(){
  85. getMotion6Scaled();
  86. get_x_rotation(ax_scaled, ay_scaled, az_scaled, &roll);
  87. get_y_rotation(ax_scaled, ay_scaled, az_scaled, &pitch);
  88. yaw = 0;
  89. gx_off = gx_scaled;
  90. gy_off = gy_scaled;
  91. gz_off = gz_scaled;
  92. }
  93. void getMotion6Scaled(){
  94. mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  95. ax_scaled = ax / accel_scale;
  96. ay_scaled = ay / accel_scale;
  97. az_scaled = az / accel_scale;
  98. gx_scaled = gx / gyro_scale;
  99. gy_scaled = gy / gyro_scale;
  100. gz_scaled = gz / gyro_scale;
  101. }
  102. void get_y_rotation(double x, double y, double z, double* y_rotation){
  103. *y_rotation = ((atan2(x, dist(y, z))) * 4068.0) / 71.0;
  104. }
  105. void get_x_rotation(double x, double y, double z, double* x_rotation){
  106. *x_rotation = ((atan2(y, dist(x, z))) * -4068.0) / 71.0;
  107. }
  108. double dist(double a, double b){
  109. return sqrt((a * a) + (b * b));
  110. }
  111. u_long lasttime;
  112. void loop(void){
  113. readMpu6050(&mpu6050data);
  114. if(millis() - lasttime > 28){
  115. lasttime = millis();
  116. //Poll udp server
  117. int noBytes = Udp.parsePacket();
  118. if ( noBytes ) {
  119. Udp.read(packetBuffer,noBytes);
  120. if(packetBuffer[0] == '1'){
  121. char tmpstr[7];
  122. strncpy(tmpstr, (char*)packetBuffer+4, 6);
  123. int rumbleDuration = atoi(tmpstr);
  124. strncpy(tmpstr, (char*)packetBuffer+11, 3);
  125. int rumblePower = atoi(tmpstr);
  126. rumble(rumbleDuration, rumblePower);
  127. Serial.printf("Received udp package! Rumble duration: %d ~ Rumble power : %d", rumbleDuration, rumblePower);
  128. }else if(packetBuffer[0] == '2'){ //Shock
  129. }
  130. Serial.println();
  131. }
  132. if(rumbleActivated == true && millis() > rumbleDuration){
  133. rumbleActivated = false;
  134. analogWrite(15, 0);
  135. }
  136. readJoystick(&joystickdata);
  137. readSwitches(&switchdata);
  138. //Send new data
  139. sendUdpMessage(&joystickdata, &mpu6050data, &switchdata);
  140. }else{
  141. delay(5);
  142. }
  143. }
  144. void readMpu6050(struct MPU6050Data *mpu6050data){
  145. getMotion6Scaled();
  146. gx_scaled -= gx_off;
  147. gy_scaled -= gy_off;
  148. gz_scaled -= gz_off;
  149. double gx_delta = (gx_scaled * 0.01);
  150. double gy_delta = (gy_scaled * 0.01);
  151. double gz_delta = (gz_scaled * 0.01);
  152. double rotationx, rotationy;
  153. get_y_rotation(ax_scaled, ay_scaled, az_scaled, &rotationy);
  154. get_x_rotation(ax_scaled, ay_scaled, az_scaled, &rotationx);
  155. pitch = 0.98 * (pitch + gy_delta) + (0.02 * rotationy);
  156. roll = 0.98 * (roll + gx_delta) + (0.02 * rotationx);
  157. mpu6050data->pitch = pitch*100;
  158. mpu6050data->roll = roll*100;
  159. mpu6050data->yaw = 0;
  160. mpu6050data->ax = ax_scaled;
  161. mpu6050data->ay = ay_scaled;
  162. mpu6050data->az = az_scaled;
  163. }
  164. void readJoystick(struct JoystickData *joystickdata){
  165. joystickdata->x = ads.readADC_SingleEnded(1, 0) - joystickoffset_x;
  166. delay(8);
  167. joystickdata->y = ads.readADC_SingleEnded(0, 0) - joystickoffset_y;
  168. joystickdata->button = !digitalRead(12);
  169. }
  170. void readSwitches(struct SwitchData *switchdata){
  171. switchdata->backSwitch = !digitalRead(0);
  172. switchdata->magnetSwitch = !digitalRead(5);
  173. if(!switchdata->backSwitch){
  174. isCounting = false;
  175. }else if(isCounting){
  176. if(millis() - startCountingTime > 8000){ //Pressed longer then 8 seconds, start searching for basestation
  177. rumble(1000, 150);
  178. searchBasestation();
  179. }
  180. }else if(switchdata->backSwitch){
  181. isCounting = true;
  182. startCountingTime = millis();
  183. }
  184. }
  185. void rumble(int duration, int power){
  186. rumbleActivated = true;
  187. analogWrite(15, power);
  188. rumbleDuration = millis() + duration;
  189. }
  190. void searchBasestation(void){
  191. Serial.print("Scanning for basestation ");
  192. for(int j = 0; j < 10; j++){
  193. int n = WiFi.scanNetworks();
  194. for (int i = 0; i < n; ++i){
  195. if(WiFi.SSID(i).startsWith(WifiSSIDPrefix)){ //We've found a basestation
  196. char WifiPassword[10];
  197. char WifiSSID[17];
  198. WiFi.SSID(i).toCharArray(WifiSSID, WiFi.SSID(i).length() + 1);
  199. calculateWiFiPassword(WiFi.SSID(i), WifiPassword);
  200. Serial.printf("Basestation found! SSID: %s", WifiSSID);
  201. Serial.printf("\nBasestation password: %s", WifiPassword);
  202. //Connect to the basestation
  203. WiFi.begin(WifiSSID, WifiPassword);
  204. while (WiFi.status() != WL_CONNECTED) {
  205. delay(500);
  206. Serial.print(".");
  207. }
  208. ///Writing data to eeprom
  209. writeEeprom(WifiSSID, WifiPassword);
  210. //Break out of the loop and stop scanning
  211. n = 254;
  212. j = 254;
  213. }
  214. }
  215. Serial.print(".");
  216. delay(1000);
  217. }
  218. }
  219. void connectLastBasestation(void){
  220. Serial.println("Reading information from EEPROM");
  221. char eepromWifiSSID[17];
  222. char eepromWifiPassword[10];
  223. //Read SSID
  224. for (int i = 0; i < 17; i++){
  225. eepromWifiSSID[i] = char(EEPROM.read(i));
  226. }
  227. eepromWifiSSID[17] = '\0';
  228. //Read Password
  229. for (int i = 0; i < 10; i++){
  230. eepromWifiPassword[i]= char(EEPROM.read(17+i));
  231. }
  232. eepromWifiPassword[10] = '\0';
  233. //Verify valid memory
  234. if(String(eepromWifiSSID).startsWith(WifiSSIDPrefix)){
  235. Serial.printf("Valid basestation information in eeprom found! \nEeprom SSID: %s \nEeprom Password: %s", eepromWifiSSID, eepromWifiPassword);
  236. //Connect to the basestation
  237. startCountingTime = millis();
  238. WiFi.begin(eepromWifiSSID, eepromWifiPassword);
  239. while (WiFi.status() != WL_CONNECTED) {
  240. delay(500);
  241. Serial.print(".");
  242. if(millis() - startCountingTime > 15000){
  243. break;
  244. }
  245. }
  246. }
  247. }
  248. void calculateWiFiPassword(String WifiSSID, char *WifiPassword)
  249. {
  250. String WifiStringPassword;
  251. for(char i=0; i < 17; i++){
  252. String s = String(WifiSSID[i], HEX);
  253. WifiStringPassword = s + WifiStringPassword;
  254. }
  255. for (int i=0; i < 10; i++)
  256. WifiPassword[i] = WifiStringPassword.charAt(i);
  257. WifiPassword[9] = '\0';
  258. }
  259. void sendUdpMessage(struct JoystickData *joystick, struct MPU6050Data *mpu6050data, struct SwitchData *switchdata){
  260. Udp.beginPacket(BasestationIp, BasestationPort);
  261. sprintf(sendBuffer, "%06d|%06d|%01d|", joystick->x, joystick->y, joystick->button);
  262. sprintf(sendBuffer, "%s%06d|%06d|%06d|", sendBuffer, mpu6050data->yaw, mpu6050data->pitch, mpu6050data->roll);
  263. sprintf(sendBuffer, "%s%01d|%01d|", sendBuffer, switchdata->backSwitch, switchdata->magnetSwitch);
  264. sprintf(sendBuffer, "%s%06d|%06d|%06d", sendBuffer, mpu6050data->ax, mpu6050data->ay, mpu6050data->az);
  265. Serial.printf("%s", sendBuffer);
  266. Serial.println();
  267. Udp.write(sendBuffer);
  268. Udp.endPacket();
  269. }
  270. void writeEeprom(char *WifiSSID, char *WifiPassword){
  271. //Clean memory
  272. clearEeprom();
  273. //Write ssid
  274. for(int i = 0; i < 17; i++){
  275. EEPROM.write(i, WifiSSID[i]);
  276. }
  277. //Write password
  278. for(int i = 0; i < 10; i++){
  279. EEPROM.write(17+i, WifiPassword[i]);
  280. }
  281. EEPROM.commit();
  282. }
  283. void clearEeprom(){
  284. for (int i = 0; i < 30; i++) { EEPROM.write(i, 0); }
  285. }