SIGN IN YOUR ACCOUNT TO HAVE ACCESS TO DIFFERENT FEATURES

FORGOT YOUR PASSWORD?

FORGOT YOUR DETAILS?

AAH, WAIT, I REMEMBER NOW!
  • LOGIN

ProtoSupplies

  • HOME
  • SHOP
    • Arduino, Teensy & IOT
    • Audio & Video
    • Breadboards & Supplies
    • Breakout Modules
    • Cables and Wires
    • Communications & Interfacing
    • Connectors & Headers
    • Displays, LEDs & Panel Meters
    • Fans & Hardware
    • ICs & Semiconductors
    • Passive Components
    • PCBs – Prototype & Adapter
    • Power Supplies & Converters
    • Proximity, Distance and Collision
    • Relays, MOSFETs & Power Ctrl
    • Robotics, Motors & Motion
    • Sensors
    • Supplies & Consumables
    • Switches & User Input
    • Temperature & Humidity
    • Test, Tools & Test Accessories
  • LEARN TEENSY
  • TECH
    • Guide To Solderless Breadboards
    • Determining Unknown I2C Addresses
    • Determining LED Resistor Values
    • DC-DC Step-Down Converter Overview
    • s
  • BLOG
  • INFO
    • About Us
    • FAQ
    • International Customers
    • My Account
    • Contact Us
  • MY CART
    No products in cart.

Home » Tutorials » Prototyping System for Teensy 4.1 – Example Software

October 15, 2026

Prototyping System for Teensy 4.1 – Example Software

< Powering Up the System
Teensy 4.1 Memory>

Example Software

If the Fully Stuffed Prototyping System is ordered along with a Teensy 4.1, the system comes preconfigured with some example software preloaded in both the Teensy 4.1 and ESP32-S. This is also true of the Project System and Mini Platform.

This software is intended to verify basic configuration and operation of the system and provide a bit of instant gratification upon receiving the system by just applying power. For those that are just getting started with learning how to program, it provides a simple framework that can easily be modified to learn about working with some of the core features of the system.

Prototyping System Demo 3

To get started, simply plug the earbuds or headphones into the Audio Adapter and apply power. If you started with your own Teensy 4.1 or ESP32-S, you will need to download the software to them which can be found near the bottom of this page.

The programs are not overly clever on the programming to make them easier to follow and modify. They pull heavily from various sample programs.  The communications between the Teensy 4.1 and ESP32-S in particular are handled in a very simplistic fashion by passing simple text strings without any error checking.

There are two programs.  One is for the Teensy 4.1 and the second is for the ESP32-S if one is installed.  The Teensy 4.1 program was updated in July 2026 to check for Ethernet cable and USB thumb drive being inserted. It also displays the CPU operating temperature.

Teensy 4.1 Program Overview

  • Initializes the LCD and serial ports.
  • Checks to see if any of the optional PSRAM or Flash memory chips have been installed and reports that info out the USB serial port and also prints it to the LCD screen.  If you ordered a system with the Teensy 4.1 already installed, this also provides a way to easily verify that you received the correct version without having to pry the Teensy 4.1 out of its socket to look at the chips.
  • Paints three buttons on the display.  One for playing audio, one for scanning for WiFi networks and the third for running the system checks.
  • Implements a simple serial communication path with the ESP32-S to see if one is attached.  First asking if one is out there by sending a ‘?’ and looking for a ‘Y’ yes in return.  If found, it enables the Scan button.
  • If Scan button is pressed, it sends the command ‘S’ for scan to the ESP32-S and then looks for a response back with the found networks.  The found networks are then listed on the display.
  • It also looks for an Audio Adapter with an SD card installed with the SDTEST2.WAV file on it (can be found at https://www.pjrc.com/teensy/td_libs_AudioDataFiles.html.)  If found, it enables the Play Audio button to allow the audio to be started and stopped. These files are included on the SD card with the Fully Stuffed version.
  • If System button is pressed, it redoes the same system checks that is done at power up. Note that this button won’t work if audio is being played and the SD card is busy.
  • It reports various things such as the touch coordinates and touch screen button hits out to the USB port for display in a Serial Monitor window if one is open.

ESP32-S Program Overview

  • Looks for incoming serial commands from the Teensy.
  • If it gets a command ‘?’, it responds with ‘Y’ to let the Teensy 4.1 know that yes, I am here.
  • If it gets a command ‘S’, it scans for networks and reports the results back to the Teensy 4.1
  • It also reports the scan information out the USB port for display in a Serial Monitor window if one is open.
  • This program is based largely on the WiFiScan example program.

Using 2 Arduino IDE Windows For Multitasking

If the ESP32-S is installed and you have two USB cables like come with the Fully Stuffed version, you can open two instances of the IDE with one connected to the Teensy 4.1 and one connected to the ESP32-S. This permits downloading programs to both processors and the Serial Monitor windows can be open simultaneously on both processors to monitor what is going on. 

This makes it easy to make program changes like changing button color to see the effect or creating new commands for communicating between the two microcontrollers and downloading new code to either processor without messing with moving cables or changing the IDE settings. 

To open two separate instances of the IDE, they both need to be launched by clicking on the application icon. You should then be able to see two IDE icons in the task bar.

Teensy 4.1 Program Details

We’ll first take a look at some of the functional sections of the Teensy 4.1 program with the complete program listings at the bottom of the page. This include the relevant libraries and definitions used.

Subroutine prototypes and system flags

Subroutine prototypes just notify the compiler that there are some subroutines that will be defined later in the code. The flags just keep track of some things like whether audio is currently being played.

// Subroutine prototypes
void SetScanButton(boolean);   // Handles Scan button when touched
void SetAudioButton(boolean);  // Handles Audio button when touched
void SetSystemButton();        // Handes System button when touched
void SystemCheck();            // System check routines

// Misc flags to keep track of things
boolean isTouched = false;        // Flag if a touch is in process
boolean scanRequested = false;    // Flag if WiFi scan is in process
boolean sDCardInstalled = false;  // Flag if SD card installed
boolean audioPlaying = false;     // Flag if audio is currently playing
boolean esp32SAttached = false;   // Flag if ESP32S is attached

Initialize the TFT LCD Display and Touchscreen

Next it initializes the TFT LCD which requires the SPI.h library for communication over the SPI bus.

It uses the ILI9341_T3.h library for LCD control and it loads Arial fonts font_Arial.h for drawing characters on the LCD screen.

The LCD uses Teensy 4.1 pin 40 for chip select and pin 9 for DC (Data / Command). The DC pin determines if the data going to the LCD is Data for it to display or a Command to execute. These pins are hardwired on the baseboard.

The LCD can display in all 4 orientations, so tft.setRotation(3) is used to rotate the image to fit the orientation it has on the baseboard.

#include <SPI.h>
#include <ILI9341_t3.h>
#include <font_Arial.h>
// LCD control pins defined by board
#define TFT_CS 40
#define TFT_DC  9

// Use main SPI bus MOSI=11, MISO=12, SCK=13 with different control pins
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC);
// Setup LCD screen
tft.begin();
tft.setRotation(3);
tft.fillScreen(ILI9341_BLUE);
tft.setCursor(1, 110);  // Set initial cursor position
tft.setFont(Arial_10);  // Set initial font style and size

