safwan092

Untitled

Oct 17th, 2025
25
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 22.22 KB | None | 0 0
  1. #include <Wire.h>
  2. #include <TinyGPSPlus.h>
  3.  
  4. //////////////////////
  5. /*
  6. get_gps_data();
  7. sendSMSLocation();
  8. */
  9. //////////////////////
  10. ////////////////////////////////////////////////
  11. String s = "www.google.com/maps/dir/";
  12. static const uint32_t GPSBaud = 9600;
  13. String Lat = "";
  14. String Lng = "";
  15. int SendSMS_Now = 0;
  16. const size_t BUFSIZE = 300;
  17. char f_buffer[BUFSIZE];
  18. float *f_buf = (float*)f_buffer;
  19. TinyGPSPlus gps;
  20. ////////////////////////////////////////////////
  21.  
  22. ////////////////////////////////////////////////
  23. const int MPU_ADDR = 0x68;
  24. // MPU6050 register addresses
  25. const int PWR_MGMT_1 = 0x6B;
  26. const int ACCEL_XOUT_H = 0x3B;
  27. const int GYRO_XOUT_H = 0x43;
  28. const int TEMP_OUT_H = 0x41;
  29. // Calibration offsets
  30. float accelOffsetX = 0;
  31. float accelOffsetY = 0;
  32. float accelOffsetZ = 0;
  33. float gyroOffsetX = 0;
  34. float gyroOffsetY = 0;
  35. float gyroOffsetZ = 0;
  36. // Adaptive thresholds - will adjust based on normal motion
  37. float adaptiveAccelThreshold = 3.0; // Start with reasonable value
  38. float adaptiveGyroThreshold = 50.0; // Start with reasonable value
  39. // Impact detection
  40. const unsigned long IMPACT_WINDOW = 100; // Time to analyze impact (ms)
  41. const unsigned long HIT_COOLDOWN = 2000; // Prevent multiple detections
  42. const float SUDDEN_CHANGE_FACTOR = 3.0; // Must be 3x normal motion
  43. // Fall detection parameters
  44. const float FREE_FALL_THRESHOLD = 0.5; // Low G-force for free fall
  45. const float FALL_IMPACT_THRESHOLD = 4.0; // G-force for fall impact
  46. const unsigned long FALL_TIME_WINDOW = 3000; // Max time for fall sequence
  47. const unsigned long FALL_COOLDOWN = 5000; // Cooldown between fall detections
  48. // State variables
  49. bool hitDetected = false;
  50. bool fallDetected = false;
  51. unsigned long lastHitTime = 0;
  52. unsigned long lastFallTime = 0;
  53. unsigned long impactStartTime = 0;
  54. bool analyzingImpact = false;
  55. // Fall detection states
  56. bool inFreeFall = false;
  57. unsigned long fallStartTime = 0;
  58. bool waitingForFallImpact = false;
  59. // For adaptive threshold calculation
  60. float normalAccelMax = 0;
  61. float normalGyroMax = 0;
  62. unsigned long lastNormalUpdate = 0;
  63. const unsigned long NORMAL_LEARNING_TIME = 5000; // Learn normal motion for 5 sec
  64. // Impact analysis
  65. float impactAccelPeaks[10] = {0};
  66. float impactGyroPeaks[10] = {0};
  67. int peakCount = 0;
  68. // Filtering
  69. const int MOVING_AVERAGE_SAMPLES = 5;
  70. float accelBuffer[MOVING_AVERAGE_SAMPLES] = {0};
  71. float gyroBuffer[MOVING_AVERAGE_SAMPLES] = {0};
  72. int bufferIndex = 0;
  73. bool calibrated = false;
  74. const int CALIBRATION_SAMPLES = 100;
  75. bool learningPhase = true;
  76. ////////////////////////////////////////////////
  77.  
  78.  
  79.  
  80. void setup() {
  81. Serial.begin(115200);
  82. Wire.begin();
  83.  
  84. // Wake up MPU6050
  85. Wire.beginTransmission(MPU_ADDR);
  86. Wire.write(PWR_MGMT_1);
  87. Wire.write(0);
  88. Wire.endTransmission(true);
  89.  
  90. Serial.println("HEAD IMPACT & FALL DETECTION SYSTEM");
  91. Serial.println("Learning normal motion for 5 seconds...");
  92. Serial.println("Please walk around normally");
  93. calibrateSensor();
  94. Serial.println("Calibration complete!");
  95. Serial.println("======================================");
  96. lastNormalUpdate = millis();
  97.  
  98. setupA9G();
  99. Serial.println("Setup Executed");
  100. }
  101.  
  102. void send_SMS_NOW() {
  103. SendSMS_Now = 1;
  104. }
  105.  
  106. void calibrateSensor() {
  107. float accelXSum = 0, accelYSum = 0, accelZSum = 0;
  108. float gyroXSum = 0, gyroYSum = 0, gyroZSum = 0;
  109.  
  110. for (int i = 0; i < CALIBRATION_SAMPLES; i++) {
  111. int16_t accelX = readSensor(ACCEL_XOUT_H);
  112. int16_t accelY = readSensor(ACCEL_XOUT_H + 2);
  113. int16_t accelZ = readSensor(ACCEL_XOUT_H + 4);
  114. int16_t gyroX = readSensor(GYRO_XOUT_H);
  115. int16_t gyroY = readSensor(GYRO_XOUT_H + 2);
  116. int16_t gyroZ = readSensor(GYRO_XOUT_H + 4);
  117.  
  118. accelXSum += accelX / 16384.0;
  119. accelYSum += accelY / 16384.0;
  120. accelZSum += accelZ / 16384.0;
  121. gyroXSum += gyroX / 131.0;
  122. gyroYSum += gyroY / 131.0;
  123. gyroZSum += gyroZ / 131.0;
  124.  
  125. delay(10);
  126. }
  127.  
  128. accelOffsetX = accelXSum / CALIBRATION_SAMPLES;
  129. accelOffsetY = accelYSum / CALIBRATION_SAMPLES;
  130. accelOffsetZ = accelZSum / CALIBRATION_SAMPLES - 1.0;
  131.  
  132. gyroOffsetX = gyroXSum / CALIBRATION_SAMPLES;
  133. gyroOffsetY = gyroYSum / CALIBRATION_SAMPLES;
  134. gyroOffsetZ = gyroZSum / CALIBRATION_SAMPLES;
  135.  
  136. calibrated = true;
  137. }
  138.  
  139. float movingAverage(float buffer[], float newValue) {
  140. buffer[bufferIndex] = newValue;
  141. bufferIndex = (bufferIndex + 1) % MOVING_AVERAGE_SAMPLES;
  142.  
  143. float sum = 0;
  144. for (int i = 0; i < MOVING_AVERAGE_SAMPLES; i++) {
  145. sum += buffer[i];
  146. }
  147. return sum / MOVING_AVERAGE_SAMPLES;
  148. }
  149.  
  150.  
  151. //////////////////////////////////////////////////////////
  152. /////////////////// LOOP //////////////////////////
  153. //////////////////////////////////////////////////////////
  154. void loop() {
  155. fullGPSSerial();
  156. readGPS_Data();
  157. //showLATLON();
  158. if (SendSMS_Now == 1) {
  159. get_gps_data();
  160. sendSMSwithLocation1();
  161. delay(2000);
  162. s = "www.google.com/maps/dir/";
  163. SendSMS_Now = 0;
  164. }
  165. // Read sensor data
  166. int16_t rawAccelX = readSensor(ACCEL_XOUT_H);
  167. int16_t rawAccelY = readSensor(ACCEL_XOUT_H + 2);
  168. int16_t rawAccelZ = readSensor(ACCEL_XOUT_H + 4);
  169.  
  170. int16_t rawGyroX = readSensor(GYRO_XOUT_H);
  171. int16_t rawGyroY = readSensor(GYRO_XOUT_H + 2);
  172. int16_t rawGyroZ = readSensor(GYRO_XOUT_H + 4);
  173.  
  174. // Convert and apply calibration
  175. float accelX_g = rawAccelX / 16384.0 - accelOffsetX;
  176. float accelY_g = rawAccelY / 16384.0 - accelOffsetY;
  177. float accelZ_g = rawAccelZ / 16384.0 - accelOffsetZ;
  178.  
  179. float gyroX_deg = rawGyroX / 131.0 - gyroOffsetX;
  180. float gyroY_deg = rawGyroY / 131.0 - gyroOffsetY;
  181. float gyroZ_deg = rawGyroZ / 131.0 - gyroOffsetZ;
  182.  
  183. // Calculate magnitudes with moving average filtering
  184. float accelMagnitude = sqrt(accelX_g * accelX_g + accelY_g * accelY_g + accelZ_g * accelZ_g);
  185. float gyroMagnitude = sqrt(gyroX_deg * gyroX_deg + gyroY_deg * gyroY_deg + gyroZ_deg * gyroZ_deg);
  186.  
  187. float filteredAccel = movingAverage(accelBuffer, accelMagnitude);
  188. float filteredGyro = movingAverage(gyroBuffer, gyroMagnitude);
  189.  
  190. unsigned long currentTime = millis();
  191.  
  192. // Learning phase - understand normal motion
  193. if (learningPhase) {
  194. updateNormalMotionLevels(filteredAccel, filteredGyro, currentTime);
  195. }
  196.  
  197. // Run both detection systems
  198. checkForImpact(filteredAccel, filteredGyro, currentTime);
  199. checkForFall(filteredAccel, currentTime);
  200.  
  201. // Print status
  202. static unsigned long lastPrint = 0;
  203. if (currentTime - lastPrint > 1000) {
  204. printStatus(accelX_g, accelY_g, accelZ_g, gyroX_deg, gyroY_deg, gyroZ_deg,
  205. filteredAccel, filteredGyro, currentTime);
  206. lastPrint = currentTime;
  207. }
  208.  
  209. delay(20);
  210. }// end of LOOP
  211. ///////////////////////////////////////////////////////////////
  212. ///////////////////////////////////////////////////////////////
  213.  
  214. ////////////////////////////////////////////////////////////
  215. void sendSMSLocation() {
  216. Serial.println("WARNING! Vehicle Overturned");
  217. Serial2.println("AT+CMGF=1\r");
  218. delay(1000);
  219. Serial2.println("AT+CNMI=2,2,0,0,0\r");
  220. delay(1000);
  221. Serial2.print("AT+CMGS=\"+966559070115\"\r");//Replace this with your mobile number
  222. delay(1000);
  223. Serial2.print("WARNING! Vehicle Overturned \n");
  224. Serial2.print(s);
  225. Serial2.write(0x1A);
  226. delay(1000);
  227. s = "www.google.com/maps/dir/";
  228. }
  229. ////////////////////////////////////////////////////////////
  230.  
  231. void updateNormalMotionLevels(float accel, float gyro, unsigned long currentTime) {
  232. // Update maximum normal motion levels during learning phase
  233. if (accel > normalAccelMax) normalAccelMax = accel;
  234. if (gyro > normalGyroMax) normalGyroMax = gyro;
  235.  
  236. // End learning phase after 5 seconds
  237. if (currentTime - lastNormalUpdate > NORMAL_LEARNING_TIME) {
  238. learningPhase = false;
  239.  
  240. // Set adaptive thresholds based on learned normal motion
  241. adaptiveAccelThreshold = normalAccelMax * SUDDEN_CHANGE_FACTOR;
  242. adaptiveGyroThreshold = normalGyroMax * SUDDEN_CHANGE_FACTOR;
  243.  
  244. // Ensure minimum thresholds
  245. if (adaptiveAccelThreshold < 2.0) adaptiveAccelThreshold = 2.0;
  246. if (adaptiveGyroThreshold < 30.0) adaptiveGyroThreshold = 30.0;
  247.  
  248. Serial.println("\n*** LEARNING PHASE COMPLETE ***");
  249. Serial.print("Normal motion - Max Accel: "); Serial.print(normalAccelMax, 2); Serial.println("g");
  250. Serial.print("Normal motion - Max Gyro: "); Serial.print(normalGyroMax, 1); Serial.println("Β°/s");
  251. Serial.print("Adaptive thresholds - Accel: "); Serial.print(adaptiveAccelThreshold, 2); Serial.println("g");
  252. Serial.print("Adaptive thresholds - Gyro: "); Serial.print(adaptiveGyroThreshold, 1); Serial.println("Β°/s");
  253. Serial.println("Now monitoring for impacts and falls...");
  254. }
  255. }
  256.  
  257. void checkForImpact(float accel, float gyro, unsigned long currentTime) {
  258. // Check if we have a sudden change that might be an impact
  259. bool suddenChange = (accel > adaptiveAccelThreshold) || (gyro > adaptiveGyroThreshold);
  260.  
  261. if (suddenChange && !analyzingImpact) {
  262. // Start analyzing potential impact
  263. analyzingImpact = true;
  264. impactStartTime = currentTime;
  265. peakCount = 0;
  266. impactAccelPeaks[0] = accel;
  267. impactGyroPeaks[0] = gyro;
  268. Serial.println("πŸ’₯ Potential impact detected - analyzing...");
  269. }
  270.  
  271. if (analyzingImpact) {
  272. // Track peaks during impact window
  273. if (accel > impactAccelPeaks[peakCount]) impactAccelPeaks[peakCount] = accel;
  274. if (gyro > impactGyroPeaks[peakCount]) impactGyroPeaks[peakCount] = gyro;
  275.  
  276. // Check if impact analysis period is over
  277. if (currentTime - impactStartTime > IMPACT_WINDOW) {
  278. analyzeImpactPattern(currentTime);
  279. analyzingImpact = false;
  280. }
  281.  
  282. // Move to next peak every 20ms
  283. if (currentTime - impactStartTime > (peakCount + 1) * 20 && peakCount < 9) {
  284. peakCount++;
  285. impactAccelPeaks[peakCount] = accel;
  286. impactGyroPeaks[peakCount] = gyro;
  287. }
  288. }
  289.  
  290. // Reset hit detection after cooldown
  291. if (currentTime - lastHitTime > HIT_COOLDOWN) {
  292. hitDetected = false;
  293. }
  294. }
  295.  
  296. void analyzeImpactPattern(unsigned long currentTime) {
  297. // Find maximum values during impact window
  298. float maxAccel = 0;
  299. float maxGyro = 0;
  300.  
  301. for (int i = 0; i <= peakCount; i++) {
  302. if (impactAccelPeaks[i] > maxAccel) maxAccel = impactAccelPeaks[i];
  303. if (impactGyroPeaks[i] > maxGyro) maxGyro = impactGyroPeaks[i];
  304. }
  305.  
  306. // Determine if this is a real head impact
  307. bool isHeadImpact = verifyHeadImpact(maxAccel, maxGyro);
  308.  
  309. if (isHeadImpact && !hitDetected) {
  310. hitDetected = true;
  311. lastHitTime = currentTime;
  312.  
  313. Serial.println("🚨 🚨 🚨 🚨 🚨 🚨 🚨 🚨 🚨 🚨 🚨 🚨");
  314. Serial.println("🚨 HEAD IMPACT DETECTED! 🚨");
  315. Serial.println("🚨 🚨 🚨 🚨 🚨 🚨 🚨 🚨 🚨 🚨 🚨 🚨");
  316. Serial.print("Impact Force: "); Serial.print(maxAccel, 1); Serial.println("g");
  317. Serial.print("Rotational Force: "); Serial.print(maxGyro, 1); Serial.println("Β°/s");
  318. Serial.print("Thresholds: "); Serial.print(adaptiveAccelThreshold, 1);
  319. Serial.print("g / "); Serial.print(adaptiveGyroThreshold, 1); Serial.println("Β°/s");
  320. Serial.println("⚠️ CHECK USER FOR CONCUSSION SYMPTOMS!");
  321. Serial.println();
  322. } else if (!isHeadImpact) {
  323. Serial.print("❌ False alarm: ");
  324. Serial.print(maxAccel, 1); Serial.print("g, ");
  325. Serial.print(maxGyro, 1); Serial.println("Β°/s - Normal motion pattern");
  326. }
  327. }
  328.  
  329. bool verifyHeadImpact(float maxAccel, float maxGyro) {
  330. // Real head impacts typically have:
  331. // 1. Very high acceleration OR very high rotation
  332. // 2. Both values significantly above normal motion
  333. // 3. Specific pattern characteristics
  334.  
  335. bool highAccel = maxAccel > (normalAccelMax * 4.0); // 4x normal motion
  336. bool highGyro = maxGyro > (normalGyroMax * 4.0); // 4x normal motion
  337.  
  338. // Head impact usually has both linear and rotational components
  339. bool hasBothComponents = (maxAccel > adaptiveAccelThreshold * 1.2) &&
  340. (maxGyro > adaptiveGyroThreshold * 1.2);
  341.  
  342. // Or extremely high values in one component
  343. bool extremeSingleComponent = (maxAccel > adaptiveAccelThreshold * 2.0) ||
  344. (maxGyro > adaptiveGyroThreshold * 2.0);
  345.  
  346. return (hasBothComponents || extremeSingleComponent) && (highAccel || highGyro);
  347. }
  348.  
  349. void checkForFall(float accel, unsigned long currentTime) {
  350. // Fall detection logic: Free fall followed by impact
  351.  
  352. // Step 1: Detect free fall (low acceleration)
  353. if (accel < FREE_FALL_THRESHOLD && !inFreeFall && !waitingForFallImpact) {
  354. inFreeFall = true;
  355. fallStartTime = currentTime;
  356. Serial.println("⚠️ Free fall detected! Monitoring for impact...");
  357. }
  358.  
  359. // Step 2: If we're in free fall, wait for impact
  360. if (inFreeFall) {
  361. // Check if free fall period is too long (might not be a real fall)
  362. if (currentTime - fallStartTime > FALL_TIME_WINDOW) {
  363. inFreeFall = false;
  364. Serial.println("❌ Free fall too long - probably not a real fall");
  365. }
  366.  
  367. // Check for impact after free fall
  368. if (accel > FALL_IMPACT_THRESHOLD) {
  369. // This is the impact after a fall
  370. if (!fallDetected && (currentTime - lastFallTime > FALL_COOLDOWN)) {
  371. fallDetected = true;
  372. lastFallTime = currentTime;
  373. inFreeFall = false;
  374. waitingForFallImpact = false;
  375.  
  376. Serial.println("🚨 🚨 🚨 🚨 🚨 🚨 🚨 🚨 🚨 🚨 🚨 🚨");
  377. Serial.println("🚨 FALL DETECTED! 🚨");
  378. Serial.println("🚨 🚨 🚨 🚨 🚨 🚨 🚨 🚨 🚨 🚨 🚨 🚨");
  379. Serial.print("Fall Impact: "); Serial.print(accel, 1); Serial.println("g");
  380. Serial.print("Free fall duration: ");
  381. Serial.print(currentTime - fallStartTime);
  382. Serial.println("ms");
  383. Serial.println("⚠️ USER MAY HAVE FALLEN - CHECK IMMEDIATELY!");
  384. Serial.println();
  385. }
  386. }
  387. }
  388.  
  389. // Reset fall detection after cooldown
  390. if (currentTime - lastFallTime > FALL_COOLDOWN) {
  391. fallDetected = false;
  392. }
  393.  
  394. // Reset free fall state if acceleration returns to normal
  395. if (inFreeFall && accel > FREE_FALL_THRESHOLD * 2.0) {
  396. inFreeFall = false;
  397. waitingForFallImpact = true;
  398. // Wait a bit to see if impact comes
  399. if (currentTime - fallStartTime > 1000) {
  400. waitingForFallImpact = false;
  401. }
  402. }
  403. }
  404.  
  405. void printStatus(float accelX, float accelY, float accelZ, float gyroX, float gyroY, float gyroZ,
  406. float accelMag, float gyroMag, unsigned long currentTime) {
  407. Serial.print("Accel: ");
  408. Serial.print(accelX, 2); Serial.print("g, ");
  409. Serial.print(accelY, 2); Serial.print("g, ");
  410. Serial.print(accelZ, 2); Serial.print("g");
  411. Serial.print(" | Total: "); Serial.print(accelMag, 2); Serial.println("g");
  412.  
  413. Serial.print("Gyro: ");
  414. Serial.print(gyroX, 1); Serial.print("Β°/s, ");
  415. Serial.print(gyroY, 1); Serial.print("Β°/s, ");
  416. Serial.print(gyroZ, 1); Serial.print("Β°/s");
  417. Serial.print(" | Total: "); Serial.print(gyroMag, 1); Serial.println("Β°/s");
  418.  
  419. if (learningPhase) {
  420. float remaining = (NORMAL_LEARNING_TIME - (currentTime - lastNormalUpdate)) / 1000.0;
  421. Serial.print("πŸ“š Learning normal motion: ");
  422. Serial.print(remaining, 0); Serial.println("s remaining");
  423. Serial.print("Current max - Accel: "); Serial.print(normalAccelMax, 2);
  424. Serial.print("g, Gyro: "); Serial.print(normalGyroMax, 1); Serial.println("Β°/s");
  425. } else {
  426. Serial.print("🎯 Thresholds: "); Serial.print(adaptiveAccelThreshold, 1);
  427. Serial.print("g / "); Serial.print(adaptiveGyroThreshold, 1); Serial.println("Β°/s");
  428.  
  429. // Status display for both systems
  430. if (hitDetected) {
  431. Serial.println("🚨 HEAD IMPACT DETECTED - CHECK USER!");
  432. } else if (fallDetected) {
  433. Serial.println("🚨 FALL DETECTED - USER MAY HAVE FALLEN!");
  434. } else if (inFreeFall) {
  435. Serial.println("⚠️ Free fall detected - watching for impact...");
  436. } else if (analyzingImpact) {
  437. Serial.println("πŸ’₯ Analyzing potential impact...");
  438. } else {
  439. Serial.println("βœ… Normal - Monitoring impacts & falls");
  440. }
  441. }
  442.  
  443. Serial.println("-----------------------");
  444. }
  445.  
  446. int16_t readSensor(uint8_t reg) {
  447. Wire.beginTransmission(MPU_ADDR);
  448. Wire.write(reg);
  449. Wire.endTransmission(false);
  450. Wire.requestFrom(MPU_ADDR, 2, true);
  451. return (Wire.read() << 8) | Wire.read();
  452. }
  453.  
  454.  
  455. void get_gps_data() {
  456. if (gps.location.lat() == 0 || gps.location.lng() == 0) {
  457. Serial.println("Return Executed");
  458. s = "http://www.google.com/maps/dir/19.204871,42.085309";
  459. Serial.println(s);
  460. return;
  461. }
  462. Serial.print("Latitude (deg): ");
  463. Lat = String(gps.location.lat(), 6);
  464. Serial.println(Lat);
  465. Serial.print("Longitude (deg): ");
  466. Lng = String(gps.location.lng(), 6);
  467. Serial.println(Lng);
  468. Serial.println();
  469. s += String(gps.location.lat(), 6);
  470. s += ",";
  471. s += String(gps.location.lng(), 6);
  472. s += "/";
  473. Serial.println(s);
  474. }
  475.  
  476. void setupA9G() {
  477. Serial2.begin(GPSBaud);
  478. Serial.println("Starting...");
  479. Serial2.println("\r");
  480. Serial2.println("AT\r");
  481. delay(10);
  482. Serial2.println("\r");
  483. Serial2.println("AT+GPS=1\r");
  484. delay(100);
  485. Serial2.println("AT+CREG=2\r");
  486. delay(6000);
  487. //ss.print("AT+CREG?\r");
  488. Serial2.println("AT+CGATT=1\r");
  489. delay(6000);
  490. Serial2.println("AT+CGDCONT=1,\"IP\",\"WWW\"\r");
  491. delay(6000);
  492. // ss.println("AT+LOCATION=1\r");
  493. Serial2.println("AT+CGACT=1,1\r");
  494. delay(6000);
  495. //Initialize ends
  496. //Initialize GPS
  497. Serial2.println("\r");
  498. Serial2.println("AT+GPS=1\r");
  499. delay(1000);
  500. //ss.println("AT+GPSMD=1\r"); // Change to only GPS mode from GPS+BDS, set to 2 to revert to default.
  501. Serial2.println("AT+GPSRD=10\r");
  502. delay(100);
  503. // set SMS mode to text mode
  504. Serial2.println("AT+CMGF=1\r");
  505. delay(1000);
  506. //ss.println("AT+LOCATION=2\r");
  507. Serial.println(F("FullExample.ino"));
  508. Serial.println(F("An extensive example of many interesting TinyGPSPlus features"));
  509. Serial.print(F("Testing TinyGPSPlus library v. ")); Serial.println(TinyGPSPlus::libraryVersion());
  510. Serial.println(F("by Mikal Hart"));
  511. Serial.println();
  512. Serial.println(F("Sats HDOP Latitude Longitude Fix Date Time Date Alt Course Speed Card Distance Course Card Chars Sentences Checksum"));
  513. Serial.println(F(" (deg) (deg) Age Age (m) --- from GPS ---- ---- to London ---- RX RX Fail"));
  514. Serial.println(F("----------------------------------------------------------------------------------------------------------------------------------------"));
  515. }
  516.  
  517. void readGPS_Data() {
  518. smartDelay(2000);
  519. if (millis() > 5000 && gps.charsProcessed() < 10)
  520. Serial.println(F("No GPS data received: check wiring"));
  521. }
  522.  
  523. void showLATLON() {
  524. Serial.print("Latitude (deg): ");
  525. Lat = String(gps.location.lat(), 6);
  526. Serial.println(Lat);
  527. Serial.print("Longitude (deg): ");
  528. Lng = String(gps.location.lng(), 6);
  529. Serial.println(Lng);
  530. Serial.println();
  531. }
  532.  
  533.  
  534. void fullGPSSerial() {
  535. static const double LONDON_LAT = 51.508131, LONDON_LON = -0.128002;
  536. printInt(gps.satellites.value(), gps.satellites.isValid(), 5);
  537. printFloat(gps.hdop.hdop(), gps.hdop.isValid(), 6, 1);
  538. printFloat(gps.location.lat(), gps.location.isValid(), 11, 6);
  539. printFloat(gps.location.lng(), gps.location.isValid(), 12, 6);
  540. printInt(gps.location.age(), gps.location.isValid(), 5);
  541. printDateTime(gps.date, gps.time);
  542. printFloat(gps.altitude.meters(), gps.altitude.isValid(), 7, 2);
  543. printFloat(gps.course.deg(), gps.course.isValid(), 7, 2);
  544. printFloat(gps.speed.kmph(), gps.speed.isValid(), 6, 2);
  545. printStr(gps.course.isValid() ? TinyGPSPlus::cardinal(gps.course.deg()) : "*** ", 6);
  546.  
  547. unsigned long distanceKmToLondon =
  548. (unsigned long)TinyGPSPlus::distanceBetween(
  549. gps.location.lat(),
  550. gps.location.lng(),
  551. LONDON_LAT,
  552. LONDON_LON) / 1000;
  553. printInt(distanceKmToLondon, gps.location.isValid(), 9);
  554.  
  555. double courseToLondon =
  556. TinyGPSPlus::courseTo(
  557. gps.location.lat(),
  558. gps.location.lng(),
  559. LONDON_LAT,
  560. LONDON_LON);
  561.  
  562. printFloat(courseToLondon, gps.location.isValid(), 7, 2);
  563.  
  564. const char *cardinalToLondon = TinyGPSPlus::cardinal(courseToLondon);
  565.  
  566. printStr(gps.location.isValid() ? cardinalToLondon : "*** ", 6);
  567.  
  568. printInt(gps.charsProcessed(), true, 6);
  569. printInt(gps.sentencesWithFix(), true, 10);
  570. printInt(gps.failedChecksum(), true, 9);
  571. Serial.println();
  572.  
  573. smartDelay(1000);
  574. if (gps.charsProcessed() > 63) {
  575. }
  576. if (millis() > 5000 && gps.charsProcessed() < 10)
  577. Serial.println(F("No GPS data received: check wiring"));
  578. }
  579.  
  580.  
  581. // This custom version of delay() ensures that the gps object
  582. // is being "fed".
  583. static void smartDelay(unsigned long ms)
  584. {
  585. unsigned long start = millis();
  586. do
  587. {
  588. while (Serial2.available())
  589. gps.encode(Serial2.read());
  590. } while (millis() - start < ms);
  591. }
  592.  
  593. static void printFloat(float val, bool valid, int len, int prec)
  594. {
  595. if (!valid)
  596. {
  597. while (len-- > 1)
  598. Serial.print('*');
  599. Serial.print(' ');
  600. }
  601. else
  602. {
  603. Serial.print(val, prec);
  604. int vi = abs((int)val);
  605. int flen = prec + (val < 0.0 ? 2 : 1); // . and -
  606. flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
  607. for (int i = flen; i < len; ++i)
  608. Serial.print(' ');
  609. }
  610. smartDelay(0);
  611. }
  612.  
  613. static void printInt(unsigned long val, bool valid, int len)
  614. {
  615. char sz[32] = "*****************";
  616. if (valid)
  617. sprintf(sz, "%ld", val);
  618. sz[len] = 0;
  619. for (int i = strlen(sz); i < len; ++i)
  620. sz[i] = ' ';
  621. if (len > 0)
  622. sz[len - 1] = ' ';
  623. Serial.print(sz);
  624. smartDelay(0);
  625. }
  626.  
  627. static void printDateTime(TinyGPSDate &d, TinyGPSTime &t)
  628. {
  629. if (!d.isValid())
  630. {
  631. Serial.print(F("********** "));
  632. }
  633. else
  634. {
  635. char sz[32];
  636. sprintf(sz, "%02d/%02d/%02d ", d.month(), d.day(), d.year());
  637. Serial.print(sz);
  638. }
  639.  
  640. if (!t.isValid())
  641. {
  642. Serial.print(F("******** "));
  643. }
  644. else
  645. {
  646. char sz[32];
  647. sprintf(sz, "%02d:%02d:%02d ", t.hour(), t.minute(), t.second());
  648. Serial.print(sz);
  649. }
  650.  
  651. printInt(d.age(), d.isValid(), 5);
  652. smartDelay(0);
  653. }
  654.  
  655. static void printStr(const char *str, int len)
  656. {
  657. int slen = strlen(str);
  658. for (int i = 0; i < len; ++i)
  659. Serial.print(i < slen ? str[i] : ' ');
  660. smartDelay(0);
  661. }
  662.  
  663.  
  664.  
  665.  
Add Comment
Please, Sign In to add comment