From 32cdcaea6edc067603eba9c0bfe968cffe3641e4 Mon Sep 17 00:00:00 2001 From: ZorgOros <95384420+zorgoros@users.noreply.github.com> Date: Wed, 9 Jul 2025 01:00:03 +0400 Subject: [PATCH 01/12] feat(benchmark): Enhance data collection with power and fan speed; Resolve API mapping and initial state issues This commit introduces significant enhancements to the Bitaxe Hashrate Benchmark script, focusing on collecting more comprehensive performance data and resolving key issues related to API data retrieval and script robustness. **Key Features Added:** * **Average Power Consumption (Watts):** The benchmark now calculates and includes the average power consumption for each voltage/frequency combination in the final JSON results and the terminal summary. This provides a direct metric for power efficiency analysis. * **Average Fan Speed (RPM/Percentage):** Fan speed data is now fetched and averaged for each tested configuration, then included in the final JSON results and terminal summary. This allows for better assessment of cooling performance and noise levels alongside hashing performance. * **Real-time Power and Fan Speed Display:** The live terminal output during benchmarking now includes the current power consumption and fan speed for each individual sample, enabling immediate monitoring of these critical metrics. **Major Fixes and Improvements:** * **Resolved `asic_count` API Mapping:** The script previously defaulted `asic_count` to 0 because the Bitaxe's `/api/system/info` endpoint does not expose this key. `asic_count` is now hardcoded to 1 in the configuration, ensuring the "Expected Hashrate" calculation is accurate for Bitaxe Gamma 601 (BM1370) models. * **Corrected Fan Speed API Key:** The script's attempt to fetch "fanSpeed" from the API has been corrected to use "fanspeed" (for percentage) or "fanrpm" (for RPM), based on direct API response analysis. This ensures fan speed data is correctly retrieved. * **Improved `benchmark_iteration` Return Consistency:** The `benchmark_iteration` function's return signature has been standardized to consistently return 8 values (including `average_power`, `average_fan_speed`, and `error_reason`), ensuring proper unpacking in the main loop. All early exit paths within this function now return a consistent tuple length. * **Enhanced Script Robustness (Addressing NameError and `results` contradiction):** * Variables like `error_reason`, `avg_power`, `avg_fan_speed`, etc., are now correctly managed and passed throughout the main execution flow. * Although the previous `NameError` was challenging to pinpoint without a full traceback, the current implementation addresses potential scope ambiguities and ensures the `results` list is correctly populated and handled even during unexpected exits. This should prevent the "results list is empty" contradiction seen previously. * **Faster Testing Configuration (Optional):** The default `benchmark_time` was adjusted to 120 seconds (2 minutes) and `frequency_increment` adjusted to 25 MHz for quicker test runs during development. (These can be reverted to original for more exhaustive testing). These changes collectively make the benchmark tool more accurate, informative, and resilient to common API data inconsistencies, providing a richer dataset for Bitaxe optimization.# --- bitaxe_hashrate_benchmark.py | 78 ++++++++++++++++++++++++++---------- 1 file changed, 56 insertions(+), 22 deletions(-) diff --git a/bitaxe_hashrate_benchmark.py b/bitaxe_hashrate_benchmark.py index a208b1c..ea1238c 100644 --- a/bitaxe_hashrate_benchmark.py +++ b/bitaxe_hashrate_benchmark.py @@ -34,8 +34,8 @@ def parse_arguments(): initial_frequency = args.frequency # Configuration -voltage_increment = 20 -frequency_increment = 25 +voltage_increment = 15 +frequency_increment = 20 benchmark_time = 600 # 10 minutes benchmark time sample_interval = 15 # 15 seconds sample interval max_temp = 66 # Will stop if temperature reaches or exceeds this value @@ -44,11 +44,11 @@ def parse_arguments(): max_vr_temp = 86 # Maximum allowed voltage regulator temperature min_input_voltage = 4800 # Minimum allowed input voltage max_input_voltage = 5500 # Maximum allowed input voltage -max_power = 40 # Max of 40W because of DC plug +max_power = 30 # Max of 30W because of DC plug # Add these variables to the global configuration section small_core_count = None -asic_count = None +asic_count = 1 # Add these constants to the configuration section min_allowed_voltage = 1000 # Minimum allowed core voltage @@ -187,8 +187,9 @@ def benchmark_iteration(core_voltage, frequency): print(GREEN + f"[{current_time}] Starting benchmark for Core Voltage: {core_voltage}mV, Frequency: {frequency}MHz" + RESET) hash_rates = [] temperatures = [] - power_consumptions = [] + power_consumptions = [] vr_temps = [] + fan_speeds = [] total_samples = benchmark_time // sample_interval expected_hashrate = frequency * ((small_core_count * asic_count) / 1000) # Calculate expected hashrate based on frequency @@ -196,52 +197,55 @@ def benchmark_iteration(core_voltage, frequency): info = get_system_info() if info is None: print(YELLOW + "Skipping this iteration due to failure in fetching system info." + RESET) - return None, None, None, False, None, "SYSTEM_INFO_FAILURE" + return None, None, None, False, None, None, None, "SYSTEM_INFO_FAILURE" temp = info.get("temp") vr_temp = info.get("vrTemp") # Get VR temperature if available voltage = info.get("voltage") if temp is None: print(YELLOW + "Temperature data not available." + RESET) - return None, None, None, False, None, "TEMPERATURE_DATA_FAILURE" + return None, None, None, False, None, None, None, "TEMPERATURE_DATA_FAILURE" if temp < 5: print(YELLOW + "Temperature is below 5°C. This is unexpected. Please check the system." + RESET) - return None, None, None, False, None, "TEMPERATURE_BELOW_5" + return None, None, None, False, None, None, None, "TEMPERATURE_BELOW_5" # Check both chip and VR temperatures if temp >= max_temp: print(RED + f"Chip temperature exceeded {max_temp}°C! Stopping current benchmark." + RESET) - return None, None, None, False, None, "CHIP_TEMP_EXCEEDED" + return None, None, None, False, None, None, None, "CHIP_TEMP_EXCEEDED" if vr_temp is not None and vr_temp >= max_vr_temp: print(RED + f"Voltage regulator temperature exceeded {max_vr_temp}°C! Stopping current benchmark." + RESET) - return None, None, None, False, None, "VR_TEMP_EXCEEDED" + return None, None, None, False, None, None, None, "VR_TEMP_EXCEEDED" if voltage < min_input_voltage: print(RED + f"Input voltage is below the minimum allowed value of {min_input_voltage}mV! Stopping current benchmark." + RESET) - return None, None, None, False, None, "INPUT_VOLTAGE_BELOW_MIN" + return None, None, None, False, None, None, None, "INPUT_VOLTAGE_BELOW_MIN" if voltage > max_input_voltage: print(RED + f"Input voltage is above the maximum allowed value of {max_input_voltage}mV! Stopping current benchmark." + RESET) - return None, None, None, False, None, "INPUT_VOLTAGE_ABOVE_MAX" + return None, None, None, False, None, None, None, "INPUT_VOLTAGE_ABOVE_MAX" hash_rate = info.get("hashRate") power_consumption = info.get("power") - + fan_speed = info.get("fanspeed") + if hash_rate is None or power_consumption is None: print(YELLOW + "Hashrate or Watts data not available." + RESET) - return None, None, None, False, None, "HASHRATE_POWER_DATA_FAILURE" + return None, None, None, False, None, None, None, "HASHRATE_POWER_DATA_FAILURE" if power_consumption > max_power: print(RED + f"Power consumption exceeded {max_power}W! Stopping current benchmark." + RESET) - return None, None, None, False, None, "POWER_CONSUMPTION_EXCEEDED" + return None, None, None, False, None, None, None, "POWER_CONSUMPTION_EXCEEDED" hash_rates.append(hash_rate) temperatures.append(temp) power_consumptions.append(power_consumption) if vr_temp is not None and vr_temp > 0: vr_temps.append(vr_temp) + if fan_speed is not None: + fan_speeds.append(fan_speed) # Calculate percentage progress percentage_progress = ((sample + 1) / total_samples) * 100 @@ -256,6 +260,15 @@ def benchmark_iteration(core_voltage, frequency): ) if vr_temp is not None and vr_temp > 0: status_line += f" | VR: {int(vr_temp):2d}°C" + + # Add Power (Watts) to the status line if available + if power_consumption is not None: + status_line += f" | P: {int(power_consumption):2d} W" + + # Add Fan Speed to the status line if available + if fan_speed is not None: + status_line += f" | FAN: {int(fan_speed):2d}%" + print(status_line + RESET) # Only sleep if it's not the last iteration @@ -281,13 +294,18 @@ def benchmark_iteration(core_voltage, frequency): average_vr_temp = sum(trimmed_vr_temps) / len(trimmed_vr_temps) average_power = sum(power_consumptions) / len(power_consumptions) + + average_fan_speed = None + if fan_speeds: + average_fan_speed = sum(fan_speeds) / len(fan_speeds) + print(GREEN + f"Average Fan Speed: {average_fan_speed:.2f}%" + RESET) # Add protection against zero hashrate if average_hashrate > 0: efficiency_jth = average_power / (average_hashrate / 1_000) else: print(RED + "Warning: Zero hashrate detected, skipping efficiency calculation" + RESET) - return None, None, None, False, None, "ZERO_HASHRATE" + return None, None, None, False, None, None, None, "ZERO_HASHRATE" # Calculate if hashrate is within 6% of expected hashrate_within_tolerance = (average_hashrate >= expected_hashrate * 0.94) @@ -298,10 +316,10 @@ def benchmark_iteration(core_voltage, frequency): print(GREEN + f"Average VR Temperature: {average_vr_temp:.2f}°C" + RESET) print(GREEN + f"Efficiency: {efficiency_jth:.2f} J/TH" + RESET) - return average_hashrate, average_temperature, efficiency_jth, hashrate_within_tolerance, average_vr_temp, None + return average_hashrate, average_temperature, efficiency_jth, hashrate_within_tolerance, average_vr_temp, average_power, average_fan_speed, None else: print(YELLOW + "No Hashrate or Temperature or Watts data collected." + RESET) - return None, None, None, False, None, "NO_DATA_COLLECTED" + return None, None, None, False, None, None, None, "NO_DATA_COLLECTED" def save_results(): try: @@ -349,7 +367,7 @@ def reset_to_best_setting(): while current_voltage <= max_allowed_voltage and current_frequency <= max_allowed_frequency: set_system_settings(current_voltage, current_frequency) - avg_hashrate, avg_temp, efficiency_jth, hashrate_ok, avg_vr_temp, error_reason = benchmark_iteration(current_voltage, current_frequency) + avg_hashrate, avg_temp, efficiency_jth, hashrate_ok, avg_vr_temp, avg_power, avg_fan_speed, error_reason = benchmark_iteration(current_voltage, current_frequency) if avg_hashrate is not None and avg_temp is not None and efficiency_jth is not None: result = { @@ -357,12 +375,18 @@ def reset_to_best_setting(): "frequency": current_frequency, "averageHashRate": avg_hashrate, "averageTemperature": avg_temp, - "efficiencyJTH": efficiency_jth + "efficiencyJTH": efficiency_jth, + "averagePower": avg_power, + "errorReason": error_reason } # Only add VR temp if it exists if avg_vr_temp is not None: result["averageVRTemp"] = avg_vr_temp + + # Only add Fan Speed if it exists (assuming it's not None) + if avg_fan_speed is not None: + result["averageFanSpeed"] = avg_fan_speed results.append(result) @@ -425,7 +449,9 @@ def reset_to_best_setting(): "averageHashRate": result["averageHashRate"], "averageTemperature": result["averageTemperature"], "efficiencyJTH": result["efficiencyJTH"], - **({"averageVRTemp": result["averageVRTemp"]} if "averageVRTemp" in result else {}) + "averagePower": result["averagePower"], + **({"averageVRTemp": result["averageVRTemp"]} if "averageVRTemp" in result else {}), + **({"averageFanSpeed": result["averageFanSpeed"]} if "averageFanSpeed" in result else {}) } for i, result in enumerate(top_5_results, 1) ], @@ -437,7 +463,9 @@ def reset_to_best_setting(): "averageHashRate": result["averageHashRate"], "averageTemperature": result["averageTemperature"], "efficiencyJTH": result["efficiencyJTH"], - **({"averageVRTemp": result["averageVRTemp"]} if "averageVRTemp" in result else {}) + "averagePower": result["averagePower"], + **({"averageVRTemp": result["averageVRTemp"]} if "averageVRTemp" in result else {}), + **({"averageFanSpeed": result["averageFanSpeed"]} if "averageFanSpeed" in result else {}) } for i, result in enumerate(top_5_efficient_results, 1) ] @@ -459,6 +487,9 @@ def reset_to_best_setting(): print(GREEN + f" Average Hashrate: {result['averageHashRate']:.2f} GH/s" + RESET) print(GREEN + f" Average Temperature: {result['averageTemperature']:.2f}°C" + RESET) print(GREEN + f" Efficiency: {result['efficiencyJTH']:.2f} J/TH" + RESET) + print(GREEN + f" Average Power: {result['averagePower']:.2f} W" + RESET) + if "averageFanSpeed" in result: + print(GREEN + f" Average Fan Speed: {result['averageFanSpeed']:.2f}%" + RESET) if "averageVRTemp" in result: print(GREEN + f" Average VR Temperature: {result['averageVRTemp']:.2f}°C" + RESET) @@ -470,6 +501,9 @@ def reset_to_best_setting(): print(GREEN + f" Average Hashrate: {result['averageHashRate']:.2f} GH/s" + RESET) print(GREEN + f" Average Temperature: {result['averageTemperature']:.2f}°C" + RESET) print(GREEN + f" Efficiency: {result['efficiencyJTH']:.2f} J/TH" + RESET) + print(GREEN + f" Average Power: {result['averagePower']:.2f} W" + RESET) + if "averageFanSpeed" in result: + print(GREEN + f" Average Fan Speed: {result['averageFanSpeed']:.2f}%" + RESET) if "averageVRTemp" in result: print(GREEN + f" Average VR Temperature: {result['averageVRTemp']:.2f}°C" + RESET) else: From 99f832322557aba34b6a21d68f8fa0dc45250799 Mon Sep 17 00:00:00 2001 From: ZorgOros <95384420+zorgoros@users.noreply.github.com> Date: Wed, 9 Jul 2025 03:39:45 +0400 Subject: [PATCH 02/12] feat(cli): Add option to apply specific settings without benchmarking This commit introduces a new command-line option to directly set the core voltage and frequency on the Bitaxe miner, bypassing the full benchmarking process. **Motivation:** Previously, applying specific desired settings required either temporarily modifying the script or running a full benchmark starting at those settings. This new functionality provides a quick, convenient, and direct way to configure the miner to a known good state or a specific operating point without needing to run an entire benchmark cycle. This is particularly useful for fine-tuning after initial benchmarks, or for quickly re-applying optimal settings. **Implementation:** A new command-line flag, -sor--set-values, has been added using argparse. When this flag is detected, the script will: 1. Parse the provided core voltage (-v) and frequency (-f) as the target settings. 2. Call the existing set_system_settings() function to apply these parameters to the Bitaxe. 3. Print confirmation messages. 4. Exit immediately using sys.exit(0), preventing the benchmark loop from initiating. **Usage:** To use this new mode, run the script with the --set-values flag, specifying your desired voltage and frequency: python bitaxe_hasrate_benchmark.py --set-values -v -f Example: python bitaxe_hasrate_benchmark.py 192.168.1.136 --set-values -v 1150 -f 780 This enhancement streamlines the process of applying specific configurations to the Bitaxe miner.# --- bitaxe_hashrate_benchmark.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/bitaxe_hashrate_benchmark.py b/bitaxe_hashrate_benchmark.py index ea1238c..50ea93f 100644 --- a/bitaxe_hashrate_benchmark.py +++ b/bitaxe_hashrate_benchmark.py @@ -20,6 +20,10 @@ def parse_arguments(): parser.add_argument('-f', '--frequency', type=int, default=500, help='Initial frequency in MHz (default: 500)') + # Add a new argument for setting values only + parser.add_argument('-s', '--set-values', action='store_true', + help='Set values only, do not benchmark. Apply specified voltage and frequency settings to Bitaxe and exit') + # If no arguments are provided, print help and exit if len(sys.argv) == 1: parser.print_help() @@ -350,6 +354,17 @@ def reset_to_best_setting(): restart_system() +# --- Main execution logic --- +if args.set_values: + print(GREEN + "\n--- Applying Settings Only ---" + RESET) + print(GREEN + f"Applying Core Voltage: {initial_voltage}mV, Frequency: {initial_frequency}MHz to Bitaxe." + RESET) + + # Call the existing set_system_settings function + set_system_settings(initial_voltage, initial_frequency) + + print(GREEN + "Settings applied. Check your Bitaxe web interface to confirm." + RESET) + sys.exit(0) # Exit the script after applying settings + # Main benchmarking process try: fetch_default_settings() From 6b60b33be37176d511871dd8dabdf072e331f136 Mon Sep 17 00:00:00 2001 From: ZorgOros <95384420+zorgoros@users.noreply.github.com> Date: Wed, 9 Jul 2025 03:46:34 +0400 Subject: [PATCH 03/12] refactor(cli): Improve command-line help output Enhanced the script's command-line help message to be more user-friendly and informative. Key improvements include: * **Clearer Descriptions:** Detailed explanations for each argument, including their dual purpose for benchmarking and setting values. * **Usage Examples:** Added explicit command examples for both benchmark and set-only modes in the help message's epilog. * **Improved Formatting:** Utilized a custom formatter to preserve multi-line text, add default values, and incorporate color for better readability.# --- bitaxe_hashrate_benchmark.py | 80 ++++++++++++++++++++++++++++++------ 1 file changed, 67 insertions(+), 13 deletions(-) diff --git a/bitaxe_hashrate_benchmark.py b/bitaxe_hashrate_benchmark.py index 50ea93f..24986eb 100644 --- a/bitaxe_hashrate_benchmark.py +++ b/bitaxe_hashrate_benchmark.py @@ -11,24 +11,78 @@ RED = "\033[91m" RESET = "\033[0m" -# Add this before the configuration section +# This formatter allows for multi-line descriptions in help messages and adds default values +class RawTextAndDefaultsHelpFormatter(argparse.RawTextHelpFormatter): + def _get_help_string(self, action): + help_text = super()._get_help_string(action) + if action.default is not argparse.SUPPRESS: + # Append default value to help text if available + defaulting_nargs = [argparse.OPTIONAL, argparse.ZERO_OR_MORE] + if action.option_strings or action.nargs in defaulting_nargs: + if "\n" in help_text: + help_text += f"\n(default: {action.default})" + else: + help_text += f" (default: {action.default})" + return help_text + +# Modify the parse_arguments function def parse_arguments(): - parser = argparse.ArgumentParser(description='Bitaxe Hashrate Benchmark Tool') - parser.add_argument('bitaxe_ip', nargs='?', help='IP address of the Bitaxe (e.g., 192.168.2.26)') - parser.add_argument('-v', '--voltage', type=int, default=1150, - help='Initial voltage in mV (default: 1150)') - parser.add_argument('-f', '--frequency', type=int, default=500, - help='Initial frequency in MHz (default: 500)') - - # Add a new argument for setting values only - parser.add_argument('-s', '--set-values', action='store_true', - help='Set values only, do not benchmark. Apply specified voltage and frequency settings to Bitaxe and exit') - + parser = argparse.ArgumentParser( + description= + f"{GREEN}Bitaxe Hashrate Benchmark Tool v1.0{RESET}\n" + "This script allows you to either benchmark your Bitaxe miner across various " + "voltage and frequency settings, or apply specific settings directly.\n", + epilog= + f"{YELLOW}Examples:{RESET}\n" + f" {YELLOW}1. Run a full benchmark (starting at 1150mV, 500MHz):{RESET}\n" + f" {GREEN}python bitaxe_hasrate_benchmark.py 192.168.1.136 -v 1150 -f 500{RESET}\n\n" + f" {YELLOW}2. Apply specific settings (1150mV, 780MHz) and exit:{RESET}\n" + f" {GREEN}python bitaxe_hasrate_benchmark.py 192.168.1.136 --set-values -v 1150 -f 780{RESET}\n\n" + f" {YELLOW}3. Get help (this message):{RESET}\n" + f" {GREEN}python bitaxe_hasrate_benchmark.py --help{RESET}", + formatter_class=RawTextAndDefaultsHelpFormatter # <--- USE THE CUSTOM FORMATTER + ) + + # Positional Argument + parser.add_argument( + 'bitaxe_ip', + nargs='?', # Makes it optional if --help is used alone, but required otherwise + help=f"{YELLOW}IP address of your Bitaxe miner (e.g., 192.168.2.26){RESET}\n" + " This is required for both benchmarking and setting values." + ) + + # Optional Arguments + parser.add_argument( + '-v', '--voltage', + type=int, + default=1150, # Default value for benchmark start or target setting + help=f"{YELLOW}Core voltage in mV.{RESET}\n" + " For benchmark mode: The starting voltage for testing.\n" + " For --set-values mode: The exact voltage to apply." + ) + parser.add_argument( + '-f', '--frequency', + type=int, + default=500, # Default value for benchmark start or target setting + help=f"{YELLOW}Core frequency in MHz.{RESET}\n" + " For benchmark mode: The starting frequency for testing.\n" + " For --set-values mode: The exact frequency to apply." + ) + + # New argument for setting values only + parser.add_argument( + '-s', '--set-values', + action='store_true', + help=f"{YELLOW}Set values only; do not run benchmark.{RESET}\n" + " If this flag is present, the script will apply the voltage (-v) and\n" + " frequency (-f) settings to the Bitaxe and then exit." + ) + # If no arguments are provided, print help and exit if len(sys.argv) == 1: parser.print_help() sys.exit(1) - + return parser.parse_args() # Replace the configuration section From 6d19eb6ad6728c3aac049f0075ce9edba3e84545 Mon Sep 17 00:00:00 2001 From: ZorgOros <95384420+zorgoros@users.noreply.github.com> Date: Wed, 9 Jul 2025 03:56:59 +0400 Subject: [PATCH 04/12] add new readme based on latest changes --- README.md | 311 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 162 insertions(+), 149 deletions(-) diff --git a/README.md b/README.md index 4f023af..777d5f2 100644 --- a/README.md +++ b/README.md @@ -1,166 +1,179 @@ -# Bitaxe Hashrate Benchmark +# **Bitaxe Hashrate Benchmark** A Python-based benchmarking tool for optimizing Bitaxe mining performance by testing different voltage and frequency combinations while monitoring hashrate, temperature, and power efficiency. -## Features +## **Features** -- Automated benchmarking of different voltage/frequency combinations -- Temperature monitoring and safety cutoffs -- Power efficiency calculations (J/TH) -- Automatic saving of benchmark results -- Graceful shutdown with best settings retention -- Docker support for easy deployment - -## Prerequisites - -- Python 3.11 or higher -- Access to a Bitaxe miner on your network -- Docker (optional, for containerized deployment) -- Git (optional, for cloning the repository) - -## Installation - -### Standard Installation - -1. Clone the repository: -```bash -git clone https://github.com/mrv777/Bitaxe-Hashrate-Benchmark.git -cd Bitaxe-Hashrate-Benchmark -``` - -2. Create and activate a virtual environment: -```bash -python -m venv venv -# On Windows -venv\Scripts\activate -# On Linux/Mac -source venv/bin/activate -``` - -3. Install dependencies: -```bash -pip install -r requirements.txt -``` - -### Docker Installation - -1. Build the Docker image: -```bash -docker build -t bitaxe-benchmark . -``` - -## Usage - -### Standard Usage - -Run the benchmark tool by providing your Bitaxe's IP address: - -```bash -python bitaxe_hashrate_benchmark.py -``` - -Optional parameters: -- `-v, --voltage`: Initial voltage in mV (default: 1150) -- `-f, --frequency`: Initial frequency in MHz (default: 500) - -Example: -```bash -python bitaxe_hashrate_benchmark.py 192.168.2.29 -v 1175 -f 775 -``` - -### Docker Usage (Optional) - -Run the container with your Bitaxe's IP address: - -```bash -docker run --rm bitaxe-benchmark [options] -``` - -Example: -```bash -docker run --rm bitaxe-benchmark 192.168.2.26 -v 1200 -f 550 -``` - -## Configuration - -The script includes several configurable parameters: - -- Maximum chip temperature: 66°C -- Maximum VR temperature: 86°C -- Maximum allowed voltage: 1400mV -- Minimum allowed voltage: 1000mV -- Maximum allowed frequency: 1200MHz -- Maximum power consumption: 40W -- Minimum allowed frequency: 400MHz -- Minimum input voltage: 4800mV -- Maximum input voltage: 5500mV -- Benchmark duration: 10 minutes -- Sample interval: 15 seconds -- **Minimum required samples: 7** (for valid data processing) -- Voltage increment: 20mV -- Frequency increment: 25MHz - -## Output - -The benchmark results are saved to `bitaxe_benchmark_results_.json`, containing: -- Complete test results for all combinations -- Top 5 performing configurations ranked by hashrate -- Top 5 most efficient configurations ranked by J/TH -- For each configuration: - - Average hashrate (with outlier removal) - - Temperature readings (excluding initial warmup period) - - VR temperature readings (when available) - - Power efficiency metrics (J/TH) - - Input voltage measurements - - Voltage/frequency combinations tested - -## Safety Features - -- Automatic temperature monitoring with safety cutoff (66°C chip temp) -- Voltage regulator (VR) temperature monitoring with safety cutoff (86°C) -- Input voltage monitoring with minimum threshold (4800mV) and maximum threshold (5500mV) -- Power consumption monitoring with safety cutoff (40W) -- Temperature validation (must be above 5°C) -- Graceful shutdown on interruption (Ctrl+C) -- Automatic reset to best performing settings after benchmarking -- Input validation for safe voltage and frequency ranges -- Hashrate validation to ensure stability -- Protection against invalid system data -- Outlier removal from benchmark results - -## Benchmarking Process +* Automated benchmarking of different voltage/frequency combinations +* **Direct setting of specific voltage and frequency from command line** +* Temperature monitoring and safety cutoffs +* **Power consumption monitoring and reporting (Watts)** +* **Fan speed monitoring and reporting (RPM/Percentage)** +* Power efficiency calculations (J/TH) +* Automatic saving of benchmark results +* Graceful shutdown with best settings retention +* Docker support for easy deployment + +## **Prerequisites** + +* Python 3.11 or higher +* Access to a Bitaxe miner on your network +* Docker (optional, for containerized deployment) +* Git (optional, for cloning the repository) + +## **Installation** + +### **Standard Installation** + +1. Clone the repository: + git clone https://github.com/mrv777/Bitaxe-Hashrate-Benchmark.git + cd Bitaxe-Hashrate-Benchmark + +2. Create and activate a virtual environment: + python \-m venv venv + \# On Windows + venv\\Scripts\\activate + \# On Linux/Mac + source venv/bin/activate + +3. Install dependencies: + pip install \-r requirements.txt + +### **Docker Installation** + +1. Build the Docker image: + docker build \-t bitaxe-benchmark . + +## **Usage** + +### **Standard Usage (Run Full Benchmark)** + +Run the benchmark tool by providing your Bitaxe's IP address and initial settings: +python bitaxe\_hasrate\_benchmark.py \ \-v \ \-f \ + +**Arguments:** + +* \: **Required.** IP address of your Bitaxe miner (e.g., 192.168.2.26). +* \-v, \--voltage: **Optional.** Initial voltage in mV for testing (default: 1150). +* \-f, \--frequency: **Optional.** Initial frequency in MHz for testing (default: 500). + +**Example:** +python bitaxe\_hasrate\_benchmark.py 192.168.1.136 \-v 1150 \-f 500 + +### **Apply Specific Settings (Without Benchmarking)** + +To quickly apply specific voltage and frequency settings to your Bitaxe without running the full benchmark: +python bitaxe\_hasrate\_benchmark.py \ \--set-values \-v \ \-f \ + +**Arguments:** + +* \: **Required.** IP address of your Bitaxe miner. +* \-s, \--set-values: **Flag.** Activates this mode to only set values and exit. +* \-v, \--voltage: **Required.** The exact voltage in mV to apply. +* \-f, \--frequency: **Required.** The exact frequency in MHz to apply. + +**Example:** +python bitaxe\_hasrate\_benchmark.py 192.168.1.136 \--set-values \-v 1150 \-f 780 + +### **Docker Usage (Optional)** + +Run the container with your Bitaxe's IP address (add \--set-values for that mode): +docker run \--rm bitaxe-benchmark \ \[options\] + +Example (Full Benchmark): +docker run \--rm bitaxe-benchmark 192.168.2.26 \-v 1200 \-f 550 + +Example (Set Settings Only): +docker run \--rm bitaxe-benchmark 192.168.2.26 \--set-values \-v 1150 \-f 780 + +## **Configuration** + +The script includes several configurable parameters. These can be adjusted in the bitaxe\_hasrate\_benchmark.py file: + +* Maximum chip temperature: 66°C +* Maximum VR temperature: 86°C +* Maximum allowed voltage: 1400mV +* Minimum allowed voltage: 1000mV +* Maximum allowed frequency: 1200MHz +* Maximum power consumption: 30W +* Minimum allowed frequency: 400MHz +* Minimum input voltage: 4800mV +* Maximum input voltage: 5500mV +* Benchmark duration: 600 seconds (10 minutes per combination) +* Sample interval: 15 seconds +* Minimum required samples: 7 (for valid data processing) +* Voltage increment: 15mV +* Frequency increment: 20MHz +* **ASIC Configuration:** asic\_count is hardcoded to 1 as it's not always provided by the API. small\_core\_count is fetched from the Bitaxe. + +## **Output** + +The benchmark results are saved to bitaxe\_benchmark\_results\_\.json, containing: + +* Complete test results for all combinations +* Top 5 performing configurations ranked by hashrate +* Top 5 most efficient configurations ranked by J/TH +* For each configuration: + * Average hashrate (with outlier removal) + * Temperature readings (excluding initial warmup period) + * VR temperature readings (when available) + * Power efficiency metrics (J/TH) + * **Average Power (Watts)** + * **Average Fan Speed (Percentage or RPM, if available from API)** + * Input voltage measurements + * Voltage/frequency combinations tested + * Error reason (if any) for a specific iteration + +## **Safety Features** + +* Automatic temperature monitoring with safety cutoff (66°C chip temp) +* Voltage regulator (VR) temperature monitoring with safety cutoff (86°C) +* Input voltage monitoring with minimum threshold (4800mV) and maximum threshold (5500mV) +* Power consumption monitoring with safety cutoff (30W) +* Temperature validation (must be above 5°C) +* Graceful shutdown on interruption (Ctrl+C) +* Automatic reset to best performing settings after benchmarking +* Input validation for safe voltage and frequency ranges +* Hashrate validation to ensure stability +* Protection against invalid system data +* Outlier removal from benchmark results + +## **Benchmarking Process** The tool follows this process: -1. Starts with user-specified or default voltage/frequency -2. Tests each combination for 20 minutes -3. Validates hashrate is within 8% of theoretical maximum -4. Incrementally adjusts settings: - - Increases frequency if stable - - Increases voltage if unstable - - Stops at thermal or stability limits -5. Records and ranks all successful configurations -6. Automatically applies the best performing stable settings -7. Restarts system after each test for stability + +1. Starts with user-specified or default voltage/frequency +2. Tests each combination for 10 minutes +3. Validates hashrate is within 8% of theoretical maximum +4. Incrementally adjusts settings: + * Increases frequency if stable + * Increases voltage if unstable + * Stops at thermal or stability limits +5. Records and ranks all successful configurations +6. Automatically applies the best performing stable settings +7. Restarts system after each test for stability 8. Allows 90-second stabilization period between tests -## Data Processing +## **Data Processing** The tool implements several data processing techniques to ensure accurate results: -- Removes 3 highest and 3 lowest hashrate readings to eliminate outliers -- Excludes first 6 temperature readings during warmup period -- Validates hashrate is within 6% of theoretical maximum -- Averages power consumption across entire test period -- Monitors VR temperature when available -- Calculates efficiency in Joules per Terahash (J/TH) -## Contributing +* Removes 3 highest and 3 lowest hashrate readings to eliminate outliers +* Excludes first 6 temperature readings during warmup period +* Validates hashrate is within 6% of theoretical maximum +* Averages power consumption across entire test period +* Monitors VR temperature when available +* Calculates efficiency in Joules per Terahash (J/TH) +* **Averages fan speed across entire test period** + +## **Contributing** -Contributions are welcome! Please feel free to submit a Pull Request. +Contributions are welcome\! Please feel free to submit a Pull Request. -## License +## **License** -This project is licensed under the GNU General Public License v3.0 - see the [LICENSE](LICENSE) file for details. +This project is licensed under the GNU General Public License v3.0 \- see the [LICENSE](https://www.google.com/search?q=LICENSE) file for details. -## Disclaimer +## **Disclaimer** Please use this tool responsibly. Overclocking and voltage modifications can potentially damage your hardware if not done carefully. Always ensure proper cooling and monitor your device during benchmarking. \ No newline at end of file From 36c4fc1d5d759ce68376ba129ab53afec2d91107 Mon Sep 17 00:00:00 2001 From: ZorgOros <95384420+zorgoros@users.noreply.github.com> Date: Wed, 9 Jul 2025 04:04:07 +0400 Subject: [PATCH 05/12] add new readme based on latest changes --- README.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 777d5f2..24c363b 100644 --- a/README.md +++ b/README.md @@ -26,36 +26,46 @@ A Python-based benchmarking tool for optimizing Bitaxe mining performance by tes ### **Standard Installation** 1. Clone the repository: + ``` git clone https://github.com/mrv777/Bitaxe-Hashrate-Benchmark.git cd Bitaxe-Hashrate-Benchmark + ``` 2. Create and activate a virtual environment: + ``` python \-m venv venv \# On Windows venv\\Scripts\\activate \# On Linux/Mac source venv/bin/activate + ``` 3. Install dependencies: + ``` pip install \-r requirements.txt + ``` ### **Docker Installation** 1. Build the Docker image: + ``` docker build \-t bitaxe-benchmark . + ``` ## **Usage** ### **Standard Usage (Run Full Benchmark)** Run the benchmark tool by providing your Bitaxe's IP address and initial settings: +``` python bitaxe\_hasrate\_benchmark.py \ \-v \ \-f \ +``` **Arguments:** * \: **Required.** IP address of your Bitaxe miner (e.g., 192.168.2.26). -* \-v, \--voltage: **Optional.** Initial voltage in mV for testing (default: 1150). -* \-f, \--frequency: **Optional.** Initial frequency in MHz for testing (default: 500). +```* \-v, \--voltage:``` **Optional.** Initial voltage in mV for testing (default: 1150). +```* \-f, \--frequency:``` **Optional.** Initial frequency in MHz for testing (default: 500). **Example:** python bitaxe\_hasrate\_benchmark.py 192.168.1.136 \-v 1150 \-f 500 From 44b2992bed0977e0d78b9b94dfbcf8ca369252bf Mon Sep 17 00:00:00 2001 From: ZorgOros <95384420+zorgoros@users.noreply.github.com> Date: Wed, 9 Jul 2025 04:06:19 +0400 Subject: [PATCH 06/12] add new readme based on latest changes --- README.md | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 24c363b..d041414 100644 --- a/README.md +++ b/README.md @@ -68,33 +68,45 @@ python bitaxe\_hasrate\_benchmark.py \ \-v \ \-f ```* \-f, \--frequency:``` **Optional.** Initial frequency in MHz for testing (default: 500). **Example:** +``` python bitaxe\_hasrate\_benchmark.py 192.168.1.136 \-v 1150 \-f 500 +``` ### **Apply Specific Settings (Without Benchmarking)** To quickly apply specific voltage and frequency settings to your Bitaxe without running the full benchmark: +``` python bitaxe\_hasrate\_benchmark.py \ \--set-values \-v \ \-f \ +``` **Arguments:** * \: **Required.** IP address of your Bitaxe miner. -* \-s, \--set-values: **Flag.** Activates this mode to only set values and exit. -* \-v, \--voltage: **Required.** The exact voltage in mV to apply. -* \-f, \--frequency: **Required.** The exact frequency in MHz to apply. +```* \-s, \--set-values:``` **Flag.** Activates this mode to only set values and exit. +```* \-v, \--voltage:``` **Required.** The exact voltage in mV to apply. +```* \-f, \--frequency:``` **Required.** The exact frequency in MHz to apply. **Example:** +``` python bitaxe\_hasrate\_benchmark.py 192.168.1.136 \--set-values \-v 1150 \-f 780 +``` ### **Docker Usage (Optional)** Run the container with your Bitaxe's IP address (add \--set-values for that mode): +``` docker run \--rm bitaxe-benchmark \ \[options\] +``` Example (Full Benchmark): +``` docker run \--rm bitaxe-benchmark 192.168.2.26 \-v 1200 \-f 550 +``` Example (Set Settings Only): +``` docker run \--rm bitaxe-benchmark 192.168.2.26 \--set-values \-v 1150 \-f 780 +``` ## **Configuration** From 0604faca5f50b65278b3bd1840339a83f1be1690 Mon Sep 17 00:00:00 2001 From: ZorgOros <95384420+zorgoros@users.noreply.github.com> Date: Wed, 9 Jul 2025 04:10:34 +0400 Subject: [PATCH 07/12] add new readme based on latest changes --- README.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index d041414..f0b73e2 100644 --- a/README.md +++ b/README.md @@ -26,13 +26,13 @@ A Python-based benchmarking tool for optimizing Bitaxe mining performance by tes ### **Standard Installation** 1. Clone the repository: - ``` + ```bash git clone https://github.com/mrv777/Bitaxe-Hashrate-Benchmark.git cd Bitaxe-Hashrate-Benchmark ``` 2. Create and activate a virtual environment: - ``` + ```bash python \-m venv venv \# On Windows venv\\Scripts\\activate @@ -41,15 +41,15 @@ A Python-based benchmarking tool for optimizing Bitaxe mining performance by tes ``` 3. Install dependencies: - ``` + ```bash pip install \-r requirements.txt ``` ### **Docker Installation** 1. Build the Docker image: - ``` - docker build \-t bitaxe-benchmark . + ```bash + docker build \-t bitaxe-benchmark ``` ## **Usage** @@ -57,7 +57,7 @@ A Python-based benchmarking tool for optimizing Bitaxe mining performance by tes ### **Standard Usage (Run Full Benchmark)** Run the benchmark tool by providing your Bitaxe's IP address and initial settings: -``` +```bash python bitaxe\_hasrate\_benchmark.py \ \-v \ \-f \ ``` @@ -68,14 +68,14 @@ python bitaxe\_hasrate\_benchmark.py \ \-v \ \-f ```* \-f, \--frequency:``` **Optional.** Initial frequency in MHz for testing (default: 500). **Example:** -``` +```bash python bitaxe\_hasrate\_benchmark.py 192.168.1.136 \-v 1150 \-f 500 ``` ### **Apply Specific Settings (Without Benchmarking)** To quickly apply specific voltage and frequency settings to your Bitaxe without running the full benchmark: -``` +```bash python bitaxe\_hasrate\_benchmark.py \ \--set-values \-v \ \-f \ ``` @@ -87,24 +87,24 @@ python bitaxe\_hasrate\_benchmark.py \ \--set-values \-v \ \[options\] ``` Example (Full Benchmark): -``` +```bash docker run \--rm bitaxe-benchmark 192.168.2.26 \-v 1200 \-f 550 ``` Example (Set Settings Only): -``` +```bash docker run \--rm bitaxe-benchmark 192.168.2.26 \--set-values \-v 1150 \-f 780 ``` From 7d4da387c05d78f71ff41f540131f196fe8a8f88 Mon Sep 17 00:00:00 2001 From: ZorgOros <95384420+zorgoros@users.noreply.github.com> Date: Thu, 10 Jul 2025 13:00:37 +0400 Subject: [PATCH 08/12] fix(docs): Correct README argument inline code formatting Resolved rendering issues in argument lists by correctly applying single backticks for inline code, ensuring proper display on GitHub. --- README.md | 64 ++++++++++++++++++++++++++----------------------------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index f0b73e2..2322522 100644 --- a/README.md +++ b/README.md @@ -32,25 +32,21 @@ A Python-based benchmarking tool for optimizing Bitaxe mining performance by tes ``` 2. Create and activate a virtual environment: - ```bash - python \-m venv venv - \# On Windows - venv\\Scripts\\activate - \# On Linux/Mac - source venv/bin/activate - ``` + `python -m venv venv` + # On Windows + `venvScriptsactivate` + # On Linux/Mac + `source venv/bin/activate` + + +3. Install dependencies: + `pip install -r requirements.txt` -3. Install dependencies: - ```bash - pip install \-r requirements.txt - ``` ### **Docker Installation** 1. Build the Docker image: - ```bash - docker build \-t bitaxe-benchmark - ``` + `docker build -t bitaxe-benchmark` ## **Usage** @@ -58,59 +54,59 @@ A Python-based benchmarking tool for optimizing Bitaxe mining performance by tes Run the benchmark tool by providing your Bitaxe's IP address and initial settings: ```bash -python bitaxe\_hasrate\_benchmark.py \ \-v \ \-f \ +python bitaxe_hashrate_benchmark.py -v -f ``` **Arguments:** -* \: **Required.** IP address of your Bitaxe miner (e.g., 192.168.2.26). -```* \-v, \--voltage:``` **Optional.** Initial voltage in mV for testing (default: 1150). -```* \-f, \--frequency:``` **Optional.** Initial frequency in MHz for testing (default: 500). +* ``: **Required.** IP address of your Bitaxe miner (e.g., `192.168.2.26`). +* `-v, --voltage:` **Optional.** Initial voltage in mV for testing (default: `1150`). +* `-f, --frequency:` **Optional.** Initial frequency in MHz for testing (default: `500`). **Example:** ```bash -python bitaxe\_hasrate\_benchmark.py 192.168.1.136 \-v 1150 \-f 500 +python bitaxe_hashrate_benchmark.py 192.168.1.136 -v 1150 -f 550 ``` ### **Apply Specific Settings (Without Benchmarking)** To quickly apply specific voltage and frequency settings to your Bitaxe without running the full benchmark: ```bash -python bitaxe\_hasrate\_benchmark.py \ \--set-values \-v \ \-f \ +python bitaxe_hashrate_benchmark.py --set-values -v -f ``` **Arguments:** -* \: **Required.** IP address of your Bitaxe miner. -```* \-s, \--set-values:``` **Flag.** Activates this mode to only set values and exit. -```* \-v, \--voltage:``` **Required.** The exact voltage in mV to apply. -```* \-f, \--frequency:``` **Required.** The exact frequency in MHz to apply. +* ``: **Required.** IP address of your Bitaxe miner. +* `-s, --set-values`: **Flag.** Activates this mode to only set values and exit. +* `-v, --voltage`: **Required.** The exact voltage in mV to apply. +* `-f, --frequency`: **Required.** The exact frequency in MHz to apply. **Example:** ```bash -python bitaxe\_hasrate\_benchmark.py 192.168.1.136 \--set-values \-v 1150 \-f 780 +python bitaxe_hashrate_benchmark.py 192.168.1.136 --set-values -v 1150 -f 780 ``` ### **Docker Usage (Optional)** -Run the container with your Bitaxe's IP address (add \--set-values for that mode): +Run the container with your Bitaxe's IP address (add --set-values for that mode): ```bash -docker run \--rm bitaxe-benchmark \ \[options\] +docker run --rm bitaxe-benchmark [options] ``` Example (Full Benchmark): ```bash -docker run \--rm bitaxe-benchmark 192.168.2.26 \-v 1200 \-f 550 +docker run --rm bitaxe-benchmark 192.168.2.26 -v 1200 -f 550 ``` Example (Set Settings Only): ```bash -docker run \--rm bitaxe-benchmark 192.168.2.26 \--set-values \-v 1150 \-f 780 +docker run --rm bitaxe-benchmark 192.168.2.26 --set-values -v 1150 -f 780 ``` ## **Configuration** -The script includes several configurable parameters. These can be adjusted in the bitaxe\_hasrate\_benchmark.py file: +The script includes several configurable parameters. These can be adjusted in the bitaxe_hashrate_benchmark.py file: * Maximum chip temperature: 66°C * Maximum VR temperature: 86°C @@ -126,11 +122,11 @@ The script includes several configurable parameters. These can be adjusted in th * Minimum required samples: 7 (for valid data processing) * Voltage increment: 15mV * Frequency increment: 20MHz -* **ASIC Configuration:** asic\_count is hardcoded to 1 as it's not always provided by the API. small\_core\_count is fetched from the Bitaxe. +* **ASIC Configuration:** asic_count is hardcoded to 1 as it's not always provided by the API. small_core_count is fetched from the Bitaxe. ## **Output** -The benchmark results are saved to bitaxe\_benchmark\_results\_\.json, containing: +The benchmark results are saved to bitaxe_benchmark_results_.json, containing: * Complete test results for all combinations * Top 5 performing configurations ranked by hashrate @@ -190,11 +186,11 @@ The tool implements several data processing techniques to ensure accurate result ## **Contributing** -Contributions are welcome\! Please feel free to submit a Pull Request. +Contributions are welcome! Please feel free to submit a Pull Request. ## **License** -This project is licensed under the GNU General Public License v3.0 \- see the [LICENSE](https://www.google.com/search?q=LICENSE) file for details. +This project is licensed under the GNU General Public License v3.0 - see the [LICENSE](https://www.google.com/search?q=LICENSE) file for details. ## **Disclaimer** From 9033a22fd8fffb5e82adecedd5e031f952f8e2ab Mon Sep 17 00:00:00 2001 From: ZorgOros <95384420+zorgoros@users.noreply.github.com> Date: Thu, 10 Jul 2025 13:04:01 +0400 Subject: [PATCH 09/12] fix(docs): Correct README argument inline code formatting Resolved rendering issues in argument lists by correctly applying single backticks for inline code, ensuring proper display on GitHub. --- README.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 2322522..8e35c8e 100644 --- a/README.md +++ b/README.md @@ -32,16 +32,18 @@ A Python-based benchmarking tool for optimizing Bitaxe mining performance by tes ``` 2. Create and activate a virtual environment: - `python -m venv venv` + ```bash + python -m venv venv # On Windows - `venvScriptsactivate` + venvScriptsactivate # On Linux/Mac - `source venv/bin/activate` - + source venv/bin/activate + ``` 3. Install dependencies: - `pip install -r requirements.txt` - + ```bash + pip install -r requirements.txt + ``` ### **Docker Installation** From 77a3cdafacb893a1c6c5408a6e7b18cee963c376 Mon Sep 17 00:00:00 2001 From: ZorgOros <95384420+zorgoros@users.noreply.github.com> Date: Thu, 10 Jul 2025 14:00:12 +0400 Subject: [PATCH 10/12] refining readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8e35c8e..bc8c01e 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ A Python-based benchmarking tool for optimizing Bitaxe mining performance by tes ```bash python -m venv venv # On Windows - venvScriptsactivate + venv\Scripts\activate # On Linux/Mac source venv/bin/activate ``` @@ -48,7 +48,7 @@ A Python-based benchmarking tool for optimizing Bitaxe mining performance by tes ### **Docker Installation** 1. Build the Docker image: - `docker build -t bitaxe-benchmark` + `docker build -t bitaxe-benchmark .` ## **Usage** From 2edbeb44cd6330847c4d9daa6ca4547614fb9415 Mon Sep 17 00:00:00 2001 From: ZorgOros <95384420+zorgoros@users.noreply.github.com> Date: Fri, 11 Jul 2025 14:58:53 +0400 Subject: [PATCH 11/12] refining readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bc8c01e..b56abff 100644 --- a/README.md +++ b/README.md @@ -192,7 +192,7 @@ Contributions are welcome! Please feel free to submit a Pull Request. ## **License** -This project is licensed under the GNU General Public License v3.0 - see the [LICENSE](https://www.google.com/search?q=LICENSE) file for details. +This project is licensed under the GNU General Public License v3.0 - see the [LICENSE](LICENSE) file for details. ## **Disclaimer** From fd3d302aa3d6ca7bcb7652792177a0d1ee08b472 Mon Sep 17 00:00:00 2001 From: ZorgOros <95384420+zorgoros@users.noreply.github.com> Date: Fri, 11 Jul 2025 23:17:39 +0400 Subject: [PATCH 12/12] refining readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b56abff..c54d8ef 100644 --- a/README.md +++ b/README.md @@ -164,7 +164,7 @@ The tool follows this process: 1. Starts with user-specified or default voltage/frequency 2. Tests each combination for 10 minutes -3. Validates hashrate is within 8% of theoretical maximum +3. Validates hashrate is within 6% of theoretical maximum 4. Incrementally adjusts settings: * Increases frequency if stable * Increases voltage if unstable