Useful Tip – SPI Bus Initialization

One key thing to keep in mind when rolling your own software is that the LCD, Touchscreen and the Audio Adapter SD card all sit on the same SPI bus. When working with this system with these installed, you need to initialize them with separate chip selects so that they do not conflict with each other even if you aren’t actively using them.

If you don’t need some modules for what you are working on, such as the LCD or Audio Adapter for instance, they can also simply be unplugged from the system when you are not using it if you don’t want to bother initializing it.

Initialize the Touchscreen

Next it initializes the touchscreen overlay of the LCD. The touchscreen used on these ILI9341 displays are resistive which detect a touch by pressure applied to the touch overlay that changes resistance at that point. The Project System and Mini Platform use capacitive touchscreens which use body capacitance to detect the touch instead.

It uses the library XPT2046_Touchscreen.h which is the touch controller used on the LCD.

The touchscreen chip select is on Teensy pin 41. The optional IRQ output of the touchscreen is on Teensy pin 2. This interrupt is not used in the example. These pins are hardwired on the baseboard. The IRQ on pin 2 can be disabled by removing the jumper labeled 2-T_IRQ by the LCD if you want to use the Teensy pin 2 for something else.

The touchscreen offsets relates to the coordinates reported by the touchscreen when it is touched in the 4 corners. Default values can be used, but these can be adjusted to best match the physical touch of the screen to the expected coordinates.

The touchscreen also has a rotation parameter, so ts.setRotation(1) is used to rotate the touch overlay to fit the orientation it has on the baseboard. Note that the orientation of the LCD and touchscreen are different as the touchscreen is inverted relatively to the LCD.

When the program is running, the Serial Monitor window will display the coordinates of any touches. If you touch the top left corner, it should report something close to 400, 400. Similarly the bottom right should report something close to 3879, 3843. If it doesn’t, these numbers can be adjusted to help calibrate the touch coordinates to the display coordinates. If these coordinates are too far off, you may have to press next to the button rather than on it to active the button.

#include <XPT2046_Touchscreen.h>
// touchscreen offset for four corners
#define TS_MINX 400
#define TS_MINY 400
#define TS_MAXX 3879
#define TS_MAXY 3843
// Touch screen control pins defined by board
// TIRQ interrupt if used is on pin 2
#define TS_CS  41
//#define TIRQ_PIN  2 
XPT2046_Touchscreen ts(TS_CS);  // Param 2 = NULL - No interrupts

// Setup touch Screen
ts.begin();
ts.setRotation(1);

Define Buttons

This section sets up the size and position of the 3 buttons on the screen. The first two X/Y setup up the upper left corner of the button in pixels relative to the upper left corner of the display. W = the width of the button in pixels. H = the height of the button in pixels.

The last two lines create a couple of different fonts to be used for either the text on the buttons or smaller text to be used for the informational portion of the screen.

// Define Audio button location and size on LCD
#define AUDIO_X 5
#define AUDIO_Y 7
#define AUDIO_W 100
#define AUDIO_H 35

// Define Scan button location and size
#define SCAN_X 110
#define SCAN_Y 7
#define SCAN_W 100
#define SCAN_H 35

// Define System checks button location and size on LCD
#define SYSTEM_X 215
#define SYSTEM_Y 7
#define SYSTEM_W 100
#define SYSTEM_H 35

#define BUTTON_FONT Arial_13
#define TXT_FONT Arial_10

// Draw buttons with current state in Setup()
SetAudioButton(false);
SetScanButton(false);
SetSystemButton();

Setup and Communicating with the ESP32

The Serial 1 port of the Teensy 4.1 is hardwired to the Serial 2 port of the ESP32-S. It initializes Serial1 for communication with the ESP32-S at 115,200 baud. The baud rate is arbitrary and just needs to match the baud rate that the ESP32-S serial port is set to.

The Teensy 4.1 sends the command ‘?’ to the ESP32. If it is present, it returns ‘Y’ for Yes to determine if it is installed. A command ‘S’ requests that the ESP32 initiate a Scan for WiFi networks.

#define ESP32SERIAL Serial1  // ESP32 is attached to Serial1 port
// Define buffer for incoming ESP32 chars to avoid overflowing
#define ESP32SERIAL_BUFFER_SIZE 512
unsigned char esp32SerialBuffer[ESP32SERIAL_BUFFER_SIZE];

ESP32SERIAL.begin(115200);  //Initialize Seria1 1 connected to ESP32S
// Setup extra memory for the ESP32 serial buffer to avoid overruns
ESP32SERIAL.addMemoryForRead(esp32SerialBuffer, ESP32SERIAL_BUFFER_SIZE);

// In SystemCheck(), check to see if ESP32 is installed.  If not, gray out button
  while (ESP32SERIAL.available()) {  // Clear ESP32 input buffer before CMD
    (char)ESP32SERIAL.read();
  }
  bool esp32SAttachedLast = esp32SAttached;

  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' for Yes, I'm here
      esp32SAttached = true;
      Serial.println("ESP32 was found");
      tft.println("ESP32 was found");
    } else {  // No response or invalid response
      Serial.println("ESP32 not found");
      tft.println("ESP32 not found");
      esp32SAttached = false;
    }
  } else {
    esp32SAttached = false;
  }
  
 // Redraw Scan button if something changes with ESP32
  if (esp32SAttached != esp32SAttachedLast) {  // redraw SCAN if ESP32 changes
    tft.setCursor(SCAN_X + 8, SCAN_Y + 12);
    tft.setFont(BUTTON_FONT);
    if (esp32SAttached) {
      tft.fillRoundRect(SCAN_X, SCAN_Y, SCAN_W, SCAN_H, 4, ILI9341_RED);
      tft.setTextColor(ILI9341_WHITE);
      tft.print("Scan WiFi");
    } else {
      tft.setTextColor(ILI9341_WHITE);
      tft.fillRoundRect(SCAN_X, SCAN_Y, SCAN_W, SCAN_H, 4, ILI9341_BLACK);
      tft.print("No Scan");
    }
  }

