can anyone suggest a method for getting the type of serial monitor display for arduino serial plotter real time graphing instead to display to TFT? Maybe this can help me in my GPS code issue described below?
I am trying to create a moving GPS map where the map center pixel remains in position while the OLD 'map track' continues to redraw itself moving away from the center pixel. This concept I think requires saving new x/y coord, plotting/drawing new x/y coord, erasing and then redrawing all saved coords PLUS newest ones, all x/y points now in new positions, WHILE maintaining the newest point at TFT center.
It's a scrolling real-time map basically. But I am having difficulty with the underlying concept....
- Should I redraw all points in relation to closest neighbor point?
- should I redraw all points in relation to map center x/y?
Here is my build so far. It draws new points in relation to the original screen center...but the map of points grows away from the center point RATHER than the center point always being the newest point.
see: XRAD'S REALLY COOL GPS TRACKER - adafruit industries
any pointers or code tips would be much appreciated!!!
current code:
/* XRAD'S REALLY COOL GPS TRACKER 1/28/22 using adafruit 3.5 touch
tft breakout, adafruit STMPE610, Teensy 3.6 w/SD. This program
obtains GPS data in decimal degrees and converts these to
approximate planar 'cartesian' x/y coordinates. It logs your
initial location and then draws a map of your journey. The
program also allows you to real-time scale the map to approximate
radii of 100meters, 5 miles, 15 miles, and 30 miles...and
zoom in and out of the scales. This is done by saving the
converted x, y coords to SD and then redrawing them via a
buffer as pixels to the tft. Additionally, I use adafruit
drawButtons off the arduino examples to show how to use the
touch screen to scale the map, color a text box, and delete/save
the SD file. In order to keep the button press functions activating
in quick fashion, the loop is paused while you select button choices.
You must return to "GPS ACTIVE" to start taking readings again.
On Boot, code draws last saved map at 100m radius.
It's one of my favorite cool project combining a few really neat
adafruit codes and products!! Enjoy!
hardware:
Teensy 3.6, or you can use a 4.1
Micro SD card
Adafruit 3.5 tft touch breakout(or you could use a 3.5 tft feather)
Adafruit stmpe610 breakout (good luck finding these..better get a 3.5 feather!)
Adafruit INA219 current sensor
Goouuu Tech GT-u7 GPS module (very nice!)
Pololu mini push button power switch
120mm aluminum case
Pololu 5v regulator
DFRobot DFR0564 2s lipo charger, I broke out the charging led to side panel
micro USB panel mount extension 30cm
things to do??
1) save more than one map and name map via buttons
2) recall selected map
3) draw recalled map AND center x/y pixel on the last GPS saved coords (ie: continue your journey)
4) draw map color selections?
5) wifi link to google maps?
5) and it never ends...
*/
#include <SD.h>
#include <TinyGPS.h>
#include <FastLED.h>//just used for timer!
#include "Adafruit_GFX.h"
#include "Adafruit_HX8357.h"
#include <Adafruit_STMPE610.h>
#include <Adafruit_INA260.h>
#define TFT_CS 10
#define TFT_DC 9
#define TFT_RST -1 // RST can be set to -1
Adafruit_HX8357 tft = Adafruit_HX8357(TFT_CS, TFT_DC, TFT_RST);
Adafruit_STMPE610 touch = Adafruit_STMPE610();
Adafruit_INA260 ina260 = Adafruit_INA260();
// For rotation 3
#define TS_MINX 3800
#define TS_MAXX 100
#define TS_MINY 100
#define TS_MAXY 3750
TinyGPS gps;
bool oneTimePosition = true;
int long oneTimeLat, oneTimeLong;
unsigned long startMillis;
unsigned long currentMillis;
const unsigned long period = 1000;
#define R 6367000 // Radius earth in m
int long x ;
int long y ;
int long homex;
int long homey;
int dx;
int dy;
//not used yet
#define MAP_WIDTH 280
#define MAP_HEIGHT 280
#define MAP_CENTERX 250
#define MAP_CENTERY 140
//map x/y boundaries
#define MAP_X_MIN 111
#define MAP_X_MAX 389
#define MAP_Y_MIN 1
#define MAP_Y_MAX 279
int counter = 0;
int oldCounter;
File myFile;//SD file
String buffer;//buffer to redraw saved SD data
//define some colors, not all are used
#define HX8357_BLACK 0x0000 ///< 0, 0, 0
#define HX8357_NAVY 0x000F ///< 0, 0, 123
#define HX8357_DARKGREEN 0x03E0 ///< 0, 125, 0
#define HX8357_DARKCYAN 0x03EF ///< 0, 125, 123
#define HX8357_MAROON 0x7800 ///< 123, 0, 0
#define HX8357_PURPLE 0x780F ///< 123, 0, 123
#define HX8357_OLIVE 0x7BE0 ///< 123, 125, 0
#define HX8357_LIGHTGREY 0xC618 ///< 198, 195, 198
#define HX8357_DARKGREY 0x7BEF ///< 123, 125, 123
#define HX8357_BLUE 0x001F ///< 0, 0, 255
#define HX8357_GREEN 0x07E0 ///< 0, 255, 0
#define HX8357_CYAN 0x07FF ///< 0, 255, 255
#define HX8357_RED 0xF800 ///< 255, 0, 0
#define HX8357_MAGENTA 0xF81F ///< 255, 0, 255
#define HX8357_YELLOW 0xFFE0 ///< 255, 255, 0
#define HX8357_WHITE 0xFFFF ///< 255, 255, 255
#define HX8357_ORANGE 0xFD20 ///< 255, 165, 0
#define HX8357_GREENYELLOW 0xAFE5 ///< 173, 255, 41
#define HX8357_PINK 0xFC18 ///< 255, 130, 198
//define buttons RIGHT side of 3.5 tft(rotation 3)
#define BUTTON_X 440
#define BUTTON_Y 40
#define BUTTON_W 80
#define BUTTON_H 80
#define BUTTON_TEXTSIZE 2
#define DISPLAY_XOFFSET 80
#define DISPLAY_TEXTOFFSET 90
#define DISPLAY_YOFFSET 0
enum ButtonName {
BTN_UP,
BTN_SELECT,
BTN_DOWN,
BTN_MENU
};
int menuCount = 0;
//button menus
//the looping button choice, you can only choose MENU
#define MENU0_BTN_CNT 4
Adafruit_GFX_Button Menu0Buttons[MENU0_BTN_CNT];
char Menu0Labels[MENU0_BTN_CNT][5] = {"", "", "", "MENU"};
uint16_t Menu0Colors[MENU0_BTN_CNT] = {HX8357_BLACK, HX8357_BLACK,
HX8357_BLACK, HX8357_ORANGE
};
//ZOOM buttons
#define MENU1_BTN_CNT 4
Adafruit_GFX_Button Menu1Buttons[MENU1_BTN_CNT];
char Menu1Labels[MENU1_BTN_CNT][5] = {"ZMOT", "Sel", "ZMIN", "MENU"};
uint16_t Menu1Colors[MENU1_BTN_CNT] = {HX8357_DARKGREY, HX8357_DARKGREY,
HX8357_DARKGREY, HX8357_ORANGE
};
//COLOR buttons
#define MENU2_BTN_CNT 4
Adafruit_GFX_Button Menu2Buttons[MENU2_BTN_CNT];
char Menu2Labels[MENU2_BTN_CNT][5] = {"Up", "Sel", "Down", "MENU"};
uint16_t Menu2Colors[MENU2_BTN_CNT] = {HX8357_BLUE, HX8357_BLUE,
HX8357_BLUE, HX8357_ORANGE
};
//save or delte SD GPS file
#define MENU3_BTN_CNT 4
Adafruit_GFX_Button Menu3Buttons[MENU3_BTN_CNT];
char Menu3Labels[MENU3_BTN_CNT][5] = {"YES", "Sel", "NO", "MENU"};
uint16_t Menu3Colors[MENU3_BTN_CNT] = {HX8357_RED, HX8357_RED,
HX8357_RED, HX8357_ORANGE
};
int textSize = 2;//starting txt size for bottom textbox, but really the only size I use
int textColorIndex = 0;
//menu 2 color selections
uint16_t textColor[7] = {
HX8357_WHITE,
HX8357_RED,
HX8357_GREEN,
HX8357_BLUE,
HX8357_CYAN,
HX8357_MAGENTA,
HX8357_YELLOW
};
//-------------------------------------------------------------------------
void setTextColorIndex(int updown) {
textColorIndex += updown;
if (textColorIndex > 6)
textColorIndex = 0;
else if (textColorIndex < 0)
textColorIndex = 6;
tft.setTextColor(textColor[textColorIndex]);
}
//-------------------------------------------------------------------------
void setTextSizeIndex(int updown) {
tft.setTextSize(2);
}
//-------------------------------------------------------------------------
bool initializeButtons(
Adafruit_GFX_Button menuButtons[],
uint16_t menuColors[],
char menuLabels[][5],
int menuButtonCount) {
//tft.fillScreen(HX8357_BLACK);
//tft.fillRect(460, 0, 20, 320, HX8357_BLACK);
for (uint8_t row = 0; row < menuButtonCount; row++)
{
menuButtons[row].initButton(& tft,
BUTTON_X,
BUTTON_Y + row * (BUTTON_H),
BUTTON_W,
BUTTON_H,
HX8357_BLACK,
menuColors[row],
HX8357_WHITE,
menuLabels[row], BUTTON_TEXTSIZE);
menuButtons[row].drawButton();
}
return true;
}
//-------------------------------------------------------------------------
void tftSetCenterCursor(String str, int16_t xIn, int16_t yIn) {
int16_t xText, yText;
uint16_t w, h;
tft.getTextBounds(str, 0, 0, &xText, &yText, &w, &h);
tft.setCursor(80, 295);
}
//--------------------------------------------------------------------------------
void tftPrint(String str) {
int16_t xText, yText;
uint16_t w, h;
tft.getTextBounds(str, 0, 0, &xText, &yText, &w, &h);
tft.fillRect( 80, 290, 320, 25, HX8357_BLACK);
tft.print(str);
}
//-------------------------------------------------------------------------
void tftCenterPrint(String str) {
tft.setTextSize(textSize);
tftSetCenterCursor(str,
DISPLAY_TEXTOFFSET + ( tft.width() - DISPLAY_TEXTOFFSET) / 2,
DISPLAY_YOFFSET + ( tft.height() - DISPLAY_YOFFSET) / 2);
tftPrint(str);
}
//--------Are you pushing my buttons???---------------------------------
int tftButtonRelease(Adafruit_GFX_Button menuButtons[], int menuButtonCount) {
int btn = -1;
TS_Point p;
if (touch.bufferSize())
{
p = touch.getPoint();
}
else
{
// this is our way of tracking touch 'release'!
p.x = p.y = p.z = -1;
}
// Scale from ~0->4000 to tft.width using the calibration #'s
if (p.z != -1)
{
int16_t px = p.x;
int16_t py = p.y;
p.x = map(py, TS_MINY, TS_MAXY, 0, tft.width());
p.y = map(px, TS_MINX, TS_MAXX, 0, tft.height());
}
// go thru all the buttons, checking if they were pressed
for (uint8_t b = 0; b < menuButtonCount; b++)
{
if (menuButtons[b].contains(p.x, p.y))
{
//Serial.print("Pressing: "); Serial.println(b);
menuButtons[b].press(true); // tell the button it is pressed
}
else
{
menuButtons[b].press(false); // tell the button it is NOT pressed
}
}
// now we can ask the buttons if their state has changed
for (uint8_t b = 0; b < menuButtonCount; b++)
{
if (menuButtons[b].justReleased())
{
//Serial.print("Released: "); Serial.println(b);
menuButtons[b].drawButton(); // draw normal
btn = b;
}
if (menuButtons[b].justPressed())
{
menuButtons[b].drawButton(true); // draw invert!
delay(100); // UI debouncing
}
}
return btn;
}
//-----MENU 3: SAVE OR CLEAR SD----------------------------
void processMenu3() {
String msg = "";
bool exitLoop = false;
bool clearSDMap = false;
initializeButtons(Menu3Buttons, Menu3Colors, Menu3Labels, MENU3_BTN_CNT);
msg = "Menu 3: CLEAR SD FILE";
//Serial.println(msg);
setTextColorIndex(0);
setTextSizeIndex(0);
tftCenterPrint(msg);
while (!exitLoop)
{
int btn = tftButtonRelease(Menu3Buttons, MENU3_BTN_CNT);
if (btn >= 0 && btn < MENU3_BTN_CNT)
{
//Serial.print("btn = "); Serial.println(btn);
}
switch (btn)
{
case BTN_UP:
msg = "OK TO CLEAR SD MAP FILE";
//Serial.println(msg);
setTextColorIndex(0);
tftCenterPrint(msg);
clearSDMap = true;
break;
case BTN_SELECT:
if (clearSDMap == false) {
msg = "SAVE SD MAP FILE";
//Serial.println(msg);
setTextColorIndex(0);
tftCenterPrint(msg);
delay(1000);
msg = "Press MENU";
//Serial.println(msg);
setTextColorIndex(0);
tftCenterPrint(msg);
//break;
}
else if (clearSDMap == true) {
msg = "CLEARING SD MAP FILE";
//Serial.println(msg);
setTextColorIndex(0);
tftCenterPrint(msg);
SD.remove("GPS");//remove prior old GPS SD file on button press
clearMap();
drawMap();
delay (1000);
msg = "Press MENU";
//Serial.println(msg);
setTextColorIndex(0);
tftCenterPrint(msg);
clearSDMap = false;
}
break;
case BTN_DOWN:
msg = "SAVE SD MAP FILE";
//Serial.println(msg);
setTextColorIndex(0);
tftCenterPrint(msg);
clearSDMap = false;
break;
case BTN_MENU:
menuCount = menuCount + 1;
exitLoop = true;
break;
default:
break;
}
}
}
//------MENU 2: COLOR CHOICES FOR TXTBOX------------------------------
void processMenu2() {
String msg = "";
bool exitLoop = false;
initializeButtons(Menu2Buttons, Menu2Colors, Menu2Labels, MENU2_BTN_CNT);
msg = "Menu 2: COLOR";
//Serial.println(msg);
setTextColorIndex(0);
setTextSizeIndex(0);
tftCenterPrint(msg);
while (!exitLoop)
{
int btn = tftButtonRelease(Menu2Buttons, MENU2_BTN_CNT);
if (btn >= 0 && btn < MENU2_BTN_CNT)
{
// Serial.print("btn = "); Serial.println(btn);
}
switch (btn)
{
case BTN_UP:
msg = "Menu 2: Color Up button";
//Serial.println(msg);
setTextColorIndex(1);
tftCenterPrint(msg);
break;
case BTN_SELECT:
msg = "Color Selected. Press MENU";
//Serial.println(msg);
setTextColorIndex(0);
tftCenterPrint(msg);
break;
case BTN_DOWN:
msg = "Menu 2: Color Down Button";
//Serial.println(msg);
setTextColorIndex(-1);
tftCenterPrint(msg);
break;
case BTN_MENU:
menuCount = menuCount + 1;
exitLoop = true;
break;
default:
break;
}
}
}
//---------MENU 1: ZOOM IN OUT--------------------------------
void processMenu1() {
String msg = "";
bool exitLoop = false;
initializeButtons(Menu1Buttons, Menu1Colors, Menu1Labels, MENU1_BTN_CNT);
msg = "Menu 1: ZOOM";
//Serial.println(msg);
setTextColorIndex(0);
setTextSizeIndex(0);
tftCenterPrint(msg);
ZOOM();
while (!exitLoop)
{
int btn = tftButtonRelease(Menu1Buttons, MENU1_BTN_CNT);
if (btn >= 0 && btn < MENU1_BTN_CNT)
{
// Serial.print("btn = "); Serial.println(btn);
}
switch (btn)
{
case BTN_UP:
counter = counter + 1;
if (counter > 3) {
counter = 3;
}
if (counter == 1) {
msg = "ZOOM OUT 5 mile radius";//these are ALL approximate r's
}
else if (counter == 2) {
msg = "ZOOM OUT 15 mile radius";
}
else if (counter == 3) {
msg = "ZOOM OUT 30 mile radius";
}
ZOOM();
//Serial.println(msg);
setTextColorIndex(0);
setTextSizeIndex(0);
tftCenterPrint(msg);
break;
case BTN_DOWN:
counter = counter - 1;
if (counter < 0) {
counter = 0;
}
if (counter == 0) {
msg = "ZOOM IN 100 meter radius";
}
else if (counter == 1) {
msg = "ZOOM IN 5 mile radius";
}
else if (counter == 2) {
msg = "ZOOM IN 15 mile radius";
}
ZOOM();
//Serial.println(msg);
setTextColorIndex(0);
setTextSizeIndex(0);
tftCenterPrint(msg);
break;
case BTN_SELECT:
msg = "Zoom Selected. Press MENU";
//Serial.println(msg);
setTextColorIndex(0);
setTextSizeIndex(0);
tftCenterPrint(msg);
break;
case BTN_MENU:
menuCount = menuCount + 1;
exitLoop = true;
break;
default:
break;
}
}
}
//MENU 0----THE LOOPING MENU FOR 'MENU' SELECTIONS----
//you must be in this menu for the GPS to be active!!
void processMenu0() {
String msg = "";
int btn = tftButtonRelease(Menu0Buttons, MENU0_BTN_CNT);
if (btn >= 0 && btn < MENU0_BTN_CNT)
{
//Serial.print("btn = "); Serial.println(btn);
}
switch (btn)
{
case BTN_UP:
break;
case BTN_DOWN:
break;
case BTN_MENU:
msg = "GPS ACTIVE";
//Serial.println(msg);
setTextColorIndex(0);
tftCenterPrint(msg);
menuCount = menuCount + 1;
if (menuCount == 1) {
initializeButtons(Menu1Buttons, Menu1Colors, Menu1Labels, MENU1_BTN_CNT);
processMenu1();
}
if (menuCount == 2) {
initializeButtons(Menu2Buttons, Menu2Colors, Menu2Labels, MENU2_BTN_CNT);
processMenu2();
}
if (menuCount == 3) {
initializeButtons(Menu3Buttons, Menu3Colors, Menu3Labels, MENU3_BTN_CNT);
processMenu3();
}
if (menuCount > 3) {
initializeButtons(Menu0Buttons, Menu0Colors, Menu0Labels, MENU0_BTN_CNT);
setTextColorIndex(0);
tftCenterPrint("GPS ACTIVE");
menuCount = 0;
processMenu0();
}
break;
case BTN_SELECT:
break;
default:
break;
}
}
void clearMap() {
tft.fillRoundRect(111, 1, 278, 278, 10, HX8357_BLACK);
}
void drawMap() { //draw a map w/dotted cross
tft.drawRoundRect(110, 0, 280, 280, 10, HX8357_GREEN);
for (int x = 55; x < 195; x++) {
tft.drawPixel((2 * x), 140, HX8357_GREEN);
}
for (int y = 0; y < 140; y++) {
tft.drawPixel(250, (2 * y), HX8357_GREEN);
}
tft.setCursor(245, 2);
tft.fillRect(245, 2, 10, 14, HX8357_BLACK);
tft.setTextColor(HX8357_GREEN); tft.setTextSize(2);
tft.println("N");
}
void drawSetup() {
tft.setCursor(0, 200);
tft.setTextColor(HX8357_WHITE); tft.setTextSize(1);
tft.print("ZOOM I/O : ");
tft.setCursor(0, 215);
tft.print("RADIANS X: ");
tft.setCursor(0, 230);
tft.print("RADIANS y: ");
tft.setCursor(0, 165);
tft.print("X: ");
tft.setCursor(0, 180);
tft.print("Y: ");
tft.setCursor(0, 45);
tft.print("SATELITES: ");
tft.setCursor(0, 60);
tft.print("PRECISION: ");
}
void ZOOM() {
if (counter != oldCounter) {
clearMap();
drawMap();
// re-open the file for reading:
myFile = SD.open("GPS");
if (myFile) {
//Serial.println("GPS:");
drawMap();
// read from the file until there's nothing else in it, line by line:
while (myFile.available()) {
//Serial.write(myFile.read());
buffer = myFile.readStringUntil('\n');
//Serial.println(buffer); //debugging compare to scaled x/y
char *x_str;
x_str = strtok((char*)buffer.c_str(), ",");//string tokens and parse line
int SDdx = atoi(x_str);//convert to int
char *y_str;
y_str = strtok(NULL, ",");//string token rest of line
int SDdy = atoi(y_str);
//for scaling: calculate SDdx here
if (counter == 1) { // ~ 5 mile map radius
SDdx = SDdx / 100;
SDdx = SDdx + 250;
}
else if (counter == 2) { // ~ 15 mile map radius
SDdx = SDdx / 300;
SDdx = SDdx + 250;
}
else if (counter == 3) { // ~ 30 mile map radius
SDdx = SDdx / 500;
SDdx = SDdx + 250;
}
//for scaling: calculate SDdy here
if (counter == 1) { // ~ 5 mile map radius
SDdy = SDdy / 100;
SDdy = SDdy + 140;//don't reverse N / S map plot, it's already calculated
}
else if (counter == 2) { // ~ 15 mile map radius
SDdy = SDdy / 300;
SDdy = SDdy + 140;
}
else if (counter == 3) { // ~ 30 mile map radius
SDdy = SDdy / 500;
SDdy = SDdy + 140;
}
//draw pixels within map boundaries
if (((SDdx > MAP_X_MIN) && (SDdx < MAP_X_MAX)) && ((SDdy > MAP_Y_MIN) && (SDdy < MAP_Y_MAX))) {
tft.drawPixel( SDdx, SDdy, HX8357_WHITE);
}
//compare to initial buffer x/y
//Serial.print("SDdx: ");
//Serial.println(SDdx);
//Serial.print("SDdy: ");
//Serial.println(SDdy);
}
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
//Serial.println("error opening test.txt");
}
tft.fillRect(60, 200, 40, 55, HX8357_BLACK);
tft.setCursor(60, 200);
tft.setTextColor(HX8357_WHITE); tft.setTextSize(1);
//tft.print("ZOOM I/O: ");//
tft.println(counter);
oldCounter = counter;
}
}
//draw saved SD map on BOOT, at 100m radius
void BOOTDrawMap() {
clearMap();
drawMap();
// re-open the file for reading:
myFile = SD.open("GPS");
if (myFile) {
//Serial.println("GPS:");
drawMap();
// read from the file until there's nothing else in it, line by line:
while (myFile.available()) {
//Serial.write(myFile.read());
buffer = myFile.readStringUntil('\n');
//Serial.println(buffer); //debugging compare to scaled x/y
char *x_str;
x_str = strtok((char*)buffer.c_str(), ",");
int SDdx = atoi(x_str);
char *y_str;
y_str = strtok(NULL, ",");
int SDdy = atoi(y_str);
//draw pixels within map boundaries
if (((SDdx > MAP_X_MIN) && (SDdx < MAP_X_MAX)) && ((SDdy > MAP_Y_MIN) && (SDdy < MAP_Y_MAX))) {
tft.drawPixel( SDdx, SDdy, HX8357_WHITE);
}
}
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
//Serial.println("error opening test.txt");
}
tft.fillRect(60, 200, 40, 55, HX8357_BLACK);
tft.setCursor(60, 200);
tft.setTextColor(HX8357_WHITE); tft.setTextSize(1);
//tft.print("ZOOM I/O: ");//
tft.println(counter);
}
void ina610() { //error should be the ina219!..only used for debugging
Serial.print("Current: ");
Serial.print(ina260.readCurrent());
Serial.println(" mA");
Serial.print("Bus Voltage: ");
Serial.print(ina260.readBusVoltage());
Serial.println(" mV");
Serial.print("Power: ");
Serial.print(ina260.readPower());
Serial.println(" mW");
Serial.println();
}
////////////////SETUP--do everything once////////////////////////
void setup()
{
Serial.begin(115200);
Serial.flush();
Serial1.begin(9600);//my GPS device uses 9600 baud, using teensy Serial1
delay(100);
//Serial.print("Initializing SD card...");
// see if the card is present and can be initialized:
if (!SD.begin(BUILTIN_SDCARD)) {
// Serial.println("Card failed, or not present");
tft.begin();
tft.setRotation(3);
tft.fillScreen(HX8357_BLACK);
tft.setCursor(80, 100);
tft.setTextColor(HX8357_WHITE); tft.setTextSize(3);
tft.println("POWER OFF AND");
tft.setCursor(80, 160);
tft.println("INSERT SD CARD");
for (;;);//break loop/setup for EVERRRRRR!
}
Serial.println("card initialized.");
//Serial.println("x,y");
myFile = SD.open("GPS", FILE_WRITE);
touch.begin();
ina260.begin();
/*
if (!ina260.begin()) {
Serial.println("Couldn't find INA260 chip");
while (1);
}
Serial.println("INA260 found");
if (! touch.begin()) {
Serial.println("STMPE not found!");
while (1);
}
Serial.println("STMPE found");
*/
tft.begin();
tft.setTextWrap(false);
tft.setRotation(3);
tft.fillScreen(HX8357_BLACK);
tft.setCursor(80, 100);
tft.setTextColor(HX8357_WHITE);
tft.setTextSize(4);
tft.println("GPS ACTIVATED");
delay(2000);
tft.fillScreen(HX8357_BLACK);
tft.setCursor(0, 0);
tft.setTextColor(HX8357_GREEN);
tft.setTextSize(1);
tft.print("CURRENT POSITION: ");
tft.setCursor(0, 90);
tft.print("INITIAL POSITION: ");
tft.setCursor(0, 150);
tft.print("CARTESIAN COORD: ");
tft.setCursor(0, 255);
tft.print("BATTERY VOLTAGE: ");
//clear radians tft X Y ...
tft.fillRect(60, 200, 40, 55, HX8357_BLACK);
tft.setCursor(0, 200);
tft.setTextColor(HX8357_WHITE);
tft.setTextSize(1);
tft.print("ZOOM I/O : ");
tft.setCursor(0, 215);
tft.print("RADIANS X: ");
tft.setCursor(0, 230);
tft.print("RADIANS y: ");
tft.setCursor(0, 295);
tft.setTextColor(HX8357_WHITE); tft.setTextSize(2);
tft.print("INFO: ");
//tft.println(counter);
BOOTDrawMap();//draw the saved SD map at 100m radius
initializeButtons(Menu0Buttons, Menu0Colors, Menu0Labels, MENU0_BTN_CNT);
startMillis = millis();
setTextColorIndex(0);
tftCenterPrint("GPS SEARCHING PLEASE WAIT");
}
///////////LOOP--run for everrrrrr///////////////////////
void loop() {
processMenu0();
bool newData = false;
// get GPS data every x seconds and report some key values
EVERY_N_MILLISECONDS(4000) { //from fastLed lib
for (unsigned long start = millis(); millis() - start < 1000;)//~minimum time to get data
{
while (Serial1.available())
{
char c = Serial1.read();
if (gps.encode(c)) // Did a new valid sentence come in?
newData = true;
}
}
if (newData) {
float flat, flon;
unsigned long age;
gps.f_get_position(&flat, &flon, &age);
tft.fillRect(20, 15, 90, 10, HX8357_BLACK);
tft.setCursor(0, 15);
tft.setTextColor(HX8357_WHITE); tft.setTextSize(1);
tft.print("LAT: ");
tft.println(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flat, 6);
tft.fillRect(20, 30, 90, 10, HX8357_BLACK);
tft.setCursor(0, 30);
tft.setTextColor(HX8357_WHITE); tft.setTextSize(1);
tft.print("LON: ");
tft.println(flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flon, 6);
//record initial home position and display data on tft
if (oneTimePosition == true) {
tft.setCursor(0, 105);
tft.setTextColor(HX8357_WHITE); tft.setTextSize(1);
tft.print("LAT: ");
tft.println(flat, 6);
tft.setCursor(0, 120);
tft.print("LON: ");
tft.println(flon, 6);
//several ways of doing this.....
float radiansX = ( flat * ((asin(1)) / 90));//arc sin(1) = π/2 radians = 90
float radiansY = ( flon * ((asin(1)) / 90));
homex = R * radiansY * cos(radiansX);
homey = R * radiansX;
tftCenterPrint("GPS ACTIVE");
oneTimePosition = false;
}
//for real time GPS to x/y for TFT draw pixel
float radiansX = ( flat * (asin(1)) / 90 );
float radiansY = ( flon * (asin(1)) / 90 );
x = R * radiansY * cos(radiansX);
y = R * radiansX;
if (homex != x) {
dx = (x - homex);
dx = dx + 250;
}
if (homey != y) {
dy = (y - homey) ;
dy = -dy + 140;//reverse N/S here
}
myFile = SD.open("GPS", FILE_WRITE);//save the base scale x/y to SD
// if the file opened okay, write to it:
if (myFile) {
myFile.print (dx);
myFile.print (", ");
myFile.println(dy);
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
//Serial.println("error opening test.txt");
}
//for scaling
if (homex != x) {
dx = (x - homex);
//calculate dx/dy here for range
if (counter == 0) { // ~ 50 meter radius
dx = dx;
}
if (counter == 1) { // ~ 5 mile map radius
dx = dx / 100;
}
if (counter == 2) { // ~ 15 mile map radius
dx = dx / 300;
}
if (counter == 3) { // ~ 30 mile map radius
dx = dx / 500;
}
dx = dx + 250;
}
if (homey != y) {
dy = (y - homey);
//calculate dx/dy here for range
if (counter == 0) { // ~ 50 meter radius
dy = dy;
}
if (counter == 1) { // ~ 5 mile map radius
dy = dy / 100;
}
if (counter == 2) { // ~ 15 mile map radius
dy = dy / 300;
}
if (counter == 3) { // ~ 30 mile map radius
dy = dy / 500;
}
dy = -dy + 140;//'-' to reverse N / S map plot
}
//draw the newest real-time x,y coord pixel every 4 seconds
//only draw pixels within map boundaries
if (((dx > MAP_X_MIN) && (dx < MAP_X_MAX)) && ((dy > MAP_Y_MIN) && (dy < MAP_Y_MAX))) {
tft.drawPixel( dx, dy, HX8357_WHITE);
}
//update and show radians tft X Y ...
tft.fillRect(60, 200, 40, 55, HX8357_BLACK);
tft.setCursor(0, 200);
tft.setTextColor(HX8357_WHITE); tft.setTextSize(1);
tft.print("ZOOM I/O : ");//0-3, 0 is 50m
tft.println(counter);
tft.setCursor(0, 215);
tft.print("RADIANS X: ");
tft.println(radiansX);
tft.setCursor(0, 230);
tft.print("RADIANS y: ");
tft.println(radiansY);
//update and show current X Y ...
tft.fillRect(10, 165, 90, 30, HX8357_BLACK);
tft.setCursor(0, 165);
tft.setTextColor(HX8357_WHITE); tft.setTextSize(1);
tft.print("X: ");
tft.println(dx);
tft.setCursor(0, 180);
tft.setTextColor(HX8357_WHITE); tft.setTextSize(1);
tft.print("Y: ");
tft.println(dy);
//update and show precision and satellites
tft.fillRect(60, 45, 40, 10, HX8357_BLACK);
tft.setCursor(0, 45);
tft.setTextColor(HX8357_WHITE); tft.setTextSize(1);
tft.print("SATELITES: ");
tft.println(gps.satellites());
tft.fillRect(60, 60, 40, 10, HX8357_BLACK);
tft.setCursor(0, 60);
tft.setTextColor(HX8357_WHITE); tft.setTextSize(1);
tft.print("PRECISION: ");
if (gps.hdop() < 1000) {
tft.println(gps.hdop());
}
}
//ina610();//read sensor every ~4 seconds debugging
tft.fillRect(35, 270, 40, 15, HX8357_BLACK);
tft.setCursor(0, 270);
tft.setTextColor(HX8357_WHITE); tft.setTextSize(1);
tft.print("VOLTS: ");
tft.println(ina260.readBusVoltage() / 1000); //convert mV to V
}
}