Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 5 of 5

Thread: XRAD'S Teensy 3.6 read write to SD x/y integer coord pairs

  1. #1

    XRAD'S Teensy 3.6 How to read write to SD x/y integer coord pairs?


    I have a GPS point set which is converted to x/y points (integers) for tft pixel display. I have the display points showing up just fine for a walk around the area within the bounds of my TFT 'map.' But when I want to scale the pixel points to a larger area (zoom in or zoom out), I will need to redraw all the current points and display the new 'map' of pixels at selected 'scale.'

    I 'think' that I have to save the points to SD in order to redraw them (otherwise, I will only have the currently calculated x/y point pair to draw)

    However! I am trying to save an 'unknown' quantity of x/y integer pair points to the SD (unknown because I may walk for 1 minute, or one hour, and the points set may need to be stored via an adaptive array (vector array?). Then, if I scale the map up or down, all the points saved would be redrawn to a TFT at the chosen scale (basically zoom in/zoom out )

    1) this the best strategy?

    2) How do I save a dynamic/variable sized array of 'pairs'?

    2) and how do I recall them in 'pairs' and display them all to the TFT as a group?

    Thank you for any tips!! Pic of a live display of plotted points at base scale.... (accuracy meters to pixels is NOT required)

    here is my code so far:
    #include <SD.h>
    #include <TinyGPS.h>
    #include <Adafruit_GFX.h>
    #include "Adafruit_ILI9341.h"
    #define TFT_CS    8      // TFT CS  pin is connected to arduino pin 8
    #define TFT_RST   9      // TFT RST pin is connected to arduino pin 9
    #define TFT_DC    10     // TFT DC  pin is connected to arduino pin 10
    // initialize ILI9341 TFT library
    Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
    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 long homeX;
    int long homeY;
    int centeredX;
    int centeredY;
    int dx;
    int dy;
    //not used yet
    #define MAP_WIDTH 210
    #define MAP_HEIGHT 240
    #define MAP_CENTERX 215
    #define MAP_CENTERY 120
    #define width 210
    #define height 240
    File myFile;
      void drawCross() {//draw a solid cross
      tft.drawFastVLine(215, 0, 240, ILI9341_GREEN);
      tft.drawFastHLine(110, 120, 210, ILI9341_GREEN);
    void drawMap() { //draw a map w/dotted cross
      tft.drawRoundRect(110, 0, 210, 240, 10, ILI9341_GREEN);
      for (int x = 55; x < 160; x++) {
        tft.drawPixel((2 * x), 120, ILI9341_GREEN);
      for (int y = 0; y < 120; y++) {
        tft.drawPixel(215, (2 * y), ILI9341_GREEN);
      tft.setCursor(210, 2);
      tft.fillRect(210, 2, 10, 14, ILI9341_BLACK);
      tft.setTextColor(ILI9341_GREEN);  tft.setTextSize(2);
    void setup()
      Serial1.begin(9600);//my GPS device uses 9600 baud, using teensy Serial1
      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");
        // don't do anything more:
      Serial.println("card initialized.");
      myFile ="test.txt", FILE_WRITE);
      // if the file opened okay, write to it:
      if (myFile) {
        Serial.print("Writing to test.txt...");
        myFile.println("testing 1, 2, 3.");
        // close the file:
      } else {
        // if the file didn't open, print an error:
        Serial.println("error opening test.txt");
      // re-open the file for reading:
      myFile ="test.txt");
      if (myFile) {
        // read from the file until there's nothing else in it:
        while (myFile.available()) {
        // close the file:
      } else {
        // if the file didn't open, print an error:
        Serial.println("error opening test.txt");
      tft.setCursor(40, 100);
      tft.setTextColor(ILI9341_WHITE);  tft.setTextSize(3);
      tft.println("GPS ACTIVATED");
      tft.setCursor(0, 0);
      tft.setTextColor(ILI9341_GREEN);  tft.setTextSize(1);
      tft.print("CURRENT POSITION: ");
      tft.setCursor(0, 90);
      tft.print("INITIAL POSITION: ");
      tft.setCursor(0, 150);
      tft.print("CARTESIAN COORD: ");
      startMillis = millis();
      delay(5000);//allow GPS power up
    void loop()
      bool newData = false;
      unsigned long chars;
      unsigned short sentences, failed;
      // For one second we parse GPS data and report some key values
      for (unsigned long start = millis(); millis() - start < 1000;)
        while (Serial1.available())
          char c =;
          // Serial.write(c); // uncomment this line if you want to see the GPS data flowing
          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);
        //Serial.print(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flat, 4);
        //Serial.print(" LON=");
        //Serial.print(flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flon, 4);
        //Serial.print(" SAT=");
        //Serial.print(gps.satellites() == TinyGPS::GPS_INVALID_SATELLITES ? 0 : gps.satellites());
        //Serial.print(" PREC=");
        //Serial.println(gps.hdop() == TinyGPS::GPS_INVALID_HDOP ? 0 : gps.hdop());
        tft.fillRect(20, 15, 90, 10, ILI9341_BLACK);
        tft.setCursor(0, 15);
        tft.setTextColor(ILI9341_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, ILI9341_BLACK);
        tft.setCursor(0, 30);
        tft.setTextColor(ILI9341_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(ILI9341_WHITE);  tft.setTextSize(1);
          tft.print("LAT: ");
          tft.println(flat, 6);
          tft.setCursor(0, 120);
          tft.print("LON: ");
          tft.println(flon, 6);
          float radiansX = ( flat * (asin(1)) / 90 );
          float radiansY = ( flon * (asin(1)) / 90 );
          //Serial.print("radians x:  ");
          //Serial.print("radians y:  ");
          homex = R * radiansY * cos(radiansX);
          homey = R * radiansX;
          //Serial.print("homex:  ");
          //Serial.print("homey:  ");
          //tft.drawPixel( homex, homey, ILI9341_WHITE);//draw home pixel
          oneTimePosition = false;
        float radiansX = ( flat * (asin(1)) / 90 );
        float radiansY = ( flon * (asin(1)) / 90 );
        //Serial.print("radians new x:  ");
        //Serial.print("radians new y:  ");
        x = R * radiansY * cos(radiansX);
        y = R * radiansX;
        if (homex != x) {
          dx = (x - homex);
          dx = dx + 215;
        if (homey != y) {
          dy = (y - homey)  ;
          dy = -dy + 120;//reverse N/S here
          //record x/y data pairs to SD here?
        //draw the newest x,y coord pixel every second
        tft.drawPixel( dx, dy, ILI9341_WHITE);
        Serial.print("x coord pixel:  ");
        Serial.print("y coord pixel:  ");
        //clear radians tft X Y ...
        tft.fillRect(60, 200, 40, 40, ILI9341_BLACK);
        tft.setCursor(0, 200);
        tft.setTextColor(ILI9341_WHITE);  tft.setTextSize(1);
        tft.print("RADIANS X: ");
        tft.setCursor(0, 220);
        tft.print("RADIANS Y: ");
        //update and show current X Y ...
        tft.fillRect(10, 165, 90, 30, ILI9341_BLACK);
        tft.setCursor(0, 165);
        tft.setTextColor(ILI9341_WHITE);  tft.setTextSize(1);
        tft.print("X: ");
        tft.setCursor(0, 180);
        tft.setTextColor(ILI9341_WHITE);  tft.setTextSize(1);
        tft.print("Y: ");
        //update and show precision and satellites
        tft.fillRect(60, 45, 40, 10, ILI9341_BLACK);
        tft.setCursor(0, 45);
        tft.setTextColor(ILI9341_WHITE);  tft.setTextSize(1);
        tft.print("SATELITES: ");
        tft.fillRect(60, 60, 40, 10, ILI9341_BLACK);
        tft.setCursor(0, 60);
        tft.setTextColor(ILI9341_WHITE);  tft.setTextSize(1);
        tft.print("PRECISION: ");
    Attached Thumbnails Attached Thumbnails Click image for larger version. 

Name:	IMG_0711.JPG 
Views:	7 
Size:	131.6 KB 
ID:	27195  
    Last edited by XRAD; 01-12-2022 at 11:38 PM.

  2. #2
    so I can save x,y integers to SD now and it looks like this in the SD file (and read them back as a batch to Serial.print) :


    or I can save x,y to SD like this:


    What is the best strategy to read back these lines of data in order to
    draw ALL the x,y coords from SD?

    tft.drawPixel( x, y, ILI9341_WHITE);

  3. #3
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    New York
    Nice job. My preference is just to write the values:

    Your first line in the file could always be
    x, y
    just for reference

  4. #4
    Quote Originally Posted by mjs513 View Post
    Nice job. My preference is just to write the values:

    Your first line in the file could always be
    x, y
    just for reference

    Thank you mjs513! I can add to the SD file each read of the GPS (1 read per second). And I can read the complete SD file. But now I have to get all these lines from the SD myfile and draw pixels with them. But I have no idea how...

    should I try to save the entire newest set of SD data lines into chip memory first and then draw them? into a buffer of size determined by # of bytes in SD file? or just set buffer as large as possible?

    should I try to read and draw the pixels straight from SD?

    And how do I do either or both of these?

    I think that for quickly drawing pixels, I would want the least number of calls to drawPixel...but not sure how to do this..

    I am trying to think of this as drawing an image from the SD to the tft...

    for( i = 0; i <sizeof (myfile)-1 ; i++){//which I know doesn't work

    read each line of myfile

    then for each line in file
    do this : tft.drawPixel( x, y, ILI9341_WHITE);

    until no more lines to read

    can anyone point me in the right direction ? Thank you
    Last edited by XRAD; 01-14-2022 at 03:16 PM.

  5. #5
    I can store my D.D. GPS converted to x/y integers to SD that look like this:


    I can draw them at original scale (of approx 1 pix per m). Or I can scale them with several scales (x/100,x/500.etc..) and draw the new scale, but I am not able to redraw the saved x/y SD pairs in entirety, only the newest SD pixel values..

    When I rescale to pixel size to say 1/100...I need to clear the tft, and then redraw all the pixels from the SD at the new scale so the tft is repopulated with all pixel points at correct scale.

    the SD file is not of a fixed length as every second from start of loop(), a new x/y pair is added, but the whole file will need to be utilized to create a new set of pixels on the tft if scale is changed...

    so maybe I need to read()SD file and as I am reading each line, convert coord pair to new scale, and then draw tft pixel....

    Does anyone have any function for retrieving all the SD comma separated line pairs one by one from beginning to end? ( in the Arduino SD notes, read file reads whole file, and that is fine on serial monitor, but I can't seem to get the SD data one line at a time into my loop functions....)

    Am I being clear or unclear?

    Any help appreciated!
    Last edited by XRAD; 01-16-2022 at 08:52 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts