Teensy 4.x + ESP32 Stack

KenHahn

Well-known member
This approach adds wireless capability to the Teensy 4.x by mounting an ESP32 directly onto the Teensy. After all, two brains are better than one - right?

Conceptually, this approach is the same as having a baseboard with both a Teensy and ESP32 on it that are connected together over a serial link as I do with some of my baseboards, but physically is is condensed down to just the Teensy footprint which can be handy for some applications.

1787431024338.jpeg


This setup uses the Seeed Studio XAIO ESP32-C6 module. It was chosen for a few reasons:
  • Very small 14-pin footprint
  • Good Wi-Fi 6 and Bluetooth capability
  • Built-in support for Zigbee and Thread for home automation applications
  • Overall excellent build quality and manufacturer documentation
  • Software support for easily switching between internal or external antenna
  • None of the edge pins have boot functionality that could cause issues with the Teensy pins at boot time.
  • Seeed XAIO ESP32-C6 Wiki

All pins are connected between the Teensy and ESP32 except for the 3.3V and the Teensy GND / D0 pin on the ESP32.

1787431174405.jpeg


Pin map overlay is shown below.

1787433438715.png



The ESP32 Serial1 pins are remapped in software to line up with the Teensy Serial5 pins to establish a high-speed serial link. 4Mbps has been tested and found to be very reliable. Theoretical maximum should be 5Mbps based on the ESP32 spec, but so far have gotten mixed results in testing at that max speed. @defragster has been assisting with some of that testing.

The rest of the ESP32 pins come up as inputs, but they are explicitly set as inputs and disconnected from the internal logic just to be sure there is no contention with the teensy pins. The final setup only consumes 2 of the Teensy pins (Serial5).

Code:
#define RX1 D7  // Teensy 4 Serial 5 is connected to serial port #1
#define TX1 D8

//===============================================================================
//  Initialization
//===============================================================================
void setup()
{
  Serial.begin(115200);   // Init USB port if being used for serial communications.

// Disconnect unused I/O to avoid possible conflicts
  gpio_reset_pin(GPIO_NUM_0);
  gpio_reset_pin(GPIO_NUM_1);
  gpio_reset_pin(GPIO_NUM_2);
  gpio_reset_pin(GPIO_NUM_16);
  gpio_reset_pin(GPIO_NUM_18);
  gpio_reset_pin(GPIO_NUM_20);
  gpio_reset_pin(GPIO_NUM_21);
  gpio_reset_pin(GPIO_NUM_22);
  gpio_reset_pin(GPIO_NUM_23);

  Serial1.begin(4000000, SERIAL_8N1, RX1, TX1);  //Initialize port connected to Teensy 4.1 and set for 4Mbps

From the Teensy perspective, it can pretty much ignore the monkey on its back. Assuming it wants to be able to talk to it, then it needs to setup Serial5 at the same comm speed as the ESP32, perhaps setup a serial buffer to avoid overruns and of course, decide on a common communication protocol to talk to said monkey.

Code:
#define ESP32SERIAL Serial5  // ESP32-C6 is attached to Serial5 port
// Create buffer to hold incoming characters from ESP32-C6
#define ESP32SERIAL_BUFFER_SIZE 1024
unsigned char esp32SerialBuffer[ESP32SERIAL_BUFFER_SIZE];

//===============================================================================
//  Initialization
//===============================================================================
void setup() {
  Serial.begin(115200);       //Initialize USB serial port to computer
 
  ESP32SERIAL.begin(4000000);  //Initialize Seria1 5 connected to ESP32-C6 at same baud rate
  // Setup extra memory for the ESP32 serial buffer to help avoid overruns
  ESP32SERIAL.addMemoryForRead(esp32SerialBuffer, ESP32SERIAL_BUFFER_SIZE);

Of course, the role of some of the shared pins could be reversed with the Teensy pins set as inputs and the corresponding ESP32 pins used to drive something like an I2C display directly. One nice feature of the ESP32 is that almost any pin functionality can be remapped to almost any physical pin as we did with the Serial1.

On the downsides, this setup does block the USB Host port and is not compatible with the Audio Adapter since it uses pins 20 & 21 on the Teensy. On the Teensy 4.0, the ESP32 sits right over the NXP processor, so under worst-case heavy Wi-Fi transmission use, the ESP32 gets pretty warm and hence the Teensy CPU could get pretty warm as well. Not really an issue with the Teensy 4.1 setup.

This approach does require programming of both the ESP32 and the Teensy which can either be a good or bad thing depending on your perspective. In theory, it should be possible to modify the Espressif AT program binary to adapt it to this application (basically change the pins being use for the serial link) so that programming could be done from the Teensy side only.

Also to note is that the stack can be powered from either the Teensy USB, ESP32 USB or the Teensy 5V pin. There is no power switching circuitry, so only one power source should be connected at a time. If you wanted to hook up both USB ports at the same time, power from one needs to be removed. The Teensy USB power could be disconnected by cutting the VUSB/VIN trace. In my setup I use a USB data extender cable with a built-in power switch off of Amazon.

This setup could be done as a DIY project for those so inclined and of course I am also offering compete and tested assemblies as well for not much more than the retail price of the parts. More info can be found here: https://protosupplies.com/product/teensy4-esp32-stacks/
 
Is there any reason why you mapped T/Rx to Teensy HWSerial5. could it be possible to remap to HWSerial1. I need I2S1
 
My thinking was that Serial5 pin functionality would be less commonly used that Serial1, but that thinking may be flawed.

To answer your question, yes the pins can be mapped to work with Serial1, you just need to remap the ESP32-C6 Serial 1 to line up with the Teensy Serial1 pins, cross connected of course. Thanks for clarifying that point. Looks like I need to update the website.

To verify I ran the simple Wifi Scan example remapped to the Teensy Serial1.

ESP32-C6 code
Code:
/*
    This sketch interfaces to the Teensy 4.x via serial port 1.
    It demonstrates how to receive a request for a scan for WiFi networks and
    report the results back via serial port.

    This is a simple variation of the ESP32 WiFiScan example program
    Select board type as XIAO ESP32-C6
*/
#include "WiFi.h"

#define RX1 D2  // Teensy 4.1 Serial 1 is connected to serial port #1
#define TX1 D1

//===============================================================================
//  Initialization
//===============================================================================
void setup()
{
  Serial.begin(115200);   // USB port

  // Disconnect unused I/O to avoid possible conflicts
  gpio_reset_pin(GPIO_NUM_0);
  gpio_reset_pin(GPIO_NUM_1);
  gpio_reset_pin(GPIO_NUM_2);
  gpio_reset_pin(GPIO_NUM_16);
  gpio_reset_pin(GPIO_NUM_18);
  gpio_reset_pin(GPIO_NUM_20);
  gpio_reset_pin(GPIO_NUM_21);
  gpio_reset_pin(GPIO_NUM_22);
  gpio_reset_pin(GPIO_NUM_23);

  //Remap Serial1 to line up with Teensy Serial1 running at 4Mbps
  Serial1.begin(4000000, SERIAL_8N1, RX1, TX1);

  // Uncomment the section below if you want to use external antenna
  /*
    pinMode(3, OUTPUT);
    digitalWrite(3, LOW);//turn on Antenna select function
    delay(100);
    pinMode(14, OUTPUT);
    digitalWrite(14, HIGH);//use external antenna
  */

  // Set WiFi to station mode and disconnect from an AP if previously connected
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);
  Serial.println("Setup done");
}
//===============================================================================
//  Main
//===============================================================================
void loop()
{
  if (Serial1.available()) {
    char command = Serial1.read();
    Serial.println(command);
    if (command == '?') { // Are you there?
      Serial.println("Y");
      Serial1.print("Y");  // Acknowledge I'm attached
    }
    if (command == 'S') {
      Serial.println("scan start");
      // WiFi.scanNetworks will return the number of networks found
      int n = WiFi.scanNetworks();
      Serial.println("scan done");
      if (n == 0) {
        Serial.println("no networks found");
        Serial1.println("No networks found");
      } else {
        Serial.print(n);
        Serial1.print(n);
        Serial.println(" Networks Found");
        Serial1.println(" Networks Found");
        for (int i = 0; i < n; ++i) {
          // Print SSID and RSSI for each network found to both USB and
          // out Serial2 to attached Teensy 4.1
          Serial.print(i + 1);
          Serial1.print(i + 1);
          Serial.print(": ");
          Serial1.print(": ");
          Serial.print(WiFi.SSID(i));
          Serial1.print(WiFi.SSID(i));
          Serial.print(" (");
          Serial1.print(" (");
          Serial.print(WiFi.RSSI(i));
          Serial1.print(WiFi.RSSI(i));
          Serial.print(")");
          Serial1.print(")");
          Serial.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN) ? " " : "*");
          Serial1.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN) ? " " : "*");
        }
      }
    }
  }
}

