XRAD'S teensy 4.1 scrolling TFT display using memset and frameBuffer, but from SD, not onboard mem

XRAD

Well-known member
I can get a great scrolling 500x500 tft display using onboard memory. I can save data to SD, but I can;t figure out how to read SD data and implement it onto new screen frameBuffer(why: I want to have a larger storage for an x,y LIDAR occupancy map)....I did try quite a few ways before asking for help...any help appreciated!! THX!

Code:
#include "ILI9341_t3n.h"
#include <SPI.h>
#include <FastLED.h>
#include <SD.h>


#define TFT_DC 9
#define TFT_CS 10
#define TFT_RST 8
#define TFT_SCK 13
#define TFT_MISO 12
#define TFT_MOSI 11
#define SD_CS BUILTIN_SDCARD


ILI9341_t3n tft1 = ILI9341_t3n(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCK, TFT_MISO);

// Grid configuration
const int MAP_SIZE = 500;
byte grid[MAP_SIZE][MAP_SIZE];  // 0=Empty, 1=Visited, 2=Occupied
const char* dataFile = "gridlog.txt";
File myFile;

// Robot Pose
float robotX = MAP_SIZE / 2;
float robotY = MAP_SIZE / 2;
float robotHeading = 0;  // Degrees

void setup() {
  tft1.begin();
  tft1.setRotation(0);  // 
  //tft1.fillScreen(ST7735_BLACK);
  tft1.useFrameBuffer(true);  // Smooth rendering with DMA-like buffering

  // Initialize SD Card
  if (!SD.begin(SD_CS)) {
    Serial.println("SD Card initialization failed!");
    return;
  }
  Serial.println("SD Card initialized.");

  memset(grid, 0, sizeof(grid));
}

// Generate test lidar scan
void updateLidarScan() {
  for (int angle = 0; angle < 360; angle += 100) {
    float rad = (angle + robotHeading) * PI / 180.0;
    float dist = 50;  //random(20, 50); // Random "wall" distance

    // Calculate occupied point (wall)
    int ox = (int)(robotX + cos(rad) * dist);
    int oy = (int)(robotY + sin(rad) * dist);

    if (ox >= 0 && ox < MAP_SIZE && oy >= 0 && oy < MAP_SIZE) {
      // Store to SD Card
      myFile = SD.open(dataFile, FILE_WRITE);
      if (myFile) {
        myFile.print(ox);
        myFile.print(",");
        myFile.println(oy);
        myFile.close();  // Close to save data

        myFile.print("Writing: ");
        myFile.print(ox);
        myFile.print(",");
        myFile.println(oy);
        Serial.print("ox:");
        Serial.println(ox);
        Serial.print("oy:");
        Serial.println(oy);

      } else {
        Serial.println("Error opening file!");
      }
      grid[ox][oy] = 2;  // Mark Occupied (Red)
    }
  }
}

void renderMap() {
  // Center screen on robot pose
  int camX = robotX - (tft1.width() / 2);
  int camY = robotY - (tft1.height() / 2);

  for (int x = 0; x < tft1.width(); x++) {
    for (int y = 0; y < tft1.height(); y++) {

      int gx = camX + x;
      int gy = camY + y;

      if (gx >= 0 && gx < MAP_SIZE && gy >= 0 && gy < MAP_SIZE) {
   
        if (grid[gx][gy] == 2) tft1.drawPixel(x, y, ILI9341_RED);
        else tft1.drawPixel(x, y, ILI9341_BLACK);
      }
    }
  }

  // Draw robot as a small yellow dot in the center
  tft1.fillCircle(tft1.width() / 2 - 2, tft1.height() / 2 - 2, 8, ILI9341_YELLOW);
  tft1.updateScreen();  // Push frame buffer to display
}


void loop() {
  EVERY_N_MILLISECONDS(200) {
    // Move robot randomly for test
    robotX += random(-3, 4);
    robotY += random(-3, 4);
    robotHeading += random(-5, 6);

    //Add new lidar data to the grid
    updateLidarScan();

    //draw scrolling viewport
    renderMap();
  }
}
 
Last edited:
Back
Top