// In Loop, if we requested a scan, look for serial data coming back from the ESP32
  if (scanRequested && ESP32SERIAL.available()) {
    Serial.print("Read incoming data");
    tft.setCursor(5, SCAN_Y + SCAN_H + 20);
    tft.setFont(TXT_FONT);
    tft.setTextColor(ILI9341_WHITE);
    while (ESP32SERIAL.available()) {  // Print the scan data to the LCD & Serial port
      String returnData = ESP32SERIAL.readString();
      tft.println(returnData);
      Serial.println(returnData);
    }
    scanRequested = false;  // Reset the scan flag and button
    SetScanButton(false);
  }

//===============================================================================
//  Routine to draw scan button current state and initiate scan request
//===============================================================================
void SetScanButton(boolean scanning) {
  tft.setCursor(SCAN_X + 8, SCAN_Y + 12);
  tft.setFont(BUTTON_FONT);

  if (!scanning) {  // Button is inactive, redraw button
    tft.fillRoundRect(SCAN_X, SCAN_Y, SCAN_W, SCAN_H, 4, ILI9341_RED);
    tft.setTextColor(ILI9341_WHITE);
    tft.print("Scan WiFi");
  } else {                                             // Button is active, redraw button
    tft.fillRect(0, SCAN_Y + SCAN_H + 1, 479, 319, ILI9341_BLUE);  // Clear previous info
    tft.fillRoundRect(SCAN_X, SCAN_Y, SCAN_W, SCAN_H, 4, ILI9341_GREEN);
    tft.setTextColor(ILI9341_BLACK);
    tft.print(" Scanning");
    ESP32SERIAL.println("S");  // Send command to ESP32 to start scan
    scanRequested = true;      // Set flag that we requested scan
    Serial.println("Scan being requested");
  }
}

Setup and Testing the USB Host Port

This code sets up a basic USB Host port called myusb. It then checks for a USB Flash drive with at least 1 file on it inserted into the USB Host port.

#include <USBHost_t36.h>
// Setup USBHost_t36 and as many HUB ports as needed.
USBHost myusb;
USBHub hub1(myusb);
// Instances for one drive
USBDrive myDrive(myusb);
// Instances for accessing the files on the drive
USBFilesystem myFiles(myusb);

// Check for USB Flash Drive attached in SystemCheck()
  myusb.Task();
  if (!myFiles) {
    Serial.println("USB Flash Drive not connected");
    tft.println("USB Flash Drive is not connected");
  } else {
    Serial.println("USB Flash Drive is connected");
    tft.println("USB Flash Drive is connected");
  }

Setup and Testing the Wired Ethernet Port

This code sets up a wired Ethernet connection. The using namespace qindesign::network; is used with the QNEthernet.h library for it to work and should always be included. There is a delay(500); to ensure that when the system first powers up that there is time for the Ethernet hardware to finish initialization before it is accessed by the software since we scan the hardware at first power up. This isn’t needed under most circumstances.

#include <QNEthernet.h>
using namespace qindesign::network;
// Start the Ethernet port
Ethernet.begin();
delay(500); // Ensures that the first cable check has time to pass

// Check for Ethernet cable connected in SystemCheck()
  auto link = Ethernet.linkStatus();
  Serial.print("Link State: ");
  switch (link) {
    case Unknown:
      Serial.println("Unknown");
      tft.println("Unknown");
      break;
    case LinkON:
      Serial.println("ON");
      tft.println("Ethernet cable is connected");
      break;
    case LinkOFF:
      Serial.println("OFF");
      tft.println("Ethernet cable is not connected");
      break;
  }

Setup and Using the Teensy Audio Adapter

This section sets up the Audio Adapter to read WAV files from the SD card and send it out to the headphone jack. The pin definitions are used to define the main SPI pins to the Audio Adapter. The Fully Stuffed setup ships with the SD card installed in the Audio Adapter.

The audio uses the SPI.h, Audio.h, Wire.h, SD.h and SerialFlash.h libraries

The Audio Adapter is configured in the section starting with AudioPlaySdWav playSdWav1; These configuration settings and required libraries are automatically generated by the Audio System Design Tool. We will explore that tool later in the Audio Workshop Tutorial.

The SD card on the Audio Adapter sits on the main SPI bus. Its chip select is on the Teensy 4.1 pin 10, MOSI on pin 11 and SCK on pin 13. These are hardwired by the baseboard. Note that the SCK pin 13 is shared with the on-board orange LED of the Teensy. This means the LED will light during SCK activity. It also means that if you intentionally set the pin, such as to turn the LED on or off, the SCK will no longer function.

The SystemCheck() looks for the SD card and if it cannot find it, it greys out the Audio button.

The built-in Teensy4.1 SD card reader uses QSPI (Quad SPI) instead of regular SPI, so it can read data 4-bits at a time instead of just 1. For optimum performance, the Teensy 4.1 SD card reader should be used, though for audio, which is relatively slow, it doesn’t really matter.

If the SD card is moved to the Teensy 4.1 SD card reader, change SDCARD_CS_PIN 10 to
SDCARD_CS_PIN BUILTIN_SDCARD.

#include <SPI.h>
#include <Audio.h>
#include <Wire.h>
#include <SD.h>
#include <SerialFlash.h>

// Setup audio system connections for WAV file off SD card to audio jack
AudioPlaySdWav playSdWav1;
AudioOutputI2S i2s1;
AudioConnection patchCord1(playSdWav1, 0, i2s1, 0);
AudioConnection patchCord2(playSdWav1, 1, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1;

// Pins used with the SD card
#define SDCARD_CS_PIN 10
#define SDCARD_MOSI_PIN 11
#define SDCARD_SCK_PIN 13

// Checks for SD card installed in Audio Adapter card slot to
// determine if the adapter and SD card is installed on the baseboard.
  if (!(SD.begin(10))) {
    Serial.println("SD card not found");
    tft.println("SD card not found");
    sDCardInstalled = false;
  } else {
    Serial.println("SD card is Inserted");
    tft.println("SD card is Inserted");
    sDCardInstalled = true;
  }

// Setup audio if Audio Adapter with SD card is found
  if (sDCardInstalled) {  
    AudioMemory(8);
    sgtl5000_1.enable();
    sgtl5000_1.volume(0.5);
    SPI.setMOSI(SDCARD_MOSI_PIN);
    SPI.setSCK(SDCARD_SCK_PIN);
  } else {  // If no audio, gray out button
    tft.setCursor(AUDIO_X + 8, AUDIO_Y + 12);
    tft.setFont(BUTTON_FONT);
    tft.setTextColor(ILI9341_WHITE);
    tft.fillRoundRect(AUDIO_X, AUDIO_Y, AUDIO_W, AUDIO_H, 4, ILI9341_BLACK);
    tft.print("No Audio");
  }
  
//===============================================================================
//  Routine to draw Audio button current state and control audio playback
//===============================================================================
void SetAudioButton(boolean audio) {
  tft.setCursor(AUDIO_X + 8, AUDIO_Y + 12);
  tft.setFont(BUTTON_FONT);

  if (!audio) {  // button is set inactive, redraw button inactive
    tft.fillRoundRect(AUDIO_X, AUDIO_Y, AUDIO_W, AUDIO_H, 4, ILI9341_RED);
    tft.setTextColor(ILI9341_WHITE);
    tft.print("Play Audio");
    audioPlaying = false;
    if (playSdWav1.isPlaying()) {  // Stop any audio that is playing
      playSdWav1.stop();
      Serial.println("Audio being stopped");
    }
  } else {  // button is active, redraw button active
    tft.fillRoundRect(AUDIO_X, AUDIO_Y, AUDIO_W, AUDIO_H, 4, ILI9341_GREEN);
    tft.setTextColor(ILI9341_BLACK);
    tft.print("   Playing");
    audioPlaying = true;
    if (sDCardInstalled && !playSdWav1.isPlaying()) {  // Play audio file
      Serial.println("Audio being played");
      playSdWav1.play("SDTEST2.WAV");
      delay(10);  // wait for library to parse WAV info
    }
  }
}

Find any PSRAM or Flash that may be installed

In SystemCheck(), the program looks to see if any PSRAM or Flash is installed on the QSPI bus on the bottom of the Teensy 4.1 and reports what it finds out to the Serial Monitor window and also displays it on the LCD.

PSRAM uses external_psram_size which is a built-in function that returns the size of any PSRAM that may be installed. This will either be 0, 8, 16, 24 or 32 Megabytes.

For flash memory, it uses the LittleFS.h library which provides access to the Flash memory.

Since the Flash memory comes in both NOR and NAND technologies depending on the memory capacity, it looks for both to see if it can find either and if not, it reports no Flash installed. It is done this way so that the Flash type (NOR or NAND) can be determined if one is present. In most cases you don’t care about the technology and the command LittleFS_QSPI myfs;  can be used instead as it will work with both Flash types.

 #include "LittleFS.h" // Used to access Flash on the Teensy
 
 // Check for PSRAM chip(s) installed on Teensy 4.1
  uint8_t size = external_psram_size;
  if (size == 0) {
    Serial.println("No PSRAM Installed");
    tft.println("No PSRAM Installed");
  } else {
    Serial.printf("PSRAM Memory Size = %d Mbyte\n", size);
    tft.printf("PSRAM Memory Size = %d Mbyte\n", size);
  }
  tft.println();

  // Check for Flash chip installed on Teensy 4.1
  LittleFS_QSPIFlash myfs_NOR;  // NOR FLASH on Teensy
  LittleFS_QPINAND myfs_NAND;   // NAND FLASH 2Gb on Teensy
  //LittleFS_QSPI myfs;         // Works with either NOR or NAND Flash

  // Check for any NOR Flash chip installed.  Normally only NAND Flash is installed
  if (myfs_NOR.begin()) {
    Serial.printf("NOR Flash Memory Size = %d Mbyte / ", myfs_NOR.totalSize() / 1048576);
    Serial.printf("%d Mbit\n", myfs_NOR.totalSize() / 131072);
    tft.printf("NOR Flash Memory Size = %d Mbyte / ", myfs_NOR.totalSize() / 1048576);
    tft.printf("%d Mbit\n", myfs_NOR.totalSize() / 131072);
  }
  // Check for NAND Flash chip installed
  else if (myfs_NAND.begin()) {
    Serial.printf("NAND Flash Memory Size =  %d bytes / ", myfs_NAND.totalSize());
    Serial.printf("%d Mbyte / ", myfs_NAND.totalSize() / 1048576);
    Serial.printf("%d Gbit\n", myfs_NAND.totalSize() * 8 / 1000000000);
    tft.print("NAND Flash Memory Size = ");
    //    tft.printf("%d bytes / ", myfs_NAND.totalSize());
    tft.printf("%d Mbyte / ", myfs_NAND.totalSize() / 1048576);
    tft.printf("%d Gbit\n", myfs_NAND.totalSize() * 8 / 1000000000);
  } else {
    Serial.printf("No Flash Installed\n");
    tft.printf("No Flash Installed\n");
  }

Check CPU Die Temperature

This section of code gets the CPU temperature using the built-in tempmonGetTemp(); function.

// Check CPU internal temperature
  Serial.print(tempmonGetTemp());
  Serial.println("°C");
  tft.print("CPU Temp: ");
  tft.print(tempmonGetTemp());
  tft.println("°C");

Main Loop

The main loop of the program does a few things.

First it checks to see if audio was previously playing and is now finished. If so, it updates the Audio button.

Next it checks to see if the touchscreen has been touched. If there is a new touch:

  • It maps the touch coordinates to the screen pixel coordinates.
  • It checks to see if if one of the buttons was touched based on their coordinates.
  • If the Scan button was touched, it calls the SetScanButton (TRUE) which sends a scan request ‘S’ to the ESP32-S. It then looks for the return scan data from the ESP32-S and displays it on the LCD.
  • If the Audio button was touched, it toggles between playing or stopping the SDTEST2.WAV file by calling the SetPlayButton with TRUE or FALSE.
  • If the System button is touched, it reruns SystemCheck();
  • It sends the touch coordinates to the USB for display in the Serial Monitor window.
//===============================================================================
//  Main
//===============================================================================
void loop() {

  // Keep an eye on any audio that may be playing and reset button when it ends
  if (playSdWav1.isStopped() && audioPlaying) {  // Audio finished playing
    SetAudioButton(false);
    Serial.println("Audio finished playing");
  }
  // Check to see if the touch screen has been touched
  if (ts.touched() && isTouched == false) {
    TS_Point p = ts.getPoint();
    Serial.print("x Raw = ");  // Show our raw touch coordinates for each touch
    Serial.print(p.x);
    Serial.print(", y Raw = ");
    Serial.print(p.y);
    Serial.print("  :  ");

    // Map the touch point to the LCD screen
    p.x = map(p.x, TS_MINY, TS_MAXY, 0, tft.width());
    p.y = map(p.y, TS_MINX, TS_MAXX, 0, tft.height());

    isTouched = true;

    // Look for a Scan Button Hit
    if ((p.x > SCAN_X) && (p.x < (SCAN_X + SCAN_W))) {
      if ((p.y > SCAN_Y) && (p.y <= (SCAN_Y + SCAN_H))) {
        Serial.println("Scan Button Hit");
        if (esp32SAttached) SetScanButton(true);
      }
    }
    // Look for an Audio Button Hit
    if ((p.x > AUDIO_X) && (p.x < (AUDIO_X + AUDIO_W))) {
      if ((p.y > AUDIO_Y) && (p.y <= (AUDIO_Y + AUDIO_H))) {
        Serial.println("Audio Button Hit");
        if (sDCardInstalled && !audioPlaying) {
          SetAudioButton(true);
        } else if (sDCardInstalled && audioPlaying) {
          SetAudioButton(false);
        }
      }
    }
    // Look for a System Button Hit
    if ((p.x > SYSTEM_X) && (p.x < (SYSTEM_X + SYSTEM_W))) {
      if ((p.y > SYSTEM_Y) && (p.y <= (SYSTEM_Y + SYSTEM_H))) {
        Serial.println("System Button Hit");
        if (scanRequested == false) SetSystemButton();
      }
    }
    Serial.print("x = ");  // Show our mapped touch coordinates for each touch
    Serial.print(p.x);
    Serial.print(", y = ");
    Serial.print(p.y);
    Serial.println();
    delay(100);  // Debounce touchscreen a bit
  }
  if (!ts.touched() && isTouched) {
    isTouched = false;  // touchscreen is no longer being touched, reset flag
  }
  // If we requested a scan, look for serial data coming back from the ESP32S
  if (scanRequested && ESP32SERIAL.available()) {
    Serial.print("Read incoming data");
    tft.setCursor(5, SCAN_Y + SCAN_H + 20);
    tft.setFont(TXT_FONT);
    tft.setTextColor(ILI9341_WHITE);
    while (ESP32SERIAL.available()) {  // Print the scan data to the LCD & USB
      String returnData = ESP32SERIAL.readString();
      tft.println(returnData);
      Serial.println(returnData);
    }
    scanRequested = false;  // Reset the scan flag and button
    SetScanButton(false);
  }
}

Below is the fully Teensy 4.1 program which can be copied and downloaded into the Teensy 4.1 if needed.

Full Teensy 4.1 Program

/*
Prototyping Platform for Teensy 4.1 Example

  This program does nothing overly useful, but illustrates some of the basic
  features and checks for presence of PSRAM/Flash memory installed, SD card
  installed and the ESP32S. It also looks for an Ethernet cable connection
  and whether a Flash drive is inderted into the Host USB connector.
  It reports the info out to the LCD and serial port.

  If SD card installed, the Audio button plays the wave file
  "SDTEST2.WAV" from the Teensy audio tutorial
  https://www.pjrc.com/teensy/td_libs_AudioDataFiles.html

  The Scan button sends a command to the ESP32S requesting a scan of
  available WiFi networks.  When the ESP32S returns the scan results,
  the Teensy 4.1 updates those results on the LCD screen and serial port.

  The System button just rechecks the same system information.  Note that the
  System button won't work if audio is playing.

  This example code is in the public domain.
*/
#include <ILI9341_t3.h>
#include <font_Arial.h>
#include <XPT2046_Touchscreen.h>
#include <SPI.h>
#include <Audio.h>
#include <Wire.h>
#include <SD.h>
#include <SerialFlash.h>
#include "LittleFS.h"
#include <USBHost_t36.h>
#include <QNEthernet.h>
using namespace qindesign::network;
extern "C" uint8_t external_psram_size;

// Setup USBHost_t36 and as many HUB ports as needed.
USBHost myusb;
USBHub hub1(myusb);
// Instances for one drive
USBDrive myDrive(myusb);
// Instances for accessing the files on the drive
USBFilesystem myFiles(myusb);

// Setup audio system
AudioPlaySdWav playSdWav1;
AudioOutputI2S i2s1;
AudioConnection patchCord1(playSdWav1, 0, i2s1, 0);
AudioConnection patchCord2(playSdWav1, 1, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1;

// Pins used with the audio adapter
#define SDCARD_CS_PIN 10
#define SDCARD_MOSI_PIN 11
#define SDCARD_SCK_PIN 13

// touchscreen offset for four corners.  May need to be adjusted
#define TS_MINX 400
#define TS_MINY 400
#define TS_MAXX 3879
#define TS_MAXY 3843

// LCD control pins defined by the baseboard
#define TFT_CS 40
#define TFT_DC 9
// Use main SPI bus MOSI=11, MISO=12, SCK=13 with different control pins
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC);

// Touch screen control pins defined by the baseboard
// TIRQ interrupt if used is on pin 2
#define TS_CS 41
//#define TIRQ_PIN  2
XPT2046_Touchscreen ts(TS_CS);  // Param 2 = NULL - No interrupts

// Define Audio button location and size on LCD
#define AUDIO_X 5
#define AUDIO_Y 7
#define AUDIO_W 100
#define AUDIO_H 35

// Define Scan button location and size
#define SCAN_X 110
#define SCAN_Y 7
#define SCAN_W 100
#define SCAN_H 35

// Define System checks button location and size on LCD
#define SYSTEM_X 215
#define SYSTEM_Y 7
#define SYSTEM_W 100
#define SYSTEM_H 35

#define BUTTON_FONT Arial_13
#define TXT_FONT Arial_10

#define ESP32SERIAL Serial1  // ESP32 is attached to Serial1 port
// Define buffer for incoming ESP32 chars
#define ESP32SERIAL_BUFFER_SIZE 512
unsigned char esp32SerialBuffer[ESP32SERIAL_BUFFER_SIZE];

// Subroutine prototypes
void SetScanButton(boolean);   // Handles Scan button when touched
void SetAudioButton(boolean);  // Handles Audio button when touched
void SetSystemButton();        // Handes System button when touched
void SystemCheck();            // System check routines

// Misc flags to keep track of things
boolean isTouched = false;        // Flag if a touch is in process
boolean scanRequested = false;    // Flag if WiFi scan is in process
boolean sDCardInstalled = false;  // Flag if SD card installed
boolean audioPlaying = false;     // Flag if audio is currently playing
boolean esp32SAttached = false;   // Flag if ESP32S is attached

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

  // Start the Ethernet port
  Ethernet.begin();
  delay(500); // Ensures that the first cable check has time to pass
  // Start the USB Host port
  myusb.begin();

  tft.begin();
  tft.setRotation(3);  // Rotates screen to match the baseboard orientation
  // Setup touch Screen
  ts.begin();
  ts.setRotation(1);  // Sets the touch screen orientation
  tft.fillScreen(ILI9341_BLUE);
  tft.setCursor(1, 110);  // Set initial cursor position
  tft.setFont(Arial_10);  // Set initial font style and size

  // Draw buttons with current state
  SetAudioButton(false);
  SetScanButton(false);
  SetSystemButton();

  // Setup audio
  if (sDCardInstalled) {  // Setup the audio if SD card is installed
    AudioMemory(8);
    sgtl5000_1.enable();
    sgtl5000_1.volume(0.5);
    SPI.setMOSI(SDCARD_MOSI_PIN);
    SPI.setSCK(SDCARD_SCK_PIN);
  } else {  // If no audio, gray out button
    tft.setCursor(AUDIO_X + 8, AUDIO_Y + 12);
    tft.setFont(BUTTON_FONT);
    tft.setTextColor(ILI9341_WHITE);
    tft.fillRoundRect(AUDIO_X, AUDIO_Y, AUDIO_W, AUDIO_H, 4, ILI9341_BLACK);
    tft.print("No Audio");
  }

  // Setup ESP32 Scan button
  if (!esp32SAttached) {  // If no ESP320C3 attached, gray out button
    tft.setCursor(SCAN_X + 8, SCAN_Y + 12);
    tft.setFont(BUTTON_FONT);
    tft.setTextColor(ILI9341_WHITE);
    tft.fillRoundRect(SCAN_X, SCAN_Y, SCAN_W, SCAN_H, 4, ILI9341_BLACK);
    tft.print("No Scan");
  }
}
//===============================================================================
//  Main
//===============================================================================
void loop() {

  // Keep an eye on any audio that may be playing and reset button when it ends
  if (playSdWav1.isStopped() && audioPlaying) {  // Audio finished playing
    SetAudioButton(false);
    Serial.println("Audio finished playing");
  }
  // Check to see if the touch screen has been touched
  if (ts.touched() && isTouched == false) {
    TS_Point p = ts.getPoint();
    Serial.print("x Raw = ");  // Show our raw touch coordinates for each touch
    Serial.print(p.x);
    Serial.print(", y Raw = ");
    Serial.print(p.y);
    Serial.print("  :  ");

    // Map the touch point to the LCD screen
    p.x = map(p.x, TS_MINY, TS_MAXY, 0, tft.width());
    p.y = map(p.y, TS_MINX, TS_MAXX, 0, tft.height());

    isTouched = true;

    // Look for a Scan Button Hit
    if ((p.x > SCAN_X) && (p.x < (SCAN_X + SCAN_W))) {
      if ((p.y > SCAN_Y) && (p.y <= (SCAN_Y + SCAN_H))) {
        Serial.println("Scan Button Hit");
        if (esp32SAttached) SetScanButton(true);
      }
    }
    // Look for an Audio Button Hit
    if ((p.x > AUDIO_X) && (p.x < (AUDIO_X + AUDIO_W))) {
      if ((p.y > AUDIO_Y) && (p.y <= (AUDIO_Y + AUDIO_H))) {
        Serial.println("Audio Button Hit");
        if (sDCardInstalled && !audioPlaying) {
          SetAudioButton(true);
        } else if (sDCardInstalled && audioPlaying) {
          SetAudioButton(false);
        }
      }
    }
    // Look for a System Button Hit
    if ((p.x > SYSTEM_X) && (p.x < (SYSTEM_X + SYSTEM_W))) {
      if ((p.y > SYSTEM_Y) && (p.y <= (SYSTEM_Y + SYSTEM_H))) {
        Serial.println("System Button Hit");
        if (scanRequested == false) SetSystemButton();
      }
    }
    Serial.print("x = ");  // Show our mapped touch coordinates for each touch
    Serial.print(p.x);
    Serial.print(", y = ");
    Serial.print(p.y);
    Serial.println();
    delay(100);  // Debounce touchscreen a bit
  }
  if (!ts.touched() && isTouched) {
    isTouched = false;  // touchscreen is no longer being touched, reset flag
  }
  // If we requested a scan, look for serial data coming back from the ESP32S
  if (scanRequested && ESP32SERIAL.available()) {
    Serial.print("Read incoming data");
    tft.setCursor(5, SCAN_Y + SCAN_H + 20);
    tft.setFont(TXT_FONT);
    tft.setTextColor(ILI9341_WHITE);
    while (ESP32SERIAL.available()) {  // Print the scan data to the LCD & USB
      String returnData = ESP32SERIAL.readString();
      tft.println(returnData);
      Serial.println(returnData);
    }
    scanRequested = false;  // Reset the scan flag and button
    SetScanButton(false);
  }
}
//===============================================================================
//  Routine to draw Audio button current state and control audio playback
//===============================================================================
void SetAudioButton(boolean audio) {
  tft.setCursor(AUDIO_X + 8, AUDIO_Y + 12);
  tft.setFont(BUTTON_FONT);

  if (!audio) {  // button is set inactive, redraw button inactive
    tft.fillRoundRect(AUDIO_X, AUDIO_Y, AUDIO_W, AUDIO_H, 4, ILI9341_RED);
    tft.setTextColor(ILI9341_WHITE);
    tft.print("Play Audio");
    audioPlaying = false;
    if (playSdWav1.isPlaying()) {  // Stop any audio that is playing
      playSdWav1.stop();
      Serial.println("Audio being stopped");
    }
  } else {  // button is active, redraw button active
    tft.fillRoundRect(AUDIO_X, AUDIO_Y, AUDIO_W, AUDIO_H, 4, ILI9341_GREEN);
    tft.setTextColor(ILI9341_BLACK);
    tft.print("   Playing");
    audioPlaying = true;
    if (sDCardInstalled && !playSdWav1.isPlaying()) {  // Play audio file
      Serial.println("Audio being played");
      playSdWav1.play("SDTEST2.WAV");
      delay(10);  // wait for library to parse WAV info
    }
  }
}
//===============================================================================
//  Routine to draw scan button current state and initiate scan request
//===============================================================================
void SetScanButton(boolean scanning) {
  tft.setCursor(SCAN_X + 8, SCAN_Y + 12);
  tft.setFont(BUTTON_FONT);

  if (!scanning) {  // Button is inactive, redraw button
    tft.fillRoundRect(SCAN_X, SCAN_Y, SCAN_W, SCAN_H, 4, ILI9341_RED);
    tft.setTextColor(ILI9341_WHITE);
    tft.print("Scan WiFi");
  } else {                                             // Button is active, redraw button
    tft.fillRect(0, SCAN_Y + SCAN_H + 1, 479, 319, ILI9341_BLUE);  // Clear previous info
    tft.fillRoundRect(SCAN_X, SCAN_Y, SCAN_W, SCAN_H, 4, ILI9341_GREEN);
    tft.setTextColor(ILI9341_BLACK);
    tft.print(" Scanning");
    ESP32SERIAL.println("S");  // Send command to ESP32 to start scan
    scanRequested = true;      // Set flag that we requested scan
    Serial.println("Scan being requested");
  }
}
//===============================================================================
//  Routine to draw system button current state and initiate system checks
//===============================================================================
void SetSystemButton() {
  tft.setCursor(SYSTEM_X + 20, SYSTEM_Y + 12);
  tft.setFont(BUTTON_FONT);

  tft.fillRect(0, SCAN_Y + SCAN_H + 1, 479, 319, ILI9341_BLUE);  // Clear previous info
  tft.fillRoundRect(SYSTEM_X, SYSTEM_Y, SYSTEM_W, SYSTEM_H, 4, ILI9341_GREEN);
  tft.setTextColor(ILI9341_WHITE);
  tft.print("System");
  Serial.println("System check requested");

  // Only do SystemCheck when audio is not playing off SD card
  if (audioPlaying == false) {
    tft.setCursor(SYSTEM_X + 16, SYSTEM_Y + 12);
    tft.setFont(BUTTON_FONT);
    tft.fillRoundRect(SYSTEM_X, SYSTEM_Y, SYSTEM_W, SYSTEM_H, 4, ILI9341_GREEN);
    tft.setTextColor(ILI9341_BLACK);
    tft.print("Checking");
    SystemCheck();
    tft.setCursor(SYSTEM_X + 20, SYSTEM_Y + 12);
    tft.setFont(BUTTON_FONT);
    tft.setTextColor(ILI9341_WHITE);
    tft.print("System");
  } else {
    tft.setCursor(5, SYSTEM_Y + SYSTEM_H + 20);  // Set initial cursor position
    tft.setFont(TXT_FONT);                       // Set initial font style and size
    tft.setTextColor(ILI9341_WHITE);
    tft.print("System check cannot run with audio playing");
  }

  tft.setCursor(SYSTEM_X + 20, SYSTEM_Y + 12);
  tft.setFont(BUTTON_FONT);
  tft.fillRoundRect(SYSTEM_X, SYSTEM_Y, SYSTEM_W, SYSTEM_H, 4, ILI9341_RED);
  tft.print("System");
}
//===============================================================================
//  Routine to query installed hardware
//===============================================================================
void SystemCheck() {

  tft.setCursor(0, SYSTEM_Y + SYSTEM_H + 10);  // Set initial cursor position
  tft.setFont(TXT_FONT);                       // Set initial font style and size
  tft.setTextColor(ILI9341_WHITE);

  // Check for PSRAM chip(s) installed on Teensy 4.1
  uint8_t size = external_psram_size;
  if (size == 0) {
    Serial.println("No PSRAM Installed");
    tft.println("No PSRAM Installed");
  } else {
    Serial.printf("PSRAM Memory Size = %d Mbyte\n", size);
    tft.printf("PSRAM Memory Size = %d Mbyte\n", size);
  }
  tft.println();

  // Check for Flash chip installed on Teensy 4.1
  LittleFS_QSPIFlash myfs_NOR;  // NOR FLASH on Teensy
  LittleFS_QPINAND myfs_NAND;   // NAND FLASH 2Gb on Teensy
  //LittleFS_QSPI myfs;         // Works with either NOR or NAND Flash

  // Check for any NOR Flash chip installed.  Normally only NAND Flash is installed
  if (myfs_NOR.begin()) {
    Serial.printf("NOR Flash Memory Size = %d Mbyte / ", myfs_NOR.totalSize() / 1048576);
    Serial.printf("%d Mbit\n", myfs_NOR.totalSize() / 131072);
    tft.printf("NOR Flash Memory Size = %d Mbyte / ", myfs_NOR.totalSize() / 1048576);
    tft.printf("%d Mbit\n", myfs_NOR.totalSize() / 131072);
  }
  // Check for NAND Flash chip installed
  else if (myfs_NAND.begin()) {
    Serial.printf("NAND Flash Memory Size =  %d bytes / ", myfs_NAND.totalSize());
    Serial.printf("%d Mbyte / ", myfs_NAND.totalSize() / 1048576);
    Serial.printf("%d Gbit\n", myfs_NAND.totalSize() * 8 / 1000000000);
    tft.print("NAND Flash Memory Size = ");
    //    tft.printf("%d bytes / ", myfs_NAND.totalSize());
    tft.printf("%d Mbyte / ", myfs_NAND.totalSize() / 1048576);
    tft.printf("%d Gbit\n", myfs_NAND.totalSize() * 8 / 1000000000);
  } else {
    Serial.printf("No Flash Installed\n");
    tft.printf("No Flash Installed\n");
  }
  tft.println();

  // Check for SD card installed in Audio Adapter card slot
  if (!(SD.begin(10))) {
    Serial.println("SD card not found");
    tft.println("SD card not found");
    sDCardInstalled = false;
  } else {
    Serial.println("SD card is Inserted");
    tft.println("SD card is Inserted");
    sDCardInstalled = true;
  }
  tft.println();

  // Check for ESP32 installed
  while (ESP32SERIAL.available()) {  // Clear ESP32 input buffer before CMD
    (char)ESP32SERIAL.read();
  }
  bool esp32SAttachedLast = esp32SAttached;

  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' for Yes, I'm here
      esp32SAttached = true;
      Serial.println("ESP32 was found");
      tft.println("ESP32 was found");
    } else {  // No response or invalid response
      Serial.println("ESP32 not found");
      tft.println("ESP32 not found");
      esp32SAttached = false;
    }
  } else {
    esp32SAttached = false;
  }
  tft.println();

  // Check for Ethernet cable connected
  auto link = Ethernet.linkStatus();
  Serial.print("Link State: ");
  switch (link) {
    case Unknown:
      Serial.println("Unknown");
      tft.println("Unknown");
      break;
    case LinkON:
      Serial.println("ON");
      tft.println("Ethernet cable is connected");
      break;
    case LinkOFF:
      Serial.println("OFF");
      tft.println("Ethernet cable is not connected");
      break;
  }
  tft.println();

  // Check for USB Flash Drive attached
  myusb.Task();
  if (!myFiles) {
    Serial.println("USB Flash Drive not connected");
    tft.println("USB Flash Drive is not connected");
  } else {
    Serial.println("USB Flash Drive is connected");
    tft.println("USB Flash Drive is connected");
  }
  tft.println();

  // Check CPU internal temperature
  Serial.print(tempmonGetTemp());
  Serial.println("°C");
  tft.print("CPU Temp: ");
  tft.print(tempmonGetTemp());
  tft.println("°C");

  // Redraw Scan button if something changes with ESP32
  if (esp32SAttached != esp32SAttachedLast) {  // redraw SCAN if ESP32 changes
    tft.setCursor(SCAN_X + 8, SCAN_Y + 12);
    tft.setFont(BUTTON_FONT);
    if (esp32SAttached) {
      tft.fillRoundRect(SCAN_X, SCAN_Y, SCAN_W, SCAN_H, 4, ILI9341_RED);
      tft.setTextColor(ILI9341_WHITE);
      tft.print("Scan WiFi");
    } else {
      tft.setTextColor(ILI9341_WHITE);
      tft.fillRoundRect(SCAN_X, SCAN_Y, SCAN_W, SCAN_H, 4, ILI9341_BLACK);
      tft.print("No Scan");
    }
  }
}