Teensy code
Code:
/*
   Teensy / ESP32-C6 Scan Example Program
   Also reports any PSRAM or Flash mounted on a Teensy 4.1
   and reports the CPU temperature
*/
//Included if compiling for Teensy 4.1 and not for Teensy 4.0
#if defined(ARDUINO_TEENSY41)
  #include "LittleFS.h"
  extern "C" uint8_t external_psram_size;
#endif

#define ESP32SERIAL Serial1  // ESP32 is attached to Serial1 port
// Create buffer to hold incoming characters from ESP32-S3
#define ESP32SERIAL_BUFFER_SIZE 1024
unsigned char esp32SerialBuffer[ESP32SERIAL_BUFFER_SIZE];

bool esp32Attached = false;   // Flag if ESP32 is attached
bool scanRequested = false;   // Flag if scan is in process

//===============================================================================
//  Initialization
//===============================================================================
void setup() {
  Serial.begin(115200);       //Initialize USB serial port to computer
  ESP32SERIAL.begin(4000000);  //Initialize Seria11 connected to ESP32 at 4Mbps
  // Setup extra memory for the ESP32 serial buffer to avoid overruns
  ESP32SERIAL.addMemoryForRead(esp32SerialBuffer, ESP32SERIAL_BUFFER_SIZE);

  // If running on a Teensy 4.1, check if PSRAM or Flash is installed
  #if defined(ARDUINO_TEENSY41)
    // Check for PSRAM chip(s) installed on Teensy 4.1
    uint8_t size = external_psram_size;
    if (size == 0) {
      Serial.println("No PSRAM Installed");
    } else {
      Serial.printf("PSRAM Memory Size = %d Mbyte\n", size);
    }

    // Check for Flash chip installed on Teensy 4.1
    LittleFS_QSPI myfs;  // Works with both types of flash

    // Check for any Flash chip installed.
    if (myfs.begin()) {
      Serial.printf("Flash Memory Size = %d Mbyte / ", myfs.totalSize() / 1048576);
      Serial.printf("%d Gbit\n", myfs.totalSize() / 131072000);
    }
    else {
      Serial.printf("No Flash Installed\n");
    }
  #endif

  // Check for ESP32-C6 installed
  while (ESP32SERIAL.available()) {  // Clear ESP32 input buffer before CMD
    (char)ESP32SERIAL.read();
  }

  ESP32SERIAL.print("?");                          // Ask ESP32 if it is there
  delay(100);                                      // Wait a bit for ESP32 to respond
  if (ESP32SERIAL.available()) {                   // If there is a response
    String returnData = ESP32SERIAL.readString();  // Read response
    if (returnData == 'Y') {                       // ESP32 responded with 'Y'es, I'm here
      esp32Attached = true;
      Serial.println("ESP32-C6 was found");
    } else {  // invalid response received
      Serial.println("ESP32-C6 invalid response - Check that baud rates match");
      esp32Attached = false;
    }
  } else {
    esp32Attached = false;
    Serial.println("ESP32-C6 did not respond - Stop execution");
  }
  if (!esp32Attached) while (true); // Don't proceed if it doesn't find ESP32
}
//===============================================================================
//  Main
//===============================================================================
void loop() {

  DoScan();
  if (scanRequested && ESP32SERIAL.available()) {
    Serial.println("Read incoming data");

    while (ESP32SERIAL.available()) {  // Print the scan data
      String returnData = ESP32SERIAL.readString();
      Serial.println(returnData);
      delay(10);
    }
    scanRequested = false;  // Reset the scan flag and button
  }
  delay (5000);
  Serial.println();
  Serial.print(tempmonGetTemp());
  Serial.println("°C");
}

//===============================================================================
//  Routine to draw scan button current state and initiate scan request
//===============================================================================
void DoScan() {

  ESP32SERIAL.println("S");  // Send command to ESP32 to start scan
  scanRequested = true;      // Set flag that we requested scan
  Serial.println("Scan being requested");
}
 
@KurtE They are available in Teensy 4.0, Teensy 4.1 NE and Teensy 4.1 NE with various memory options preinstalled at the link below. I use the NE since the physical Ethernet header is blocked anyway.

https://protosupplies.com/product/teensy4-esp32-stacks/

I can also build them on top of the Teensy 4.1 for Prototyping System version which brings the I/O down from the bottom for use with a PCB baseboard. In that case I use the standard Teensy 4.1 since the hardware Ethernet along with the USB Host can be used.

It is basically a $15 adder to add it to existing Teensy configurations. The XAIO ESP32-C6 module costs $12 in qty one on Amazon for anyone that wants to build their own, plus you need the extended headers which I sell for $2.50.

On a related note, due to the high cost of memory right now, parts like the 2Gb Flash chips for the Teensy 4.1 are around $23 if you can even find them. Digikey currently has 5 in stock at that price. Since I stocked up on the parts at the lower costs, it is currently cheaper to buy the Teensy with the memory preinstalled than to try to DIY these days.
 
Alcon
Decided to give the mini-dev board a try with the C3 and the Teensy 4.1 in prep for the c6. In process of converting weather app. So far got the two boards talking and the T41 parsing the JSON data I get from the c3
Code:
Requesting City: 11357

--- [GEOCODING DATA RECEIVED] ---
{"results":[{"id":5144400,"name":"Whitestone","latitude":40.79455,"longitude":-73.81847,"elevation":15.0,"feature_code":"PPLX","country_code":"US","admin1_id":5128638,"admin2_id":5133268,"timezone":"America/New_York","population":36984,"postcodes":["11357"],"country_id":6252001,"country":"United States","admin1":"New York","admin2":"Queens County"}],"generationtime_ms":0.22614002}

====================== Map City ======================
Name:                Whitestone
latitude:            40.794548
longitude:           -73.818466
Time Zone:           America/New_York

--- [CURRENT WEATHER RECEIVED] ---
{"latitude":40.787308,"longitude":-73.819305,"generationtime_ms":0.5037784576416016,"utc_offset_seconds":-14400,"timezone":"America/New_York","timezone_abbreviation":"GMT-4","elevation":16.0,"current_units":{"time":"iso8601","interval":"seconds","temperature_2m":"°F","wind_speed_10m":"mp/h","wind_direction_10m":"°","weather_code":"wmo code","surface_pressure":"hPa","rain":"inch","snowfall":"inch","precipitation":"inch"},"current":{"time":"2026-09-05T14:45","interval":900,"temperature_2m":79.2,"wind_speed_10m":10.3,"wind_direction_10m":356,"weather_code":2,"surface_pressure":1008.1,"rain":0.000,"snowfall":0.000,"precipitation":0.000}}

====================== CURRENT WEATHER ======================
Time:                2026-09-05T14:45
Condition:           Partly cloudy (Code 2)
Temperature:         79.2 °F
Pressure (MSL):      0.0 hPa
Wind Speed:          10.3 mph
Wind Direction:      356°
Rain:                0.00 in
Snowfall:            0.00 in

--- [DAILY FORECAST RECEIVED] ---
{"latitude":40.787308,"longitude":-73.819305,"generationtime_ms":1.4668703079223633,"utc_offset_seconds":-14400,"timezone":"America/New_York","timezone_abbreviation":"GMT-4","elevation":16.0,"daily_units":{"time":"iso8601","temperature_2m_max":"°F","temperature_2m_min":"°F","snowfall_sum":"inch","precipitation_probability_max":"%","weather_code":"wmo code","wind_speed_10m_max":"mp/h","wind_gusts_10m_max":"mp/h","wind_direction_10m_dominant":"°","rain_sum":"inch","precipitation_sum":"inch","sunrise":"iso8601","sunset":"iso8601","relative_humidity_2m_mean":"%"},"daily":{"time":["2026-09-05","2026-09-06","2026-09-07","2026-09-08","2026-09-09","2026-09-10","2026-09-11"],"temperature_2m_max":[79.0,70.6,81.7,83.8,85.6,88.5,79.3],"temperature_2m_min":[68.1,61.3,58.8,68.2,72.1,73.9,64.4],"snowfall_sum":[0.000,0.000,0.000,0.000,0.000,0.000,0.000],"precipitation_probability_max":[3,13,1,0,5,11,11],"weather_code":[3,51,3,3,3,53,51],"wind_speed_10m_max":[11.7,11.3,10.3,7.6,14.7,14.9,13.8],"wind_gusts_10m_max":[17.7,14.5,13.2,13.0,34.2,36.7,19.9],"wind_direction_10m_dominant":[344,45,338,341,209,244,316],"rain_sum":[0.000,0.016,0.000,0.000,0.000,0.047,0.012],"precipitation_sum":[0.000,0.016,0.000,0.000,0.000,0.075,0.012],"sunrise":["2026-09-05T06:26","2026-09-06T06:27","2026-09-07T06:28","2026-09-08T06:29","2026-09-09T06:30","2026-09-10T06:31","2026-09-11T06:32"],"sunset":["2026-09-05T19:20","2026-09-06T19:19","2026-09-07T19:17","2026-09-08T19:15","2026-09-09T19:14","2026-09-10T19:12","2026-09-11T19:10"],"relative_humidity_2m_mean":[57,80,50,41,53,55,53]}}

====================================================== DAILY FORECAST ======================================================
   Date       Max/Min Temp    PoP%   Precip    Rain    Snow    MaxWind   Gusts   Sunrise  Sunset   Hum%  Condition
----------------------------------------------------------------------------------------------------------------------------
   09-05     79.0 / 68.1 deg F    3%   0.00 in  0.00 in  0.00 in 11.7 mph 17.7 mph  06:26  19:20    57%  Overcast
   09-06     70.6 / 61.3 deg F   13%   0.02 in  0.02 in  0.00 in 11.3 mph 14.5 mph  06:27  19:19    80%  Light drizzle
   09-07     81.7 / 58.8 deg F    1%   0.00 in  0.00 in  0.00 in 10.3 mph 13.2 mph  06:28  19:17    50%  Overcast
   09-08     83.8 / 68.2 deg F    0%   0.00 in  0.00 in  0.00 in  7.6 mph 13.0 mph  06:29  19:15    41%  Overcast
   09-09     85.6 / 72.1 deg F    5%   0.00 in  0.00 in  0.00 in 14.7 mph 34.2 mph  06:30  19:14    53%  Overcast
   09-10     88.5 / 73.9 deg F   11%   0.07 in  0.05 in  0.00 in 14.9 mph 36.7 mph  06:31  19:12    55%  Moderate drizzle
   09-11     79.3 / 64.4 deg F   11%   0.01 in  0.01 in  0.00 in 13.8 mph 19.9 mph  06:32  19:10    53%  Light drizzle
================================================================================--------------------------------------------


--- [AIR QUALITY RECEIVED] ---
{"latitude":40.800003,"longitude":-73.799995,"generationtime_ms":0.34058094024658203,"utc_offset_seconds":-14400,"timezone":"America/New_York","timezone_abbreviation":"GMT-4","elevation":16.0,"current_units":{"time":"iso8601","interval":"seconds","us_aqi":"USAQI","pm2_5":"μg/m³","pm10":"μg/m³"},"current":{"time":"2026-09-05T14:00","interval":3600,"us_aqi":52,"pm2_5":9.0,"pm10":9.2}}
JSON Parsing failed: InvalidInput
null
*** ALL METRICS SUCCESSFULLY UPDATED ***

Next up the display stuff
 
Very cool. I was wondering what it would take to port it to an ESP32 setup.

BTW, there has been pretty good interest in the ESP32 stack, so I am also going to offer a C5 version as well as the C6.

C5 adds 5GHz operation, a faster 240MHz processor, larger 8MB Flash and 8MB PSRAM , but it also requires using an external antenna which is why I used the C6 as the default configuration since not everyone wants to mess with an antenna.

A small antenna with an adhesive pad comes with it as shown and it works well, but a larger chassis mounted one can also be used, it just needs to be 5GHz compatible.

1788637672926.jpeg
 
@KenHahn

I would say about 98% of the code is reused between the sketches. Biggest challenge was breaking it up so only the queries went on the C3 and all the other stuff on the T4.1. Of course getting the 2 talking was fun. Had an initial version that was working and then gave Gemini a crack at it, and after telling it nope not that way a couple of times got a nicer version.

Anyways here are the 2 sketches. Screens are the same.

On the esp32 side you will have to edit the secrets.h file for your ssid and password. Give it a try and let me know. I know @defragster and @KurtE has a board as well.

Havent ordered it so may wait until the C5 version is available to try the 5ghz.

EDIT: Feel free to modify for your use.
 

Attachments

  • teensy_esp32.zip
    71.8 KB · Views: 14
  • esp32_teensy_v1.zip
    3.1 KB · Views: 13
I am in the process of setting it up to try it out...
But found I uninstalled the ESP32 stuff, so in the process of reinstalling it.

I am sort of lazy today, spent most of the afternoon sanding beams up on several different ladders. Tomorrow will put on first coat of Sikkens on them... Recovering from what the painters we hired screwed up on!

Also in the process of playing on the Arduino GIGA (with Zephyr), trying to get away from "Secret" headers for each sketch that may have
my Wifi name and Password.

So instead I am using a setup to create a JSON file, with this information as well as my default location:
Currently setting this up as external sketch:
Code:
#include <Arduino.h>
#include <zephyr/fs/fs.h>
#include <ArduinoJson.h>

#define JSON_FILENAME "/storage/security.jsn"

void setup() {
  char wifi_ssid[256];
  char wifi_passwd[256];
  char location[256];
  Serial.begin(115200);
  while (!Serial) {}

  get_string("Enter Wifi SSID:", wifi_ssid);
  get_string("Password:", wifi_passwd);
  get_string("Weather city or zip:", location);

  JsonDocument doc;

  JsonObject wifi = doc["wifi"].to<JsonObject>();
  wifi["ssid"] = wifi_ssid;
  wifi["password"] = wifi_passwd;

  JsonObject weather_loc = doc["weather"].to<JsonObject>();
  weather_loc["city"] = location;

  char buffer[512];  // ensure it's large enough
  size_t len = serializeJson(doc, buffer, sizeof(buffer));
  /* Write to file (example: MemFS) */
  buffer[len] = '\0';
  Serial.print("Generated Json: ");
  Serial.println(buffer);

  Serial.println("Trying to write to ");
  Serial.println(JSON_FILENAME);
  int ret = write_json_file(buffer, len);
  Serial.print("Return code: ");
  Serial.println(ret);

  // Now see if we can read in the JSON file
  Serial.println("Trying to read Json file");
  ret = read_json_file(buffer, len);
  Serial.print("Return code: ");
  Serial.println(ret);

}

int write_json_file(const char *buffer, size_t len) {
  struct fs_file_t file;
  fs_file_t_init(&file);
  int ret;
  ret = fs_open(&file, JSON_FILENAME, FS_O_CREATE | FS_O_WRITE);
  if (ret < 0) {
    Serial.println("failed to create file");
    return ret;
  }

  ret = fs_write(&file, buffer, len);
  if (ret < 0) {
    Serial.println("Failed to write to file");
    return ret;
  }

  ret = fs_close(&file);
  if (ret < 0) {
    Serial.println("Failed to close file");
    return ret;
  }
  Serial.println("File written successfully\n");
  return 0;
}

int read_json_file(const char *buffer, size_t len) {
  struct fs_file_t file;
  fs_file_t_init(&file);
  int ret;
  ret = fs_open(&file, JSON_FILENAME, FS_O_READ);
  if (ret < 0) {
    Serial.println("failed to open file");
    return ret;
  }


  ssize_t cb_read = fs_read(&file, (void*)buffer, len);
  if (cb_read < 0) {
    Serial.println("Failed to write to file");
    return cb_read;
  }

  ret = fs_close(&file);
  if (ret < 0) {
    Serial.println("Failed to close file");
    return ret;
  }

  JsonDocument doc;
  DeserializationError error = deserializeJson(doc, buffer, cb_read);
  if (error) {
    Serial.print("Failed to deserialize: ");
    Serial.println(error.c_str());
  }

  serializeJsonPretty(doc, Serial);
  Serial.println();
  return 0;
}



void get_string(const char *title, char *sz) {
  while (Serial.read() != -1) {}
  int chr;
  Serial.println(title);
  while ((chr = Serial.read()) == -1) {}
  while (chr >= ' ') {
    *sz++ = chr;
    chr = Serial.read();
  }
  *sz = '\0';
}


void loop() {
}
On the GIGA, I am storing it in the "Storage" FS on flash...
on Teensy, could store in LittleFS on the flash...

Currently it has two sections:
One [wifi] with the ssid, and password
the second [weather] currently with city.

Will probably extend this section, to also include maybe how many minutes before it queries for new data...

Thoughts are in the main weather display sketch, that if you type in a new city, it will update that section.
Also once it maps city name to Lat/Lon - maybe store this information there as well and not have to query it again...
That way when sketch starts up again, it can avoid one WiFi request ...

Will try out the new board with the ESP32 piggyback soon,

Note: One thing I like about the GIGA is that it has a nice display and all of the stuff needed, without needing to solder anything.
Likewise the Minibaseboard.

Next up figure out how I want to play with the new Teensy with the ESP32 piggybacked on it.
 
The C3 has 16-pins instead of 14 like the C6 and the serial port connection is attached to one of the pins that would be physically missing on the C6, so not a drop-in replacement. The socket also powers the C3 from 3.3V and there is no 5V on the socket. The C6 can't be powered from 3.3V, it needs 5V.

Can't remember if you got the plugin breadboard with the Mini or not, but if you have that, you could put a pinned C6 on it and jumper to Serial1 or Serial6 that comes out on that IDC connector.

Bringing up your software on my own Mini here. Have the Teensy code running so far after a few tweaks.
 
Works good, though it did take me a minute to figure out that I needed to enter a city before I got anything on the display.

The FT6236.h is a library I haven't used before, I have been using the Adafruit version. I did have to modify it slightly to get it to work for anyone following along. Line 31 of the .cpp file needed to change from Wire.begin(sda, scl); to Wire.begin(); to get it to compile.

1788660677073.jpeg
 
Works good, though it did take me a minute to figure out that I needed to enter a city before I got anything on the display.

The FT6236.h is a library I haven't used before, I have been using the Adafruit version. I did have to modify it slightly to get it to work for anyone following along. Line 31 of the .cpp file needed to change from Wire.begin(sda, scl); to Wire.begin(); to get it to compile.
Ditto,
First forgot to edit secret…

FT6236 I noticed you were using the Adafruit version, I had one from bitbank2

I also waited a little to see something come up, but then noticed prompt
 
Good morning all

I updated the Teensy sketch so it will load a DEFAULT_CITY, use the Adafruit FT8236 touch library, and support landscape 1 and 3,
Code:
/**********************************************
*  Setup display and touch
***********************************************/
//#define ILI488_DISP // esle ST7796
//#define XPT_TOUCH  //else FT6236

#define orientation 3  // or 1 (landscape)

String DEFAULT_CITY = "Disneyland"; // Default startup city

Hope this helps

@KenHahn
going to test on the C6 later today, and yes I have the plugin breadboard for the mini :)
 

Attachments

  • teensy_esp32-260906a.zip
    72 KB · Views: 12
@KurtE - @KenHahn - @defragster - @wwatson

I have been at it again. One thing that has bothered me is that Open-Meteo daily WMO codes 1,2,3 are all collapsed into code 3 for overcast so even though its partly cloudy according to NWS its still shows as overcast. Doing some digging found that we can manually refine this based on cloud cover if the code is 3. So went ahead and updated both sketches to get it looking better and hopefully more accurate.

Let me know what you all think is it worth it.
 

