Advertisement
Guest User

Untitled

a guest
Feb 19th, 2019
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.11 KB | None | 0 0
  1. /******************************************************************************
  2.  
  3. GeoCache Hunt Project (GeoCache.ino)
  4.  
  5. This is skeleton code provided as a project development guideline only. You
  6. are not required to follow this coding structure. You are free to implement
  7. your project however you wish. Be sure you compile in "RELEASE" mode.
  8.  
  9. Complete the team information below before submitting code for grading.
  10.  
  11. Team Number: ?
  12.  
  13. Team Members: ?
  14.  
  15. NOTES:
  16. You only have 32k of program space and 2k of data space. You must
  17. use your program and data space wisely and sparingly. You must also be
  18. very conscious to properly configure the digital pin usage of the boards,
  19. else weird things will happen.
  20.  
  21. The Arduino GCC sprintf() does not support printing floats or doubles. You should
  22. consider using sprintf(), dtostrf(), strtok() and strtod() for message string
  23. parsing and converting between floats and strings.
  24.  
  25. The GPS provides latitude and longitude in degrees minutes format (DDDMM.MMMM).
  26. You will need convert it to Decimal Degrees format (DDD.DDDD). The switch on the
  27. GPS Shield must be set to the "Soft Serial" position, else you will not receive
  28. any GPS messages.
  29.  
  30. *******************************************************************************
  31.  
  32. Following is the GPS Shield "GPRMC" Message Structure. This message is received
  33. once a second. You must parse the message to obtain the parameters required for
  34. the GeoCache project. GPS provides coordinates in Degrees Minutes (DDDMM.MMMM).
  35. The coordinates in the following GPRMC sample message, after converting to Decimal
  36. Degrees format(DDD.DDDDDD) is latitude(23.118757) and longitude(120.274060). By
  37. the way, this coordinate is GlobalTop Technology in Taiwan, who designed and
  38. manufactured the GPS Chip.
  39.  
  40. "$GPRMC,064951.000,A,2307.1256,N,12016.4438,E,0.03,165.48,260406,3.05,W,A*2C/r/n"
  41.  
  42. $GPRMC, // GPRMC Message
  43. 064951.000, // utc time hhmmss.sss
  44. A, // status A=data valid or V=data not valid
  45. 2307.1256, // Latitude 2307.1256 (degrees minutes format dddmm.mmmm)
  46. N, // N/S Indicator N=north or S=south
  47. 12016.4438, // Longitude 12016.4438 (degrees minutes format dddmm.mmmm)
  48. E, // E/W Indicator E=east or W=west
  49. 0.03, // Speed over ground knots
  50. 165.48, // Course over ground (decimal degrees format ddd.dd)
  51. 260406, // date ddmmyy
  52. 3.05, // Magnetic variation (decimal degrees format ddd.dd)
  53. W, // E=east or W=west
  54. A // Mode A=Autonomous D=differential E=Estimated
  55. *2C // checksum
  56. /r/n // return and newline
  57.  
  58. Following are the results calculated from above GPS GPRMC message (current
  59. location) to the provided GEOLAT0/GEOLON0 tree (target location). Your
  60. results should be nearly identical, if not exactly the same.
  61.  
  62. degMin2DecDeg() LAT_2307.1256_N = 23.118757 decimal degrees
  63. degMin2DecDeg() LON_12016.4438_E = 120.274055 decimal degrees
  64. calcDistance() to GEOLAT0/GEOLON0 target = 45335760 feet
  65. calcBearing() to GEOLAT0/GEOLON0 target = 22.999652 degrees
  66. Relative target bearing to the tree = 217.519650 degrees
  67.  
  68. Note that the above calculated results display 6 decimial places to the right.
  69. This is accomplished setting the second String class parameter to 6, as in the
  70. following example:
  71.  
  72. String sstr = String(float, 6);
  73.  
  74. ******************************************************************************/
  75.  
  76. /*
  77. Configuration settings.
  78.  
  79. These defines makes it easy for you to enable/disable certain
  80. code during the development and debugging cycle of this project.
  81. There may not be sufficient room in the PROGRAM or DATA memory to
  82. enable all these libraries at the same time. You must have NEO_ON,
  83. GPS_ON and SDC_ON during the actual GeoCache Flag Hunt on Finals Day.
  84. */
  85. #define NEO_ON 0 // NeoPixel Shield (0=OFF, 1=ON)
  86. #define LOG_ON 1 // Serial Terminal Logging (0=OFF, 1=ON)
  87. #define SDC_ON 0 // Secure Digital Card (0=OFF, 1=ON)
  88. #define GPS_ON 0 // 0 = simulated GPS message, 1 = actual GPS message
  89.  
  90. // define pin usage
  91. #define NEO_TX 6 // NEO transmit
  92. #define GPS_TX 7 // GPS transmit
  93. #define GPS_RX 8 // GPS receive
  94.  
  95. #define GPS_BUFSIZ 96 // max size of GPS char buffer
  96.  
  97. // global variables
  98. uint8_t target = 0; // target number
  99. float heading = 0.0; // target heading
  100. float distance = 0.0; // target distance
  101.  
  102. #if GPS_ON
  103. #include <SoftwareSerial.h>
  104. SoftwareSerial gps(GPS_RX, GPS_TX);
  105. #endif
  106.  
  107. #if NEO_ON
  108. #include <Adafruit_NeoPixel.h>
  109. Adafruit_NeoPixel strip = Adafruit_NeoPixel(40, NEO_TX, NEO_GRB + NEO_KHZ800);
  110. #endif
  111.  
  112. #if SDC_ON
  113. #include <SD.h>
  114. #endif
  115.  
  116. /*
  117. Following is a Decimal Degrees formatted waypoint for the large tree
  118. in the parking lot just outside the front entrance of FS3B-116.
  119.  
  120. On GeoCache day, you will be given waypoints in Decimal Degrees format for 4x
  121. flags located on Full Sail campus.
  122. */
  123. #define GEOLAT0 28.594532
  124. #define GEOLON0 -81.304437
  125.  
  126. #if GPS_ON
  127. /*
  128. These are GPS command messages (only a few are used).
  129. */
  130. #define PMTK_AWAKE "$PMTK010,002*2D"
  131. #define PMTK_STANDBY "$PMTK161,0*28"
  132. #define PMTK_Q_RELEASE "$PMTK605*31"
  133. #define PMTK_ENABLE_WAAS "$PMTK301,2*2E"
  134. #define PMTK_ENABLE_SBAS "$PMTK313,1*2E"
  135. #define PMTK_CMD_HOT_START "$PMTK101*32"
  136. #define PMTK_CMD_WARM_START "$PMTK102*31"
  137. #define PMTK_CMD_COLD_START "$PMTK103*30"
  138. #define PMTK_CMD_FULL_COLD_START "$PMTK104*37"
  139. #define PMTK_SET_BAUD_9600 "$PMTK251,9600*17"
  140. #define PMTK_SET_BAUD_57600 "$PMTK251,57600*2C"
  141. #define PMTK_SET_NMEA_UPDATE_1HZ "$PMTK220,1000*1F"
  142. #define PMTK_SET_NMEA_UPDATE_5HZ "$PMTK220,200*2C"
  143. #define PMTK_API_SET_FIX_CTL_1HZ "$PMTK300,1000,0,0,0,0*1C"
  144. #define PMTK_API_SET_FIX_CTL_5HZ "$PMTK300,200,0,0,0,0*2F"
  145. #define PMTK_SET_NMEA_OUTPUT_RMC "$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29"
  146. #define PMTK_SET_NMEA_OUTPUT_GGA "$PMTK314,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29"
  147. #define PMTK_SET_NMEA_OUTPUT_RMCGGA "$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28"
  148. #define PMTK_SET_NMEA_OUTPUT_OFF "$PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28"
  149. #endif
  150.  
  151. /*************************************************
  152. **** GEO FUNCTIONS - BEGIN ***********************
  153. *************************************************/
  154.  
  155. /**************************************************
  156. Convert Degrees Minutes (DDMM.MMMM) into Decimal Degrees (DDD.DDDD)
  157.  
  158. float degMin2DecDeg(char *cind, char *ccor)
  159.  
  160. Input:
  161. cind = char string pointer containing the GPRMC latitude(N/S) or longitude (E/W) indicator
  162. ccor = char string pointer containing the GPRMC latitude or longitude DDDMM.MMMM coordinate
  163.  
  164. Return:
  165. Decimal degrees coordinate.
  166.  
  167. **************************************************/
  168. float degMin2DecDeg(char *cind, char *ccor)
  169. {
  170.  
  171. }
  172.  
  173. /**************************************************
  174. Calculate Great Circle Distance between to coordinates using
  175. Haversine formula.
  176.  
  177. float calcDistance(float flat1, float flon1, float flat2, float flon2)
  178.  
  179. EARTH_RADIUS_FEET = 3959.00 radius miles * 5280 feet per mile
  180.  
  181. Input:
  182. flat1, flon1 = GPS latitude and longitude coordinate in decimal degrees
  183. flat2, flon2 = Target latitude and longitude coordinate in decimal degrees
  184.  
  185. Return:
  186. distance in feet (3959 earth radius in miles * 5280 feet per mile)
  187. **************************************************/
  188. float calcDistance(float flat1, float flon1, float flat2, float flon2)
  189. {
  190. float distance = 0.0;
  191.  
  192. // add code here
  193.  
  194. return(distance);
  195. }
  196.  
  197. /**************************************************
  198. Calculate Great Circle Bearing between two coordinates
  199.  
  200. float calcBearing(float flat1, float flon1, float flat2, float flon2)
  201.  
  202. Input:
  203. flat1, flon1 = course over ground latitude and longitude coordinate in decimal degrees
  204. flat2, flon2 = target latitude and longitude coordinate in decimal degrees
  205.  
  206. Return:
  207. angle in decimal degrees from magnetic north (NOTE: arc tangent returns range of -pi/2 to +pi/2)
  208. **************************************************/
  209. float calcBearing(float flat1, float flon1, float flat2, float flon2)
  210. {
  211. float bearing = 0.0;
  212.  
  213. // add code here
  214.  
  215. return(bearing);
  216. }
  217.  
  218. /*************************************************
  219. **** GEO FUNCTIONS - END**************************
  220. *************************************************/
  221.  
  222. #if NEO_ON
  223. /*
  224. Sets target number, heading and distance on NeoPixel Display
  225.  
  226. NOTE: Target number, bearing and distance parameters used
  227. by this function do not need to be passed in, since these
  228. parameters are in global data space.
  229.  
  230. */
  231. void setNeoPixel(void)
  232. {
  233. // add code here
  234. }
  235.  
  236. #endif // NEO_ON
  237.  
  238. #if GPS_ON
  239. /*
  240. Get valid GPS message.
  241.  
  242. char* getGpsMessage(void)
  243.  
  244. Side affects:
  245. Message is placed in local static char buffer.
  246.  
  247. Input:
  248. none
  249.  
  250. Return:
  251. char* = null char pointer if message not received
  252. char* = pointer to static char buffer if message received
  253.  
  254. */
  255. char* getGpsMessage(void)
  256. {
  257. bool rv = false;
  258. static uint8_t x = 0;
  259. static char cstr[GPS_BUFSIZ];
  260.  
  261. // get nmea string
  262. while (gps.peek() != -1)
  263. {
  264. // reset or bound cstr
  265. if (x == 0) memset(cstr, 0, sizeof(cstr));
  266. else if (x >= (GPS_BUFSIZ - 1)) x = 0;
  267.  
  268. // read next char
  269. cstr[x] = gps.read();
  270.  
  271. // toss invalid or undesired message
  272. if ((x >= 3) && (cstr[0] != '$') && (cstr[3] != 'R'))
  273. {
  274. x = 0;
  275. break;
  276. }
  277.  
  278. // if end of message received (sequence is \r\n)
  279. if (cstr[x] == '\n')
  280. {
  281. // nul terminate char buffer (before \r\n)
  282. cstr[x - 1] = 0;
  283.  
  284. // if checksum not found
  285. if (cstr[x - 4] != '*')
  286. {
  287. x = 0;
  288. break;
  289. }
  290.  
  291. // convert hex checksum to binary
  292. uint8_t isum = strtol(&cstr[x - 3], NULL, 16);
  293.  
  294. // reverse checksum
  295. for (uint8_t y = 1; y < (x - 4); y++) isum ^= cstr[y];
  296.  
  297. // if invalid checksum
  298. if (isum != 0)
  299. {
  300. x = 0;
  301. break;
  302. }
  303.  
  304. // else valid message
  305. rv = true;
  306. x = 0;
  307. break;
  308. }
  309.  
  310. // increment buffer position
  311. else x++;
  312.  
  313. // software serial must breath, else miss incoming characters
  314. delay(1);
  315. }
  316.  
  317. if (rv) return(cstr);
  318. else return(nullptr);
  319. }
  320.  
  321. #else
  322.  
  323. /*
  324. Get simulated GPS message (same as message described at top of this *.ino file)
  325.  
  326. char* getGpsMessage(void)
  327.  
  328. Side affects:
  329. Message is place in local static char buffer
  330.  
  331. Input:
  332. none
  333.  
  334. Return:
  335. char* = null char pointer if message not received
  336. char* = pointer to static char buffer if message received
  337.  
  338. */
  339. char* getGpsMessage(void)
  340. {
  341. static char cstr[GPS_BUFSIZ];
  342. static uint32_t timestamp = 0;
  343.  
  344. uint32_t timenow = millis();
  345.  
  346. // provide message every second
  347. if (timestamp >= timenow) return(nullptr);
  348.  
  349. memcpy(cstr, "$GPRMC,064951.000,A,2307.1256,N,12016.4438,E,0.03,165.48,260406,3.05,W,A*2C", sizeof(cstr));
  350.  
  351. timestamp = timenow + 1000;
  352.  
  353. return(cstr);
  354. }
  355. #endif
  356.  
  357. void setup(void)
  358. {
  359. #if LOG_ON
  360. // init serial interface
  361. Serial.begin(115200);
  362. #endif
  363.  
  364. #if NEO_ON
  365. // init NeoPixel Shield
  366. #endif
  367.  
  368. #if SDC_ON
  369. /*
  370. Initialize the SecureDigitalCard and open a numbered sequenced file
  371. name "MyMapN.txt" for storing your coordinates, where N is the
  372. sequential number of the file. The filename can not be more than 8
  373. chars in length (excluding the ".txt"). Do not close this file,
  374. but remains open. The file automatcially closes when the program
  375. is reloaded or the board is reset.
  376. */
  377. #endif
  378.  
  379. #if GPS_ON
  380. // enable GPS sending GPRMC message
  381. gps.begin(9600);
  382. gps.println(PMTK_SET_NMEA_UPDATE_1HZ);
  383. gps.println(PMTK_API_SET_FIX_CTL_1HZ);
  384. gps.println(PMTK_SET_NMEA_OUTPUT_RMC);
  385. #endif
  386.  
  387. // set target button pinmode
  388. }
  389.  
  390. void loop(void)
  391. {
  392. // get GPS message
  393. char *cstr = getGpsMessage();
  394.  
  395. // if valid message delivered (happens once a second)
  396. if (cstr)
  397. {
  398. #if LOG_ON
  399. // print the GPRMC message
  400. Serial.println(cstr);
  401. #endif
  402.  
  403. // check button for incrementing target index
  404.  
  405. // parse required latitude, longitude and course over ground message parameters
  406.  
  407. // convert latitude and longitude degrees minutes to decimal degrees
  408.  
  409. // calculate destination distance
  410.  
  411. // calculate destination heading
  412.  
  413. // calculate relative bearing
  414.  
  415. #if SDC_ON
  416. // write required data to SecureDigital then execute flush()
  417. #endif
  418.  
  419. #if NEO_ON
  420. // set NeoPixel target display information
  421. setNeoPixel(target, heading, distance);
  422. #endif
  423. }
  424. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement