# 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 ![T-HMI-Pinout-Diagram-850x758](https://hackmd.io/_uploads/H1dRVDxEA.jpg) ## 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 ![22222IMG_20240123_215510](https://github.com/BitMaker-hub/NerdMiner_v2/assets/122713120/cdeeef38-c07f-48e1-a42e-c9c2c5b6a51b) ![I11111MG_20240123_221837](https://github.com/BitMaker-hub/NerdMiner_v2/assets/122713120/ed3629b3-3379-4d61-babe-e89ade9e9e50) ## 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"); } } /*=============================================*/ ```