Description
If you love Teensy, but wished it had Wi-Fi or Bluetooth capability like the ESP32 line, this Teensy 4.x ESP32-C6 stack can help bridge that gap for some applications.
The ESP32 acts as a smart coprocessor and communicates with the Teensy over a high-speed serial link. If the ESP32-C6 is not being used for a project, it can be configured so that it has no impact on the Teensy and the Teensy still has full use of all its pins.
Conceptually this is the same as having a baseboard with both a Teensy and ESP32 on it connected together over a serial link as is done on some of our own baseboards, but physically it is condensed down to just the Teensy footprint which can be handy for many use cases.
The ESP32 used in this version is the very small 14-pin XIAO ESP32-C6 module soldered on top of the Teensy 4.0 or Teensy 4.1. We also offer a C5 version that adds 5GHz support, but which also requires the use of an external antenna.
Please Note: Parts are kept in stock to build any configurations required. Backordered items will typically ship by the next business day.
Key Features of the XIAO ESP32-C6 module:
- Very small 14-pin footprint
- Excellent build quality
- Excellent documentation from the manufacturer
- 32-bit RISC-V processor operating at 160MHz
- 2nd low power core operating at 20MHz
- 4MB Flash
- 512KB SRAM
- 2.4GHz Wi-Fi 6 subsystem
- Bluetooth Low Energy 5.0
- Zigbee, Thread, IEEE 802.15.4 support
- Software switchable internal / external antenna support
- USB-C connector
Package Includes:
- Teensy 4.0 or Teensy 4.1 NE and XIAO ESP32-C6 preassembled in a vertical stack.
- Teensy 4.1 NE optionally configured with PSRAM or Flash installed and tested
KEY FEATURES OF THE TEENSY 4.x ESP32-C6 STACK:
- Provides the processing power of the Teensy 4.0 or Teensy 4.1 NE.
- Provides the wireless connectivity of the ESP32-C6.
- Teensy 4.1 NE can optionally have 8MB PSRAM/16MB Flash, 16MB PRAM, 8MB PSRAM/256MB Flash or 32MB PSRAM installed and tested.
- High speed serial link for data sharing.
- The soldered configuration provides for a very robust assembly with good signal integrity between modules.
- Shared pins can either be controlled by the Teensy or the ESP32-C6
- Compact size is perfect for embedding.
- 5V operation, 3.3V logic compatible.
Please Note: We offer both ESP32-C6 and ESP32-C5 versions of the stack. The C5 version can be found here.
This table lists the main features of each version.
Communication between the Teensy and ESP32 is handled over a serial link using the Teensy Serial5 pins (20 & 21) and Serial1 on the ESP32-C6 (GPIO17 & GPIO19) that are remapped to line up with the Teensy pins.
Note: You can also map the pins to use Serial1 on the Teensy if you want to keep pins 20 & 21 available for other uses.
The serial link has been tested at 4Mbps and found to be very reliable and can potentially operate up to 5Mpbs.
This setup only consumes 2 of the Teensy pins. The GPIO0 and 3.3V pins on the ESP32-C6 are removed to avoid conflicts with the Teensy GND and 3.3V pins. The other ESP32-C6 pins are disconnected from internal logic and set as inputs to avoid any conflict with the other attached Teensy pins.
Conversely, the matching Teensy pins could be set as inputs and the ESP32-C6 functionality can drive those shared pins. This might be handy if it is desired to have the ESP32-C6 directly control an attached I2C display or sensor module. One nice feature of the ESP32 architecture is that almost any functionality can be remapped to almost any physical pin.
The C6 variant was chosen as the best suited ESP32 option for establishing basic wireless operation. It has good wireless functionality and none of the edge pins are used for boot functions, so there is no issue with the Teensy holding the pins in a state that would cause issues at boot.
This diagram shows the pinout overlay of the ESP32-C6 on the Teensy 4.1. The shared Teensy 4.0 pins would be the same.
Below is the pinout of the XIAO ESP32-C6 module with its default I/O definitions. Most of this I/O can be remapped to other pins.
The Teensy 4.1 versions can also be selected to have optional memory upgrades as well to include up to 32MB PSRAM and up to 256MB Flash.
Please note: These items can be backordered. We keep all parts in stock to build the different versions and backordered items will typically ship by the next business day.
Please also note: We can also build the Teensy 4.1 version of the ESP32 Stack based on our Fully Loaded for Prototyping System versions of Teensy 4.1 with bottom mounted I/O. In that case, the standard Teensy 4.1 is used since wired Ethernet becomes an option along with USB Host. If interested in one of these, email me with your requirements at [email protected].
Things to Consider
As with many things in life, there is no completely free lunch.
The ESP32 stack requires programming both the ESP32 and the Teensy rather than just programming the Teensy side as when working with a dumb peripheral.
The ESP32 module does physically block the USB Host port and hardwired Ethernet port on the Teensy 4.1. If using with a PCB baseboard, these can still exit from the bottom of the Teensy.
On the Teensy 4.0 stack, due to the more compact form factor, the NXP processor sits directly under the ESP32 module. For that reason, thermals can run warmer than on the Teensy 4.1. How warm will depend heavily on how the ESP32 is being used. Heavy transmit operations is the worst case for thermals.
The Reset and Boot buttons, should you need to use them on the ESP32-C6, are extremely small due to the very compact nature of the module. In fact, they are the smallest buttons I have ever seen.
Important Notes About Power
The stack can be powered from either the USB on the Teensy or the ESP32 or by using the 5V pin on the Teensy. There is no power switching circuitry, so only one power source should be connected at a time.
If you want to connect USB cables to both the ESP32 and Teensy at the same time, one of the cables should have the power wires disconnected. The red wire in the cable can be cut and there are USB data extender cables with built-in power switches that can be handy for this purpose as well. Just make sure that they are a data cable and not just a charging cable.
As an option, the VUSB trace on the bottom of the Teensy can be cut. That disconnects power from the Teensy USB port so that both USB cables can be safely connected. In that case, the assembly needs to be powered from the ESP32 USB or the Teensy 5V pin, but not both at the same time.
The basic combo draws about 135mA at idle. The Teensy 4.1 can potentially draw up to 250mA during SD card accesses. The ESP32-C6 can potentially draw up to 360mA during heavy Wi-Fi transmit operations. Under worst case conditions, it might be possible to overload the USB 2.0 500mA maximum current rating. In that case, powering from USB 3.0 or Teensy 5V pin is recommended.
Getting Started with the Teensy 4.x ESP32-C6 Stack
Software Configuration
The section below illustrates the basic requirements for setting up the basic communication link between the Teensy and the ESP32-C6 as well as getting the extra ESP32-C6 pins out of the way of the mating Teensy pins to avoid contention issues.
ESP32-C6 side
The ESP32-C6 uses a USB-C connector so be sure that you have a USB-C data cable available. Many USB-C cables are power only cables for charging devices like cell phones. If you need a cable, they are available at the bottom of the page.
When using the Arduino IDE, select XIAO ESP32-C6 as the board type. It is way down the ESP32 list. Also remember to select the port it is attached to.
The ESP32-C6 basic programming just requires a couple of things to configure it for use on the Teensy.
First, the Serial1 port needs to be redirected to line up with the Teensy serial5 pins which are pins D7 and D8 on the ESP32-C6 and pins 20 and 21 on the Teensy. If you want to use Serial1 on the Teensy, then use these defines for the ESP32-C6 instead:
#define RX1 D2
#define TX1 D1
Note: When referencing the ESP32-C6 pins, you can either use the pin label such as “D7” or the corresponding GPIO pin number which is “17” in this case.
In addition, even though the other pins will tend to come up as inputs by default, it is good practice to use the gpio_reset_pin command to ensure that the pins other than those used by Serial1 are disconnected from any internal logic on the ESP32-C6 and are set as inputs to ensure there are no possibility of conflicts with the attached Teensy pins.
If you change to Serial1 on the Teensy, also be sure to change the gpio_reset_pin(GPIO_NUM_1); and (GPIO_NUM_2); to gpio_reset_pin(GPIO_NUM_17); and (GPIO_NUM_19);
This code snippet accomplishes those tasks.
#define RX1 D7 // Teensy 4.x Serial5 is connected to serial port #1 #define TX1 D8 //#define RX1 D2 // Use these instead if you want to use Teensy Serial1 //#define TX1 D1 //=============================================================================== // Initialization //=============================================================================== void setup() { Serial.begin(115200); // USB port // Disconnect unused I/O to avoid possible pin conflicts with Teensy // If using Serial1 on the Teensy, change the gpio_reset_pin from // GPIO_NUM_1 and GPIO_NUM_2 to GPIO_17 and GPIO_19 as noted below gpio_reset_pin(GPIO_NUM_0); gpio_reset_pin(GPIO_NUM_1); // Change to GPIO_NUM_17 if using Serial1 on teensy gpio_reset_pin(GPIO_NUM_2); // Change to GPIO_NUM_19 if using Serial1 on teensy 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 Serial5 running at 4Mbps Serial1.begin(4000000, SERIAL_8N1, RX1, TX1);
Teensy Side
On the Teensy side of the stack, the main requirement is simply to initialize the Serial5 (or Serial1) port for operation at the same baud rate that the ESP32-C6 is set for. In addition, it may be desired to implement serial buffers to help hold the data that is being passed. Whether to use a buffer or not and its size would depend on what kind of serial traffic is planned to be passed between the modules.
#define ESP32SERIAL Serial5 // ESP32 is attached to Serial5 port //#define ESP32SERIAL Serial1 // Use this instead to use Teensy Serial1 port // Create buffer to hold incoming characters from ESP32-S3 #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 at 4Mbps // Setup extra memory for the ESP32 serial buffer to avoid overruns ESP32SERIAL.addMemoryForRead(esp32SerialBuffer, ESP32SERIAL_BUFFER_SIZE);
Note: When modifying the code in either the Teensy or the ESP32-C6, depending on the nature of the programs they may get out of sync, and so a power cycle may be needed to resync them.
Our Evaluation Results:
The Teensy 4.x ESP32-C6 Stacks provide a compact and mechanically sound setup and open up some interesting possibilities for the application of Teensy.
These stacks are built using extended length headers which are clipped off on the Teensy pins that do not mate with the ESP32-C6.
The ESP32-C6 is mounted on top primarily to avoid shadowing the built-in antenna and so that the Teensy 3.3V remains available, though that functionality could be replaced with the ESP32-C6 3.3V supply. The ESP32-C6 is mounted as high as possible on the pins to make room for both USB cables to potentially be connected at the same time.
One nice feature of this ESP32-C6 module is that it has both a built-in antenna as well as support for an external antenna. That functionality can be switched in software whereas some other ESP32 modules require a small component to be unsoldered and moved to change the functionality.
The module uses the internal antenna by default. The code snippet to use the external antenna is show below. Setting GPIO3 as an output and then set to LOW enables the antenna switching functionality. Setting GPIO14 to HIGH uses an external antenna and setting it LOW uses the internal antenna. Note that neither of this signals are brought out to the edge pins so do not conflict with the Teensy.
The external antenna connector is a standard U.FL type.
void setup() { pinMode(3, OUTPUT); digitalWrite(3, LOW);//turn on this function delay(100); pinMode(14, OUTPUT); digitalWrite(14, HIGH);//use external antenna }
Per the ESP32-C6 documentation, 5Mbps is the maximum supported serial communications rate though the Teensy can theoretically go higher than that. In our testing, 4Mbps gives good high speed communications between the modules with virtually no errors. The test programs below can be used to play with that aspect of the product.
The ESP32-C6 module has a red LED that is connected to the built-in battery charging circuit that is not used in this application. It may come on when power is first applied and then will go off on its own after about 30 seconds.
There is also a yellow user LED. It is connected to GPIO15 and can be accessed using the usual LED_BUILTIN constant. GPIO15 does not come out to the edge pins and so does not conflict with the Teensy.
The Teensy line of boards are an excellent product that provides high performance and advanced I/O to tackle even the hardest problems which is why they are often found in advanced hobbyist projects as well as low volume production builds.
The PJRC forum provides access to excellent technical advice that is far more advanced than found on the normal Arduino forums. It is the best place to find information on how to use the advanced features found in the Teensy.
It is highly suggested to checkout the PJRC website and Teensy forum at the links below for additional information.
The XIAO ESP32 line by Seeed Studio is also a well supported and documented product and more information can be found at those links below as well.
Teensy ESP32-C6 Stack WiFi Scan Example Programs
The two programs below implement the WiFi Scan example. These programs are loaded into the Teensy and ESP32-C6 before shipment to serve as a verification of the basic functionality out of the box. Plug USB into the Teensy and open the Serial Monitor to see the output.
Teensy 4.0 / 4.1 WiFi Scan Example Program
The Teensy program checks for installed PSRAM or Flash upgrades if it is compiled to run on a Teensy 4.1. It then checks to see if the ESP32 is connected. It then loops every 5 seconds, requesting a scan of wireless networks and reports the results as well as the operating temperature of the CPU out to the USB serial port.
/* 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 Serial5 // ESP32 is attached to Serial5 port //#define ESP32SERIAL Serial1 // Use this instead to use Teensy 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 Seria1 5 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) { // Wait until ESP32 sends something back while (ESP32SERIAL.available() < 1) { delay(1); } Serial.println("Read incoming data"); while (ESP32SERIAL.available()) { String returnData = ESP32SERIAL.readStringUntil('\n'); Serial.println(returnData); delay(10); } scanRequested = false; delay(5000); } Serial.println(); Serial.print(tempmonGetTemp()); Serial.println("°C"); } //=============================================================================== // Routine to request Scan from ESP32-C6 //=============================================================================== 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"); }
ESP32-C6 WiFi Scan Example Program
The ESP32 program just implements the Wifi Scan example program along with the changes need to work with this configuration. The code to allow an external antenna to be used can be uncommented to implement that functionality.
/* This sketch interfaces to the Teensy 4.x via serial port 1 which is remapped to line up with Teensy Serial5 or Serial1 pins. 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 in the IDE */ #include "WiFi.h" #define RX1 D7 // Teensy 4.x Serial5 is connected to serial port #1 #define TX1 D8 //#define RX1 D2 // Use these instead if you want to use Teensy Serial1 //#define TX1 D1 //=============================================================================== // Initialization //=============================================================================== void setup() { Serial.begin(115200); // USB port // Disconnect unused I/O to avoid possible pin conflicts with Teensy // If using Serial1 on the Teensy, change the gpio_reset_pin from // GPIO_NUM_1 and GPIO_NUM_2 to GPIO_17 and GPIO_19 as noted below gpio_reset_pin(GPIO_NUM_0); gpio_reset_pin(GPIO_NUM_1); // Change to GPIO_NUM_17 if using Serial1 on teensy gpio_reset_pin(GPIO_NUM_2); // Change to GPIO_NUM_19 if using Serial1 on teensy 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 Serial5 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 ESP32-C6 Stack Comm Test Programs
These programs simply establish serial comm between the Teensy and ESP32-C6 and transmits 64 byte packets in a loop-back arrangement at 4Mbps to test for link integrity. The Teensy checks for data integrity on the returning incoming packet from the ESP32-C6 to verify it matches what was transmitted.
Once both programs are downloaded, the stack should be power cycled so that both programs are reinitialized.
Note that the serial can be changed to use Teensy Serial1 as shown in the examples above.
Teensy 4.0 / 4.1 Comm Test Program
// Master (Block-Stream & Speed Evaluator) // Teensy 4.0 or 4.1 #define ESP32_SERIAL Serial5 const unsigned long TEST_BAUD = 4000000; // Target Link Speed const size_t BLOCK_SIZE = 64; // Send packets in 64 byte blocks uint8_t txBuffer[BLOCK_SIZE]; uint8_t rxBuffer[BLOCK_SIZE]; unsigned long totalPacketsSent = 0; unsigned long totalErrorsDetected = 0; unsigned long successfulBytesTransferred = 0; unsigned long speedTrackingStartTime = 0; const unsigned long REFRESH_INTERVAL_MS = 2000; // Update Serial Monitor uint8_t bigserialbuffer[16384]; // Extra large buffer to hold data void setup() { Serial.begin(115200); while(!Serial); ESP32_SERIAL.begin(TEST_BAUD); ESP32_SERIAL.addMemoryForRead(&bigserialbuffer, sizeof(bigserialbuffer)); delay(1000); // Fill the buffer with a known test pattern for(size_t i = 0; i < BLOCK_SIZE; i++) { txBuffer[i] = (uint8_t)i; } Serial.print("--- UART High-Speed Block Test- Baud Rate: "); Serial.println(TEST_BAUD); speedTrackingStartTime = millis(); } void loop() { // Step 1: Write the entire block natively to the hardware serial buffer ESP32_SERIAL.write(txBuffer, BLOCK_SIZE); totalPacketsSent += BLOCK_SIZE; // Step 2: Await the response block with a timeout fallback unsigned long startTime = millis(); size_t bytesRead = 0; while (bytesRead < BLOCK_SIZE) { if (millis() - startTime > 100) { // 100ms Timeout totalErrorsDetected += (BLOCK_SIZE - bytesRead); Serial.println("Error: Block Timeout."); return; } // Read whatever bytes have made it to the hardware buffer if (ESP32_SERIAL.available() > 0) { rxBuffer[bytesRead] = ESP32_SERIAL.read(); bytesRead++; } } // Step 3: Validate the data block integrity for(size_t i = 0; i < BLOCK_SIZE; i++) { if (rxBuffer[i] == txBuffer[i]) { successfulBytesTransferred++; } else { totalErrorsDetected++; } // Increment pattern slightly for dynamic testing txBuffer[i]++; } // Step 4: Speed Report Interval unsigned long currentMillis = millis(); if (currentMillis - speedTrackingStartTime >= REFRESH_INTERVAL_MS) { unsigned long timeElapsedMs = currentMillis - speedTrackingStartTime; // Bits calculation: (Bytes * 10 bits per frame * 2 directions) unsigned long totalBitsMoved = successfulBytesTransferred * 10 * 2; float speedMbps = ((float)totalBitsMoved / 1000000.0) / ((float)timeElapsedMs / 1000.0); float errorRate = ((float)totalErrorsDetected / totalPacketsSent) * 100.0; Serial.print("Total Bytes: "); Serial.print(totalPacketsSent); Serial.print(" | Errors: "); Serial.print(totalErrorsDetected); Serial.print(" | BER: "); Serial.print(errorRate, 4); Serial.print("%"); Serial.print(" | ACTUAL SPEED: "); Serial.print(speedMbps, 4); Serial.println(" Mbps"); successfulBytesTransferred = 0; speedTrackingStartTime = millis(); } }
Note that the serial can be changed to use Teensy Serial1 as shown in the examples above.
ESP32-C6 Test Program
// Slave (Block-Stream Echo) // ESP32-C6 #define RX1 D7 //GPIO17 Teensy 4.1 is connected to serial port #1 #define TX1 D8 //GPIO19 #define TEENSY_SERIAL Serial1 const unsigned long TEST_BAUD = 4000000; // Target link speed const size_t BLOCK_SIZE = 64; // Packet size uint8_t slaveBuffer[BLOCK_SIZE]; void setup() { // Disconnect unused I/O to avoid possible pin conflicts with Teensy 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); // Assign 4096-byte buffers to avoid overflow at higher speeds TEENSY_SERIAL.setRxBufferSize(4096); TEENSY_SERIAL.setTxBufferSize(4096); // Serial.begin(115200); TEENSY_SERIAL.begin(TEST_BAUD, SERIAL_8N1, RX1, TX1); //Port connected to Teensy 4.1 } void loop() { // Wait until the hardware buffer holds an entire chunk of data if (TEENSY_SERIAL.available() >= BLOCK_SIZE) { // Read the chunk natively into memory TEENSY_SERIAL.readBytes(slaveBuffer, BLOCK_SIZE); // Blast the chunk directly back down the TX hardware FIFO pipeline TEENSY_SERIAL.write(slaveBuffer, BLOCK_SIZE); } }
Before they are shipped, these modules are:
- Any PSRAM or Flash chips are installed depending on the configuration ordered.
- Boards are soldered together.
- Flux residue is cleaned.
- Any installed memory is tested.
- Basic functionality of the stack is tested by installing WiFi example before shipment.
- Packaged in resealable ESD bag for safe storage.
Further Reading:
You can read more about the basic Teensy hardware on our product pages.
Highly recommended to also checkout the PJRC Teensy website and forum.
PJRC Forum – Excellent source of technical information
PJRC Teensy Forum link about these stacks
WIKI for Seeed Studio ESP32-C6 – Excellent source of information about the module with programming examples.
Notes:
- None
Technical Specifications
| Operating Voltage | 3.3V |
| Typical Operating Current | 135mA (typical) at idle Teensy 4.1 max draw is up to 250mA (SD card access ESP32-C6 max draw is up to 380mA (Transmit) |
| Board Dimensions | |
| Teensy 4.0 ESP32 Stack | 38x 18mm (1.4 x 1.5″) |
| Teensy 4.1 ESP32 Stack | 65 x 18mm (2.4 x 1.5″) |
| Stacked Height (not including Teensy pins | 14mm (0.55″) |
| Country of Origin | Teensy and final assembly is USA XIAO ESP32-C6 is China |

















