Libraries, utilities, bootloaders...
by Georgian » Sat Aug 27, 2016 5:09 pm
Hi guys,
I'm planning to make a "game" for gamebuino that shows the GPS location and some other info on the screen. I'll have to make a small board and use the i2c connector for software serial. All fine with that. I'll keep posting as I advance if you guys are intersted. I'm not an professional so do expect some bugs in my code
PS: Can I use the SD card for data logging? Like create a folder and make files just like if the hex was burnt on the Atmega chip not in the SD? Hope you understand what i mean.
EDIT**:
I just looked on the battery logger example and i see that the SD card can be used as normal.
![Very Happy :D](./images/smilies/icon_e_biggrin.gif)
-
Georgian
-
- Posts: 22
- Joined: Sat Aug 27, 2016 4:56 pm
by Georgian » Mon Aug 29, 2016 7:50 pm
So, this is what i have done so far. The code it's quite messy but it works. Should work with any GPS device but you will have to change the output to RMC only. Maybe the coordinates should be in degree format instead of decimal?
![Image](https://s17.postimg.org/xc6vsn5iz/WP_20160829_21_44_40_Pro.jpg)
- Code: Select all
#include <Gamebuino.h>
#include <SPI.h>
#include <SoftwareSerial.h>
SoftwareSerial GPS(A4, A5); //GPS is connected on i2c port
//gps stuff
#define GPSBUFFSIZE 100
char gpsBuff[GPSBUFFSIZE];
//char time[7];
//Variable for MENU
#define MENULENGTH 3
const char strLiveDATA[] PROGMEM = "View GPS DATA";
const char strLogDATA[] PROGMEM = "Start GPS Logger";
const char strEXIT[] PROGMEM = "EXIT";
const char* const menu[MENULENGTH] PROGMEM = {
strLiveDATA,
strLogDATA,
strEXIT,
};
Gamebuino gb;
char folderName[9] = "GPSLOG";
void setup() {
GPS.begin(9600);
delay(500);
gb.begin();
gb.titleScreen(F("GPS Position :)"));
gb.popup(F("Welcome :)"), 100);
gb.battery.show = true;
GPS.print(F("$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29\r\n"));
delay(500);
GPS.print(F("$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29\r\n"));
}
void loop() {
switch(gb.menu(menu, MENULENGTH)) {
case -1: {
gb.titleScreen(F("GPS Position :)"));
break;
}
case 0: {
liveDATA();
break;
}
case 1: {
logDATA();
break;
}
case 2: {
gb.changeGame();
break;
}
default: {
break;
}
}
}
void liveDATA() {
while(1) {
if(gb.update()) {
if (gb.buttons.pressed(BTN_C)) {
return;
}
if (!processGPS(false)) {
gb.display.println(F("Searching..."));
Serial.println(F("NO FIX"));
}
}
}
}
void logDATA() {
gb.keyboard(folderName, 9);
while(1) {
if(gb.update()) {
if (gb.buttons.pressed(BTN_C)) {
return;
}
gb.display.print(F("Folder name: "));
gb.display.println(folderName);
}
}
}
boolean processGPS(boolean toLOG) {
byte i = 0;
memset(gpsBuff, '\0', GPSBUFFSIZE);
while(GPS.available()) GPS.read(); //Empty the buffer before we read and parse!
while(1) {
if (GPS.available() > 0) {
char c = GPS.read();
gpsBuff[i] = c;
//Serial.print(c);
i++;
if (c == '\n') {
gpsBuff[i] = 0;
break;
}
if (i == GPSBUFFSIZE -1) {
gpsBuff[i] = 0;
break;
}
}
}
if (gpsBuff[18] != 'A') {
return false;
} else if (gpsBuff[18] == 'A') { //We have a FIX!
char time[7];
float flat, flong;
//$GPRMC,190411.000,A,4815.0434,N,01417.4215,E,2.99,100.48,271015,,,A*67\r\n
strtok_P(gpsBuff, PSTR (","));
strcpy(time, strtok_P(NULL, PSTR (".")));
strtok_P(NULL, PSTR (","));
strtok_P(NULL, PSTR (","));
flat = atof(strtok_P(NULL, PSTR (",")));
flat = conv_coords(flat);
if (strtok_P(NULL, PSTR (",")) != "N") {
flat = flat * -1;
}
flong = atof(strtok_P(NULL, PSTR (",")));
flong = conv_coords(flong);
if (strtok_P(NULL, PSTR (",")) != "E") {
flat = flat * -1;
}
gb.display.print(F("UTC time: "));
gb.display.print(time[0]);
gb.display.print(time[1]);
gb.display.print(F(":"));
gb.display.print(time[2]);
gb.display.print(time[3]);
gb.display.print(F(":"));
gb.display.print(time[4]);
gb.display.println(time[5]);
gb.display.print(F("LAT: ")); gb.display.println(flat, 6);
gb.display.print(F("LON: ")); gb.display.println(flong, 6);
return true;
}
return false;
}
float conv_coords(float in_coords) {
//Initialize the location.
float f = in_coords;
// Get the first two digits by turning f into an integer, then doing an integer divide by 100;
// first two digits should be 77 at this point.
int firsttwodigits = ((int)f)/100; //This assumes that f < 10000.
float nexttwodigits = f - (float)(firsttwodigits*100);
float theFinalAnswer = (float)(firsttwodigits + nexttwodigits/60.0);
return theFinalAnswer;
}
-
Georgian
-
- Posts: 22
- Joined: Sat Aug 27, 2016 4:56 pm
by Georgian » Tue Aug 30, 2016 8:27 pm
Can someone help me with this pice of code?
I want to increment a counter every time a line is writen to the SD card. Dose the file.write() function returnes true when finished writing?
Here is the part of code:
- Code: Select all
if (file.writeLn(gpsBuff)) {
count++;
} else {
errCount++;
}
So only the errCount is incremented. Is there any other way to do it?
Thanks.
-
Georgian
-
- Posts: 22
- Joined: Sat Aug 27, 2016 4:56 pm
by Georgian » Tue Aug 30, 2016 9:17 pm
I got it working with a small modification.
- Code: Select all
if (file.writeLn(gpsBuff) == NO_ERROR) {
count++;
} else {
errCount++;
}
Now the counter increments but there is nothing in the file. The file is empty but it dose have a few Kilobytes.
I tried to run the battery logger exemple from the gamebuino library with the same results.
This line dose not add any text to the file:
- Code: Select all
file.writeLn("I will log battery voltage every 10 minutes");
-
Georgian
-
- Posts: 22
- Joined: Sat Aug 27, 2016 4:56 pm
by Georgian » Wed Aug 31, 2016 8:14 pm
I managed to solve the issue by using the sdFAT library instead of tinyFAT.
-
Georgian
-
- Posts: 22
- Joined: Sat Aug 27, 2016 4:56 pm
by Georgian » Sat Sep 03, 2016 7:17 pm
Finaly i have managed to finish it. On my desk it works just fine, still need to do some tests outside.
If you chose to log the data, you will be prompted to enter the file name. The name must be no longer than 8 chars. The ".TXT" extensien will be added after. The second menu is the interval. Press the down arraw to toggle the light and thats it. You are free to do whatever you want with this code. Have fun playing
![Smile :)](./images/smilies/icon_e_smile.gif)
- Code: Select all
#include <Gamebuino.h>
#include <SPI.h>
#include <SoftwareSerial.h>
//#include <tinyFAT.h> //requires the tinyFAT library. You can download it here : http://www.henningkarlsen.com/electronics/library.php?id=37
#include <SdFat.h>
#define SD_CS_PIN SS
SoftwareSerial GPS(A4, A5); //GPS is connected on i2c port
extern const byte font3x3[]; //a really tiny font
extern const byte font3x5[]; //a small but efficient font (default)
extern const byte font5x7[]; //a large, comfy font
//gps stuff
#define GPSBUFFSIZE 90
char gpsBuff[GPSBUFFSIZE];
//char time[7];
//Variable for MAIN MENU
#define MENULENGTH 3
const char strLiveDATA[] PROGMEM = "View GPS DATA";
const char strLogDATA[] PROGMEM = "Start GPS Logger";
const char strEXIT[] PROGMEM = "EXIT";
const char* const menu[MENULENGTH] PROGMEM = {
strLiveDATA,
strLogDATA,
strEXIT,
};
//Variable for MAIN MENU
#define INTERVALMENULENGTH 3
const char str5[] PROGMEM = "5s";
const char str10[] PROGMEM = "10s";
const char str20[] PROGMEM = "20S";
const char* const intervalMenu[MENULENGTH] PROGMEM = {
str5,
str10,
str20,
};
Gamebuino gb;
SdFat SD;
File myFile;
char fileNAME[15] = "GPSLOG";
boolean light = false;
long timer = 0;
void setup() {
GPS.begin(9600);
delay(500);
gb.begin();
gb.backlight.automatic = false;
gb.backlight.set(0);
//gb.display.setFont(font5x7);
gb.display.setFont(font3x5);
gb.display.fontSize = 2;
gb.titleScreen(F("GPS Position :)"));
//gb.popup(F("Welcome :)"), 100);
gb.battery.show = true;
GPS.print(F("$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29\r\n"));
delay(500);
GPS.print(F("$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29\r\n"));
//gb.setFrameRate(1);
}
void loop() {
switch(gb.menu(menu, MENULENGTH)) {
case -1: {
gb.titleScreen(F("GPS Position :)"));
break;
}
case 0: {
liveDATA();
break;
}
case 1: {
logDATA();
break;
}
case 2: {
gb.changeGame();
break;
}
default: {
break;
}
}
}
void liveDATA() {
while(1) {
if(gb.update()) {
if (gb.buttons.pressed(BTN_C)) {
return;
}
if (gb.buttons.pressed(BTN_DOWN)) {
light = !light;
}
if (light) {
gb.backlight.set(200);
} else {
gb.backlight.set(0);
}
if (!processGPS(false)) {
gb.display.println(F("Searching..."));
}
}
}
}
void logDATA() {
boolean light = false;
int count = 0;
byte errCount = 0;
if (!SD.begin(SD_CS_PIN)) {
gb.display.clear();
gb.display.update();
gb.display.println(F("NO SD!"));
gb.display.update();
while(1);
}
delay(500);
gb.keyboard(fileNAME, 8);
char fname[15];
sprintf_P(fname, PSTR ("%s.TXT"), fileNAME);
int interval = 0;
//while(1) {
switch(gb.menu(intervalMenu, INTERVALMENULENGTH)) {
case -1: {
interval = 100;
break;
}
case 0: {
interval = 100;
break;
}
case 1: {
interval = 200;
break;
}
case 2: {
interval = 400;
break;
}
default: {
interval = 100;
break;
}
}
//}
myFile = SD.open(fname, FILE_WRITE);
if (!myFile) {
gb.display.clear();
gb.display.update();
gb.display.println(F("File ERROR!"));
gb.display.println(fname);
gb.display.update();
while(1);
}
while(1) {
if(gb.update()) {
if (gb.buttons.pressed(BTN_C)) {
myFile.close();
return;
}
if (gb.buttons.pressed(BTN_DOWN)) {
light = !light;
}
if (light) {
gb.backlight.set(200);
} else {
gb.backlight.set(0);
}
if (gb.frameCount - timer >= interval) {
if (processGPS(true)) {
if (myFile.print(gpsBuff)) {
count++;
} else {
errCount++;
}
} else {
gb.display.println(F("Searching..."));
}
timer = gb.frameCount;
}
gb.display.print(F("Stored: ")); gb.display.println(count);
gb.display.print(F("failed: ")); gb.display.println(errCount);
//gb.display.println(gb.frameCount);
gb.display.cursorX = 0;
gb.display.cursorY = 42;
gb.display.print(F("Voltage: ")); gb.display.println(gb.battery.voltage);// gb.display.println(F(" mV"));
}
}
}
boolean processGPS(boolean toLOG) {
byte i = 0;
memset(gpsBuff, '\0', GPSBUFFSIZE);
while(GPS.available()) GPS.read(); //Empty the buffer before we read and parse!
while(1) {
if (GPS.available() > 0) {
char c = GPS.read();
gpsBuff[i] = c;
//Serial.print(c);
i++;
if (c == '\n') {
gpsBuff[i] = 0;
break;
}
if (i == GPSBUFFSIZE -1) {
gpsBuff[i] = 0;
break;
}
}
}
if (gpsBuff[18] != 'A') {
return false;
} else if (gpsBuff[18] == 'A') { //We have a FIX!
if (toLOG) {
return true;
} else {
char time[7];
float flat, flong, fspeed;
//$GPRMC,190411.000,A,4815.0434,N,01417.4215,E,2.99,100.48,271015,,,A*67\r\n
strtok_P(gpsBuff, PSTR (","));
strcpy(time, strtok_P(NULL, PSTR (".")));
strtok_P(NULL, PSTR (","));
strtok_P(NULL, PSTR (","));
flat = atof(strtok_P(NULL, PSTR (",")));
flat = conv_coords(flat);
if (strtok_P(NULL, PSTR (",")) != "N") {
flat = flat * -1;
}
flong = atof(strtok_P(NULL, PSTR (",")));
flong = conv_coords(flong);
if (strtok_P(NULL, PSTR (",")) != "E") {
flat = flat * -1;
}
fspeed = atof(strtok_P(NULL, PSTR (",")));
fspeed = fspeed * 1.852;
gb.display.print(F("UTC time: "));
gb.display.print(time[0]);
gb.display.print(time[1]);
gb.display.print(F(":"));
gb.display.print(time[2]);
gb.display.print(time[3]);
gb.display.print(F(":"));
gb.display.print(time[4]);
gb.display.println(time[5]);
gb.display.print(F("LAT: ")); gb.display.println(flat, 6);
gb.display.print(F("LON: ")); gb.display.println(flong, 6);
gb.display.print(F("Speed: ")); gb.display.print(fspeed); gb.display.println(F("Km/h"));
//gb.display.println(gb.getCpuLoad());
gb.display.cursorX = 0;
gb.display.cursorY = 42;
gb.display.print(F("Voltage: ")); gb.display.println(gb.battery.voltage);// gb.display.println(F(" mV"));
return true;
}
}
return false;
}
float conv_coords(float in_coords) {
//Initialize the location.
float f = in_coords;
// Get the first two digits by turning f into an integer, then doing an integer divide by 100;
// first two digits should be 77 at this point.
int firsttwodigits = ((int)f)/100; //This assumes that f < 10000.
float nexttwodigits = f - (float)(firsttwodigits*100);
float theFinalAnswer = (float)(firsttwodigits + nexttwodigits/60.0);
return theFinalAnswer;
}
-
Georgian
-
- Posts: 22
- Joined: Sat Aug 27, 2016 4:56 pm
Return to Software Development
Who is online
Users browsing this forum: No registered users and 138 guests