So our end goal is to create a code that will utilize the Flora and the Flora Wearable Ultimate GPS Module, to log and store positioning data when turned on and off.
Thinking through this, the first thing that we wanted to do was create a simple bit of code that would recognize that there was a switch and do something when turned on and off. In order to write the code for this, we pulled bits of code from labs 3 and 6:
#include <EEPROM.h>
const int inPin = 6; // the number of the pushbutton pin
const int ledPin = 7; // the number of the LED pin
int buttonState = 0; // variable for reading the pushbutton status
void setup() {
// put your setup code here, to run once:
// initialize the pushbutton pin as an input:
pinMode(inPin, INPUT);
pinMode(ledPin, OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
buttonState = digitalRead(inPin);
if (buttonState == HIGH) {
digitalWrite(ledPin, HIGH);
}
else {
digitalWrite(ledPin, LOW);
}
}
This bit of code recognizes the switch and turns on and off the red LED on the Flora board.
We wired the switch using a breadboard connecting the Flora to the breadboard. We went 3.3V to positive terminal on the breadboard, GND to negative terminal. Pin #6, negative terminal, and one end of a resistor to the switch. The other end of the resistor was wired to the positive terminal. Pictures attached.
The next step was to set up the actual hardware, which was rather simple, we actually found a very useful tutorial pdf online at https://cdn-learn.adafruit.com/downloads/pdf/flora-wearable-gps.pdf, which helped us learn how to hook up the flora to the GPS.
We hooked up the Flora to the GPS as such: alligator clips to connect Flora's 3.3V pad to the 3.3V pad on the GPS. Likewise connect RX to TX and TX to RX, then finally GND to GND. The Flora board got plugged directly into the laptop that was running Arduino.
Once we had the hardware set up, we modified the code to include the GPS, this we found in an Adafruit tutorial and had to include certain libraries, full code below. We set up the code so that when the switch is turned on or off, a light on the Flora board also turns on and off, such that we can tell it is actually working. We got to a point with this code and set up in which in the serial monitor, the GPS was spitting out strings of numbers to us, not yet coordinates. From here, we have to convert this string of random characters to an actual latitude and longitude coordinate system.
It does seem like we will have to be outside for the GPS to work however, as Adafruit themselves says that this is required. This will be next class, as well as working on making this battery powered and logging to something other than a computer, so we can go mobile.
#include <Adafruit_GPS.h>
#include <EEPROM.h>
const int inPin = 6; // the number of the pushbutton pin
const int ledPin = 7; // the number of the LED pin
int buttonState = 0; // variable for reading the pushbutton status
// what's the name of the hardware serial port?
#define GPSSerial Serial1
void setup() {
// put your setup code here, to run once:
// initialize the pushbutton pin as an input:
pinMode(inPin, INPUT);
pinMode(ledPin, OUTPUT);
// 9600 baud is the default rate for the Ultimate GPS
GPSSerial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
buttonState = digitalRead(inPin);
if (buttonState == HIGH) {
//GPSSerial.begin(9600);
digitalWrite(ledPin, HIGH);
if (GPSSerial.available()) {
char c = GPSSerial.read();
Serial.write(c);
}
}
else {
digitalWrite(ledPin, LOW);
//GPSSerial.begin(9600);
}
}
DAY 2We started exactly from where we left of last session, the GPS module set up and connected with the Flora board and then back to the computer, running off of a switch. Our code right now, seems to be operating properly, but we're getting strings of random characters, rather than a latitude and longitude. For today, we will be working on converting this to an actual position, potentially having to go outside for this to work, as Adafruit states that their GPS module will only work outdoors.So we took the computer and hardware outside, and sure enough it was able to pinpoint our location, after a minute or so of random characters being printed, the red light on the GPS module went solid and a location, and even other information was printed out to us.The location is stated as 4300.0302N and 7846.9946W, but its obvious that this is translated as 43N 78.5W, which is completely accurate.Once we came back inside, we updated the code to write to EEPROM rather than just the terminal. The code we are writing would save the first four characters of the latitude and longitude only, not any of the other information, as this would be a waste of space and non essential. We wrote a bit of test code, to dry run this idea, having the serial monitor write back the first for letters of messages that we saved. After this, being sure that we were able to write to EEPROM, we wrote a final bit of code.#include <Adafruit_GPS.h> #include <EEPROM.h> int addr = 0; const int inPin = 6; // the number of the pushbutton pin const int ledPin = 7; // the number of the LED pin int buttonState = 0; // variable for reading the pushbutton status // what's the name of the hardware serial port? #define GPSSerial Serial1 // Connect to the GPS on the hardware port Adafruit_GPS GPS(&GPSSerial); // Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console // Set to 'true' if you want to debug and listen to the raw GPS sentences #define GPSECHO false uint32_t timer = millis(); void setup() { // put your setup code here, to run once: // initialize the pushbutton pin as an input: pinMode(inPin, INPUT); pinMode(ledPin, OUTPUT); //while (!Serial); // uncomment to have the sketch wait until Serial is ready // connect at 115200 so we can read the GPS fast enough and echo without dropping chars // also spit it out Serial.begin(115200); // 9600 NMEA is the default baud rate for Adafruit MTK GPS's- some use 4800 GPS.begin(9600); // uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); // uncomment this line to turn on only the "minimum recommended" data //GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY); // For parsing data, we don't suggest using anything but either RMC only or RMC+GGA since // the parser doesn't care about other sentences at this time // Set the update rate GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1 Hz update rate // For the parsing code to work nicely and have time to sort thru the data, and // print it out we don't suggest using anything higher than 1 Hz // Request updates on antenna status, comment out to keep quiet GPS.sendCommand(PGCMD_ANTENNA); delay(1000); // Ask for firmware version GPSSerial.println(PMTK_Q_RELEASE); clearEeprom(); } void loop() { // put your main code here, to run repeatedly: buttonState = digitalRead(inPin); if (buttonState == HIGH) { //GPSSerial.begin(9600); digitalWrite(ledPin, HIGH); // read data from the GPS in the 'main loop' char c = GPS.read(); // if you want to debug, this is a good time to do it! if (GPSECHO) if (c) Serial.print(c); // if a sentence is received, we can check the checksum, parse it... if (GPS.newNMEAreceived()) { // a tricky thing here is if we print the NMEA sentence, or data // we end up not listening and catching other sentences! // so be very wary if using OUTPUT_ALLDATA and trytng to print out data Serial.println(GPS.lastNMEA()); // this also sets the newNMEAreceived() flag to false if (!GPS.parse(GPS.lastNMEA())) // this also sets the newNMEAreceived() flag to false return; // we can fail to parse a sentence in which case we should just wait for another } // if millis() or timer wraps around, we'll just reset it if (timer > millis()) timer = millis(); // approximately every 2 seconds or so, print out the current stats if (millis() - timer > 2000) { timer = millis(); // reset the timer if (GPS.fix) { Serial.print("Location: "); Serial.print(GPS.latitude, 4); Serial.print(GPS.lat); Serial.print(", "); Serial.print(GPS.longitude, 4); Serial.println(GPS.lon); // Save location to eeprom in the format // lat,lon\n // ie. 43000.0302N,78468.9946W\n // writen as ints (ASCII value) //23 spaces taken per addr saved //1024 space total // about 44 addresses able to be logged writeToEeprom((String)GPS.latitude); EEPROM.write(addr, "."); addr = addr + 1; delay(1); writeToEeprom((String)GPS.lat); EEPROM.write(addr, ","); addr = addr + 1; delay(1); writeToEeprom((String)GPS.longitude); EEPROM.write(addr, "."); addr = addr + 1; delay(1); writeToEeprom((String)GPS.lon); EEPROM.write(addr, ","); addr = addr + 1; delay(1); // write endline char EEPROM.write(addr, "\n"); addr = addr + 1; delay(1); } } } else { digitalWrite(ledPin, LOW); //GPSSerial.begin(9600); } } // function to clear memory int clearEeprom(){ for(int i = 0; i< 1024; i++){ EEPROM.write(i,""); } return 0; } // writes first 4 chars byte by byte int writeToEeprom(String data){ for(int i = 0; i < 5; i++){ EEPROM.write(addr, (int)data[i]); addr = addr + 1; if (addr == EEPROM.length()) { addr = 0; // resets addr counter break; } } return 0; }With the updated code running and working properly when outside, we got a smaller, thinner and lighter breadboard (right side), which we soldered all of the hardware to.In order to create a more permanent and mobile setup, we will eventually forgo alligator clips in general as those are not very secure when mobile. After this, we are going to look into make everything battery powered, rather than by the computer, and will it writing to EEPROM, we will be able to go fully mobile. The EEPROM has space for around 50 locations to be saved to.Ideally, the switch would be turned on, the GPS module would blink red until it gathers our location data, go solid red and then save the location, at which point we can switch it off again. This data would be logged to EEPROM.We will be testing our model during our next session.
DAY 3
So today will be our first test run with the soldered hardware. The code has not been modified since last class and will still be working the same.Indoors it obviously still does not work, so we had to take everything outside.Once we took it outside, we checked to see if the GPS module was working, which it was and then we checked to see if it was reading and writing to the EEPROM, which it was.So the soldered hardware is sleeker, more permanent and working well. As you can see in the video however, when it prints from EEPROM, there is some awkward spacing and a random character, so we went back through the code, line by line, in order to clean it up a little bit and ideally make the print out, more cohesive.#include <Adafruit_GPS.h> #include <EEPROM.h> int addr = 0; const int inPin = 6; // the number of the toggle pin to enable logging const int ledPin = 7; // the number of the LED pin (displays if logging is on) int buttonState = 0; // variable for reading the toggle status // what's the name of the hardware serial port? #define GPSSerial Serial1 // Connect to the GPS on the hardware port Adafruit_GPS GPS(&GPSSerial); // Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console // Set to 'true' if you want to debug and listen to the raw GPS sentences #define GPSECHO false uint32_t timer = millis(); void setup() { // put your setup code here, to run once: // initialize the pushbutton pin as an input: pinMode(inPin, INPUT); pinMode(ledPin, OUTPUT); //while (!Serial); // uncomment to have the sketch wait until Serial is ready // connect at 115200 so we can read the GPS fast enough and echo without dropping chars // also spit it out Serial.begin(115200); // 9600 NMEA is the default baud rate for Adafruit MTK GPS's- some use 4800 GPS.begin(9600); // uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); // uncomment this line to turn on only the "minimum recommended" data //GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY); // For parsing data, we don't suggest using anything but either RMC only or RMC+GGA since // the parser doesn't care about other sentences at this time // Set the update rate GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1 Hz update rate // For the parsing code to work nicely and have time to sort thru the data, and // print it out we don't suggest using anything higher than 1 Hz // Request updates on antenna status, comment out to keep quiet GPS.sendCommand(PGCMD_ANTENNA); delay(1000); // Ask for firmware version GPSSerial.println(PMTK_Q_RELEASE); // clear the eeprom of stale data on inital start clearEeprom(); } void loop() { // put your main code here, to run repeatedly: buttonState = digitalRead(inPin); // button state high when logging is on if (buttonState == HIGH) { // turn on LED to display logging is on digitalWrite(ledPin, HIGH); // read data from the GPS in the 'main loop' char c = GPS.read(); // this if is a place to debug if set true at top of file if (GPSECHO) if (c) Serial.print(c); // if a sentence is received, we can check the checksum, parse it... if (GPS.newNMEAreceived()) { // a tricky thing here is if we print the NMEA sentence, or data // we end up not listening and catching other sentences! // so be very wary if using OUTPUT_ALLDATA and trytng to print out data Serial.println(GPS.lastNMEA()); // this also sets the newNMEAreceived() flag to false if (!GPS.parse(GPS.lastNMEA())) // this also sets the newNMEAreceived() flag to false return; // we can fail to parse a sentence in which case we should just wait for another } // if millis() or timer wraps around, we'll just reset it if (timer > millis()) timer = millis(); // approximately every 2 seconds or so, print out (and write to eeprom) the current location if (millis() - timer > 2000) { timer = millis(); // reset the timer // make sure the GPS has a fix on location before continuing if (GPS.fix) { Serial.print("Location: "); Serial.print(GPS.latitude, 4); Serial.print(GPS.lat); Serial.print(", "); Serial.print(GPS.longitude, 4); Serial.println(GPS.lon); // Save location to eeprom in the format // lat,lon; // ie. 4300.0302N,7868.9946W; // writen as ints (ASCII value) //23 spaces taken per addr saved //1024 space total // about 44 addresses able to be logged writeToEeprom((String)GPS.latitude,9); delay(1); writeToEeprom((String)GPS.lat,1); EEPROM.write(addr, (int)","); addr = addr + 1; delay(1); writeToEeprom((String)GPS.longitude,9); delay(1); writeToEeprom((String)GPS.lon,1); delay(1); // write endline char in our case ';' EEPROM.write(addr, (int)";"); addr = addr + 1; delay(1); } } } else { digitalWrite(ledPin, LOW); } } // function to clear memory int clearEeprom(){ for(int i = 0; i< 1024; i++){ EEPROM.write(i,""); } return 0; } // writes first count number of chars byte by byte int writeToEeprom(String data, int count){ for(int i = 0; i < count; i++){ EEPROM.write(addr, (int)data[i]); addr = addr + 1; if (addr >= EEPROM.length()) { addr = 0; // resets addr counter break; } } return 0; }The last step, will be to take this to battery powered, rather than having to have it plugged into the computer, which would make it fully mobile.To do this, we just need a battery pack with 3 AAA into the JST port on the Flora board. Once we had the battery pack, all we had to do was plug the Flora into the computer, to load the code, and then unplug it, plug in the battery pack, and we were good to go.We were able to take the now fully mobile Flora outside, turn it on and flip the switch, wait for the red light on the GPS module to stop blinking, signifying it has gained satellites.Then once we took it back inside, we were able to plug it into the computer and print out the location data. We were having a little bit of trouble with this, it working sometimes but not all the time, but we were not quite able to figure it out completely.Basic Work Flow:PsuedocodeBasic code to figure out functionalityCreate hardwareWrite specific sketch for GPS moduleTestingSolder Hardware to make more permanentWrite code to log data to EEPROMTestingSwitch to battery powered.