Attachments

  • teensy_esp32-260906a.zip
    72.4 KB · Views: 14
  • esp32_teensy_v1-260906a.zip
    3.1 KB · Views: 14
Everything compiled clean and came up and ran with no fuss on my setup. Living in the PNW, it is useful to differentiate between levels of cloudy and overcast so that we feel like the weather is changing.

I really like the look of the interface. Ideally the icons would be a little smaller so that they didn't cut off the day of the week, but that's a nit...
 
@KenHahn @mjs513 @defragster @wwatson -

I also rebuilt and everything appears to works.

I have been playing with the GIGA version, and pulled in several of the later changes.
1788727186932.png
1788727233389.png


Note the display has more pixels available...

Some of the stuff in my current version includes:
Security/Location information is stored in a json file, that is stored in a littleFS partition in Flash memory...
I have a separate sketch I used initially to setup the json file, but now, the code is setup that if the file is not found
it prompts you for things like: ssid, password, location and saves it away. After the first time it gets through
the Web page to convert location to: lat/long, Timzeone, location name, it updates this Json file with this information
and code bypasses the first step in subsequent startings... If you type in a new location (City or Zip code) it will then
do the mapping page and update the file...

There is also a value in Json on how many minutes to wait before you ask for new data, and after that much time, it does
the query again and updates the screen...

Will post more on the Arduino forum.
 
MINI T_4.1 working for weather! Nice work @mjs513

HAD build GRIEF - IDE 2 builds esp32 and IDE1 Teensy - something wrong with ESP32 3.3.11 install - redone still wrong?
riscv32-esp-elf-g++: fatal error: cannot execute 'as': CreateProcess: No such file or directory
Seems IDE's shares board - IDE1 showed it - Removed and reinstalled there and finally the ESP32C3 builds for MINI in IDE 2 ?!?!?

Moving print of ' // Weather Icon' before '// Date & Day' fixes day of week ICON overwrite in drawWeatherDashboard()

ESP32 loop() edit like this seems to allow ReSync on Teensy upload with ESP32 running?
EDIT: maybe not reliably? Maybe ESP32 restart triggered?
Code:
void loop() {
  // 1. Process Incoming Commands from Teensy 4.1
  if (Serial1.available()) {
    String commandLine = Serial1.readStringUntil('\n');
    commandLine.trim();

    if (commandLine.startsWith("?")) {
        Serial1.print("Y\n");
        Serial.println("Teensy Handshake Complete!");
      }
 
Last edited:
Also

this comment: //#define ILI488_DISP // esle ST7796
should be : //#define ILI9488_DISP // else ST7796

And I added any touch not a day entry does an update:
Code:
      else if (weather_city.length() > 0) {
        static elapsedMillis debounce;
        if ( debounce > 2000 ) {
          debounce = 0;
          Serial.print("Requesting City: ");
          Serial.println(weather_city);

          // Send execution commands across UART
          ESP32SERIAL.print("CMD:CITY:");
          ESP32SERIAL.println(weather_city);
        }
      }
Longer than 2 secs would be fine - but WOW does it trip FAST if not debounced. Did see an easy way at hand to update screen for ACK of touch as all screen UI in the other INO.
 
@KenHahn @mjs513 @defragster @wwatson -

Morning all

Spent the day yesterday modifying @KrisKasprzak Keypad library to support not only the ILI9341 but also the ILI9488 and the ST776. Also supports both the FT6236 and XPT2046 Touch drivers. Only tested with the mini dev board so far so may have to edit a bit more. The modified library is in my Github Branch: https://github.com/mjs513/ILI9341_t3_Keypad/tree/ST7796_keyboard

Also did what @defragster mentioned about moving the daily images before print the daily info on the main screen.

1, Included @KurtE's refresh data every 60 minutes.
2. Moved hi/low down a little bit on the main screen.
3. And a little bit of clean up.
4. Added a little keyboard icon on the top right side of screen
5. If you leave city blank hit done then the back key works on the keyboard screen. If you enter a city and hit done it auto updates the screen

Still a few annoying things but if you want to give it a try here it is.
 

Attachments

  • teensy_esp32-260907a.zip
    74.6 KB · Views: 11
Back
Top