ESP32 Program Details

The ESP32 program is simply the WiFiScan example program that has been modified slightly to interact with the Teensy 4.1 through its Serial 2 port.

It looks for the ‘?’ and ‘S’ characters on the Serial 2 port. If it receives a ‘?’, it responds with a ‘Y’ to let the Teensy 4.1 know that it is present. If it receives an ‘S’, it initiates a scan. Once a scan is completed, the data it sends to the USB port for display in the Serial Monitor window is also now mirrored to the Serial 2 port for use by the Teensy 4.1.

Below is the fully ESP32 program which can be copied and downloaded into the ESP32-S if needed. Use the ESP32 Dev Module for the board type.

Full ESP32 Program

/*
    This sketch interfaces to the Teensy 4.1 via serial port 2.
    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
*/
#include "WiFi.h"

#define RX2 16  // Teensy 4.1 is connected to serial port #2
#define TX2 17

const int LED_PIN = 2;  // We will light the LED when Scan is in process.
//===============================================================================
//  Initialization
//===============================================================================
void setup()
{
  Serial.begin(115200);   // USB port
  Serial2.begin(115200, SERIAL_8N1, RX2, TX2);  //Port connected to Teensy 4.1

  // Set WiFi to station mode and disconnect from an AP if previously connected
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);
  pinMode(LED_PIN, OUTPUT);
  Serial.println("Setup done");
}
//===============================================================================
//  Main
//===============================================================================
void loop()
{
  if (Serial2.available()) {
    char command = Serial2.read();
    Serial.println(command);
    if (command == '?') { // Are you there?
      Serial.println("Y");
      Serial2.print("Y");  // Acknowledge I'm attached
    }
    if (command == 'S'){
      Serial.println("scan start");
      digitalWrite(LED_PIN, HIGH);   // turn the LED on
      // 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");
        Serial2.println("No networks found");
      } else {
        Serial.print(n);
        Serial2.print(n);
        Serial.println(" Networks Found");
        Serial2.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);
          Serial2.print(i + 1);
          Serial.print(": ");
          Serial2.print(": ");
          Serial.print(WiFi.SSID(i));
          Serial2.print(WiFi.SSID(i));
          Serial.print(" (");
          Serial2.print(" (");
          Serial.print(WiFi.RSSI(i));
          Serial2.print(WiFi.RSSI(i));
          Serial.print(")");
          Serial2.print(")");
          Serial.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN) ? " " : "*");
          Serial2.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN) ? " " : "*");
        }
       }
      }
  digitalWrite(LED_PIN, LOW);    // turn the LED off
  }
}
< Powering Up the System
Teensy 4.1 Memory >

