# Nerdminer V2 Lilygo T-HMI
[Toc]
# Overview
## Where to buy it
[LILYGO T-HMI at Aliexpress >>](https://s.click.aliexpress.com/e/_oFII4s2)
## GitHub for T-HMI
[T-HMI Libraries and Examples](https://github.com/Xinyuan-LilyGO/T-HMI)
## Pinout diagram

## 3D Model
[T-HMI Model](https://www.printables.com/model/871409-lilygo-t-hmi-model)
# Release Goals
## Initial release added 9 April 2024
https://github.com/BitMaker-hub/NerdMiner_v2/pull/302
- add lilygo t-hmi
- add fees bottom panel
- experimented with price in bottom title
- touch screen not enabled
- screen advance: mining (pool), clock (fees), global(fees), price (pool)
- button function left to right : b1 (advance screen) b2 (reset) b3 (none) usb-c side
- diagram: https://www.electronics-lab.com/wp-content/uploads/2023/07/T-HMI-Pinout-Diagram-850x758.webp
- thanks for the graphic assistance @nitroxgas


## Next features added 25 May 2024
https://github.com/BitMaker-hub/NerdMiner_v2/pull/379
- enable battery option
- improve pool data api URL discovery based on Settings.PoolAddress and/or Settings.PoolPort it is possible that this is applicable to ESP32_2432S028R or ESP32_2432S028_2USB or ESP32_2432S024 or NERDMINER_T_HMI models
## 3 for Three
https://github.com/BitMaker-hub/NerdMiner_v2/pull/420
- SDCard enable; two separate issues
- proper detecting of the sdcard by reducing the SD_MMC frequency
details at https://github.com/Xinyuan-LilyGO/T-HMI/issues/27#issuecomment-2132046978
- class SDcard blows up in 1bit mode requiring `initSDCard()` move to public
- Touch screen support
- Top 3/4 advances through screens
- Bottom 1/4 switch lower between workers and fees
- [Remove vkbit.com pool #410](https://github.com/BitMaker-hub/NerdMiner_v2/pull/410)
- Update OneButton to 2.5.0
See [Video>>](https://youtu.be/El1wv85a0DI)
## Using esptoool to flash
Using the esptool.py to flash, the port for the first device is /dev/ttyACM0 and is use in this example. yours may be different.
```
git clone https://github.com/Xinyuan-LilyGO/T-HMI.git
cd T-HMI/examples/factory/
```
after building, find the artifacts, and flash factory app
```
cd .pio/build/debug
esptool.py --port /dev/ttyACM0 erase_flash
esptool.py --port /dev/ttyACM0 write_flash 0x0 bootloader.bin 0x8000 partitions.bin 0x10000 firmware.bin
```
after building flash NerdminerV2 firmware
```
cd NerdMiner_v2/.pio/build/NerdminerV2-T-HMI
esptool.py --port /dev/ttyACM0 write_flash 0x10000 firmware.bin
```
## SD_MMC detection by frequency example
### Formatting sdcard on Linux
With the SD card inserted into a Linux machine with an open terminal session type the following:
1. Type `lsblk` to list all block devices and identify the name of your SD card (e.g., it may be `sdb`).
2. Ensure the SD card is unmounted using the `umount` command:
```bash
sudo umount /dev/sdb*
```
3. Create a W95 FAT32 partition
```bash
echo ",,b;" | sudo sfdisk /dev/sdb
```
4. Format the SD card to o FAT32 using the `mkfs` command:
```bash
sudo mkfs.vfat /dev/sdb1
````
Alternatively,
```bash
sudo mkfs.fat -F32 -v -I /dev/sdb1
```
### When the sdcard is not detected
A solution to when an inserted sdcard is not detected on T-HMI reducing the SD_MMC frequency from the default 40000 in esp_idf v5.0.2
- different result in your environment. perhaps, a different esp_idf version (v5.0.2)
- the same behavior was observed in the example factory.ino
So, here is the output *before* the SD__MMC the fix:
```cpp
bool rlst = SD_MMC.begin("/sdcard", true);
```
- without sdcard inserted the return code is 0x107
```
E (6044) sdmmc_common: sdmmc_init_ocr: send_op_cond (1) returned 0x107
E (6045) vfs_fat_sdmmc: sdmmc_card_init failed (0x107).
[ 6149][E][SD_MMC.cpp:138] begin(): Failed to initialize the card (0x107). Make sure SD card lines have pull-up resistors in place.
SD init failed
➸ No detected SdCard
SD close
```
- with the sdcard inserted the return code is 0x109 and fails
```
E (26223) sdmmc_sd: sdmmc_check_scr: send_scr returned 0x109
E (26223) vfs_fat_sdmmc: sdmmc_card_init failed (0x109).
[ 26328][E][SD_MMC.cpp:138] begin(): Failed to initialize the card (0x109). Make sure SD card lines have pull-up resistors in place.
SD init failed
➸ No detected SdCard
```
After poking around SD_MMC.h I tried different frequencies. Both 5000 and 20000 work while the default of 40000 does not.
```cpp
bool rlst = SD_MMC.begin("/sdcard", true, false, 20000);
```
- without the sdcard inserted the return code is 0x107
```
(427144) sdmmc_common: sdmmc_init_ocr: send_op_cond (1) returned 0x107
E (427145) vfs_fat_sdmmc: sdmmc_card_init failed (0x107).
[427250][E][SD_MMC.cpp:138] begin(): Failed to initialize the card (0x107). Make sure SD card lines have pull-up resistors in place.
SD init failed
➸ No detected SdCard
SD close
```
- with the sdcard inserted
```
SD close
SD init success
➸ Detected SdCard insert: 7.40 GB
SD close
```
Here is the original code with the fix and a small adjustment to better see the log messages from the console:
```cpp
#include "pins.h"
#include <Arduino.h>
#include <SD_MMC.h>
#include <FS.h>
#include <SPI.h>
#include <SD.h>
void setup() {
pinMode(PWR_ON_PIN, OUTPUT);
digitalWrite(PWR_ON_PIN, HIGH);
Serial.begin(115200);
delay(1000);
pinMode(PWR_EN_PIN, OUTPUT);
digitalWrite(PWR_EN_PIN, HIGH);
SD_MMC.setPins(SD_SCLK_PIN, SD_MOSI_PIN, SD_MISO_PIN);
}
void loop() {
delay(5000);
bool rlst = SD_MMC.begin("/sdcard", true, false, 20000);
if (!rlst) {
Serial.println("SD init failed");
Serial.println("➸ No detected SdCard");
} else {
Serial.println("SD init success");
Serial.printf("➸ Detected SdCard insert: %.2f GB\r\n", SD_MMC.cardSize() / 1024.0 / 1024.0 / 1024.0);
}
delay(15000);
Serial.println("SD close");
SD_MMC.end();
}
```
## NerdMiner_V2 enable 1Bit SDMMC with sdcard inserted
In this situation the T-HMI serial port becomes stable. To reset hold the BOOT button then press the RST button and let go and then let go BOOT
To reproduce, add the following defines to src/drivers/devices/lilygoT_HMI.h
```cpp
#define SDMMC_CLK (12)
#define SDMMC_CMD (11)
#define SDMMC_D0 (13)
```
Presumably src/drivers/storage/SDCard.cpp initializes 1Bit mode in bool SDCard::initSDcard() where the frequency can be adjusted for the T-HMI.
```cpp
#warning SDMMC : 1 - bit mode is not always working. If you experience issues, try other modes.
iSD_->setPins(SDMMC_CLK, SDMMC_CMD, SDMMC_D0);
#ifdef NERDMINER_T_HMI
cardInitialized_ = iSD_->begin("/sd", true, false, 20000);
#else
cardInitialized_ = iSD_->begin("/sd", true);
#endif
Serial.println("SDCard: 1-Bit Mode.");
}
```
After the image is built, flashed, and reset the screen remains black and the serial console repeats the following very fast forever.
See "Using esptoool.py to flash"
```
entry 0x403c98d4
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x3 (RTC_SW_SYS_RST),boot:0x8 (SPI_FAST_FLASH_BOOT)
Saved PC:0x403cd9f6
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce3808,len:0x44c
load:0x403c9700,len:0xbe4
load:0x403cc700,len:0x2a38
entry 0x403c98d4
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x3 (RTC_SW_SYS_RST),boot:0x8 (SPI_FAST_FLASH_BOOT)
Saved PC:0x403cd9f6
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce3808,len:0x44c
load:0x403c9700,len:0xbe4
load:0x403cc700,len:0x2a38
entry 0x403c98d4
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x3 (RTC_SW_SYS_RST),boot:0x8 (SPI_FAST_FLASH_BOOT)
Saved PC:0x403cd9f6
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce3808,len:0x44c
load:0x403c9700,len:0xbe4
load:0x403cc700,len:0x2a38
```
Flash first boot
```
--- Terminal on /dev/ttyACM0 | 115200 8-N-1
--- Available filters and text transformations: colorize, debug, default, direct, esp32_exception_decoder, hexlify, log2file, nocontrol, printable, send_on_enter, time
--- More details at https://bit.ly/pio-monitor-filters
--- Quit: Ctrl+C | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H
20:54:54.513 > SPIFS: Mounting File System...
20:54:54.514 > E (4843) SPIFFS: mount failed, -10025
20:54:54.515 > [ 5221][E][SPIFFS.cpp:89] begin(): Mounting SPIFFS failed! Error: -1
20:54:54.516 > E (4844) SPIFFS: mount failed, -10025
20:54:54.524 > [ 5223][E][esp32-hal-misc.c:128] disableCore0WDT(): Failed to remove Core 0 IDLE task from WDT
```
## Initialize SDCard and move data to NVM
```C
/*=============================================*/
#include <FS.h>
#include <ArduinoJson.h>
#include <WiFi.h>
#include "drivers/storage/nvMemory.h"
#include "drivers/storage/SDCard.h"
extern nvMemory nvMem;
extern TSettings Settings;
void t_hmiCheckForSDCardAndMoveToNVM(void)
{
// workaround removing use of class SDCard
// SCard SDCrd = SDCard() blows up in SDCard::initSDcard()
// Need to lower frequency to 20000
SD_MMC.setPins(SDMMC_CLK, SDMMC_CMD, SDMMC_D0);
delay(500);
bool rlst = SD_MMC.begin("/sd", true, false, 20000);
if (!rlst)
{
Serial.println("SD init failed");
Serial.println("➸ No detected SdCard");
}
else
{
Serial.println("SD init success");
Serial.printf("➸ Detected SdCard insert: %.2f GB\r\n", SD_MMC.cardSize() / 1024.0 / 1024.0 / 1024.0);
// SDCrd.SD2nvMemory(&nvMem, &Settings);
if (SD_MMC.exists(JSON_CONFIG_FILE))
{
// The file exists, reading and loading
File configFile = SD_MMC.open(JSON_CONFIG_FILE, "r");
if (configFile)
{
StaticJsonDocument<512> json;
DeserializationError error = deserializeJson(json, configFile);
configFile.close();
Serial.println("SDCard: Loading config file");
if (!error)
{
serializeJsonPretty(json, Serial);
Serial.print('\n');
TSettings *pSettings = &Settings;
pSettings->WifiSSID = json[JSON_KEY_SSID] | pSettings->WifiSSID;
pSettings->WifiPW = json[JSON_KEY_PASW] | pSettings->WifiPW;
pSettings->PoolAddress = json[JSON_KEY_POOLURL] | pSettings->PoolAddress;
strcpy(pSettings->PoolPassword, json[JSON_KEY_POOLPASS] | pSettings->PoolPassword);
strcpy(pSettings->BtcWallet, json[JSON_KEY_WALLETID] | pSettings->BtcWallet);
if (json.containsKey(JSON_KEY_POOLPORT))
pSettings->PoolPort = json[JSON_KEY_POOLPORT].as<int>();
if (json.containsKey(JSON_KEY_TIMEZONE))
pSettings->Timezone = json[JSON_KEY_TIMEZONE].as<int>();
if (json.containsKey(JSON_KEY_STATS2NV))
pSettings->saveStats = json[JSON_KEY_STATS2NV].as<bool>();
nvMem.saveConfig(pSettings);
WiFi.begin(pSettings->WifiSSID, pSettings->WifiPW);
Serial.println("SDCard: Settings transfered to internal memory. Restarting now.");
ESP.restart();
}
else
{
// Error loading JSON data
Serial.println("SDCard: Error parsing config file!");
}
}
else
{
Serial.println("SDCard: Error opening config file!");
}
}
else
{
Serial.println("SDCard: No config file available!");
}
// delay(15000);
SD_MMC.end();
Serial.println("SD close");
}
}
/*=============================================*/
```