From b68a9500621735b523f4f30c986e3c0cc190b911 Mon Sep 17 00:00:00 2001 From: ms Date: Tue, 17 Feb 2026 14:01:59 +0100 Subject: [PATCH] Update modb_orno_tester.c ocena szybkosci oparta tylko na poprawnych ramkach ignorowane ramki z blednym CRC lub timoutem --- modb_orno_tester.c | 189 +++++++++++++++++++++++++++++++-------------- 1 file changed, 130 insertions(+), 59 deletions(-) diff --git a/modb_orno_tester.c b/modb_orno_tester.c index 44fe200..6044352 100644 --- a/modb_orno_tester.c +++ b/modb_orno_tester.c @@ -8,6 +8,7 @@ #include #include #include +#include /* Konfiguracja */ #define USB_DEV_DEFAULT "/dev/ttyUSB0" @@ -23,6 +24,9 @@ #define SUN2K_RTS_DELAY 5000 #define SUN2K_BYTE_TIMEOUT 2500 +/* Stała dla timeoutu - wartości powyżej tego są uznawane za timeout */ +#define TIMEOUT_THRESHOLD_US 100000 /* 100ms */ + /* Struktura do przechowywania wyników testu */ typedef struct { long total_time_us; @@ -31,60 +35,88 @@ typedef struct { double avg_time_ms; int successful_reads; int total_reads; + int crc_errors; + int timeouts; } test_results_t; /* Timed wrapper for modbus_read_registers - logs start/stop and duration */ -long modbus_read_timed(modbus_t *ctx, int addr, int nb, uint16_t *dest) +long modbus_read_timed(modbus_t *ctx, int addr, int nb, uint16_t *dest, int *success) { struct timeval t0, t1; gettimeofday(&t0, NULL); int res = modbus_read_registers(ctx, addr, nb, dest); gettimeofday(&t1, NULL); long elapsed_us = (t1.tv_sec - t0.tv_sec) * 1000000 + (t1.tv_usec - t0.tv_usec); - + if (res < 0) { - printf("MBUS: modbus_read_registers addr=0x%X nb=%d -> ERR (%s) elapsed=%ldus\n", - addr, nb, modbus_strerror(errno), elapsed_us); + const char *error_str = modbus_strerror(errno); + printf("MBUS: modbus_read_registers addr=0x%X nb=%d -> ERR (%s) elapsed=%ldus\n", + addr, nb, error_str, elapsed_us); + + if (strstr(error_str, "timeout") || strstr(error_str, "Timed out") || elapsed_us > TIMEOUT_THRESHOLD_US) { + *success = 0; /* Timeout */ + return -2; + } else if (strstr(error_str, "CRC") || strstr(error_str, "crc")) { + *success = -1; /* CRC error */ + return -1; + } else { + *success = 0; /* Inny błąd */ + return 0; + } } else { - printf("MBUS: modbus_read_registers addr=0x%X nb=%d -> OK (%d) elapsed=%ldus\n", + printf("MBUS: modbus_read_registers addr=0x%X nb=%d -> OK (%d) elapsed=%ldus\n", addr, nb, res, elapsed_us); + *success = 1; /* Sukces */ + return elapsed_us; } - return elapsed_us; } /* Test function for ORNO voltage reading */ int test_orno_voltage(modbus_t *ctx, test_results_t *results) { uint16_t reg[6]; long elapsed_time; - + int success_flag; + results->total_time_us = 0; results->min_time_us = LONG_MAX; results->max_time_us = 0; results->successful_reads = 0; results->total_reads = NUM_READINGS; - + results->crc_errors = 0; + results->timeouts = 0; + printf("\n=== TESTING ORNO VOLTAGE READING ===\n"); printf("Performing %d voltage readings...\n", NUM_READINGS); - + for (int i = 0; i < NUM_READINGS; i++) { printf("Reading %d: ", i+1); - elapsed_time = modbus_read_timed(ctx, 0x0e, 6, reg); - - if (elapsed_time > 0) { + elapsed_time = modbus_read_timed(ctx, 0x0e, 6, reg, &success_flag); + + if (success_flag == 1) { + /* Poprawny odczyt */ results->total_time_us += elapsed_time; if (elapsed_time < results->min_time_us) results->min_time_us = elapsed_time; if (elapsed_time > results->max_time_us) results->max_time_us = elapsed_time; results->successful_reads++; - + float U1 = modbus_get_float_abcd(®[0]); float U2 = modbus_get_float_abcd(®[2]); float U3 = modbus_get_float_abcd(®[4]); printf("Voltages: L1=%.1fV L2=%.1fV L3=%.1fV\n", U1, U2, U3); + } else if (success_flag == -1) { + /* Błąd CRC */ + results->crc_errors++; + printf("CRC Error\n"); + } else if (success_flag == 0) { + /* Timeout lub inny błąd */ + results->timeouts++; + printf("Timeout/Error\n"); } - + usleep(10000); // 10ms delay between reads } - + + /* Oblicz statystyki tylko dla poprawnych odczytów */ if (results->successful_reads > 0) { results->avg_time_ms = (double)results->total_time_us / results->successful_reads / 1000.0; } else { @@ -92,7 +124,7 @@ int test_orno_voltage(modbus_t *ctx, test_results_t *results) { results->min_time_us = 0; results->max_time_us = 0; } - + return 0; } @@ -100,35 +132,48 @@ int test_orno_voltage(modbus_t *ctx, test_results_t *results) { int test_sun2k_voltage(modbus_t *ctx, test_results_t *results) { uint16_t reg[3]; long elapsed_time; - + int success_flag; + results->total_time_us = 0; results->min_time_us = LONG_MAX; results->max_time_us = 0; results->successful_reads = 0; results->total_reads = NUM_READINGS; - + results->crc_errors = 0; + results->timeouts = 0; + printf("\n=== TESTING SUN2K VOLTAGE READING ===\n"); printf("Performing %d voltage readings...\n", NUM_READINGS); - + for (int i = 0; i < NUM_READINGS; i++) { printf("Reading %d: ", i+1); - elapsed_time = modbus_read_timed(ctx, 32069, 3, reg); - - if (elapsed_time > 0) { + elapsed_time = modbus_read_timed(ctx, 32069, 3, reg, &success_flag); + + if (success_flag == 1) { + /* Poprawny odczyt */ results->total_time_us += elapsed_time; if (elapsed_time < results->min_time_us) results->min_time_us = elapsed_time; if (elapsed_time > results->max_time_us) results->max_time_us = elapsed_time; results->successful_reads++; - + float U_A = (float)reg[0] / 10.0; float U_B = (float)reg[1] / 10.0; float U_C = (float)reg[2] / 10.0; printf("Voltages: U_A=%.1fV U_B=%.1fV U_C=%.1fV\n", U_A, U_B, U_C); + } else if (success_flag == -1) { + /* Błąd CRC */ + results->crc_errors++; + printf("CRC Error\n"); + } else if (success_flag == 0) { + /* Timeout lub inny błąd */ + results->timeouts++; + printf("Timeout/Error\n"); } - + usleep(10000); // 10ms delay between reads } - + + /* Oblicz statystyki tylko dla poprawnych odczytów */ if (results->successful_reads > 0) { results->avg_time_ms = (double)results->total_time_us / results->successful_reads / 1000.0; } else { @@ -136,7 +181,7 @@ int test_sun2k_voltage(modbus_t *ctx, test_results_t *results) { results->min_time_us = 0; results->max_time_us = 0; } - + return 0; } @@ -147,19 +192,19 @@ modbus_t* init_orno_context(const char *device, int slave_addr) { fprintf(stderr, "ORNO: Failed to create the context: %s\n", modbus_strerror(errno)); return NULL; } - + modbus_set_slave(ctx, slave_addr); - + if (modbus_connect(ctx) == -1) { fprintf(stderr, "ORNO: Unable to connect: %s\n", modbus_strerror(errno)); modbus_free(ctx); return NULL; } - + modbus_rtu_set_rts_delay(ctx, ORNO_RTS_DELAY); modbus_set_response_timeout(ctx, 0, 900000); /* 0.9s */ modbus_set_byte_timeout(ctx, 0, ORNO_BYTE_TIMEOUT); - + printf("ORNO: Context initialized successfully\n"); return ctx; } @@ -171,19 +216,19 @@ modbus_t* init_sun2k_context(const char *device, int slave_addr) { fprintf(stderr, "SUN2K: Failed to create the context: %s\n", modbus_strerror(errno)); return NULL; } - + modbus_set_slave(ctx, slave_addr); - + if (modbus_connect(ctx) == -1) { fprintf(stderr, "SUN2K: Unable to connect: %s\n", modbus_strerror(errno)); modbus_free(ctx); return NULL; } - + modbus_rtu_set_rts_delay(ctx, SUN2K_RTS_DELAY); modbus_set_response_timeout(ctx, 0, 900000); /* 0.9s */ modbus_set_byte_timeout(ctx, 0, SUN2K_BYTE_TIMEOUT); - + printf("SUN2K: Context initialized successfully\n"); return ctx; } @@ -193,49 +238,74 @@ void print_results(const char *device_name, test_results_t *results) { printf("\n=== %s TEST RESULTS ===\n", device_name); printf("Total readings: %d\n", results->total_reads); printf("Successful readings: %d\n", results->successful_reads); - printf("Success rate: %.1f%%\n", + printf("CRC errors: %d\n", results->crc_errors); + printf("Timeouts/Other errors: %d\n", results->timeouts); + printf("Success rate: %.1f%%\n", (results->total_reads > 0) ? (100.0 * results->successful_reads / results->total_reads) : 0); - + if (results->successful_reads > 0) { printf("Average time per reading: %.2f ms\n", results->avg_time_ms); printf("Minimum time: %.2f ms\n", results->min_time_us / 1000.0); printf("Maximum time: %.2f ms\n", results->max_time_us / 1000.0); - printf("Total time for all readings: %.2f ms\n", results->total_time_us / 1000.0); + printf("Total time for successful readings: %.2f ms\n", results->total_time_us / 1000.0); } else { printf("No successful readings!\n"); } printf("========================\n\n"); } -/* Compare devices and recommend faster one */ +/* Compare devices and recommend faster one (based only on successful readings) */ void compare_and_recommend(test_results_t *orno_results, test_results_t *sun2k_results) { printf("=== COMPARISON AND RECOMMENDATION ===\n"); - + if (orno_results->successful_reads == 0 && sun2k_results->successful_reads == 0) { printf("ERROR: Neither device could be read successfully!\n"); return; } - + if (orno_results->successful_reads > 0 && sun2k_results->successful_reads > 0) { printf("Both devices are working. Comparison:\n"); - printf("- ORNO average time: %.2f ms\n", orno_results->avg_time_ms); - printf("- SUN2K average time: %.2f ms\n", sun2k_results->avg_time_ms); - + printf("- ORNO average time: %.2f ms (from %d successful readings)\n", + orno_results->avg_time_ms, orno_results->successful_reads); + printf("- SUN2K average time: %.2f ms (from %d successful readings)\n", + sun2k_results->avg_time_ms, sun2k_results->successful_reads); + if (orno_results->avg_time_ms < sun2k_results->avg_time_ms) { - printf("RECOMMENDATION: ORNO is faster by %.2f ms per reading\n", + printf("RECOMMENDATION: ORNO is faster by %.2f ms per reading\n", sun2k_results->avg_time_ms - orno_results->avg_time_ms); } else if (sun2k_results->avg_time_ms < orno_results->avg_time_ms) { - printf("RECOMMENDATION: SUN2K is faster by %.2f ms per reading\n", + printf("RECOMMENDATION: SUN2K is faster by %.2f ms per reading\n", orno_results->avg_time_ms - sun2k_results->avg_time_ms); } else { printf("RECOMMENDATION: Both devices have similar performance\n"); } } else if (orno_results->successful_reads > 0) { - printf("RECOMMENDATION: Only ORNO is working properly. Use ORNO for fast voltage readings.\n"); + printf("RECOMMENDATION: Only ORNO has successful readings (%d). Use ORNO for fast voltage readings.\n", + orno_results->successful_reads); } else if (sun2k_results->successful_reads > 0) { - printf("RECOMMENDATION: Only SUN2K is working properly. Use SUN2K for fast voltage readings.\n"); + printf("RECOMMENDATION: Only SUN2K has successful readings (%d). Use SUN2K for fast voltage readings.\n", + sun2k_results->successful_reads); } - + + /* Reliability analysis */ + printf("\nReliability Analysis:\n"); + if (orno_results->crc_errors > 0 || orno_results->timeouts > 0) { + printf("- ORNO had %d CRC errors and %d timeouts\n", + orno_results->crc_errors, orno_results->timeouts); + } + if (sun2k_results->crc_errors > 0 || sun2k_results->timeouts > 0) { + printf("- SUN2K had %d CRC errors and %d timeouts\n", + sun2k_results->crc_errors, sun2k_results->timeouts); + } + + if ((orno_results->crc_errors + orno_results->timeouts) > (sun2k_results->crc_errors + sun2k_results->timeouts)) { + printf("RELIABILITY: SUN2K is more reliable\n"); + } else if ((orno_results->crc_errors + orno_results->timeouts) < (sun2k_results->crc_errors + sun2k_results->timeouts)) { + printf("RELIABILITY: ORNO is more reliable\n"); + } else { + printf("RELIABILITY: Both devices show similar reliability\n"); + } + printf("=====================================\n"); } @@ -243,10 +313,10 @@ int main(int argc, char *argv[]) { const char *USB_DEV = USB_DEV_DEFAULT; int ORNO_SLAVE = ORNO_SLAVE_ADR; int SUN2000_SLAVE = SUN2000_SLAVE_ADR; - + test_results_t orno_results = {0}; test_results_t sun2k_results = {0}; - + printf("==============================================\n"); printf("Voltage Reading Speed Test\n"); printf("Testing ORNO vs SUN2K voltage reading speed\n"); @@ -257,7 +327,7 @@ int main(int argc, char *argv[]) { printf(" SUN2K slave address: %d\n", SUN2000_SLAVE); printf(" Number of readings per device: %d\n", NUM_READINGS); printf("==============================================\n\n"); - + // Test ORNO modbus_t *orno_ctx = init_orno_context(USB_DEV, ORNO_SLAVE); if (orno_ctx) { @@ -268,9 +338,9 @@ int main(int argc, char *argv[]) { printf("ORNO: Could not initialize context. Skipping ORNO tests.\n"); orno_results.successful_reads = 0; } - + usleep(100000); // 100ms delay between devices - + // Test SUN2K modbus_t *sun2k_ctx = init_sun2k_context(USB_DEV, SUN2000_SLAVE); if (sun2k_ctx) { @@ -281,19 +351,20 @@ int main(int argc, char *argv[]) { printf("SUN2K: Could not initialize context. Skipping SUN2K tests.\n"); sun2k_results.successful_reads = 0; } - + // Print results - if (orno_results.successful_reads > 0) { + if (orno_results.total_reads > 0) { print_results("ORNO", &orno_results); } - - if (sun2k_results.successful_reads > 0) { + + if (sun2k_results.total_reads > 0) { print_results("SUN2K", &sun2k_results); } - + // Compare and recommend compare_and_recommend(&orno_results, &sun2k_results); - + printf("\nTest completed.\n"); return 0; } +