NerdMiner – Public-Pool.io Shares Stalled
Warning — Should be addressed soon
Symptoms
- On-device `Valid Shares` counter froze (e.g. at `47`) and hasn't moved for 30+ minutes
- On-device `Hashrate` display oscillates between `0 kH/s` and `~76 kH/s` on a 10-30 second cycle
- Wall power draw is steady ~5 W and the BM1387 / BM1366 is warm — chip hashing, pool not crediting
- `web.public-pool.io` worker dashboard shows the `bc1q...` address online with `0 H/s` 5-minute average and `0` accepted shares in the last hour
- Block height + BTC ticker continue to refresh on the idle screen — confirms WiFi/DNS/HTTPS are healthy
- Serial console at `115200` baud shows repeated `mining.submit` lines followed by pool replies of `{"result": false, "error": [23, "Low difficulty share", null]}` or `[24, "Stale share", null]`
- Multiple NerdMiners on the same LAN against `public-pool.io:21496` stalled at the same time (consistent with GitHub `BitMaker-hub/NerdMiner_v2` issue #247)
- Switching to `solo.ckpool.org:3333` or `pool.nerdminers.org:3333` immediately resumes share submission
- Restarting the device gives a temporary 5-30 minute burst of accepted shares before stalling again
- No physical changes (no firmware flash, no PSU swap, no overclock) preceded the stall — config-stable miner stopped getting credit
Step-by-Step Fix
Confirm the device is hashing. Watch the NerdMiner display — `Hashrate` should cycle between `0 kH/s` and `~50-78 kH/s` and wall power draw should be ~5 W. If it sits permanently at `0 kH/s` or 0.5 W, this is a different fault class (display / WiFi / chip), not a vardiff stall. Open the NerdMinerAP captive portal to verify settings: power-cycle while holding `BOOT`, connect to the `NerdMinerAP` network, browse to `http://192.168.4.1`, read the `Pool URL` and `Pool Port` fields. Confirm `public-pool.io` + `21496` to verify this is the documented stall — if you're on a different pool, see Diagnostic Steps to isolate.
Switch to a NerdMiner-tuned pool. In NerdMinerAP, change `Pool URL` to `pool.nerdminers.org` and `Pool Port` to `3333`. Leave the `bc1q...` BTC address unchanged. Password remains `x`. Save / Apply, the device reboots into the new config. Within 60 seconds the on-device `Valid Shares` counter should resume incrementing — watch for 5 minutes to confirm the counter rises by at least 2-3 shares. This pool is configured specifically for ESP32-class hashrates with a fixed low-diff floor that NerdMiner firmware handles cleanly.
If `pool.nerdminers.org` is unreachable from your network or geography, try alternates: `pool.nerdminer.io:3333`, `pool.pyblock.xyz:3333`, `pool.solomining.de:3333`, `pool.sethforprivacy.com:3333`, `pool.stompi.de:3333`. All six are NerdMiner-friendly solo pools with low-diff floors. Pick one geographically close to you for the lowest stratum-job round-trip — every 100 ms of latency cuts your effective time-on-job before stale-rotation invalidates the search.
If you specifically want Solo CKPool semantics, set `Pool URL` to `solo.ckpool.org` and `Pool Port` to `3333`. CKPool runs at a fixed share difficulty appropriate for ASICs — your NerdMiner submits far fewer shares (one every 10-30 minutes is normal, sometimes longer), but every submission is accepted. Save and reboot. The lower share-rate on CKPool is normal and expected for the hashrate class — it does not mean the miner is broken.
Verify on the new pool's worker dashboard. After 5-10 minutes, open the pool's web dashboard and search your `bc1q...` address. You should see your worker listed with a non-zero hashrate average and a recent `last share` timestamp. Bookmark that page for ongoing monitoring — it's the authoritative source for whether the pool is actually crediting your work, which is what matters for block-finding probability. The on-device counter alone is unreliable as a stall-detector.
Update NerdMiner_v2 firmware to the latest release. Browse to `https://github.com/BitMaker-hub/NerdMiner_v2/releases`. Identify your exact board variant from the device's idle screen (e.g. `LILYGO T-DISPLAY-S3`, `LILYGO T-DONGLE-S3`, `ESP32-S3`, `ESP32-WROOM-32`, `ESP32-2432S028R`). Download the matching `.bin` — flashing the wrong variant bricks the display. Use the official web flasher at `https://bitmaker-hub.github.io/NerdMiner_v2_WebFlasher/` in Chrome or Edge (WebSerial API required). Connect via USB while holding `BOOT`, hit Connect, select COM port, flash. Reconfigure NerdMinerAP from scratch.
Capture serial output during the stall to validate root cause. USB-to-serial cable to the NerdMiner. Open PuTTY, Tera Term, `screen /dev/ttyUSB0 115200`, or `minicom`. Power-cycle, capture from boot through 30 minutes of operation. Look for: (a) the `mining.set_difficulty` value the pool sends, (b) the rate of `mining.submit` lines, (c) the proportion of `result: true` vs `result: false` replies. A capture showing 95%+ rejections at a `mining.set_difficulty` above `0.001` is the canonical evidence that Public Pool's vardiff floor is above the firmware's reliable floor.
Increase firmware-side stale-job tolerance if your build supports it. Some NerdMiner_v2 forks expose a `stale_share_max_age_ms` or similar tunable in `Config.json`. Raise it to `120000` (2 minutes) so work received from the pool isn't invalidated mid-search — this addresses the issue #247 case where new jobs arrive before the chip can find a valid nonce at the assigned difficulty. Save, reboot, observe for 30 minutes.
Open a request to Public Pool admins for a static low-difficulty override. Public Pool's stratum server supports per-worker static-difficulty assignments on request. File an issue or DM on `https://github.com/benjamin-wilson/public-pool` including: your `bc1q...` worker address, device type (`NerdMiner v2 ESP32`), and a request for static `mining.set_difficulty 0.001` (or whatever floor your firmware build reliably handles). Most Public Pool admins are responsive — this is a single-line server-side change and they routinely whitelist NerdMiner-class miners explicitly.
Build NerdMiner_v2 from source with verbose stratum logging if you suspect a firmware-side fractional-difficulty bug. Clone `BitMaker-hub/NerdMiner_v2`. Open `src/stratum.cpp` and `src/mining.cpp`, raise log level to `DEBUG` (look for `Serial.printf` or `ESP_LOG*` macros). In PlatformIO, select the `env:` matching your board variant. Flash via USB: `pio run -e <yourenv> -t upload`. Serial output now shows every byte of the stratum exchange — definitive evidence for whether your firmware is mishandling fractional difficulty values.
Inspect the difficulty-to-target arithmetic. In `src/mining.cpp` (or the equivalent in your variant's build), find the function that converts an inbound `mining.set_difficulty` to a 256-bit target hash. Verify it correctly handles `double`-precision difficulties below `1.0`. Reference implementation: `target = max_target / difficulty` where `max_target` is the standard Bitcoin difficulty-1 target. If the firmware uses 32-bit integer math or fixed-point scaling, fractional difficulties round to zero or to an unintended value. The fix is to use `double` or `int64_t` with appropriate scaling — about 30 lines of C.
File or contribute upstream. If you find a concrete arithmetic bug, submit a pull request to `BitMaker-hub/NerdMiner_v2/pulls` with: the failing log capture, the patch, and a regression test using the standard Bitcoin difficulty-1 vector. Reference issues `#247`, `#750`, and `#763` for context. This is a textbook open-source contribution — small, well-bounded, demonstrably correct, with affected users who'll thank you.
Erase NVS and reconfigure to clear cached state. Some NerdMiner variants persist the most-recent `mining.set_difficulty` value in ESP32 NVS, and a soft reboot won't clear it. Use esptool: `esptool.py --chip esp32s3 --port COM5 erase_flash` (Windows) or `esptool.py --chip esp32s3 --port /dev/ttyUSB0 erase_flash` (Linux/macOS). Re-flash the firmware image, reconfigure NerdMinerAP from scratch with the new pool. This is the nuclear option for stuck-cached state when standard Tier 1 / 2 fixes don't take.
Run a self-hosted public-pool fork with a pinned vardiff floor. If you operate a small fleet of NerdMiners (5+), the cleanest long-term fix is running `https://github.com/benjamin-wilson/public-pool` yourself with the `vardiff` config block pinned to a constant `0.001` floor. The repo includes a docker-compose deployment that fits on a Raspberry Pi 4 or a small VPS. Point your fleet at `your-host:3333`, get full solo-pool semantics, and never worry about vardiff drift again.
Stop DIY and escalate to D-Central support. You've tried at least two NerdMiner-tuned pools, updated to the latest firmware release, captured serial logs showing the stratum exchange, performed `esptool.py erase_flash` and full reconfigure, and the device still isn't accumulating shares on any pool. At that point it's hardware fault, board-variant firmware mismatch, or a known-bad shipped firmware build. Open a ticket at `https://d-central.tech/contact/` with: serial log capture (5+ minutes), board variant exact name, firmware version, list of pools tested, photo of NerdMinerAP config screen. Free with any Nerd-family device purchased from D-Central.
When to Seek Professional Repair
If the steps above do not resolve the issue, or if you are not comfortable performing these repairs yourself, professional service is recommended. Attempting advanced repairs without proper equipment can cause further damage.
Related Error Codes
Still Having Issues?
Our team of Bitcoin Mining Hackers has been repairing ASIC miners since 2016. We have seen it all and fixed it all. Get a professional diagnosis.