PRODUCT SEARCH

PRODUCT CATEGORIES

  • Arduino, Teensy & IOT
  • Audio & Video
  • Breadboards & Supplies
  • Breakout Modules
  • Cables & Wires
  • Communications & Interfacing
  • Connectors & Headers
  • Displays, LEDs & Panel Meters
  • Fans & Hardware
  • ICs & Semiconductors
  • Passive Components
  • PCBs - Prototype & Adapter
  • Power Supplies & Converters
  • Proximity, Distance & Collision
  • Relays, MOSFETs & Power Ctrl
  • Robotics, Motors & Motion
  • Sensors
  • Supplies & Consumables
  • Switches & User Input
  • Temperature & Humidity
  • Test, Tools & Test Accessories

Pay Additional Charges

Dollar SignClick to add additional charges to your order

Recent Blog Entries

  • Teensy ESP32-C5 Stacks

    Teensy 4.x + ESP32-C5 Stacks Support 5GHz Wi-Fi Operation

    This Teensy 4.x + ESP32-C5 stack is the same as...
  • Teensy 4.1 Fully Loaded - 16MB PSRAM and 2Gb NAND Flash Chips Low Profile

    Teensy 4.1 Memory Upgrade Costs and the Impact of AI

    For anyone that has been paying attention to th...

Fine Print

  • Terms of Service
  • Shipping & Returns
credit-card-paypal-logos
RapidSSL_SEAL-90x50

GET IN TOUCH

Email: [email protected]

ProtoSupplies.com / ReefCorner Inc
Veteran Owned and Operated
Lake Stevens WA 98258, USA

  • Terms of Service
  • Shipping & Returns

© 2026 All rights reserved.

TOP