Update modb_orno_tester.c

ocena szybkosci oparta tylko na poprawnych ramkach ignorowane ramki z blednym CRC lub timoutem
This commit is contained in:
ms
2026-02-17 14:01:59 +01:00
parent 7a03a794ba
commit b68a950062

View File

@@ -8,6 +8,7 @@
#include <unistd.h> #include <unistd.h>
#include <sys/time.h> #include <sys/time.h>
#include <math.h> #include <math.h>
#include <limits.h>
/* Konfiguracja */ /* Konfiguracja */
#define USB_DEV_DEFAULT "/dev/ttyUSB0" #define USB_DEV_DEFAULT "/dev/ttyUSB0"
@@ -23,6 +24,9 @@
#define SUN2K_RTS_DELAY 5000 #define SUN2K_RTS_DELAY 5000
#define SUN2K_BYTE_TIMEOUT 2500 #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 */ /* Struktura do przechowywania wyników testu */
typedef struct { typedef struct {
long total_time_us; long total_time_us;
@@ -31,10 +35,12 @@ typedef struct {
double avg_time_ms; double avg_time_ms;
int successful_reads; int successful_reads;
int total_reads; int total_reads;
int crc_errors;
int timeouts;
} test_results_t; } test_results_t;
/* Timed wrapper for modbus_read_registers - logs start/stop and duration */ /* 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; struct timeval t0, t1;
gettimeofday(&t0, NULL); gettimeofday(&t0, NULL);
@@ -43,34 +49,51 @@ long modbus_read_timed(modbus_t *ctx, int addr, int nb, uint16_t *dest)
long elapsed_us = (t1.tv_sec - t0.tv_sec) * 1000000 + (t1.tv_usec - t0.tv_usec); long elapsed_us = (t1.tv_sec - t0.tv_sec) * 1000000 + (t1.tv_usec - t0.tv_usec);
if (res < 0) { if (res < 0) {
const char *error_str = modbus_strerror(errno);
printf("MBUS: modbus_read_registers addr=0x%X nb=%d -> ERR (%s) elapsed=%ldus\n", printf("MBUS: modbus_read_registers addr=0x%X nb=%d -> ERR (%s) elapsed=%ldus\n",
addr, nb, modbus_strerror(errno), elapsed_us); 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 { } 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); addr, nb, res, elapsed_us);
} *success = 1; /* Sukces */
return elapsed_us; return elapsed_us;
}
} }
/* Test function for ORNO voltage reading */ /* Test function for ORNO voltage reading */
int test_orno_voltage(modbus_t *ctx, test_results_t *results) { int test_orno_voltage(modbus_t *ctx, test_results_t *results) {
uint16_t reg[6]; uint16_t reg[6];
long elapsed_time; long elapsed_time;
int success_flag;
results->total_time_us = 0; results->total_time_us = 0;
results->min_time_us = LONG_MAX; results->min_time_us = LONG_MAX;
results->max_time_us = 0; results->max_time_us = 0;
results->successful_reads = 0; results->successful_reads = 0;
results->total_reads = NUM_READINGS; results->total_reads = NUM_READINGS;
results->crc_errors = 0;
results->timeouts = 0;
printf("\n=== TESTING ORNO VOLTAGE READING ===\n"); printf("\n=== TESTING ORNO VOLTAGE READING ===\n");
printf("Performing %d voltage readings...\n", NUM_READINGS); printf("Performing %d voltage readings...\n", NUM_READINGS);
for (int i = 0; i < NUM_READINGS; i++) { for (int i = 0; i < NUM_READINGS; i++) {
printf("Reading %d: ", i+1); printf("Reading %d: ", i+1);
elapsed_time = modbus_read_timed(ctx, 0x0e, 6, reg); elapsed_time = modbus_read_timed(ctx, 0x0e, 6, reg, &success_flag);
if (elapsed_time > 0) { if (success_flag == 1) {
/* Poprawny odczyt */
results->total_time_us += elapsed_time; results->total_time_us += elapsed_time;
if (elapsed_time < results->min_time_us) results->min_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; if (elapsed_time > results->max_time_us) results->max_time_us = elapsed_time;
@@ -80,11 +103,20 @@ int test_orno_voltage(modbus_t *ctx, test_results_t *results) {
float U2 = modbus_get_float_abcd(&reg[2]); float U2 = modbus_get_float_abcd(&reg[2]);
float U3 = modbus_get_float_abcd(&reg[4]); float U3 = modbus_get_float_abcd(&reg[4]);
printf("Voltages: L1=%.1fV L2=%.1fV L3=%.1fV\n", U1, U2, U3); 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 usleep(10000); // 10ms delay between reads
} }
/* Oblicz statystyki tylko dla poprawnych odczytów */
if (results->successful_reads > 0) { if (results->successful_reads > 0) {
results->avg_time_ms = (double)results->total_time_us / results->successful_reads / 1000.0; results->avg_time_ms = (double)results->total_time_us / results->successful_reads / 1000.0;
} else { } else {
@@ -100,21 +132,25 @@ int test_orno_voltage(modbus_t *ctx, test_results_t *results) {
int test_sun2k_voltage(modbus_t *ctx, test_results_t *results) { int test_sun2k_voltage(modbus_t *ctx, test_results_t *results) {
uint16_t reg[3]; uint16_t reg[3];
long elapsed_time; long elapsed_time;
int success_flag;
results->total_time_us = 0; results->total_time_us = 0;
results->min_time_us = LONG_MAX; results->min_time_us = LONG_MAX;
results->max_time_us = 0; results->max_time_us = 0;
results->successful_reads = 0; results->successful_reads = 0;
results->total_reads = NUM_READINGS; results->total_reads = NUM_READINGS;
results->crc_errors = 0;
results->timeouts = 0;
printf("\n=== TESTING SUN2K VOLTAGE READING ===\n"); printf("\n=== TESTING SUN2K VOLTAGE READING ===\n");
printf("Performing %d voltage readings...\n", NUM_READINGS); printf("Performing %d voltage readings...\n", NUM_READINGS);
for (int i = 0; i < NUM_READINGS; i++) { for (int i = 0; i < NUM_READINGS; i++) {
printf("Reading %d: ", i+1); printf("Reading %d: ", i+1);
elapsed_time = modbus_read_timed(ctx, 32069, 3, reg); elapsed_time = modbus_read_timed(ctx, 32069, 3, reg, &success_flag);
if (elapsed_time > 0) { if (success_flag == 1) {
/* Poprawny odczyt */
results->total_time_us += elapsed_time; results->total_time_us += elapsed_time;
if (elapsed_time < results->min_time_us) results->min_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; if (elapsed_time > results->max_time_us) results->max_time_us = elapsed_time;
@@ -124,11 +160,20 @@ int test_sun2k_voltage(modbus_t *ctx, test_results_t *results) {
float U_B = (float)reg[1] / 10.0; float U_B = (float)reg[1] / 10.0;
float U_C = (float)reg[2] / 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); 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 usleep(10000); // 10ms delay between reads
} }
/* Oblicz statystyki tylko dla poprawnych odczytów */
if (results->successful_reads > 0) { if (results->successful_reads > 0) {
results->avg_time_ms = (double)results->total_time_us / results->successful_reads / 1000.0; results->avg_time_ms = (double)results->total_time_us / results->successful_reads / 1000.0;
} else { } else {
@@ -193,6 +238,8 @@ void print_results(const char *device_name, test_results_t *results) {
printf("\n=== %s TEST RESULTS ===\n", device_name); printf("\n=== %s TEST RESULTS ===\n", device_name);
printf("Total readings: %d\n", results->total_reads); printf("Total readings: %d\n", results->total_reads);
printf("Successful readings: %d\n", results->successful_reads); printf("Successful readings: %d\n", results->successful_reads);
printf("CRC errors: %d\n", results->crc_errors);
printf("Timeouts/Other errors: %d\n", results->timeouts);
printf("Success rate: %.1f%%\n", printf("Success rate: %.1f%%\n",
(results->total_reads > 0) ? (100.0 * results->successful_reads / results->total_reads) : 0); (results->total_reads > 0) ? (100.0 * results->successful_reads / results->total_reads) : 0);
@@ -200,14 +247,14 @@ void print_results(const char *device_name, test_results_t *results) {
printf("Average time per reading: %.2f ms\n", results->avg_time_ms); 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("Minimum time: %.2f ms\n", results->min_time_us / 1000.0);
printf("Maximum time: %.2f ms\n", results->max_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 { } else {
printf("No successful readings!\n"); printf("No successful readings!\n");
} }
printf("========================\n\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) { void compare_and_recommend(test_results_t *orno_results, test_results_t *sun2k_results) {
printf("=== COMPARISON AND RECOMMENDATION ===\n"); printf("=== COMPARISON AND RECOMMENDATION ===\n");
@@ -218,8 +265,10 @@ void compare_and_recommend(test_results_t *orno_results, test_results_t *sun2k_r
if (orno_results->successful_reads > 0 && sun2k_results->successful_reads > 0) { if (orno_results->successful_reads > 0 && sun2k_results->successful_reads > 0) {
printf("Both devices are working. Comparison:\n"); printf("Both devices are working. Comparison:\n");
printf("- ORNO average time: %.2f ms\n", orno_results->avg_time_ms); printf("- ORNO average time: %.2f ms (from %d successful readings)\n",
printf("- SUN2K average time: %.2f ms\n", sun2k_results->avg_time_ms); 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) { 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",
@@ -231,9 +280,30 @@ void compare_and_recommend(test_results_t *orno_results, test_results_t *sun2k_r
printf("RECOMMENDATION: Both devices have similar performance\n"); printf("RECOMMENDATION: Both devices have similar performance\n");
} }
} else if (orno_results->successful_reads > 0) { } 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) { } 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"); printf("=====================================\n");
@@ -283,11 +353,11 @@ int main(int argc, char *argv[]) {
} }
// Print results // Print results
if (orno_results.successful_reads > 0) { if (orno_results.total_reads > 0) {
print_results("ORNO", &orno_results); print_results("ORNO", &orno_results);
} }
if (sun2k_results.successful_reads > 0) { if (sun2k_results.total_reads > 0) {
print_results("SUN2K", &sun2k_results); print_results("SUN2K", &sun2k_results);
} }
@@ -297,3 +367,4 @@ int main(int argc, char *argv[]) {
printf("\nTest completed.\n"); printf("\nTest completed.\n");
return 0; return 0;
} }