# Adafruit MatrixPortal S3

## Overview

Warning: Some MatrixPortal S3 boards may not have the UF2 bootloader installed. Double-clicking will not produce a BOOT drive. Follow these instructions to install the UF2 bootloader: https://learn.adafruit.com/adafruit-matrixportal-s3/factory-reset#factory-reset-and-bootloader-repair-3107941

![](https://cdn-learn.adafruit.com/assets/assets/000/122/569/medium800thumb/led_matrices_5778-06.jpg?1689347988)

Folks love our&nbsp;[wide selection of RGB matrices](https://www.adafruit.com/category/327)&nbsp;and accessories&nbsp;for making custom colorful LED displays... and our RGB Matrix Shields and FeatherWings can be quickly soldered together to make the wiring much easier. But what if we made it&nbsp;_even easier_&nbsp;than that?&nbsp; **Like, no solder, no wiring, just instant plug-and-play?&nbsp;** Dream no more - with the&nbsp; **Adafruit Matrix Portal S3 add-on for RGB Matrices** , there's never been an easier way to create powerful Internet-connected LED displays.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/570/medium800/led_matrices_5778-01.jpg?1689348043)

You can plug directly into the back of&nbsp;[any HUB-75 compatible display (all the ones we stock will work) from 16x32 up to 64x64](https://www.adafruit.com/category/327) or use the stock 2x8 IDC cables to plug into the front. Further matrix panels can be chained together. Use the included screws to attach the power cable to the power plugs with a common screwdriver, then power it with any USB C power supply. Chain dozens of displays for long stretches, or you can panelize them in a grid for bigger displays. For larger projects, power the matrices with a separate 5V power adapter.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/571/medium800/led_matrices_5778-05.jpg?1689348104)

Then code up your project in&nbsp;[CircuitPython](https://learn.adafruit.com/rgb-led-matrices-matrix-panels-with-circuitpython)&nbsp;or&nbsp;[Arduino](https://learn.adafruit.com/adafruit-protomatter-rgb-matrix-library), our Protomatter matrix library works great on the ESP32-S3 chipset, knowing that you've got the wiring and level shifting all handled. Here's what you get:

- **ESP32-S3 processor** , 8 MB flash, 2 MB of PSRAM, with full Arduino or CircuitPython support
- **WiFi&nbsp; and Bluetooth LE&nbsp;** baked right in,&nbsp;full Arduino support. CircuitPython only supports WiFi at this time, not BLE on the S3 chip.
- **USB Type C** &nbsp;connector for data and power connectivity
- [**I2C STEMMA QT connector&nbsp;** for plug-n-play use of any of our STEMMA QT devices or sensors](https://www.adafruit.com/category/620)&nbsp;can also be used with&nbsp;[any Grove I2C devices using this adapter cable](https://www.adafruit.com/product/4528)
- **JST 3-pin connector** &nbsp;that also has analog input&nbsp;[for quick connection with any JST PH 2.0mm pitch cable](https://www.adafruit.com/search?q=jst+2mm).
- **LIS3DH accelerometer** &nbsp;for digital sand projects or detecting taps/orientation.
- **GPIO breakout strip -&nbsp;** has reset, boot selection, TX debug output, and 6 GPIO including 4 analog inputs with PWM, SPI, or I2S support for adding other hardware.
- **Address E line jumper** &nbsp;for use with 64x64 matrices (check your matrix to see which pin is used for address E, we default to pin 8
- **Two user interface buttons** &nbsp;+ one reset button
- **Indicator NeoPixel** &nbsp;and red LED
- **Green power indicator LEDs** &nbsp;for both 3V and 5V power
- **2x10 socket connector** &nbsp;fits snugly into 2x8 HUB75 ports without worrying about 'off by one' errors
- **2x8 IDC plug connector** &nbsp;works with standard cables that come with matrices.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/572/medium800/led_matrices_5778-02.jpg?1689348115)

The Matrix Portal uses an Espressif ESP32-S3 Wi-Fi+BLE chipset, and has dropped the SAMD51 from the original Matrix Portal due to silicon shortages. But turns out the S3 is really great at doing all the work of the original all on its own:

- The S3 has a parallel output drive peripheral which means that controlling the matrix is done without bitbanging.
- The S3 has two cores so one can be dedicated to WiFi networking or matrix control while the other runs your code.&nbsp;
- With native USB, its easy to have it act like a keyboard, or mouse, or MIDI device and it also has plenty of I2C, SPI, I2S, UART and analog inputs.
- Lots of memory: 8MB of Flash means plenty of space for code, files, GIFs and more. 2MB of PSRAM means you can read and parse a lot of IoT data and still have plenty of RAM for the matrix display buffers.
- The only real thing missing from the original Matrix Portal is the S3 does not have an analog output DAC pin, we recommend an I2S amplifier for audio instead.

Comes with one fully programmed and assembled MatrixPortal, preprogrammed with a basic display demo for 32x64 LED matrices.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/573/medium800/led_matrices_5778-04.jpg?1689348229)

# Adafruit MatrixPortal S3

## Pinouts

![](https://cdn-learn.adafruit.com/assets/assets/000/122/576/medium800/led_matrices_pinouts.jpg?1689349295)

![](https://cdn-learn.adafruit.com/assets/assets/000/140/086/medium800/led_matrices_Adafruit_Matrix_Portal_S3_PrettyPins.jpg?1759351254 )

There are so many great features on the Adafruit MatrixPortal S3. Let's take a look at what's available!

## Microcontroller and WiFi
The main processor chip is the **Espressif**  **ESP32-S3** with 3.3v logic/power. It has **8MB** of Flash and **2MB** of RAM.

The ESP32-S3 comes with WiFi and Bluetooth LE baked right in, though CircuitPython only supports WiFi at this time, not BLE on the S3 chip.

![led_matrices_MicroController_and_WiFi.jpg](https://cdn-learn.adafruit.com/assets/assets/000/122/577/medium640/led_matrices_MicroController_and_WiFi.jpg?1689351976)

## HUB75 Connectors
There is a **2x8 pin HUB75 plug** connector on the reverse side that plugs directly into the HUB75 port on your RGB Matrix. The socket itself is 2x10 so that it fits snug and lined up in a 2x8 IDC socket. Otherwise its easy to get it 'off by one'

There is also a **2x8 pin HUB75 socket** connector on the component side that allows you the option to instead connect a 2x8 IDC cable to your RGB Matrix.

![led_matrices_HUB75_Connectors.jpg](https://cdn-learn.adafruit.com/assets/assets/000/122/579/medium640/led_matrices_HUB75_Connectors.jpg?1689352460)

![led_matrices_HUB75_Connectors-Reverse.jpg](https://cdn-learn.adafruit.com/assets/assets/000/122/580/medium640/led_matrices_HUB75_Connectors-Reverse.jpg?1689352469)

## RGB Matrix Power
There are **+5V** and **Ground** M3-threaded screw terminals on either side of the HUB75 connector. These provide power to the RGB Matrix.

If you would like to power the RGB Matrix with external power, we recommend disconnecting it from here and providing power directly to the matrix.

These terminals were designed as outputs ONLY - power from the USB port connects directly to these pads, so you should power from USB and then connect the matrix power inputs to these terminals.

While it's _technically_ possible to power the MatrixPortal through here, we strongly discourage that because **plugging anything into the USB port at the same time could result in damage.**

![led_matrices_RGB_Matrix_Power.jpg](https://cdn-learn.adafruit.com/assets/assets/000/122/581/medium640/led_matrices_RGB_Matrix_Power.jpg?1689352793)

## Accelerometer
The MatrixPortal S3 includes a **LIS3DH Triple-Axis Accelerometer**. The accelerometer is connected via the I2C bus.

**Please note the address of the accelerometer is 0x19 not 0x18 which is the default in our libraries.**

![led_matrices_Accelerometer.jpg](https://cdn-learn.adafruit.com/assets/assets/000/122/583/medium640/led_matrices_Accelerometer.jpg?1689354455)

## Stemma QT Connector
There is a 4-pin **Stemma QT&nbsp;connector** on the left. The I2C has pullups to 3.3V power and is connected to the LIS3DH already.

In CircuitPython, you can use the STEMMA connector with&nbsp;`board.SCL`&nbsp;and&nbsp;`board.SDA`, or&nbsp;`board.STEMMA_I2C()`.

![led_matrices_Stemma_QT_Connector.jpg](https://cdn-learn.adafruit.com/assets/assets/000/122/584/medium640/led_matrices_Stemma_QT_Connector.jpg?1689354508)

## Power Pins
 **3V** is the output from the 3.3V regulator, it can supply 500mA peak.

**GND** is the common ground for all power and logic.

![led_matrices_Power_Pins.jpg](https://cdn-learn.adafruit.com/assets/assets/000/122/594/medium640/led_matrices_Power_Pins.jpg?1689358090)

## Reset and Boot Pins
 **RESET** is the Reset pin. Tie to ground to manually reset the ESP32-S3.

Tying **BOOT** to ground while resetting will place the ESP32-S3 in ROM bootloader mode.

![led_matrices_Reset_Pin.jpg](https://cdn-learn.adafruit.com/assets/assets/000/122/585/medium640/led_matrices_Reset_Pin.jpg?1689354730)

## Debug Pin
If you'd like to do lower level debugging, we have the ESP32-S3's TXD0 debug pin exposed to view messages.

To read, you would connect a Serial UART cable's Receive connection here and the cable's ground connection to the GND pin.&nbsp;

![led_matrices_Debugging.jpg](https://cdn-learn.adafruit.com/assets/assets/000/122/593/medium640/led_matrices_Debugging.jpg?1689357733)

## Serial UART Pins
The **TXO pin** and **RXI pin** are for serial communication with the ESP32-S3 microcontroller and can be used to connect various peripherals such as a GPS.

The RXI pin is attached to `board.RX` and Arduino `8` and the TXO pin is attached to `board.TX` and Arduino `18`.

Both of these pins can be used for digital I/O.

![led_matrices_Serial_UART.jpg](https://cdn-learn.adafruit.com/assets/assets/000/122/595/medium640/led_matrices_Serial_UART.jpg?1689358171)

## Analog Connector/Pins
On the bottom side towards the right, there is a connector labeled&nbsp; **A0**. This is a&nbsp; **3-pin JST analog connector** for sensors, NeoPixels, digital input/output, or analog input.

For the JST connected, there is a jumper above that can be cut and soldered to use **3V** instead of **5V**.

Along the bottom there are also pins labeled `A1` through `A4`.

All of these pins can be used for analog inputs or digital I/O.

![led_matrices_Analog_Connector_and_Pins.jpg](https://cdn-learn.adafruit.com/assets/assets/000/122/596/medium640/led_matrices_Analog_Connector_and_Pins.jpg?1689358504)

## Status LED and NeoPixel
There are two LEDs on the board controllable through programming.

There is the RGB&nbsp; **status NeoPixel** &nbsp;labeled "NeoPixel". It is connected to&nbsp;`board.NEOPIXEL`&nbsp;or Arduino&nbsp;`4`

As well, there is the&nbsp; **D13 LED**. This is attached to&nbsp;`board.LED`&nbsp;and Arduino&nbsp;`13`

![led_matrices_Status_LED_and_NeoPixel.jpg](https://cdn-learn.adafruit.com/assets/assets/000/122/597/medium640/led_matrices_Status_LED_and_NeoPixel.jpg?1689358576)

## USB-C Connector
There is one USB port on the board.

On the left side, towards the bottom, is a&nbsp; **USB Type C&nbsp;** port, which is used for powering and programming both the board and RGB Matrix.

![led_matrices_USB-C_Connector.jpg](https://cdn-learn.adafruit.com/assets/assets/000/122/598/medium640/led_matrices_USB-C_Connector.jpg?1689358669)

## Buttons
There are three buttons along the left side of the MatrixPortal S3.

The&nbsp; **reset button&nbsp;** is located in the top position. Click it once to re-start your firmware. Click it again while the NeoPixel is Purple to enter bootloader mode.

The **up button** is located in the middle and is attached to&nbsp;`board.BUTTON_UP`&nbsp;and Arduino&nbsp;`6`.

The **down button** is located on the bottom and is attached to `board.BUTTON_DOWN`&nbsp;and Arduino&nbsp;`7`.

The up and down buttons do not have any pull-up resistors connected to them and pressing either of them pulls the input low.

The&nbsp; **boot button&nbsp;** is located between the up button and the Microcontroller. Hold it while pressing reset to enter ROM Bootloader mode.

![led_matrices_Buttons.jpg](https://cdn-learn.adafruit.com/assets/assets/000/122/599/medium640/led_matrices_Buttons.jpg?1689358709)

## Address E Line Jumper
This jumper is used for use with **64x64 matrices** and is either connected to pin 8 or pin 16 of the HUB75 connector. Check your matrix to see which pin is used for address E.

You can close the jumper by using your soldering iron to melt a blob of solder on the bottom solder jumper so the middle pad is 'shorted' to 8. _(This is compatible with 64x64 matrices in the Adafruit store. For 64x64 matrices from other sources, you might need to use 16 instead, check the datasheet of your display.)_

![led_matrices_Address_E_Line_Jumper.jpg](https://cdn-learn.adafruit.com/assets/assets/000/122/600/medium640/led_matrices_Address_E_Line_Jumper.jpg?1689359040)

# Adafruit MatrixPortal S3

## Prep the MatrixPortal

## Power Prep

The MatrixPortal supplies power to the matrix display panel via two standoffs. These come with protective tape applied (part of our manufacturing process) which MUST BE REMOVED!

Use some tweezers or a fingernail to remove the two amber circles.

![adafruit_io_mxprtl-3866.jpg](https://cdn-learn.adafruit.com/assets/assets/000/094/902/medium640/adafruit_io_mxprtl-3866.jpg?1600706317)

![adafruit_io_mxprtl-3867.jpg](https://cdn-learn.adafruit.com/assets/assets/000/094/903/medium640/adafruit_io_mxprtl-3867.jpg?1600706324)

## Power Terminals

Next, screw in the spade connectors to the corresponding standoff.

- **red** wire goes to **+5V** &nbsp;
- **black** wire goes to **GND**

![adafruit_io_mxprtl-3869.jpg](https://cdn-learn.adafruit.com/assets/assets/000/094/907/medium640/adafruit_io_mxprtl-3869.jpg?1600706432)

![adafruit_io_mxprtl-3871.jpg](https://cdn-learn.adafruit.com/assets/assets/000/094/908/medium640/adafruit_io_mxprtl-3871.jpg?1600706551)

## Panel Power

Plug either one of the four-conductor power plugs into the power connector pins on the panel. The plug can only go in one way, and that way is marked on the board's silkscreen.

![adafruit_io_mxprtl-3872.jpg](https://cdn-learn.adafruit.com/assets/assets/000/094/910/medium640/adafruit_io_mxprtl-3872.jpg?1600706597)

![adafruit_io_mxprtl-3873.jpg](https://cdn-learn.adafruit.com/assets/assets/000/094/911/medium640/adafruit_io_mxprtl-3873.jpg?1600706672)

## Dual Matrix Setup

If you're planning to use a 64x64 matrix, [follow these instructions on soldering the Address E Line jumper](https://learn.adafruit.com/adafruit-matrixportal-m4/pinouts#address-e-line-jumper-3072815).

## Board Connection

Now, plug the board into the left side shrouded 8x2 connector as shown. The orientation matters, so take a moment to confirm that the **white indicator arrow on the matrix panel is oriented pointing up and right** as seen here and the MatrixPortal overhangs the edge of the panel when connected. This allows you to use the edge buttons from the front side.

&nbsp;

Check nothing is impeding the board from plugging in firmly. If there's a plastic nub on the matrix that's keeping the Portal from sitting flat, cut it off with diagonal cutters

![adafruit_io_mxprtl-3874.jpg](https://cdn-learn.adafruit.com/assets/assets/000/094/912/medium640/adafruit_io_mxprtl-3874.jpg?1600706721)

![adafruit_io_mxprtl-3875.jpg](https://cdn-learn.adafruit.com/assets/assets/000/094/913/medium640/adafruit_io_mxprtl-3875.jpg?1600706732)

![](https://cdn-learn.adafruit.com/assets/assets/000/094/914/medium800/adafruit_io_mxprtl-3876.jpg?1600706891)

![](https://cdn-learn.adafruit.com/assets/assets/000/094/915/medium800/adafruit_io_mxprtl-3877.jpg?1600706894)

Info: 

# Adafruit MatrixPortal S3

## LED Matrix Diffuser

## LED Diffusion Acrylic

You can add an [LED diffusion acrylic faceplate](https://www.adafruit.com/product/4594) to the your LED matrix display. (Pictured here with the [ON AIR project](https://learn.adafruit.com/rgb-matrix-automatic-youtube-on-air-sign))

This can help protect the LEDs as well as enhance the look of the sign both indoors and out by reducing glare and specular highlights of the plastic matrix grid.

![led_matrices_onairbuild-3367.jpg](https://cdn-learn.adafruit.com/assets/assets/000/093/987/medium640/led_matrices_onairbuild-3367.jpg?1597088161)

## Measure and Cut the Plastic

You can use the sign to measure and mark cut lines on the paper backing of the acrylic sheet.

Then, use a tablesaw or bandsaw with a fine toothed blade and a guide or sled to make the cuts.

Note: it is possible to score and snap acrylic, but it can be very tricky to get an even snap without proper clamping.

![led_matrices_onairbuild-3343.jpg](https://cdn-learn.adafruit.com/assets/assets/000/093/988/medium640/led_matrices_onairbuild-3343.jpg?1597088278)

![led_matrices_onairbuild-3346.jpg](https://cdn-learn.adafruit.com/assets/assets/000/093/989/medium640/led_matrices_onairbuild-3346.jpg?1597088290)

![led_matrices_onairbuild-3347.jpg](https://cdn-learn.adafruit.com/assets/assets/000/093/991/medium640/led_matrices_onairbuild-3347.jpg?1597089259)

![led_matrices_onairbuild-3349.jpg](https://cdn-learn.adafruit.com/assets/assets/000/093/992/medium640/led_matrices_onairbuild-3349.jpg?1597089270)

![](https://cdn-learn.adafruit.com/assets/assets/000/093/998/medium800/led_matrices_onairbuild-3352.jpg?1597089308)

Peel away the paper backing from both sides and set the acrylic onto your matrix display with the matte finished side facing out.

![led_matrices_onairbuild-3355.jpg](https://cdn-learn.adafruit.com/assets/assets/000/093/999/medium640/led_matrices_onairbuild-3355.jpg?1597089331)

## Uglu Dashes

The best method we've found for adhering acrylic to the matrix display is to use [Uglu Dashes clear adhesive rectangles from Pro Tapes](https://www.protapes.com/products/uglu-600-dashes-sheets). They are incredibly strong (although can be removed if necessary), easy to apply, and are invisible once attached.

Use one at each corner and one each at the halfway point of the long edges, then press the acrylic and matrix panel together for about 20 seconds.

![adafruit_io_weathermx-2-3.jpg](https://cdn-learn.adafruit.com/assets/assets/000/094/842/medium640/adafruit_io_weathermx-2-3.jpg?1600463849)

![adafruit_io_weathermx-2.jpg](https://cdn-learn.adafruit.com/assets/assets/000/094/843/medium640/adafruit_io_weathermx-2.jpg?1600463856)

![adafruit_io_weathermx-2-2.jpg](https://cdn-learn.adafruit.com/assets/assets/000/094/844/medium640/adafruit_io_weathermx-2-2.jpg?1600463866)

Here you can see the impact of using the diffusion acrylic. (Pictured here with the ON AIR sign project)

![](https://cdn-learn.adafruit.com/assets/assets/000/094/006/medium800thumb/led_matrices_diffusionOnAir.jpg?1597089757)

## Stand

A very simple and attractive way to display your matrix is with the adjustable [bent-wire stand](https://www.adafruit.com/product/1679).

![led_matrices_onairbuild-3418.jpg](https://cdn-learn.adafruit.com/assets/assets/000/094/032/medium640/led_matrices_onairbuild-3418.jpg?1597094067)

![led_matrices_onairbuild-3419.jpg](https://cdn-learn.adafruit.com/assets/assets/000/094/033/medium640/led_matrices_onairbuild-3419.jpg?1597094085)

![led_matrices_onairbuild-3421.jpg](https://cdn-learn.adafruit.com/assets/assets/000/094/034/medium640/led_matrices_onairbuild-3421.jpg?1597094097)

![led_matrices_onairbuild-3422.jpg](https://cdn-learn.adafruit.com/assets/assets/000/094/035/medium640/led_matrices_onairbuild-3422.jpg?1597094107)

![](https://cdn-learn.adafruit.com/assets/assets/000/095/378/medium800/adafruit_io_led_matrices_onairbuild-3383.jpg?1602006263)

Alternately, you can use a frame, [3D printed brackets](https://learn.adafruit.com/led-protest-sign/build-the-sign#step-3065326), tape, glue, or even large binder clips to secure the acrylic to the sign and then mount it on on a wall, shelf, or display cabinet.

[These mini-magnet feet](https://www.adafruit.com/product/4631) can be used to stick the sign to a ferrous surface.

# Adafruit MatrixPortal S3

## Install CircuitPython

[CircuitPython](https://github.com/adafruit/circuitpython) is a derivative of [MicroPython](https://micropython.org) designed to simplify experimentation and education on low-cost microcontrollers. It makes it easier than ever to get prototyping by requiring no upfront desktop software downloads. Simply copy and edit files on the **CIRCUITPY** drive to iterate.

## Set up CircuitPython Quick Start!

Follow this quick step-by-step for super-fast Python power :)

Info: 

[Download the latest version of CircuitPython for this board via circuitpython.org](https://circuitpython.org/board/adafruit_matrixportal_s3/)
## Further Information

For more detailed info on installing CircuitPython, check out [Installing CircuitPython](https://learn.adafruit.com/welcome-to-circuitpython/installing-circuitpython).

 **Click the link above and download the latest UF2 file.**

Download and save it to your desktop (or wherever is handy).

![led_matrices_Save_to_Desktop.png](https://cdn-learn.adafruit.com/assets/assets/000/095/075/medium640/led_matrices_Save_to_Desktop.png?1601050695)

Plug your MatrixPortal S3 into your computer using a known-good USB cable.

**A lot of people end up using charge-only USB cables and it is very frustrating! So make sure you have a USB cable you know is good for data sync.**

Click the **Reset** button (indicated by the green arrow) on your board. When you see the NeoPixel RGB LED (indicated by the magenta arrow) turn purple, press it again. At that point, the NeoPixel should turn green. If it turns red, check the USB cable, try another USB port, etc.

If double-clicking doesn't work the first time, try again. Sometimes it can take a few tries to get the rhythm right!

![led_matrices_Buttons.jpg](https://cdn-learn.adafruit.com/assets/assets/000/126/017/medium640/led_matrices_Buttons.jpg?1699492993)

Info: 

You will see a new disk drive appear called **MATRXS3BOOT**.

Drag the **adafruit\_circuitpython\_etc.uf2** file over to **MATRXS3BOOT****.**

![led_matrices_matrix.png](https://cdn-learn.adafruit.com/assets/assets/000/126/018/medium640/led_matrices_matrix.png?1699493436)

The LED will flash. Then, the **MATRXS3BOOT** &nbsp;drive will disappear and a new disk drive called **CIRCUITPY** will appear.

That's it, you're done! :)

![led_matrices_CircuitPy.png](https://cdn-learn.adafruit.com/assets/assets/000/122/618/medium640/led_matrices_CircuitPy.png?1689369656)

# Adafruit MatrixPortal S3

## What is CircuitPython?

CircuitPython is a programming language designed to simplify experimenting and learning to program on low-cost microcontroller boards. It makes getting started easier than ever with no upfront desktop downloads needed. Once you get your board set up, open any text editor, and get started editing code. It's that simple.

![](https://cdn-learn.adafruit.com/assets/assets/000/049/445/medium800/circuitpython_python-logo-master-flat.png?1513729728)

# CircuitPython is based on Python

Python is the fastest growing programming language. It's taught in schools and universities. It's a high-level programming language which means it's designed to be easier to read, write and maintain. It supports modules and packages which means it's easy to reuse your code for other projects. It has a built in interpreter which means there are no extra steps, like _compiling_, to get your code to work. And of course, Python is Open Source Software which means it's free for anyone to use, modify or improve upon.

CircuitPython adds hardware support to all of these amazing features. If you already have Python knowledge, you can easily apply that to using CircuitPython. If you have no previous experience, it's really simple to get started!

![](https://cdn-learn.adafruit.com/assets/assets/000/049/441/medium800/circuitpython_circuit_playground_adafruit_blinka_computer.png?1513729326)

## Why would I use CircuitPython?
CircuitPython is designed to run on microcontroller boards. A microcontroller board is a board with a microcontroller chip that's essentially an itty-bitty all-in-one computer. The board you're holding is a microcontroller board! CircuitPython is easy to use because all you need is that little board, a USB cable, and a computer with a USB connection. But that's only the beginning.

Other reasons to use CircuitPython include:

- **You want to get up and running quickly.** Create a file, edit your code, save the file, and it runs immediately. There is no compiling, no downloading and no uploading needed.
- **You're new to programming.** CircuitPython is designed with education in mind. It's easy to start learning how to program and you get immediate feedback from the board.
- **Easily update your code.** Since your code lives on the disk drive, you can edit it whenever you like, you can also keep multiple files around for easy experimentation.
- **The serial console and REPL.** These allow for live feedback from your code and interactive programming.
- **File storage.** The internal storage for CircuitPython makes it great for data-logging, playing audio clips, and otherwise interacting with files.
- **Strong hardware support.** CircuitPython has builtin support for microcontroller hardware features like digital I/O pins, hardware buses (UART, I2C, SPI), audio I/O, and other capabilities. There are also many libraries and drivers for sensors, breakout boards and other external components.
- **It's Python!** Python is the fastest-growing programming language. It's taught in schools and universities. CircuitPython is almost-completely compatible with Python. It simply adds hardware support.

This is just the beginning. CircuitPython continues to evolve, and is constantly being updated. Adafruit welcomes and encourages feedback from the community, and incorporate it into the development of CircuitPython. That's the core of the open source concept. This makes CircuitPython better for you and everyone who uses it!

# Adafruit MatrixPortal S3

## CircuitPython Internet Test

One of the great things about most Espressif microcontrollers are their built-in WiFi capabilities. This page covers the basics of getting connected using CircuitPython.

The first thing you need to do is update your **code.py** to the following (it will error until WiFi details are added). Click the **Download Project Bundle** button to download the necessary libraries and the&nbsp; **code.py** file in a zip file. Extract the contents of the zip file, and copy the **entire**  **lib**  **folder** and the **code.py** file to your **CIRCUITPY** drive.

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/ESP32_S2_WiFi_Tests/CPy_Native_WiFi_Test/code.py

Your **CIRCUITPY** drive should resemble the following.

![CIRCUITPY](https://adafruit.github.io/Adafruit_Learning_System_Guides/ESP32_S2_WiFi_Tests_CPy_Native_WiFi_Test.png )

To get connected, the next thing you need to do is update the **settings.toml** file.

## The settings.toml File

We expect people to share tons of projects as they build CircuitPython WiFi widgets. What we want to avoid is people accidentally sharing their passwords or secret tokens and API keys. So, we designed all our examples to use a **settings.toml** file, that is on your&nbsp; **CIRCUITPY** &nbsp;drive, to hold secret/private/custom data. That way you can share your main project without worrying about accidentally sharing private stuff.

If you have a fresh install of CircuitPython on your board, the initial **settings.toml** file on your **CIRCUITPY** drive is empty.

To get started, you can update the **settings.toml** on your **CIRCUITPY** drive to contain the following code.

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/ESP32_S2_WiFi_Tests/CPy_Native_WiFi_Test/settings.toml

This file should contain a series of Python variables, each assigned to a string. Each variable should describe what it represents (say&nbsp;`wifi_ssid`), followed by an **=&nbsp;** (equals sign), followed by the data in the form of a Python string (such as `"my-wifi-password"` including the quote marks).

**At a minimum you'll need to add/update your WiFi SSID and WiFi password, so do that now!**

As you make projects you may need more tokens and keys, just add them one line at a time. See for example other tokens such as one for accessing GitHub or the Hackaday API. Other non-secret data like your timezone can also go here.

For the correct time zone string, look at&nbsp;[http://worldtimeapi.org/timezones](http://worldtimeapi.org/timezones)&nbsp;and remember that if your city is not listed, look for a city in the same time zone, for example Boston, New York, Philadelphia, Washington DC, and Miami are all on the same time as New York.

Of course, don't share your **settings.toml** - keep that out of GitHub, Discord or other project-sharing sites.

Warning: 

If you connect to the serial console, you should see something like the following:

![](https://cdn-learn.adafruit.com/assets/assets/000/097/014/medium800/adafruit_products_1__screen__Users_brentrubell__screen_.png?1605218222)

In order, the example code...

Checks the ESP32's MAC address.

```python
print(f"My MAC address: {[hex(i) for i in wifi.radio.mac_address]}")
```

Performs a scan of all access points and prints out the access point's name (SSID), signal strength (RSSI), and channel.

```python
print("Available WiFi networks:")
for network in wifi.radio.start_scanning_networks():
    print("\t%s\t\tRSSI: %d\tChannel: %d" % (str(network.ssid, "utf-8"),
                                             network.rssi, network.channel))
wifi.radio.stop_scanning_networks()
```

Connects to the access point you defined in the **settings.toml** file, and prints out its local IP address.

```python
print(f"Connecting to {os.getenv('WIFI_SSID')}")
wifi.radio.connect(os.getenv("WIFI_SSID"), os.getenv("WIFI_PASSWORD"))
print(f"Connected to {os.getenv('WIFI_SSID')}")
print(f"My IP address: {wifi.radio.ipv4_address}")
```

Attempts to ping a Google DNS server to test connectivity. If a ping fails, it returns `None`. Initial pings can sometimes fail for various reasons. So, if the initial ping is successful (`is not None`), it will print the echo speed in ms. If the initial ping fails, it will try one more time to ping, and then print the returned value. If the second ping fails, it will result in `"Ping google.com: None ms"` being printed to the serial console. Failure to ping does not always indicate a lack of connectivity, so the code will continue to run.

```python
ping_ip = ipaddress.IPv4Address("8.8.8.8")
ping = wifi.radio.ping(ip=ping_ip) * 1000
if ping is not None:
    print(f"Ping google.com: {ping} ms")
else:
    ping = wifi.radio.ping(ip=ping_ip)
    print(f"Ping google.com: {ping} ms")
```

The code creates a socketpool using the wifi radio's available sockets. This is performed so we don't need to re-use sockets. Then, it initializes a a new instance of the [requests](http://docs.python-requests.org/en/master/) interface - which makes getting data from the internet _really really easy._

```python
pool = socketpool.SocketPool(wifi.radio)
requests = adafruit_requests.Session(pool, ssl.create_default_context())
```

To read in plain-text from a web URL, call `requests.get` - you may pass in either a http, or a http **s** url for SSL connectivity.&nbsp;

```python
print(f"Fetching text from {TEXT_URL}")
response = requests.get(TEXT_URL)
print("-" * 40)
print(response.text)
print("-" * 40)
```

Requests can also display a JSON-formatted response from a web URL using a call to `requests.get`.&nbsp;

```python
print(f"Fetching json from {JSON_QUOTES_URL}")
response = requests.get(JSON_QUOTES_URL)
print("-" * 40)
print(response.json())
print("-" * 40)
```

Finally, you can fetch and parse a JSON URL using `requests.get`. This code snippet obtains the `stargazers_count` field from a call to the GitHub API.

```python
print(f"Fetching and parsing json from {JSON_STARS_URL}")
response = requests.get(JSON_STARS_URL)
print("-" * 40)
print(f"CircuitPython GitHub Stars: {response.json()['stargazers_count']}")
print("-" * 40)
```

OK you now have your ESP32 board set up with a proper **settings.toml** file and can connect over the Internet. If not, check that your **settings.toml** file has the right SSID and password and retrace your steps until you get the Internet connectivity working!

## IPv6 Networking

Starting in CircuitPython 9.2, IPv6 networking is available on most Espressif wifi boards. Socket-using libraries like **adafruit\_requests** and **adafruit\_ntp** will need to be updated to use the new APIs and for now can only connect to services on IPv4.

### IPv6 connectivity & privacy

IPv6 addresses are divided into many special kinds, and many of those kinds (like those starting with&nbsp; **FC** , **FD** , **FE** ) are private or local; Addresses starting with other prefixes like&nbsp; **2002:** and **2001:** are globally routable. In 2024, far from all ISPs and home networks support IPv6 internet connectivity. For more info consult resources like [Wikipedia](https://en.wikipedia.org/wiki/IPv6_address#Local_addresses). If you're interested in global IPv6 connectivity you can use services like [Hurricane Electric](https://www.he.net/) to create an "IPv6 tunnel" (free as of 2024, but requires expertise and a compatible router or host computer to set up)

It's also important to be aware that, as currently implemented by Espressif, there are privacy concerns especially when these devices operate on the global IPv6 network: The device's unique identifier (its EUI-64 or MAC address) is used by default as part of its IPv6 address. This means that the device identity can be tracked across multiple networks by any service it connects to.

### Enable IPv6 networking

Due to the privacy consideration, IPv6 networking is not automatically enabled. Instead, it must be explicitly enabled by a call to `start_dhcp_client` with the `ipv6=True` argument specified:

```python
wifi.start_dhcp_client(ipv6=True)
```

### Check IP addresses

The read-only&nbsp;`addresses` property of the `wifi.radio` object holds all addresses, including IPv4 and IPv6 addresses:

```python
&gt;&gt;&gt; wifi.radio.addresses
('FE80::7EDF:A1FF:FE00:518C', 'FD5F:3F5C:FE50:0:7EDF:A1FF:FE00:518C', '10.0.3.96')
```

The `wifi.radio.dns` servers can be IPv4 or IPv6:

```python
&gt;&gt;&gt; wifi.radio.dns
('FD5F:3F5C:FE50::1',)
&gt;&gt;&gt; wifi.radio.dns = ("1.1.1.1",)
&gt;&gt;&gt; wifi.radio.dns
('1.1.1.1',)
```

### Ping v6 networks

`wifi.radio.ping` accepts v6 addresses and names:

```python
&gt;&gt;&gt; wifi.radio.ping("google.com")
0.043
&gt;&gt;&gt; wifi.radio.ping("ipv6.google.com")
0.048
```

### Create & use IPv6 sockets

Use the address family `socket.AF_INET6`. After the socket is created, use methods like `connect`, `send`, `recfrom_into`, etc just like for IPv4 sockets. This code snippet shows communicating with a private-network NTP server; this IPv6 address will not work on your network:

```python
&gt;&gt;&gt; ntp_addr = ("fd5f:3f5c:fe50::20e", 123)
&gt;&gt;&gt; PACKET_SIZE = 48
&gt;&gt;&gt; 
&gt;&gt;&gt; buf = bytearray(PACKET_SIZE)
&gt;&gt;&gt; with socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) as s:
...     s.settimeout(1)
...     buf[0] = 0b0010_0011
...     s.sendto(buf, ntp_addr)
...     print(s.recvfrom_into(buf))
...     print(buf)
... 
48
(48, ('fd5f:3f5c:fe50::20e', 123))
bytearray(b'$\x01\x03\xeb\x00\x00\x00\x00\x00\x00\x00GGPS\x00\xeaA0h\x07s;\xc0\x00\x00\x00\x00\x00\x00\x00\x00\xeaA0n\xeb4\x82-\xeaA0n\xebAU\xb1')
```

# Adafruit MatrixPortal S3

## MatrixPortal Library Overview

The MatrixPortal library was inspired by the PyPortal library, but a slightly different approach was taken. Rather than having everything in a single module, it was divided into layers. The reason for having different layers is you can use lower layers if you want more control and better memory usage.

The main library now piggyback's on top of the base library. The base library was named PortalBase which is split up into 3 components. The main base, the GraphicsBase, and the NetworkBase. In the diagram, you can see these components represented in blue.

[We also have a library for lower-level control of just the RGB Matrix](https://learn.adafruit.com/rgb-led-matrices-matrix-panels-with-circuitpython), but it doesn't have integrated WiFi access so we recommend using the MatrixPortal library.

Here is the way it is logically laid out with dependencies. The MatrixPortal library is comprised of the top layer, the Network and Graphics layers, and the WiFi and Matrix layers in the diagram.

![](https://cdn-learn.adafruit.com/assets/assets/000/098/460/medium800/led_matrices_MatrixPortal_Hierarchy.png?1609871487)

There are two main branches of dependencies related to Network Functionality and Graphics functionality. The **MatrixPortal** library ties them both together and allows easier coding, but at the cost of more memory usage and less control. We'll go through each of the classes starting from the bottom and working our way up the diagram starting with the Network branch.

## Network Branch

The network branch contains all of the functionality related to connecting to the internet and retrieving data. You will want to use this branch if your project need to retrieve any data that is not stored on the device itself.

### WiFi Module

The WiFi module is responsible for initializing the hardware libraries, controlling the status NeoPixel colors, and initializing the WiFi manager. You would want to use this library if you only wanted to handle the automatic initialization of hardware and connection to WiFi and didn't need any other functionality.

### Network Module

The network module has many convenience functions for making network calls. It handles a lot of things from automatically establishing the connection to getting the time from the internet, to getting data at certain URLs. This is one of the largest of the modules as there is a lot of functionality packed into this.

## Graphics Branch

This branch is a lot lighter than the Network Branch because so much of the functionality is built into CircuitPython and displayio.

### Matrix Module

The matrix module is responsible for detecting and initializing the matrix through the CircuitPython rgbmatrix and framebufferio modules. It currently supports the MatrixPortal M4 and Metro M4 with RGB Matrix Shield. If you just wanted to initialize the matrix, you could use this module. If you would like to go lower level than this and use the rgbmatrix and framebufferio libraries directly, be sure to check out the guide [RGB LED Matrices with CircuitPython](https://learn.adafruit.com/rgb-led-matrices-matrix-panels-with-circuitpython).

### Graphics Module

This module will initialize the Matrix through the matrix module. The main purpose of this module was to add any graphics convenience functions in such as displaying a background easily.

## MatrixPortal Module

The MatrixPortal module is top level module and will handle initializing everything below it. Using this module is very similar to using the PyPortal library. The main differences are:

- Text labels are added after the module is initialized.
- Text labels can either be scrolling or static.
- There are more Adafruit IO functions

## Library Demos

The MatrixPortal library has been used in a number of projects. Here are a few of them with guides available.

- [RGB Matrix Automatic YouTube ON AIR Sign](https://learn.adafruit.com/rgb-matrix-automatic-youtube-on-air-sign)
- [Network Connected RGB Matrix Clock](https://learn.adafruit.com/network-connected-metro-rgb-matrix-clock)
- [Weather Display Matrix](https://learn.adafruit.com/weather-display-matrix)
- [Custom Scrolling Quote Board Matrix Display](https://learn.adafruit.com/aio-quote-board-matrix-display)
- [Halloween Countdown Display Matrix](https://learn.adafruit.com/halloween-countdown-display-matrix)
- [Moon Phase Clock for Adafruit Matrix Portal](https://learn.adafruit.com/moon-phase-clock-for-adafruit-matrixportal)

# Adafruit MatrixPortal S3

## CircuitPython Pins and Modules

CircuitPython is designed to run on microcontrollers and allows you to interface with all kinds of sensors, inputs and other hardware peripherals. There are tons of guides showing how to wire up a circuit, and use CircuitPython to, for example, read data from a sensor, or detect a button press. Most CircuitPython code includes hardware setup which requires various modules, such as `board` or `digitalio`. You import these modules and then use them in your code. How does CircuitPython know to look for hardware in the specific place you connected it, and where do these modules come from?

This page explains both. You'll learn how CircuitPython finds the pins on your microcontroller board, including how to find the available pins for your board and what each pin is named. You'll also learn about the modules built into CircuitPython, including how to find all the modules available for your board.

# CircuitPython Pins

When using hardware peripherals with a CircuitPython compatible microcontroller, you'll almost certainly be utilising pins. This section will cover how to access your board's pins using CircuitPython, how to discover what pins and board-specific objects are available in CircuitPython for your board, how to use the board-specific objects, and how to determine all available pin names for a given pin on your board.

## `import board`

When you're using any kind of hardware peripherals wired up to your microcontroller board, the import list in your code will include `import board`. The `board` module is built into CircuitPython, and is used to provide access to a series of board-specific objects, including pins. Take a look at your microcontroller board. You'll notice that next to the pins are pin labels. You can always access a pin by its pin label. However, there are almost always multiple names for a given pin.

To see all the available board-specific objects and pins for your board, enter the REPL (`>>>`) and run the following commands:

```python
import board
dir(board)
```

Here is the output for the QT Py SAMD21. **You may have a different board, and this list will vary, based on the board.**

![](https://cdn-learn.adafruit.com/assets/assets/000/099/189/medium800/circuitpython_dir-board-output-qt-py.png?1612291495)

The following pins have labels on the physical QT Py SAMD21 board: A0, A1, A2, A3, SDA, SCL, TX, RX, SCK, MISO, and MOSI. You see that there are many more entries available in `board` than the labels on the QT Py.

You can use the pin names on the physical board, regardless of whether they seem to be specific to a certain protocol.

For example, you do not _have_ to use the SDA pin for I2C - you can use it for a button or LED.

On the flip side, there may be multiple names for one pin. For example, on the QT Py SAMD21, pin **A0** is labeled on the physical board silkscreen, but it is available in CircuitPython as both `A0` and `D0`. For more information on finding all the names for a given pin, see the [What Are All the Available Pin Names?](https://learn.adafruit.com/circuitpython-essentials/circuitpython-pins-and-modules#what-are-all-the-available-names-3082670-14) section below.

The results of `dir(board)` for CircuitPython compatible boards will look similar to the results for the QT Py SAMD21 in terms of the pin names, e.g. A0, D0, etc. However, some boards, for example, the Metro ESP32-S2, have different styled pin names. Here is the output for the Metro ESP32-S2.

![](https://cdn-learn.adafruit.com/assets/assets/000/099/215/medium800/circuitpython_Essentials_dir_board_Metro_ESP32-S2.png?1612374794)

Note that most of the pins are named in an IO# style, such as **IO1** and **IO2**. Those pins on the physical board are labeled only with a number, so an easy way to know how to access them in CircuitPython, is to run those commands in the REPL and find the pin naming scheme.

Info: 

## I2C, SPI, and UART

You'll also see there are often (_ **but not always!** _) three special board-specific objects included: `I2C`, `SPI`, and `UART` - each one is for the default pin-set used for each of the three common protocol busses they are named for. These are called _singletons_.

What's a singleton? When you create an object in CircuitPython, you are _instantiating_ ('creating') it. Instantiating an object means you are creating an instance of the object with the unique values that are provided, or "passed", to it.

For example, When you instantiate an I2C object using the `busio` module, it expects two pins: clock and data, typically SCL and SDA. It often looks like this:

```python
i2c = busio.I2C(board.SCL, board.SDA)
```

Then, you pass the I2C object to a driver for the hardware you're using. For example, if you were using the TSL2591 light sensor and its CircuitPython library, the next line of code would be:

```python
tsl2591 = adafruit_tsl2591.TSL2591(i2c)
```

However, CircuitPython makes this simpler by including the `I2C` singleton in the `board` module. Instead of the two lines of code above, you simply provide the singleton as the I2C object. So if you were using the TSL2591 and its CircuitPython library, the two above lines of code would be replaced with:

```python
tsl2591 = adafruit_tsl2591.TSL2591(board.I2C())
```

Info: 

This eliminates the need for the `busio` module, and simplifies the code. Behind the scenes, the `board.I2C()`&nbsp; object is instantiated when you call it, but not before, and on subsequent calls, it returns the same object. Basically, it does not create an object until you need it, and provides the same object every time you need it. You can call `board.I2C()` as many times as you like, and it will always return the same object.

Info: 

## What Are All the Available Names?

Many pins on CircuitPython compatible microcontroller boards have multiple names, however, typically, there's only one name labeled on the physical board. So how do you find out what the other available pin names are? Simple, with the following script! Each line printed out to the serial console contains the set of names for a particular pin.

On a microcontroller board running CircuitPython, first, connect to the serial console.

In the example below, click the **Download Project Bundle** button below to download the necessary libraries and the **code.py** file in a zip file. Extract the contents of the zip file, open the directory **CircuitPython\_Essentials/Pin\_Map\_Script/** and then click on the directory that matches the version of CircuitPython you're using and copy the contents of that directory to your **CIRCUITPY** drive.

Your **CIRCUITPY** drive should now look similar to the following image:

![CIRCUITPY](https://adafruit.github.io/Adafruit_Learning_System_Guides/CircuitPython_Essentials_Pin_Map_Script.png )

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/CircuitPython_Essentials/Pin_Map_Script/code.py

Here is the result when this script is run on QT Py SAMD21:

![](https://cdn-learn.adafruit.com/assets/assets/000/122/945/medium800/leds_CPE_pin_map_script_QT_Py_M0.png?1690233285)

Each line represents a single pin. Find the line containing the pin name that's labeled on the physical board, and you'll find the other names available for that pin. For example, the first pin on the board is labeled **A0**. The first line in the output is `board.A0 board.D0 (PA02)`. This means that you can access pin **A0** in CircuitPython using both `board.A0` and `board.D0`.

The pins in parentheses are the microcontroller pin names. See the next section for more info on those.

You'll notice there are two "pins" that aren't labeled on the board but appear in the list: `board.NEOPIXEL` and `board.NEOPIXEL_POWER`. Many boards have several of these special pins that give you access to built-in board hardware, such as an LED or an on-board sensor. The QT Py SAMD21 only has one on-board extra piece of hardware, a NeoPixel LED, so there's only the one available in the list. But you can also control whether or not power is applied to the NeoPixel, so there's a separate pin for that.

That's all there is to figuring out the available names for a pin on a compatible microcontroller board in CircuitPython!

## Microcontroller Pin Names

The pin names available to you in the CircuitPython `board` module are not the same as the names of the pins on the microcontroller itself. The board pin names are aliases to the microcontroller pin names. If you look at the datasheet for your microcontroller, you'll likely find a pinout with a series of pin names, such as "PA18" or "GPIO5". If you want to get to the actual microcontroller pin name in CircuitPython, you'll need the `microcontroller.pin` module. As with `board`, you can run `dir(microcontroller.pin)` in the REPL to receive a list of the microcontroller pin names.

![](https://cdn-learn.adafruit.com/assets/assets/000/099/290/medium800/circuitpython_Essentials_microcontroller_pin_names.png?1612822277 Microcontroller pin names for QT Py SAMD21.)

# CircuitPython Built-In Modules

There is a set of modules used in most CircuitPython programs. One or more of these modules is always used in projects involving hardware. Often hardware requires installing a separate library from the Adafruit CircuitPython Bundle. But, if you try to find `board` or `digitalio` in the same bundle, you'll come up lacking. So, where do these modules come from? They're built into CircuitPython! You can find an comprehensive list of built-in CircuitPython modules and the technical details of their functionality from CircuitPython [here](https://circuitpython.readthedocs.io/en/latest/shared-bindings/index.html#modules) and the Python-like modules included [here](https://circuitpython.readthedocs.io/en/latest/docs/library/index.html). However, **not every module is available for every board** due to size constraints or hardware limitations. How do you find out what modules are available for your board?

There are two options for this. You can check the [support matrix](https://circuitpython.readthedocs.io/en/latest/shared-bindings/support_matrix.html#), and search for your board by name. Or, you can use the REPL.

Plug in your board, connect to the serial console and enter the REPL. Type the following command.

```python
help("modules")
```

![](https://cdn-learn.adafruit.com/assets/assets/000/099/208/medium800/circuitpython_Essentials_help_modules_QT_Py.png?1612372532 help("modules") results for QT Py)

That's it! You now know two ways to find all of the modules built into CircuitPython for your compatible microcontroller board.

# Adafruit MatrixPortal S3

## PortalBase Library Docs

# Adafruit MatrixPortal S3

## MatrixPortal Library Docs

# Adafruit MatrixPortal S3

## CircuitPython RGB Matrix Library

# Adafruit MatrixPortal S3

## Arduino IDE Setup

Warning: 

The first thing you will need to do is to download the latest release of the Arduino IDE. You will need to&nbsp;be using&nbsp; **version 1.8** &nbsp;or higher for this guide

[Arduino IDE Download](http://www.arduino.cc/en/Main/Software)
To use the ESP32-S2/S3 with Arduino, you'll need to follow the steps below for your operating system. You can also [check out the Espressif Arduino repository for the most up to date details on how to install it](https://github.com/espressif/arduino-esp32#using-through-arduino-ide).

After you have downloaded and installed **&nbsp;the latest version of Arduino IDE** , you will need to start the IDE&nbsp;and navigate to&nbsp;the&nbsp; **Preferences** &nbsp;menu. You can access it from the&nbsp; **File** &nbsp;menu in&nbsp;_Windows_&nbsp;or&nbsp;_Linux_, or the&nbsp; **Arduino** &nbsp;menu on&nbsp;_OS X_.

![](https://cdn-learn.adafruit.com/assets/assets/000/101/639/medium800/esp32_s2_arduino_ide_setup_flora_prefs.png?1618870383)

A dialog will pop up just like the one shown below.

![](https://cdn-learn.adafruit.com/assets/assets/000/101/640/medium800/esp32_s2_arduino_ide_setup_flora_Screen_Shot_2015-05-07_at_9.07.21_AM.png?1618870405)

We will be adding a URL to the new&nbsp; **Additional Boards Manager URLs** &nbsp;option. The list of URLs is comma separated, and&nbsp;_you will only have to add each&nbsp;URL once._&nbsp;New Adafruit boards and updates to existing boards&nbsp;will automatically be picked up&nbsp;by the Board Manager each time&nbsp;it is opened. The URLs point to index files that the Board Manager uses to build the list of available & installed boards.

To find the most up to date list of URLs you can&nbsp;add, you can visit the list of&nbsp;[third party board URLs on the Arduino IDE wiki](https://github.com/arduino/Arduino/wiki/Unofficial-list-of-3rd-party-boards-support-urls#list-of-3rd-party-boards-support-urls). We will only need to add one URL to the IDE in this example, but&nbsp;_ **you can add multiple URLS by separating them with commas** _. Copy and paste the link below into the&nbsp; **Additional Boards Manager URLs** &nbsp;option in the Arduino IDE preferences.

`https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json`

![](https://cdn-learn.adafruit.com/assets/assets/000/125/110/medium800/esp32_s2_s3_arduino_ide_setup_Screenshot_2023-10-12_at_11.05.03_AM.png?1697133995)

If you're an advanced hacker and want the 'bleeding edge' release that may have fixes (or bugs!) you can check out the dev url instead:

`https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json`

If you have multiple boards you want to support, say ESP8266 and Adafruit, have both URLs in the text box separated by a comma (,)

Once done click&nbsp; **OK** &nbsp;to save the new preference settings.

The next step is to actually install the Board Support Package (BSP). Go to the **Tools → Board → Board Manager** &nbsp;submenu. A dialog should come up with various BSPs. Search for **esp32**. Choose the latest version, which may be later than the version shown in the screenshot below.

![](https://cdn-learn.adafruit.com/assets/assets/000/107/162/medium800/esp32_s2_arduino_ide_setup_Screen_Shot_2021-12-09_at_9.58.40_AM.png?1639072797)

Click the **Install** button and wait for it to finish. Once it is finished, you can close the dialog.

In the **Tools → Board** submenu you should see **ESP32 Arduino** and in that dropdown it should contain the ESP32 boards along with all the latest ESP32-S2/S3 boards.

Look for the board called Adafruit MatrixPortal ESP32-S3.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/686/medium800/led_matrices_Arduino_Board_Select.png?1689702908)

## Manually Resetting ESP32-S3 Boards

Due to an issue in the Espressif code base, boards with an ESP32-S3 need to be manually reset after uploading code from the Arduino IDE. After your code has been uploaded to the ESP32-S3, press the reset button. After pressing the reset button, your code will begin running.

For additional information, you can track&nbsp;[the issue](https://github.com/espressif/arduino-esp32/issues/6762)&nbsp;on GitHub in the arduino-esp32 repository.

Warning: 

# Adafruit MatrixPortal S3

## Using with Arduino IDE

## Blink

Now you can upload your first blink sketch!

Plug in the ESP32-S2/S3 board and wait for it to be recognized by the OS (just takes a few seconds).

## Select ESP32-S2/S3 Board in Arduino IDE
On the Arduino IDE, **click** :

**Tools -\> Board -\> ESP32 Arduino -\> Your Adafruit ESP32-S2/S3 board&nbsp;**

The screenshot shows Metro S2 but you may have a different board. Make sure the name matches the exact product you purchased. If you don't see your board, make sure you have the latest version of the ESP32 board support package

![adafruit_products_board_esp32s2.png](https://cdn-learn.adafruit.com/assets/assets/000/096/985/medium640/adafruit_products_board_esp32s2.png?1605114060)

![adafruit_products_board_manager.png](https://cdn-learn.adafruit.com/assets/assets/000/096/986/medium640/adafruit_products_board_manager.png?1605114097)

## Launch ESP32-S2/S3 ROM Bootloader
Warning: 

Before we upload a sketch, [place your ESP32-S2/S3 board into ROM bootloader mode](https://learn.adafruit.com/adafruit-metro-esp32-s2/rom-bootloader#enter-rom-bootloader-mode-3076820-1).

Look for the Reset button and a second DFU / BOOT0 button

**HOLD down the DFU/Boot0 button while you click Reset. Then release DFU/Boot0 button**

The GIF shows a Metro S2 but your board may look different. It will still have BOOT and Reset buttons somewhere

![adafruit_products_Metro_ESP32-S2_bootloader.gif](https://cdn-learn.adafruit.com/assets/assets/000/096/987/medium640thumb/adafruit_products_Metro_ESP32-S2_bootloader.jpg?1605219913)

It should appear under **Tools -\> Port** as **ESP32-S2/S3 Dev Module**.&nbsp;

![](https://cdn-learn.adafruit.com/assets/assets/000/096/989/medium800/adafruit_products_Screen_Shot_2020-11-11_at_12_07_35_PM.png?1605114516)

Info: In the **Port** menu, select the serial port that is labelled "ESP32S2 Dev Module" or "ESP32S3 Dev Module".

(Note this is the **Port** menu, not the **Board** menu. In the **Board** menu choose the exact board you are using.)

## Load Blink Sketch

Now open up this Blink example in a new sketch window

```python
// the setup function runs once when you press reset or power the board
void setup() {
  // initialize built in LED pin as an output.
  pinMode(LED_BUILTIN, OUTPUT);
  // initialize USB serial converter so we have a port created
  Serial.begin();
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);              // wait for a second
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);              // wait for a second
}
```

Info: 

And click upload! After uploading, you may see something like this:

And click upload! After uploading, you may see something like this, warning you that we could not get out of reset.

This is normal! **Press the RESET button on your board to launch the sketch**

![adafruit_products_Blink___Arduino_1_8_13_and_Using_with_Arduino_IDE___Adafruit_Metro_M4_Express_AirLift__WiFi____Adafruit_Learning_System.png](https://cdn-learn.adafruit.com/assets/assets/000/096/990/medium640/adafruit_products_Blink___Arduino_1_8_13_and_Using_with_Arduino_IDE___Adafruit_Metro_M4_Express_AirLift__WiFi____Adafruit_Learning_System.png?1605220031)

That's it, you will be able to see the red LED blink. You will also see a new serial port created.

You may call `Serial.begin();` in your sketch to create the serial port so don't forget it, it is not required for other Arduinos or previous ESP boards!

![](https://cdn-learn.adafruit.com/assets/assets/000/097/021/medium800/adafruit_products_image.png?1605221220)

You can now select the **new serial port** name which will be different than the bootloader serial port. Arduino IDE will try to use auto-reset to automatically put the board into bootloader mode when you ask it to upload new code

**If you ever DON'T see a serial port, or something is not working out with upload you can always manually enter bootloader mode:**

- Reset board into ROM bootloader with DFU/BOOT0 + Reset buttons
- Select the ESP32S2/S3 Dev Board ROM bootloader serial port in Tools-\>Port menu
- Upload sketch
- Click reset button to launch code

# Adafruit MatrixPortal S3

## Arduino Blink

The first and most basic program you can upload to your Arduino is the classic Blink sketch. This takes something on the board and makes it, well, blink! On and off. It's a great way to make sure everything is working and you're uploading your sketch to the right board and right configuration.

When all else fails, you can always come back to Blink!

![](https://cdn-learn.adafruit.com/assets/assets/000/122/798/medium800thumb/led_matrices_blink.jpg?1689784523)

# Pre-Flight Check: Get Arduino IDE & Hardware Set Up

This lesson assumes you have Arduino IDE set up. This is a generalized checklist, some elements may not apply to your hardware. If you haven't yet, check the previous steps in the guide to make sure you:

- **Install the very latest Arduino IDE for Desktop** (not all boards are supported by the Web IDE so we don't recommend it).
- **Install any board support packages (BSP) required for your hardware.** Some boards are built in defaults on the IDE, but lots are not! You may need to install plug-in support which is called the BSP.
- **Get a Data/Sync USB cable for connecting your hardware.** A _significant_ amount of problems folks have stem from not having a USB cable with data pins. Yes, these cursed cables roam the land, making your life hard. If you find a USB cable that doesn't work for data/sync, _throw it away immediately_! There is no need to keep it around, cables are very inexpensive these days.
- **Install any drivers required** - If you have a board with a FTDI or CP210x chip, you may need to get separate drivers. If your board has native USB, it probably doesn't need anything. After installing, reboot to make sure the driver sinks in.
- **Connect the board to your computer.** If your board has a power LED, make sure its lit. Is there a power switch? Make sure its turned On!

# Start up Arduino IDE and Select Board/Port

OK now you are prepared! Open the Arduino IDE on your computer. Now you have to tell the IDE what board you are using, and how you want to connect to it.

In the IDE find the **Tools** menu. You will use this to select the board. If you switch boards, you _must switch the selection!_ So always double-check before you upload code in a new session.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/800/medium800/led_matrices_Arduino_Board_Select.png?1689785669)

![](https://cdn-learn.adafruit.com/assets/assets/000/122/801/medium800/led_matrices_Screenshot_2023-07-19_at_9.52.32_AM.png?1689785709)

# New Blink Sketch

OK lets make a new blink sketch! From the **File** menu, select **New**

![](https://cdn-learn.adafruit.com/assets/assets/000/107/498/medium800/blink__image.png?1640454932)

Then in the new window, copy and paste this text:

```auto
int led = LED_BUILTIN;

void setup() {
  // Some boards work best if we also make a serial connection
  Serial.begin(115200);

  // set LED to be an output pin
  pinMode(led, OUTPUT);
}

void loop() {
  // Say hi!
  Serial.println("Hello!");
  
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(500);                // wait for a half second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(500);                // wait for a half second
}
```

Info: 

One note you'll see is that we reference the LED with the constant `LED_BUILTIN` rather than a number. That's because, historically, the built in LED was on pin 13 for Arduinos. But in the decades since, boards don't always have a pin 13, or maybe it could not be used for an LED. So the LED could have moved to another pin. It's best to use `LED_BUILTIN` so you don't get the pin number confused!

Info: 

# Verify (Compile) Sketch

OK now you can click the Verify button to convert the sketch into binary data to be uploaded to the board.

Note that Verifying a sketch is the same as Compiling a sketch - so we will use the words interchangeably

![](https://cdn-learn.adafruit.com/assets/assets/000/107/503/medium800/blink__image.png?1640455847)

During verification/compilation, the computer will do a bunch of work to collect all the libraries and code and the results will appear in the bottom window of the IDE.

![](https://cdn-learn.adafruit.com/assets/assets/000/140/268/medium800/arduino_blink_Untitled22.png?1759872469)

If something went wrong with compilation, you will get red warning/error text in the bottom window letting you know what the error was. It will also highlight the line with an error.

For example, here I had the wrong board selected - and the selected board does not have a built in LED!

![](https://cdn-learn.adafruit.com/assets/assets/000/107/501/medium800/blink__image.png?1640455513)

Here's another common error, in my haste I forgot to add a `;` at the end of a line. The compiler warns me that it's looking for one - note that the error is actually a few lines up!

![](https://cdn-learn.adafruit.com/assets/assets/000/107/502/medium800/blink__image.png?1640455650)

Info: 

On success you will see something like this white text output and the message **Done compiling.** in the message area.

![](https://cdn-learn.adafruit.com/assets/assets/000/107/504/medium800/blink__image.png?1640455995)

# Upload Sketch

Once the code is verified/compiling cleanly you can upload it to your board. Click the **Upload** button.

Warning: 

![](https://cdn-learn.adafruit.com/assets/assets/000/107/499/medium800/blink__image.png?1640455265)

The IDE will try to compile the sketch again for good measure, then it will try to connect to the board and upload a the file.

**This is actually one of the hardest parts for beginners because it's where a lot of things can go wrong.**

However, lets start with what it looks like on success! Here's what your board upload process looks like when it goes right:

![](https://cdn-learn.adafruit.com/assets/assets/000/122/802/medium800/led_matrices_Upload_Success.png?1689785910)

Often times you will get a warning like this, which is kind of vague:

`No device found on COM66` (or whatever port is selected)  
`An error occurred while uploading the sketch`

![](https://cdn-learn.adafruit.com/assets/assets/000/107/505/medium800/blink__image.png?1640456582)

This could be a few things.

**First up, check again that you have the correct board selected!** Many electronics boards have very similar names or look, and often times folks grab a board different from what they thought.

If you're positive the right board is selected, we recommend the next step is to put the board into manual bootloading mode.

## Native USB and manual bootloading

Historically, microcontroller boards contained two chips: the main micro chip (say, ATmega328 or ESP8266 or ESP32) and a separate chip for USB interface that would be used for bootloading (a CH430, FT232, CP210x, etc). With these older designs, the microcontroller is put into a bootloading state for uploading code by the separate chip. It allows for easier uploading but is more expensive as two chips are needed, and also the microcontroller can't act like a keyboard or disk drive.

Modern chips often have 'native' USB - that means that there is no separate chip for USB interface. It's all in one! Great for cost savings, simplicity of design, reduced size and more control. However, it means the chip must be self-aware enough to be able to put _itself_ into bootload/upload mode on its own. That's fine 99% of the time but is very likely you will at some point get the board into an odd state that makes it too confused to bootload.

Warning: 

Before continuing we _really, really_ suggest turning on **Verbose Upload** messages, it will help in this process because you will be able to see what the IDE is trying to do. It's a checkbox in the **Preferences** menu.

![](https://cdn-learn.adafruit.com/assets/assets/000/107/507/medium800/blink__image.png?1640457254)

## Enter Manual Bootload Mode

OK now you know it's probably time to try manual bootloading. No problem! Here is how you do that for this board:

 **Before you start, make sure your MatrixPortal S3 is plugged into USB port to your computer using a data/sync cable.** &nbsp;Charge-only cables will not work!

To enter the bootloader:

1. **Press and hold the Boot button down.** &nbsp;Don't let go of it yet!
2. **Press and release the Reset button.** &nbsp;You should still have the Boot button pressed while you do this.
3. **Now you can release the Boot button.**

No USB drive will appear when you've entered the ROM bootloader. This is normal!

Once you are in manual bootload mode, go to the Tools menu, and make sure you have selected the bootloader serial port. **It is almost certain that the serial port has changed now that the bootloader is enabled**

![](https://cdn-learn.adafruit.com/assets/assets/000/122/803/medium800/led_matrices_Screenshot_2023-07-19_at_10.00.24_AM.png?1689786082)

Now you can try uploading again!

![](https://cdn-learn.adafruit.com/assets/assets/000/107/506/medium800/blink__image.png?1640457185)

Info: 

This time, you should have success!

After uploading this way, be sure to **click the reset button** - it sort of makes sure that the board got a good reset and will come back to life nicely.

Warning: 

It's also a good idea to try to re-upload the sketch again now that you've performed a manual bootload to get the chip into a good state. It should perform an auto-reset the second time, so you don't have to manually bootload again.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/804/medium800/led_matrices_Screenshot_2023-07-19_at_10.02.28_AM.png?1689786180)

Once you've finished the re-upload, don't forget to press RESET and then select the old Port again!

# Finally, a Blink!

OK it was a journey but now we're here and you can enjoy your blinking LED. Next up, try to change the delay between blinks and re-upload. It's a good way to make sure your upload process is smooth and practiced.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/799/medium800thumb/led_matrices_blink.jpg?1689784563)

# Adafruit MatrixPortal S3

## I2C Scan Test

A lot of sensors, displays, and devices can connect over I2C. I2C is a 2-wire 'bus' that allows multiple devices to all connect on one set of pins so it's very convenient for wiring!

When using your board, you'll probably want to connect up I2C devices, and it can be a little tricky the first time. The best way to debug I2C is go through a checklist and then perform an I2C scan

# Common I2C Connectivity Issues

- **Have you connected four wires (at a minimum) for each I2C device?** Power the device with whatever is the logic level of your microcontroller board (probably 3.3V), then a ground wire, and a SCL clock wire, and and a SDA data wire.
- **If you're using a STEMMA QT board - check if the power LED is lit.** It's usually a green LED to the left side of the board.
- **Does the STEMMA QT/I2C port have switchable power or pullups?** To reduce power, some boards have the ability to cut power to I2C devices or the pullup resistors. Check the documentation if you have to do something special to turn on the power or pullups.
- **If you are using a DIY I2C device, do you have pullup resistors?** Many boards do _not_ have pullup resistors built in and they are _required!_ We suggest any common 2.2K to 10K resistors. You'll need two: one each connects from SDA to positive power, and SCL to positive power. Again, positive power (a.k.a VCC, VDD or V+) is often 3.3V
- **Do you have an address collision?** You can only have _one_ board per address. So you cannot, say, connect two AHT20's to one I2C port because they have the same address and will interfere. Check the sensor or documentation for the address. Sometimes there are ways to adjust the address.
- **Does your board have multiple I2C ports?** Historically, boards only came with one. But nowadays you can have two or even three! This can help solve the "hey, but what if I want two devices with the same address" problem: just put one on each bus.
- **Are you hot-plugging devices?** I2C does _not_ support dynamic re-connection, you cannot connect and disconnect sensors as you please. They should all be connected on boot and not change. ([Only exception is if you're using a hot-plug assistant but that'll cost you](https://www.adafruit.com/product/5159)).
- **Are you keeping the total bus length reasonable?** I2C was designed for maybe 6" max length. We like to push that with plug-n-play cables, but really please keep them as short as possible! ([Only exception is if you're using an active bus extender](https://www.adafruit.com/product/4756)).

## MatrixPortal S3 I2C Setup

The MatrixPortal S3 only has one I2C port,&nbsp;`Wire`, that is on the STEMMA QT connector.

It does have a built in LIS3DH accelerometer that is listening on address&nbsp;`0x19`, so that address cannot be used by other devices.

# Perform an I2C scan!

### Install TestBed Library

To scan I2C, the Adafruit TestBed library is used. This library and example just makes the scan a little easier to run because it takes care of some of the basics. You will need to add support by installing the library. Good news: it is _very easy_ to do it. Go to the **Arduino Library Manager.**

![](https://cdn-learn.adafruit.com/assets/assets/000/107/555/medium800/i2c_scan_test_installlib.png?1640562425)

Search for **TestBed** and install the **Adafruit TestBed** library

![](https://cdn-learn.adafruit.com/assets/assets/000/107/556/medium800/i2c_scan_test_testbedlib.png?1640562581)

Now open up the I2C Scan example

![](https://cdn-learn.adafruit.com/assets/assets/000/107/557/medium800/i2c_scan_test_i2cscan.png?1640562632)

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/I2C_Scanners/arduino/i2c_scanner/i2c_scanner.ino

### Wire up I2C device

While the examples here will be using the [Adafruit MCP9808](https://www.adafruit.com/product/5027), a high accuracy temperature sensor, the overall process is the same for just about any I2C sensor or device.

The first thing you'll want to do is get the sensor connected so your board has I2C to talk to.

### Adafruit MCP9808 High Accuracy I2C Temperature Sensor Breakout

[Adafruit MCP9808 High Accuracy I2C Temperature Sensor Breakout](https://www.adafruit.com/product/5027)
The MCP9808 digital temperature sensor is one of the more accurate/precise we've ever seen, with a typical accuracy of ±0.25°C over the sensor's -40°C to +125°C range and precision of +0.0625°C. They work great with any microcontroller using standard I2C. With...

In Stock
[Buy Now](https://www.adafruit.com/product/5027)
[Related Guides to the Product](https://learn.adafruit.com/products/5027/guides)
![Top view of temperature sensor breakout above an OLED display FeatherWing. The OLED display reads "MCP9808 Temp: 24.19ºC"](https://cdn-shop.adafruit.com/640x480/5027-04.jpg)

### STEMMA QT / Qwiic JST SH 4-Pin Cable - 50mm Long

[STEMMA QT / Qwiic JST SH 4-Pin Cable - 50mm Long](https://www.adafruit.com/product/4399)
This 4-wire cable is&nbsp;50mm / 1.9" long and fitted with JST SH female 4-pin connectors on both ends. Compared with the chunkier JST PH these are 1mm pitch instead of 2mm, but still have a nice latching feel, while being easy to insert and remove.

<a...></a...>

Out of Stock
[Buy Now](https://www.adafruit.com/product/4399)
[Related Guides to the Product](https://learn.adafruit.com/products/4399/guides)
![Angled of of JST SH 4-Pin Cable.](https://cdn-shop.adafruit.com/640x480/4399-00.jpg)

## Wiring the MCP9808

The MCP9808 comes with a STEMMA QT connector, which makes wiring it up quite simple and solder-free.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/792/medium800/led_matrices_MCP9808_I2C_Scan_bb.jpg?1689780615)

Now upload the scanning sketch to your microcontroller and open the serial port to see the output. You should see something like this:

Warning: 

Info: 

![](https://cdn-learn.adafruit.com/assets/assets/000/122/797/medium800/led_matrices_Screenshot_2023-07-19_at_9.21.06_AM.png?1689783731)

# Adafruit MatrixPortal S3

## WiFi Test

Thanksfully if you have ESP32 sketches, they'll 'just work' with variations of ESP32. You can find a wide range of examples in the **File-\>Examples-\>Examples for Adafruit Metro ESP32-S2** subheading (the name of the board may vary so it could be **"Examples for Adafruit Feather ESP32 V2"** etc)

![](https://cdn-learn.adafruit.com/assets/assets/000/097/028/medium800/adafruit_products_image.png?1605222761)

Let's start by scanning the local networks.

**Load up the WiFiScan example** under **Examples-\>Examples for YOUR BOARDNAME-\>WiFi-\>WiFiScan**

![](https://cdn-learn.adafruit.com/assets/assets/000/096/993/medium800/adafruit_products_Screen_Shot_2020-11-11_at_12.28.51_PM.png?1605115789)

And **upload this example to your board**. The ESP32 should scan and find WiFi networks around you.

For ESP32, open the serial monitor, to see the scan begin.

For ESP32-S2, -S3 and -C3, don't forget you have to click Reset after uploading through the ROM bootloader. Then select the new USB Serial port created by the ESP32. It will take a few seconds for the board to complete the scan.

![](https://cdn-learn.adafruit.com/assets/assets/000/097/029/medium800/adafruit_products_image.png?1605223012)

If you can not scan any networks, check your power supply. You need a solid power supply in order for the ESP32 to not brown out. A skinny USB cable or drained battery can cause issues.

## WiFi Connection Test

Now that you can scan networks around you, its time to connect to the Internet!

Copy the example below and paste it into the Arduino IDE:

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/ESP32_S2_WiFi_Tests/WiFiWebClient/WiFiWebClient.ino

 **NOTE:** You must **change the `SECRET_SSID` and `SECRET_PASS` in the example code to your WiFi SSID and password** before uploading this to your board.

![](https://cdn-learn.adafruit.com/assets/assets/000/097/030/medium800/adafruit_products_image.png?1605223125)

After you've set it correctly, upload and check the serial monitor. You should see the following. If not, go back, check wiring, power and your SSID/password

![](https://cdn-learn.adafruit.com/assets/assets/000/097/009/medium800/adafruit_products__dev_cu_usbmodem14101.png?1605127946)

## Secure Connection Example

Many servers today do not allow non-SSL connectivity. Lucky for you the ESP32 has a great TLS/SSL stack so you can have that all taken care of for you. Here's an example of a using a secure WiFi connection to connect to the Twitter API.

Copy and paste it into the Arduino IDE:

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/ESP32_S2_WiFi_Tests/WiFiSSLClient/WiFiSSLClient.ino

As before, **update the ssid and password first** , then upload the example to your board.

Note we use `WiFiClientSecure client` instead of `WiFiClient client;` to require a SSL connection!&nbsp;

![](https://cdn-learn.adafruit.com/assets/assets/000/097/010/medium800/adafruit_products__dev_cu_usbmodem14101.png?1605128497)

# Adafruit MatrixPortal S3

## Usage with Adafruit IO

The ESP32-S2/S3 is an affordable, all-in-one, option for connecting your projects to the internet [using our IoT platform, Adafruit IO](https://io.adafruit.com/welcome).

- For more information and guides about Adafruit IO, check out the [Adafruit IO Basics Series.](https://learn.adafruit.com/series/adafruit-io-basics)

## Install Libraries
In the Arduino IDE, navigate to&nbsp; **Sketch -\> Include Library-\>Manage Libraries...**

![](https://cdn-learn.adafruit.com/assets/assets/000/097/024/medium800/adafruit_products_adafruit_io_library_menu.png?1605222421)

Enter&nbsp; **Adafruit IO Arduino** &nbsp;into the search box, and click&nbsp; **Install** &nbsp;on the&nbsp; **Adafruit IO Arduino** &nbsp;library option to install version 4.0.0 or higher.

![](https://cdn-learn.adafruit.com/assets/assets/000/097/023/medium800/adafruit_products_Library_Manager_and_adafruitio_esp32_s2_pub_sub___Arduino_1_8_13_and_1__fish__Users_brentrubell_Documents_Arduino_libraries__fish_.png?1605222398)

When asked to install dependencies, **click Install all**.

![](https://cdn-learn.adafruit.com/assets/assets/000/097/022/medium800/adafruit_products_Banners_and_Alerts_and_Dependencies_for_library_Adafruit_IO_Arduino_4_0_0_and_Library_Manager_and_adafruitio_esp32_s2_pub_sub___Arduino_1_8_13_and_Adafruit_Learning_System.png?1605222276)

## Adafruit IO Setup
If you do not already have an Adafruit IO account, [create one now](http://io.adafruit.com/). Next, **navigate to the Adafruit IO Dashboards page**.

We'll create a dashboard to visualize and interact with the data being sent between your ESP32-S2/S3 board and Adafruit IO.&nbsp;

- **Click** the New Dashboard button.
- **Name your dashboard** _My ESP32-S2_ or _My ESP32-S3_ depending on your board.
- Your new dashboard should appear in the list.
- **Click** the link to be brought to your new dashboard.

![adafruit_products_IO_-_Dashboards.png](https://cdn-learn.adafruit.com/assets/assets/000/097/031/medium640/adafruit_products_IO_-_Dashboards.png?1605223177)

![adafruit_products_IO_-_Dashboards.png](https://cdn-learn.adafruit.com/assets/assets/000/097/032/medium640/adafruit_products_IO_-_Dashboards.png?1605223193)

![adafruit_products_IO_-_Dashboards.png](https://cdn-learn.adafruit.com/assets/assets/000/097/033/medium640/adafruit_products_IO_-_Dashboards.png?1605223355)

We'll want to turn the board's LED on or off from Adafruit IO. To do this, **we'll need to add a toggle button to our dashboard**.

- **Click the cog** at the top right hand corner of your dashboard.
- In the dashboard settings dropdown, **click Create New Block.**
- **Select&nbsp;** the toggle block.
- Under My Feeds, **enter _led&nbsp;_as a feed name**. **Click Create**.
- **Choose the _led_ feed** to connect it to the toggle block. **Click Next step**.

![adafruit_products_IO_-_My_ESP32-S2.png](https://cdn-learn.adafruit.com/assets/assets/000/097/038/medium640/adafruit_products_IO_-_My_ESP32-S2.png?1605282578)

![adafruit_products_IO_-_My_ESP32-S2.png](https://cdn-learn.adafruit.com/assets/assets/000/097/039/medium640/adafruit_products_IO_-_My_ESP32-S2.png?1605282770)

![adafruit_products_IO_-_My_ESP32-S2.png](https://cdn-learn.adafruit.com/assets/assets/000/097/040/medium640/adafruit_products_IO_-_My_ESP32-S2.png?1605282842)

![adafruit_products_IO_-_My_ESP32-S2.png](https://cdn-learn.adafruit.com/assets/assets/000/097/041/medium640/adafruit_products_IO_-_My_ESP32-S2.png?1605282872)

Under Block Settings,

- **Change Button On Text** to **1**
- **Change Button Off Text** to **0**
- **Click Create block**

![adafruit_products_IO_-_My_ESP32-S2.png](https://cdn-learn.adafruit.com/assets/assets/000/097/044/medium640/adafruit_products_IO_-_My_ESP32-S2.png?1605283221)

![](https://cdn-learn.adafruit.com/assets/assets/000/097/045/medium800/adafruit_products_IO_-_My_ESP32-S2.png?1605283313 Dashboard may be called My ESP32-S3 if that is the board you are using!)

Next up, we'll want to display button press data from your board on Adafruit IO. To do this, **we'll add a gauge block to the Adafruit IO dashboard**. A gauge is a read only block type that shows a fixed range of values.

- **Click the cog** &nbsp;at the top right hand corner of your dashboard.
- In the dashboard settings dropdown,&nbsp; **click Create New Block.**
- **Select&nbsp;** the gauge block.
- Under My Feeds,&nbsp; **enter&nbsp;_button_ as a feed name**.&nbsp;
  - **Click Create**.

- **Choose the&nbsp;_button_&nbsp;feed** &nbsp;to connect it to the toggle block. **&nbsp;**
  - **Click Next step**.

![adafruit_products_IO_-_My_ESP32-S2.png](https://cdn-learn.adafruit.com/assets/assets/000/097/046/medium640/adafruit_products_IO_-_My_ESP32-S2.png?1605283766)

![adafruit_products_IO_-_My_ESP32-S2.png](https://cdn-learn.adafruit.com/assets/assets/000/097/047/medium640/adafruit_products_IO_-_My_ESP32-S2.png?1605283845)

![adafruit_products_IO_-_My_ESP32-S2.png](https://cdn-learn.adafruit.com/assets/assets/000/097/048/medium640/adafruit_products_IO_-_My_ESP32-S2.png?1605283879)

Under block settings,

- **Change**  **Block Title** to **Button Value**
- **Change Gauge Min Value** to **0** , the button's state when it's off
- **Change Gauge Max Value** to **1** , the button's state when it's on
- **Click** Create block

![adafruit_products_IO_-_My_ESP32-S2.png](https://cdn-learn.adafruit.com/assets/assets/000/097/049/medium640/adafruit_products_IO_-_My_ESP32-S2.png?1605284114)

Your dashboard should look like the following:

![](https://cdn-learn.adafruit.com/assets/assets/000/097/051/medium800/adafruit_products_IO_-_My_ESP32-S2.png?1605284271)

## Code Usage
For this example, you will need to open the&nbsp; **adafruitio\_26\_led\_btn** &nbsp;example included with the&nbsp; **Adafruit IO Arduino** &nbsp;library. In the Arduino IDE, navigate to **File -\> Examples -\> Adafruit IO Arduino -\> adafruitio\_26\_led\_btn**.&nbsp;

Before uploading this code to the ESP32-S2/S3, you'll need to add your network and Adafruit IO credentials. **Click on the config.h tab** in the sketch.&nbsp;

Obtain your Adafruit IO Credentials from [navigating to io.adafruit.com and clicking My Key](https://io.adafruit.com/). Copy and paste these credentials next to `IO_USERNAME` and `IO_KEY`.

![](https://cdn-learn.adafruit.com/assets/assets/000/097/052/medium800/adafruit_products_adafruitio_26_led_btn_-_config_h___Arduino_1_8_13.png?1605286871)

Enter your network credentials next to `WIFI_SSID` and `WIFI_PASS`.

![](https://cdn-learn.adafruit.com/assets/assets/000/097/054/medium800/adafruit_products_adafruitio_26_led_btn_-_config_h___Arduino_1_8_13.png?1605287355)

Click the Upload button to upload your sketch to the ESP32-S2/S3. After uploading, **press the RESET button on your board to launch the sketch.**

Open the Arduino Serial monitor and **navigate to the Adafruit IO dashboard you created**. You should see the gauge response to button press and the board's LED light up in response to the Toggle Switch block.

![](https://cdn-learn.adafruit.com/assets/assets/000/097/057/medium800thumb/adafruit_products_esp32s2_dash_capture.jpg?1605288255)

You should also see the ESP32-S2/S3's LED turning on and off when the LED is toggled:

![](https://cdn-learn.adafruit.com/assets/assets/000/097/064/medium800thumb/adafruit_products_ezgif.com-gif-maker_%285%29.jpg?1605546603)

# Adafruit MatrixPortal S3

## Arduino Sand Demo

We have a Sand/Pixel Dust demo available for the MatrixPortal that runs in Arduino. Below is the code to run it. The demo is also available as an example in the **Arduino Protomatter** library.

https://github.com/adafruit/Adafruit_Protomatter/blob/master/examples/pixeldust/pixeldust.ino

This sketch was written for a **64x32** pixel matrix but is **easily modified** for a **64x64** matrix!

Look for this line in the code:

```cpp
#define HEIGHT  32 // Matrix height (pixels) - SET TO 64 FOR 64x64 MATRIX!
```

and change it to:

```cpp
#define HEIGHT  64 // Matrix height (pixels) - SET TO 64 FOR 64x64 MATRIX!
```

Now upload the sketch to your Qualia S3and make sure a round display is connected. You may need to press the Reset button to reset the microcontroller. You should see a series of colored rectangles along the bottom. Go ahead and start moving the matrix around!

![](https://cdn-learn.adafruit.com/assets/assets/000/095/081/medium800thumb/led_matrices_pixel_dust_demo.jpg?1601055861)

If you have a 3D Printer, be sure to check out the [Matrix Portal Sand Handles](https://learn.adafruit.com/matrix-portal-sand) guide.

# Adafruit MatrixPortal S3

## Protomatter Library

# Adafruit MatrixPortal S3

## Migrating from MatrixPortal M4

If you have a project that was working on the MatrixPortal M4 and you would like it to work on the newer hardware, most of the features should work without needing to do a lot of modification. The path to updating your project will differ a bit depending on whether it was done using Arduino or CircuitPython.

In most cases, you will not need to update your hardware configuration, but there is one particular case where you may have to. If you were using DAC Audio output, this is no longer supported by the ESP32-S3. Instead it uses I2S audio output, so that part of your circuit would need to be changed.

Some of the other differences that may require code changes include:

- The WiFi is no longer a coprocessor, but is integrated into the ESP32-S3 itself.
- The flash memory is no longer a separate chip, which may have required a separate library in Arduino.
- The ESP32-S3 has A LOT more flash memory and RAM, so if you were limited by these on the MatrixPortal M4, you no longer need to worry.
- The ESP32-S3 pins are much more flexible and most of them are capable of DigitalIO and analog input in addition to any other special functions. This includes the TXO and RXI pins.

If your project uses CircuitPython and the MatrixPortal library, most of the changes should carry over automatically. If you are accessing some of the lower level functions directly, you may need to change the instantiation if it is expecting to access the WiFi coprocessor directly.

If your project uses Arduino, you will likely need to change pin numbers as some of the pin names have changed.

# Adafruit MatrixPortal S3

## Install UF2 Bootloader

Warning: If your board already has the UF2 bootloader, installed you do not need to follow the steps on this page. Try to enter the UF2 bootloader before continuing! Double-tap the reset button to do so.

The MatrixPortal S3 ships with a UF2 bootloader which allows the board to show up as **MATRXS3BOOT**** &nbsp;**when you double-tap the reset button, and enables you to drag and drop UF2 files to update the firmware.

On ESP32-S2 and ESP32-S3, there is no bootloader protection for the UF2 bootloader. That means it is possible to erase or damage the UF2 bootloader, especially if you upload an Arduino sketch to an ESP32-S2/S3 board that doesn't "know" there's a bootloader it should not overwrite!

It turns out, however, the ESP32-S2/S3 comes with a second bootloader: the ROM bootloader. Thanks to the ROM bootloader, you don't have to worry about damaging the UF2 bootloader. The ROM bootloader can never be disabled or erased, so its always there if you need it! You can simply re-load the UF2 bootloader from the ROM bootloader.

If your UF2 bootloader ends up damaged or overwritten, you can follow the steps found in the [Factory Reset and Bootloader Repair](https://learn.adafruit.com/adafruit-matrixportal-s3/factory-reset#factory-reset-and-bootloader-repair-3107941) section of the Factory Reset page in this guide.

Once completed, you'll return to where the board was when you opened the package. Then you'll be back in business, and able to continue with your existing plans!

# Adafruit MatrixPortal S3

## Factory Reset

The MatrixPortal S3 microcontroller ships running a self test demo It's lovely, but you probably had other plans for the board. As you start working with your board, you may want to return to the original code to begin again, or you may find your board gets into a bad state. Either way, this page has you covered.

You're probably used to seeing the&nbsp; **MATRXS3BOOT** &nbsp;drive when loading CircuitPython or Arduino. The **MATRXS3BOOT** &nbsp;drive is part of the UF2 bootloader, and allows you to drag and drop files, such as CircuitPython. However, on the ESP32-S3 the UF2 bootloader can become damaged.

# Install the Factory Reset Firmware UF2
If you have a bootloader still installed - which means you can double-click to get the&nbsp; **MATRXS3BOOT** &nbsp;drive to appear, then you can simply drag this UF2 file over to the&nbsp; **BOOT** &nbsp;drive.

To enter UF2 bootloader mode, plug in the board into a USB cable with data/sync capability. Press the reset button once, wait till the RGB LED turns purple, then quickly press the reset button again. (You are doing a "slow double-click"). Then drag this file over:

[MatrixPortal S3 Factory Reset](https://github.com/adafruit/Adafruit-MatrixPortal-S3-PCB/raw/main/factory-reset/MatrixPortal_S3_FactoryReset.uf2)
Your board is now back to its factory-shipped state, running again with the original factory program. You can now begin again with your plans for your board.

Info: Re-loading the factory reset UF2 isn't necessary to start over with the board, but it's a good way to show the board is working.

# UF2 Bootloader Installation and Repair
What if you tried double-tapping the reset button, and you still can't get into the UF2 bootloader? Whether your board shipped without the UF2 bootloader, or something damaged it, this section has you covered.

Warning: There is no protection for the UF2 bootloader. That means it is possible to erase or damage the UF2 bootloader, especially if you upload an Arduino sketch to an ESP32-S2/S3 board that doesn't "know" there's a bootloader it should not overwrite!

It turns out, however, the ESP32-S2/S3 comes with a second, built-in, bootloader, the ROM bootloader, which cannot be erased or damaged. You can always reload the UF2 bootloader using&nbsp;the ROM bootloader.

There are three ways to do a factory reset and bootloader repair. The first and easiest is to [use the **OPEN INSTALLER** button](https://learn.adafruit.com/using-open-installer-on-circuitpython-org) on the page for your board on [circuitpython.org](https://circuitpython.org). This method requires no manual downloads and guides you through the steps interactively. **We highly recommend this method as your first choice.**

The second method is to use&nbsp;the browser-based **Adafruit WebSerial ESPTool** , and the third is to use `esptool.py` via the command line.&nbsp;

For both OPEN INSTALLER and the Adafruit WebSerial tool, you must use a Chromium-based browser such as Chrome, Edge, Opera, or Chromium.

Danger: Installing the UF2 bootloader will erase everything on your board, including CircuitPython, any Arduino program, and any files stored in flash! Be sure to back up your data first.

## OPEN INSTALLER Method for UF2 Bootloader Installation
The OPEN INSTALLER button on&nbsp;[circuitpython.org](https://circuitpython.org/) is the easiest way to install or update the UF2 bootloader. See the Learn Guide [Using the OPEN INSTALLER Button on circuitpython.org](https://learn.adafruit.com/using-open-installer-on-circuitpython-org) for all the details.

![This image shows OPEN INSTALLER button for firmware installation available on some boards on circuitpython.org.](https://cdn-learn.adafruit.com/assets/assets/000/140/085/medium640/esp32_s2_s3_factory_reset_open-installer-hero.png?1759343276)

## Adafruit WebSerial ESPTool and `esptool.py` Methods for UF2 Bootloader Installation

The other methods for bootloader installation require you to download the bootloader yourself. The next section walks you through the prerequisite steps needed for both of these methods.

## Step 1. Download the UF2 Bootloader&nbsp; **.bin** File for your board
Clik on the green button below to download the **.bin** file you need (there may be more than one listed), and save wherever is convenient for you. You will need to be able to access the file from the Adafruit WebSerial ESPTool or another upload method.

Primary: Note that this file is approximately 3MB. This is not because the bootloader is that large, but because the bootloader needs to write data at both the beginning and end of flash. Most of the file is empty.

[MatrixPortal S3 bootloader 0.33.0 combined.bin](https://adafruit-circuit-python.s3.amazonaws.com/bootloaders/esp32/adafruit_matrixportal_s3/tinyuf2-adafruit_matrixportal_s3-0.33.0-combined.bin)
## Step 2. Enter ROM bootloader mode

Entering the ROM bootloader is easy. Complete the following steps.

**Before you start, make sure your ESP32-S2/S3 is plugged into USB port to your computer using a data/sync cable.** &nbsp;Charge-only cables will not work!

To enter the bootloader:

1. **Press and hold the BOOT/DFU button down.** &nbsp;Don't let go of it yet!
2. **Press and release the Reset button.** &nbsp;You should still have the BOOT/DFU button pressed while you do this.
3. **Now you can release the BOOT/DFU button.**

No USB drive will appear when you've entered the ROM bootloader. This is normal!

Now that you've downloaded the **.bin** file and entered the ROM bootloader, you're ready to continue installing the UF2 bootloader. The next two sections walk you through using the Adafruit WebSerial ESPTool (Alternative A) or&nbsp;`esptool.py`&nbsp;(Alternative B).

(There is also an Alternative C below, using the Arduino IDE, but it is less desirable, because it does not allow you to choose the bootloader that will be used.)

## Step 3: Alternative A. The Adafruit WebSerial ESPTool Method
Primary: We highly recommend using the Adafruit  WebSerial ESPTool method to perform a factory reset and bootloader repair. However, if you'd rather use **esptool.py** via the command line, you can skip this section and use Alternative B instead.

This method uses the Adafruit WebSerial ESPTool through Chrome or a Chromium-based browser (including Opera and Edge). Adafruit WebSerial ESPTool is a web-based option for programming ESP32-S2/S3 boards. It allows you to erase the the microcontroller flash and program up to four files at different offsets.

You have to use a Chromium-based browser (Chrome, Opera, Edge, etc.) for this to work. Safari and Firefox are _not_ supported because they don't have adequate support for Web Serial functionality.

Follow the steps below to flash the UF2 bootloader.

Warning: 

## Connect

You should have plugged in **only the ESP32-S2/S3 that you intend to flash**. That way there's no confusion in picking the proper port when it's time!

In the **Chrome browser** visit [https://adafruit.github.io/Adafruit\_WebSerial\_ESPTool/](https://adafruit.github.io/Adafruit_WebSerial_ESPTool/). You should see something like the image shown.

Leave the **No reset for Passthrough updates** toggle **off**.

![](https://cdn-learn.adafruit.com/assets/assets/000/138/135/medium640/esp32_s2_s3_factory_reset_adafruit.github.io_Adafruit_WebSerial_ESPTool_.png?1751474093)

Press the&nbsp; **Connect** &nbsp;button in the top right of the web browser. You will get a pop up asking you to select the COM or Serial port.

**Remember, you should remove all other USB devices so**  **_only_ the ESP32-S2/S3 board is attached, that way there's no confusion over multiple ports!**

On some systems, such as MacOS, there may be additional system ports that appear in the list.

![factory_reset___esp32_s2_s3_Select_Device.png](https://cdn-learn.adafruit.com/assets/assets/000/116/446/medium640/factory_reset___esp32_s2_s3_Select_Device.png?1667580185)

The JavaScript code will now try to connect to the ROM bootloader. It may timeout for a bit until it succeeds. On success, you will see that it is **Connected** and will print out a unique **MAC address** identifying the board along with other information that was detected.

![factory_reset___esp32_s2_Screen_Shot_2022-04-04_at_3.16.00_PM.png](https://cdn-learn.adafruit.com/assets/assets/000/110/503/medium640/factory_reset___esp32_s2_Screen_Shot_2022-04-04_at_3.16.00_PM.png?1649111586)

&nbsp;

&nbsp;

Once you have successfully connected, the command toolbar will appear.

![factory_reset___esp32_s2_s3_Connected.png](https://cdn-learn.adafruit.com/assets/assets/000/116/447/medium640/factory_reset___esp32_s2_s3_Connected.png?1667580336)

## Erase the Contents of Flash
Warning: 

To erase the contents, click the Erase button. You will be prompted whether you want to continue. Click OK to continue or if you changed your mind, just click cancel.

![factory_reset___esp32_s2_s3_Erase.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/448/medium640/factory_reset___esp32_s2_s3_Erase.jpg?1667580381)

&nbsp;

You'll see "Erasing flash memory. Please wait..." This will eventually be followed by "Finished." and the amount of time it took to erase.

**Do not disconnect!** Immediately continue on to programming the ESP32-S2/S3.

![factory_reset___esp32_s2_WebSerial_ESPTool_erase_board_text.png](https://cdn-learn.adafruit.com/assets/assets/000/106/947/medium640/factory_reset___esp32_s2_WebSerial_ESPTool_erase_board_text.png?1638491869)

Danger: 

## Flash the Bootloader **.bin** File
Programming the ESP32-S2/S3 can be done with up to four files at different locations, but with the board-specific bootloader **.bin** file, which you should have downloaded under **Step 1** on this&nbsp;page, you only need to use one file.

Click on the first **Choose a file...**. (The tool will only attempt to program buttons with a file and a unique location.) Then, select the bootloader **.bin** file you downloaded in Step 1 that matches your board.

Verify that the&nbsp; **Offset** &nbsp;box next to the file location you used is (0x) **0**.

![install_uf2_bootloader_adafruit_products_image_(3).png](https://cdn-learn.adafruit.com/assets/assets/000/101/574/medium640/install_uf2_bootloader_adafruit_products_image_%283%29.png?1618608677)

Once you choose a file, the button text will change to match your filename. You can then select the **Program** button to begin flashing.

![factory_reset___esp32_s2_s3_Program.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/449/medium640/factory_reset___esp32_s2_s3_Program.jpg?1667580433)

A progress bar will appear and after a minute or two, you will have written the firmware.

![factory_reset___esp32_s2_s3_Programming.jpg](https://cdn-learn.adafruit.com/assets/assets/000/116/450/medium640/factory_reset___esp32_s2_s3_Programming.jpg?1667580456)

Once completed, you can skip down to the section titled Reset the Board.

## Step 3: Alternative B. The&nbsp;`esptool.py` Method (for advanced users)
Danger: If you used Adafruit WebSerial ESPTool, you do not need to complete the steps in this section!

Once you have entered ROM bootloader mode, you can then&nbsp;[use Espressif's esptool program](https://github.com/espressif/esptool)&nbsp;to communicate with the chip!&nbsp;`esptool`&nbsp;is the 'official' programming tool and is the most common/complete way to program an ESP chip.

## Install `esptool.py`

You will need to use the command line or Terminal to install and run&nbsp;`esptool`.

You will also need to have pip and Python installed (any version!).

Install the latest version using pip (you may be able to run&nbsp;`pip`&nbsp;without the&nbsp;`3`&nbsp;depending on your setup):

`pip3 install --upgrade esptool`

Then, you can run:

`esptool.py`

Info: 

## Test the Installation

Run&nbsp;`esptool.py`&nbsp;in a new terminal/command line and verify you get something like the below:

![](https://cdn-learn.adafruit.com/assets/assets/000/107/692/medium800/factory_reset___esp32_s2_install_uf2_bootloader_adafruit_products_image_%282%29.png?1641494911)

## Find the Serial Port

First, you need to determine the name of the serial port you board has when it's plugged in and ROM bootloader mode.

- For Windows, it will be a COM port, such as `COM5`. Look in Device Manager -\> Ports.
- For macOS, you can do `ls /dev/tty.*` in a Terminal to find the names of the serial ports.&nbsp;
- For Linux, you can do ls `/dev/tty*` in a terminal window. The name is often /dev/ttyACM0 or similar.

If you are not sure you've found the right port, unplug the board, and see if the port disappears.

For more information on determining serial ports, follow these links for help on [Windows](https://learn.adafruit.com/welcome-to-circuitpython/advanced-serial-console-on-windows#whats-the-com-2977217), [macOS](https://learn.adafruit.com/welcome-to-circuitpython/advanced-serial-console-on-mac-and-linux#whats-the-port-2977243), or [Linux](https://learn.adafruit.com/welcome-to-circuitpython/advanced-serial-console-on-linux#whats-the-port-3104855).

## Connect

Run the following command, replacing the identifier after&nbsp;`--port`&nbsp;with the&nbsp;`COMxx`,&nbsp;`/dev/cu.usbmodemxx`&nbsp;or&nbsp;`/dev/ttySxx`&nbsp;you found above.

For example, if you're using Windows, and you think the board is on COM88, type this following:

`esptool.py --port COM88 chip_id`

You should get a notice that it connected over that port and found an ESP32-S2/S3.

![](https://cdn-learn.adafruit.com/assets/assets/000/107/693/medium800/factory_reset___esp32_s2_install_uf2_bootloader_adafruit_products_image_%283%29.png?1641495017)

## Erase the Flash

Before programming the board, it is a good idea to erase the flash. Run the following command.

`esptool.py --port COM88 erase_flash`

You must be connected (by running the command in the previous section) for this command to work as shown.

![](https://cdn-learn.adafruit.com/assets/assets/000/123/927/medium800/factory_reset___esp32_s2_s3_esptool_erase_flash.png?1692912297)

## Flash the UF2 Bootloader

Run this command and replace the serial port name with your matching port and the file you just downloaded

`esptool.py --port COM88 write_flash 0x0 tinyuf2-some-board-0.32.0-combined.bin`

Don't forget to change the `--port` name to match.

Info: Adjust the bootloader filename accordingly if it differs from `tinyuf2-some-board-0.32.0-combined.bin`.

There might be a bit of a 'wait' when programming, where it doesn't seem like it's working. Give it a minute, it has to erase the old flash code which can cause it to seem like it's not running.

You'll finally get an output like this:

![](https://cdn-learn.adafruit.com/assets/assets/000/107/694/medium800/factory_reset___esp32_s2_install_uf2_bootloader_adafruit_products_image.png?1641495051)

Once completed, you can continue to the next section.

## Step 4. Reset the board
The board should restart automatically, and start up the UF2 bootloader. If not, press the reset button to start the bootloader.

If you have the board plugged into a 64x32 LED Matrix, you should see some shapes and lines in Red, Green, Blue, and White along with the text ADAFRUIT in white at the top.

You've successfully returned installed the UF2 bootloader on your board. If you now want to return the board to a factory reset state, follow the instructions at the top of the page to **Install the Factory Reset Firmware UF2**.

## Older Versions of Chrome
Primary: 

We suggest updating to Chrome 89 or newer, as Web Serial is enabled by default.

If you must continue using an older version of Chrome, follow these steps to enable Web Serial.

If you receive an error like the one shown when you visit the Adafruit WebSerial ESPTool site, you're likely running an older version of Chrome.

**You must be using Chrome 78 or later to use Web Serial.**

![factory_reset___esp32_s2_WebSerial_ESPTool_Not_Supported_Error.png](https://cdn-learn.adafruit.com/assets/assets/000/106/929/medium640/factory_reset___esp32_s2_WebSerial_ESPTool_Not_Supported_Error.png?1638484333)

To enable Web Serial in Chrome versions 78 through 88:

- Visit **chrome://flags** &nbsp;from within Chrome.
- Find and enable the&nbsp; **Experimental Web Platform features**
- **Restart Chrome**

![install_uf2_bootloader_adafruit_products_Enable_Features.jpg](https://cdn-learn.adafruit.com/assets/assets/000/101/562/medium640/install_uf2_bootloader_adafruit_products_Enable_Features.jpg?1618608210)

# Step 3: Alternative C. The Flash an Arduino Sketch Method

This section outlines flashing an Arduino sketch onto your ESP32-S2/S3 board, which automatically installs the UF2 bootloader as well. However, it does not allow you to choose which UF2 bootloader to install, so Alternative A or B above are preferred.

## Arduino IDE Setup

If you don't already have the Arduino IDE installed, the first thing you will need to do is to download the latest release of the Arduino IDE. ESP32-S2/S3 requires **version 1.8** &nbsp;or higher. Click the link to download the latest.

[Arduino IDE Download](https://www.arduino.cc/en/software)
After you have downloaded and installed **&nbsp;** the latest version of Arduino IDE, you will need to start the IDE&nbsp;and navigate to&nbsp;the&nbsp; **Preferences** &nbsp;menu. You can access it from the&nbsp; **File \> Preferences** menu in&nbsp;Windows&nbsp;or&nbsp;Linux, or the&nbsp; **Arduino \> Preferences** menu on&nbsp;OS X.

The **Preferences** window will open.

In the **Additional Boards Manager URLs** field, you'll want to add a new URL. The list of URLs is comma separated, and&nbsp;_you will only have to add each&nbsp;URL once._ The URLs point to index files that the Board Manager uses to build the list of available & installed boards.

Copy the following URL.

`https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json`

Add the URL to the the **Additional Boards Manager URLs** field (highlighted in red below).

![](https://cdn-learn.adafruit.com/assets/assets/000/107/697/medium800/factory_reset___esp32_s2_CP_Template_ESP32-S2_factory_reset_Arduino_preferences_window.png?1641495433)

Click **OK** to save and close **Preferences**.

In the **Tools \> Boards** menu you should see the **ESP32 Arduino** menu. In the expanded menu, it should contain the ESP32 boards along with all the latest ESP32-S2 boards.

Now that your IDE is setup, you can continue on to loading the sketch.

## Load the Blink Sketch
In the&nbsp; **Tools \> Boards** &nbsp;menu you should see the&nbsp; **ESP32 Arduino** &nbsp;menu. In the expanded menu, look for the menu option for the&nbsp; **Adafruit MatrixPortal ESP32-S3** , and click on it to choose it.

Open the Blink sketch by clicking through **File \> Examples \> 01.Basics \> Blink**.

![](https://cdn-learn.adafruit.com/assets/assets/000/107/696/medium800/factory_reset___esp32_s2_Arduino_Template_RP2040_open_Blink.png?1641495423)

For the Arduino IDE to upload TinyUF2 you must select a TinyUF2 partition layout, under the&nbsp; **Tools \> Partition Scheme** &nbsp;menu.

If you have a 4MB board, won't be doing Over-The-Air firmware updates (OTA), or are unsure, then choose the 'No OTA' TinyUF2 entry.

![](https://cdn-learn.adafruit.com/assets/assets/000/138/883/medium800/adafruit_products_pjIhorTc9w.png?1754610534)

Finally, click Upload from the sketch window.

![](https://cdn-learn.adafruit.com/assets/assets/000/138/885/medium800/adafruit_products_Bvj2oHayFn.png?1754610624)

Once successfully uploaded, the little red LED will begin blinking once every second. At that point, you can now enter the bootloader.

# Adafruit MatrixPortal S3

## USB Power

If powering a MatrixPortal and associated LED matrix solely through the USB port, you might encounter a situation where the image appears stable when only a few pixels are lit, but brighter images with more pixels lit may exhibit “ghosting” or “sparkling” artifacts.

This is **not a software bug**. Please do not report it as a software bug.

This is a **USB power issue**. It does not affect everyone because there are _so many_ different USB power sources and permutations. What follows is an explanation and some workarounds.

## The Source of Gremlins
Not all USB ports are created equal. The ports on many computers are designed to provide 5 Volts at a maximum of 1 Ampere (1A)…or sometimes as little as 500 mA (0.5A). Likewise with USB wall chargers: small ones might deliver 1A or less, and even beefier models seldom exceed 2–2.5A.

LED matrices can be power hungry. And the more pixels in use, the hungrier they are. When a matrix demands more power than is available through the USB port, this can result in a momentary _brown-out_ condition, and the sort of visual glitches described above. This can be exacerbated by cheap, thin USB cables that have a lot of resistance.

Complicating issues, the _voltage and current from a USB port are not rock steady._ This is especially true of USB battery banks. The buck/boost converter circuit in these devices creates a sort of “buzz” in the output; on _average_ it might be 5V 2A, but the _instantaneous_ voltage and current will oscillate around this. This is no problem for a typical steady use like charging a phone, but LED matrices are weird…it’s not just that they’re hungry, but like the supply voltage, the LED current draw _also_ oscillates they’re actually flashed on and off hundreds of times a second to produce an image.

## Some Solutions to Try

If you encounter the aforementioned phenomenon, here are some things to try, starting from the very simple and working our way up…

- Try **swapping the USB cable** if the one you have seems thin. That free cable included for charging a mouse or Bluetooth speaker might be unsuitable for the amount of current we need. Look for something beefy, like a tablet or laptop charging cable. Those luxury braided cables are also sometimes a sign of “substance.”
- If powering from a **computer’s USB port** : try using a sizable (2A or better) **USB wall charger** instead.
- If powering from a **USB wall charger** or **USB battery bank** : Try **swapping out** for any others you might have on hand. More current (higher amperage) is always nice, but that’s not the whole story. As explained above, the output filtering (or lack of) can affect the steadiness of the output voltage and current.

Those are the easy “switch something out” fixes. If none of those address the issue, now things get progressively more complex…

- Try **powering the MatrixPortal and LED matrix separately** : USB for the MatrixPortal, and a 5V DC “wall wart” supply (2A or preferably more) for the matrix, using one of these screw terminal power adapters (i.e. don’t use the screw terminals on the MatrixPortal, use this instead):

### Female DC Power adapter - 2.1mm jack to screw terminal block

[Female DC Power adapter - 2.1mm jack to screw terminal block](https://www.adafruit.com/product/368)
If you need to connect a DC power wall wart to a board that doesn't have a DC jack - this adapter will come in very handy! There is a 2.1mm DC jack on one end, and a screw terminal block on the other. The terminals are labeled with positive/negative assuming a positive-tip configuration...

In Stock
[Buy Now](https://www.adafruit.com/product/368)
[Related Guides to the Product](https://learn.adafruit.com/products/368/guides)
![Angle shot Female DC Power adapter - 2.1mm jack to screw terminal block](https://cdn-shop.adafruit.com/640x480/368-03.jpg)

- If the project _must_ be powered from a **USB battery bank** and you’ve already tested some others: try powering the LED matrix and the MatrixPortal **separately**. This might involve two power banks, or one with multiple ports might suffice (most enforce per-port current limits), you’ll need to experiment. Cables exist to convert USB type A or C to a DC plug that’s compatible with the screw terminal adapter above — one would power the LED matrix through this, and the MatrixPortal through a normal USB cable. Just make sure the cable provides 5V output; some are “booster” cables to higher voltages that could _destroy_ the matrix.

- If nothing else seems to work, the last line of defense is **better filtering** on the power supply output. This involves adding one or more **capacitors** across the + and – terminals until the image stabilizes. Unfortunately there is no one-size-fits-all solution here…it requires **experimentation** with an assortment of caps on hand. One might start with a 1000 µF cap, and work up or down from there. If something seems promising but imperfect, two or more with different values might be needed in parallel (e.g. 100 µF + 1000 µF).

This photo shows NeoPixels, but the principle is _exactly_ the same: capacitance helps smooth out fluctuations in the power supply. Look for something at least 10V rated (higher is OK) and values from 50 µF to 2000 µF. Folks who’ve been doing electronics for a while usually end up with a little parts drawer of random caps, so maybe you (or someone you know, or a local maker space) already have something suitable.

![led_matrices_leds_cap.jpg](https://cdn-learn.adafruit.com/assets/assets/000/125/104/medium640/led_matrices_leds_cap.jpg?1697061543)

# Adafruit MatrixPortal S3

## Downloads

- [ESP32-S3 product page with resources](https://www.espressif.com/en/products/socs/esp32-s3)
- [ESP32-S3 datasheet](https://cdn-learn.adafruit.com/assets/assets/000/110/711/original/esp32-s3_datasheet_en.pdf?1649790878)
- [ESP32-S3 Technical Reference](https://cdn-learn.adafruit.com/assets/assets/000/110/710/original/esp32-s3_technical_reference_manual_en.pdf?1649790877)
- [MatrixPortal S3 EagleCAD PCB files on GitHub](https://github.com/adafruit/Adafruit-MatrixPortal-S3-PCB)
- [3D models on GitHub](https://github.com/adafruit/Adafruit_CAD_Parts/tree/main/5778%20Matrix%20Portal%20S3)
- [MatrixPortal S3 Fritzing object in the Adafruit Fritzing Library](https://github.com/adafruit/Fritzing-Library/blob/master/parts/Adafruit%20Matrix%20Portal%20S3.fzpz)

[Simpletest UF2 for MatrixPortal S3 + 64x32 Matrix](https://cdn-learn.adafruit.com/assets/assets/000/123/408/original/matrixportal_s3_simpletest.UF2?1691711797)
[Simpletest UF2 for MatrixPortal S3 + 64x64 Matrix](https://cdn-learn.adafruit.com/assets/assets/000/123/409/original/matrixportal_s3_simpletest_64x64.UF2?1691711829)
## Schematic

**Note:** the ALS-PT19 light sense phototransistor is NOT part of the final design for this board, even though it appears on the schematic. We apologize for any confusion.

![](https://cdn-learn.adafruit.com/assets/assets/000/122/683/medium800/led_matrices_MatrixPortal_S3_Schematic.png?1689695239)

## Fab Print
![](https://cdn-learn.adafruit.com/assets/assets/000/123/526/medium800/led_matrices_MatrixPortal_S3_Fab_Print.png?1692218558)

## 3D Model
![](https://cdn-learn.adafruit.com/assets/assets/000/123/498/medium800/led_matrices_5778_Matrix_Portal_S3.jpg?1692122646)


## Primary Products

### Adafruit Matrix Portal S3 CircuitPython Powered Internet Display

[Adafruit Matrix Portal S3 CircuitPython Powered Internet Display](https://www.adafruit.com/product/5778)
Folks love our [wide selection of RGB matrices](https://www.adafruit.com/category/327) and accessories&nbsp;for making custom colorful LED displays... and our RGB Matrix Shields and FeatherWings can be quickly soldered together to make the wiring much easier. But what if we made it...

Out of Stock
[Buy Now](https://www.adafruit.com/product/5778)
[Related Guides to the Product](https://learn.adafruit.com/products/5778/guides)

## Related Guides

- [Matrix Portal Stained Glass with WLED](https://learn.adafruit.com/matrix-portal-stained-glass-with-wled.md)
- [Blurry Analog Clock](https://learn.adafruit.com/blurry-analog-clock.md)
- [MatrixPortal S3 Flight Proximity Tracker](https://learn.adafruit.com/matrixportal-s3-flight-proximity-tracker.md)
- [RGB Matrix New York Times Title Scroller](https://learn.adafruit.com/rgb-matix-nyt-text-scroller.md)
- [Animated GIF Player for Matrix Portal](https://learn.adafruit.com/animated-gif-player-for-matrix-portal.md)
- [MatrixPortal CircuitPython Animated Message Board](https://learn.adafruit.com/matrixportal-circuitpython-animated-message-board.md)
- [LED Matrix Sports Scoreboard](https://learn.adafruit.com/led-matrix-sports-scoreboard.md)
- [itsaSNAP Apple Health Status Board](https://learn.adafruit.com/itssnap-apple-fitness-status-board.md)
- [Scroll an SMS Text Message on your RGB Matrix](https://learn.adafruit.com/scroll-an-sms-text-message-on-your-rgb-matrix.md)
- [itsaSNAP Daily Weather Forecast Board](https://learn.adafruit.com/itsasnap-daily-weather-forecast-board.md)
- [Multi-tasking with CircuitPython](https://learn.adafruit.com/multi-tasking-with-circuitpython.md)
- [Sketch Drawing Toy with CircuitPython](https://learn.adafruit.com/sketch-drawing-toy.md)
- [Tiny Wiki for CircuitPython](https://learn.adafruit.com/tiny-wiki-for-circuitpython.md)
- [FunHouse IoT Fume Extractor and Air Quality Sensor](https://learn.adafruit.com/funhouse-fume-extractor-iot-air-quality-sensor.md)
- [Multi-tasking the Arduino - Part 3](https://learn.adafruit.com/multi-tasking-the-arduino-part-3.md)
