The 2.8-inch ESP32 Solo Miner LCD Display from Elecrow is a compact integrated module that combines a color TFT touchscreen with an ESP32-WROOM-32 microcontroller to provide both user interface and standalone processing capability on a single board.
The 320 × 240 pixel resistive touch display is driven by an ILI9341V controller and the onboard ESP32 dual-core LX6 CPU. It also integrates 2.4 GHz Wi-Fi and Bluetooth. The board furthermore exposes a TF card slot, multiple I/O ports, USB-C and UART interfaces, and a speaker/battery connector.
When used with compatible mining firmware such as NMMiner or NerdMiner, the device can participate in cryptocurrency solo mining for educational purposes. Don’t expect to generate any revenue with it ; )
In this tutorial we will focus on programming the display with Arduino IDE using the TFT_eSPI graphics library. You will also learn how to use the GPIO port, the speaker and the SD Card reader.
Required Parts
The required parts include the display and if you want to connect some external hardware; some cables, resistors, LEDs and a breadboard will come in handy.

2.8″ ESP32 Solo Miner LCD

Dupont Wire Set

Breadboard

Resistor & LED kit
Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.
Features of the 2.8″ ESP32 Solo Miner LCD
The 2.8″ ESP32 Solo Miner is built around the ESP32-WROOM-32-N4 system-on-module, which integrates a dual-core Xtensa LX6 microprocessor capable of clocking up to 240 MHz. The ESP32 core provides Wi-Fi (802.11 b/g/n, 2.4 GHz) and Bluetooth (Bluetooth 5.0/BLE) connectivity natively on-chip.
Display and Touch Interface
The module features a 2.8-inch TFT-LCD panel with a resolution of 320 × 240 pixels and a TN (Twisted Nematic) display type. The display uses an ILI9341V display driver IC that communicates with the ESP32 over an SPI interface, responsible for pixel control, color rendering, and backlight operation. The picture below show the front of the display module:

A resistive touch overlay is laminated over the LCD surface, enabling coordinate input through pressure contact. The resistive panel accommodates a stylus or finger and interfaces with the ESP32 via dedicated analog/digital lines managed by an onboard touch controller (XPT2046).
Power and Physical Specifications
The board can be powered via an external 5 V DC source at up to 2 A for stable operation under load, or a 3.7–4.2 V Li-ion/LiPo battery connected to the integrated battery port. It includes physical BOOT and RESET pushbuttons for user control during development or firmware flashing.
The active display area measures approximately 43.2 mm by 56.7 mm, and the entire board’s net weight is around 61 g, making it compact for embedded or portable applications.
Peripheral and I/O Interfaces
Beyond the display and touch, the board exposes multiple peripheral interfaces. A TF (microSD) card slot enables local storage or firmware/data loading. Communication interfaces include I2C, UART0, and UART1 for serial integration with sensors or external controllers.

The USB-C connector (UART0) functions as both a power input and a USB-to-TTL programming interface for firmware flashing and serial debugging.
A general-purpose GPIO header exposes additional digital I/O lines, while a dedicated speaker port supports simple audio signaling. Connectors use standard pin headers and PH2.0/HY2.0 micro-connectors. The following table summarizes which GPIO pins are assigned to the IO interfaces, the speaker and the SD Card reader:
| Display | GPIO |
|---|---|
| GPIO_D | IO25; IO32 |
| UART | RX(IO16); TX(IO17) |
| I2C | SDA(IO22); SCL(IO21) |
| SPK | IO26 |
| SD Card Slot(SPI) | MOSI(IO23); MISO(IO19); SDK(IO18); CS(IO5) |
Development Support
The board supports multiple development environments such as Arduino IDE, Espressif IDF, Lua RTOS, and Micro Python, and is compatible with the LVGL graphics library. However, in this tutorial I will focus on the Arduino IDE and the TFT_eSPI graphics library.
Technical Specification
The following table summarizes the technical specification of the 2.8″ ESP32 Solo Miner LCD Display:
| Category | Specification |
|---|---|
| Main Controller | ESP32-WROOM-32-N4 |
| CPU Architecture | Dual-core Xtensa LX6 |
| Maximum Clock Frequency | Up to 240 MHz |
| Wireless Connectivity | Wi-Fi 802.11 b/g/n (2.4 GHz), Bluetooth 5.0 / BLE |
| Display Size | 2.8-inch TFT LCD |
| Display Resolution | 320 × 240 pixels |
| Display Type | TN TFT |
| Display Driver IC | ILI9341V |
| Touch Panel | Resistive touchscreen (XPT2046 controller) |
| Display Interface | SPI |
| External Storage | MicroSD (TF) card slot |
| Power Input (Wired) | 5 V DC via USB-C |
| Power Input (Battery) | 3.7–4.2 V Li-ion / LiPo |
| User Controls | BOOT and RESET buttons |
| Audio Interface | Speaker connector (SC8002B amplifier) |
| Communication Interfaces | UART0, UART1, I2C, GPIO |
| Programming Interface | USB-C (USB-to-TTL) |
| Supported Development Platforms | Arduino IDE, ESP-IDF, PlatformIO, MicroPython, Lua RTOS, ESPHome |
| Operating Temperature | −20 °C to +70 °C |
| Storage Temperature | −30 °C to +80 °C |
| Active Display Area | 43.2 mm × 56.7 mm |
| Approximate Weight | ~61 g |
Install ESP32 Core
The 2.8″ ESP32 Solo Miner LCD Display is based on the ESP32. If you want to program it you need to install the ESP32 core in your Arduino IDE.
Start by opening the Preferences dialog by selecting “Preferences…” from the “File” menu. This will open the Preferences dialog shown below.
Under the Settings tab you will find an edit box at the bottom of the dialog that is labelled “Additional boards manager URLs“:

In this input field copy the following URL:
https://espressif.github.io/arduino-esp32/package_esp32_dev_index.json
This will let the Arduino IDE know, where to find the ESP32 core libraries. Next we will install the ESP32 boards using the Boards Manager.
Open the Boards Manager via “Tools -> Boards -> Board Manager”. You will see the Boards Manager appearing in the left Sidebar. Enter “ESP32” in the search field at the top and you should see two types of ESP32 boards; the “Arduino ESP32 Boards” and the “esp32 by Espressif” boards. We want the “esp32 libraries by Espressif”. Click on the INSTALL button and wait until the download and install is complete.

I am using the version 3.3.5 here but any other of the 3.x version should work as well for this project. If you need more information read our Install ESP32 core in Arduino IDE tutorial.
Selecting Board
You also need to select a ESP32 board. In case of the 2.8″ ESP32 Solo Miner LCD Display, you can pick the generic “ESP32S3 Dev Module”. For that, click on the drop-down menu and then on “Select other board and port…”:

This will open a dialog where you can enter “esp32s3 dev” in the search bar. You will see the “ESP32S3 Dev Module” board under Boards. Click on it and the COM port to activate it and then click OK:

Note that you need to connect the board via the USB cable to your computer, before you can select a COM port.
Testing GPIO
The Solo Miner board exposes two GPIO pins on the GPIO_D port. In this example we implement a simple Blink program to test the GPIO port.
Since, the display has no built-in LED we are going to connect and control two external LEDs. The wiring diagram below shows you how to connect the two LEDs to the port:

The pins within the GPIO_D port are as follows IO25; IO32, 3.3V, GND. We don’t need the 3.3V output, just the two GPIO pins and ground. When building the circuit, don’t forget the 220Ω resistors to limit the current to the LEDs and make sure ground is properly connected.
After that you can upload the following code that blinks the two LEDs alternatingly. It also prints to the Serial monitor, so if there is some issue with the wiring, you can at least verify that the program is running. Make sure the baud rate for the Serial monitor is set to 115200.
const int led1 = 25;
const int led2 = 32;
void setup() {
Serial.begin(115200);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
}
void loop() {
Serial.println("on");
digitalWrite(led1, HIGH);
digitalWrite(led2, LOW);
delay(1000);
Serial.println("off");
digitalWrite(led1, LOW);
digitalWrite(led2, HIGH);
delay(1000);
}
Setting up TFT_eSPI library
If you want show something on the display you will need to use a graphics library. We are going to use the TFT_eSPI library by Bodmer. To install it, open the LIBRARY MANAGER, type “TFT_eSPI” in the search bar, and click in the INSTALL button. The picture below shows you how a successful install looks like:

Next we need to create file named tft_setup.h with the correct parameters for the display. This file needs to be part of any Arduino project that uses the display.
Here is how that works in detail. First create a new Arduino project and save it as “tft_test“, for instance. That will create a folder tft_test with a file tft_test.ino in it:

In this folder, create a file named “tft_setup.h“. The name needs to be exact! Your project folder should then look like this:

tft_setup.hIn your Arduino IDE you now should see two tabs; tft_test.ino and tft_setup.h that you can click on to edit the files.

tft_test.ino and tft_setup.h tabsIn the file tft_setup.h copy following parameter settings:
#define ILI9341_DRIVER #define TFT_WIDTH 320 #define TFT_HEIGHT 240 #define TFT_BACKLIGHT_ON HIGH #define TFT_BL 27 #define TFT_MISO 4 #define TFT_MOSI 13 #define TFT_SCLK 14 #define TFT_CS 15 #define TFT_DC 2 #define TFT_RST -1 #define TOUCH_CS 33 #define SPI_FREQUENCY 27000000 #define SPI_TOUCH_FREQUENCY 2500000 #define SPI_READ_FREQUENCY 16000000 #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters #define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts #define SMOOTH_FONT
In the file copy the following code. This a little test that uses the TFT_eSPI library to display the text “Makerguides” in the center of the screen.tft_test.ino
#include "tft_setup.h"
#include"TFT_eSPI.h"
TFT_eSPI tft = TFT_eSPI();
void setup(void) {
tft.init();
tft.setRotation(3);
tft.fillScreen(TFT_BLACK);
}
void loop() {
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.setTextSize(2);
tft.setTextDatum(MC_DATUM);
tft.drawString("Makerguides", tft.width() / 2, tft.height() / 2);
delay(5000);
}
Note that tft_setup.h is included at the top of the program. The code itself is easy to understand. We create a TFT_eSPI object and initialize it in the setup() function. In the loop function, we set the text color, size, and alignment, and draw the string “Makerguides” in center of the TFT display.
If you compile and upload this program, you should see the following output on your display:

In the next sections, you will learn how to read touch data.
Detecting Touch Events
The following code shows you how to detect touch events. It draws a small yellow circle, where ever you touch the screen:
#include "tft_setup.h"
#include "TFT_eSPI.h"
TFT_eSPI tft = TFT_eSPI();
uint16_t cal[5] = { 210, 3484, 285, 3511, 7 };
void setup() {
tft.begin();
tft.setRotation(3);
tft.setTouch(cal);
tft.fillScreen(TFT_BLACK);
}
void loop() {
static uint16_t x = 0, y = 0;
if (tft.getTouch(&x, &y)) {
tft.fillCircle(x, y, 5, TFT_YELLOW);
}
delay(100);
}
As before we include tft_setup.h and the TFT_eSPI library. Next we create a the display object and an array with calibration data. The cal array essentially contains the corner coordinates and orientation of the touch screen. I will show you in the next section how you can find the calibration data but the one given here should work for a start.
In the setup function we then initialize the screen, set the orientation, set the touch calibration data and fill the screen with black.
In the loop function we continuously call getTouch() to get the coordinates of a touch event. The function returns true if a touch was detected. In this case we draw a yellow circle with a radius of 5 pixels at the coordinates of the touch. Here is an example on how this looks like on the screen:

Calibrating the Touchscreen
The touch screen sits on top of the display and has a different resolution, location and orientation to the display. To match the location of touch events with locations on the display we need to calibrate the touch screen by measuring the corner coordinates and orientation of the touch screen.
These settings are stored in the calibration array. Run the following program to extract the calibration parameters and to print them to the Serial Monitor:
#include "tft_setup.h"
#include "TFT_eSPI.h"
TFT_eSPI tft = TFT_eSPI();
void setup() {
Serial.begin(115200);
tft.begin();
tft.setRotation(3);
}
void loop() {
static uint16_t cal[5];
tft.fillScreen(TFT_BLACK);
tft.setCursor(20, 0);
tft.setTextFont(2);
tft.setTextSize(1);
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.print("Touch corners ... ");
tft.calibrateTouch(cal, TFT_YELLOW, TFT_BLACK, 15);
tft.println("done.");
Serial.printf("cal: {%d, %d, %d, %d, %d}\n",
cal[0], cal[1], cal[2], cal[3], cal[4]);
delay(10000);
}
When you run this program it it asks you to touch the four corners of the the screen and then prints out the five calibration parameters (corner coordinates and screen orientation). Your display during calibration should look like this:

And on the Serial Monitor you should see something like this printed out, after you have touched the four corners:
cal: { 210, 3484, 285, 3511, 7 }
The calibration repeats itself every 10 seconds, so you can have several tries to get the most accurate parameters. Then use these parameters when initializing the display in the setup function:
...
uint16_t cal[5] = { 210, 3484, 285, 3511, 7 };
void setup() {
...
tft.setTouch(cal);
...
}
In the next two section, I quickly show you how to generate sound and how to use the SD Card reader.
Play Sound on Speaker
The following code shows you how to play sound on the speaker. It produces a 440Hz tone for one second with a pause of one second:
const int speakerPin = 26;
void setup() {
pinMode(speakerPin, OUTPUT);
}
void loop() {
tone(speakerPin, 440); // 440Hz tone
delay(1000);
noTone(speakerPin);
delay(1000);
}
Note that you will need to connect an external speaker (3W, 4-8 Ohms) to the speaker connector of the display board, since the board has no integrated speaker or buzzer.
Detect SD Card Type
This last code example shows you how to use the integrated SD Card Reader of the display to detect an SD Card:
#include "FS.h"
#include "SD.h"
#include "SPI.h"
void setup() {
Serial.begin(115200);
if (!SD.begin()) {
Serial.println("Card Mount Failed");
return;
}
uint8_t cardType = SD.cardType();
if (cardType == CARD_NONE) {
Serial.println("No SD card attached");
} else if (cardType == CARD_MMC) {
Serial.println("MMC Card");
} else if (cardType == CARD_SD) {
Serial.println("Standard SD Card");
} else if (cardType == CARD_SDHC) {
Serial.println("SDHC Card");
} else {
Serial.println("Unknown Card Type");
}
}
void loop() { }
If you need more information and examples about SD Card Readers have a look at the SD Card Module with ESP32 tutorial.
Schematics
For convenience here are the most important parts of the Schematics for the 2.8″ ESP32 Solo Miner LCD Display board:



Conclusion
This tutorial showed you how to use the display, touch screen, speaker and SD Card reader of the 2.8-inch ESP32 Solo Miner LCD Display. For additional information see the Github repo and Wiki at Elecrow.
The Solo Miner ESP32 Display board come with pretty much everything you need for a project that involves a display. It includes a TFT touch screen, an ESP32, a TF Card slot, a battery connector with charger, a speaker interface and a I2C interface.
However, this also means that the number of free GPIO pins is limited to only two. But since there is a I2C interface, you can use a GPIO expander to add more GPIOs. Have a look at our tutorial Using GPIO Expander MCP23017 With Arduino.
The hardware of the 2.8″ ESP32 Solo Miner Display is essentially identical to the CrowPanel 2.8″ ESP32 Display. Have a look at the CrowPanel 2.8″ ESP32 Display : Easy Setup Guide tutorial for more information.
For example application of the ESP32 Displays see our Digital Clock with CrowPanel 3.5″ ESP32 Display, Parking sensor with CrowPanel ESP32 Display and the Digital Timer Switch with CrowPanel ESP32 Display tutorials.
If you have any questions feel free to leave them in the comment section.
Happy Tinkering ; )
Stefan is a professional software developer and researcher. He has worked in robotics, bioinformatics, image/audio processing and education at Siemens, IBM and Google. He specializes in AI and machine learning and has a keen interest in DIY projects involving Arduino and 3D printing.

