numpy 数组设置小数点显示的位数--转载自 “呆萌的代Ma”

使用np.around(ndarry,保留的位数)

案例

import numpy as np

array = np.array([1.123456789, 2.23456, 4.5643])
print(np.around(array, 3))  # 保留三位小数,保留方式为四舍五入

结果:[1.123 2.235 4.564]

#include "./SYSTEM/sys/sys.h" #include "./SYSTEM/usart/usart.h" #include "./SYSTEM/delay/delay.h" #include "./BSP/LED/led.h" #include "./BSP/LCD/lcd.h" #include "./BSP/RS485/rs485.h" #include "i2c.h" #include <math.h> #include <string.h> #include <stdio.h> // RS485设备参数 #define DEVICE_ADDR 0x01 #define VOLTAGE_REG_ADDR 0x0020 #define MODBUS_READ_HOLDING_REG 0x03 // ADS1115参数 #define ADS1115_DEV_ADDR 0x90 #define ADS1115_Conversion 0x00 #define ADS1115_Config 0x01 // ZMCT103C模块参数(根据图片精确配置) #define ZMCT103C_RATED_INPUT_CURRENT 5.0f // 额定输入电流:5A #define ZMCT103C_RATED_OUTPUT_CURRENT 0.005f // 额定输出电流:5mA #define ZMCT103C_TRANSFORMER_RATIO 1000.0f // 变比:1000:1 #define ZMCT103C_BURDEN_RESISTOR 100.0f // 负载电阻:100Ω(相位差测试条件) #define ZMCT103C_LINEAR_RANGE 10.0f // 线性范围:0-10A #define ZMCT103C_LINEARITY 0.002f // 线性度:0.2% #define ZMCT103C_ACCURACY_CLASS 0.002f // 精度等级:0.2级 #define ZMCT103C_PHASE_SHIFT 20.0f // 相位差:≤20° // ADS1115采样参数 #define SAMPLING_RATE 860 // ADS1115采样率:860 SPS #define SAMPLES_PER_CYCLE 17 // 每个周期采样点数(50Hz时,860/50≈17) #define NUM_CYCLES 2 // 采样周期数 #define TOTAL_SAMPLES (SAMPLES_PER_CYCLE * NUM_CYCLES) // 总采样点数 uint8_t BYTE_BUF[2]; // 全局变量 float g_zero_offset_voltage = 0.0f; // 零点偏移电压 uint8_t g_offset_calibrated = 0; // 校准标志 uint32_t last_calibration_time = 0; // 上次校准时间 const uint32_t CALIBRATION_INTERVAL = 10 * 60 * 1000; // 10分钟校准间隔 // 显示通道结构体 typedef struct { char* label; float value; uint16_t color; uint16_t x; uint16_t y; char last_display[30]; } DisplayChannel; /* 计算Modbus CRC16校验 */ uint16_t modbus_crc16(uint8_t *data, uint8_t length) { uint16_t crc = 0xFFFF; for (uint8_t pos = 0; pos < length; pos++) { crc ^= (uint16_t)data[pos]; for (uint8_t i = 8; i != 0; i--) { if ((crc & 0x0001) != 0) { crc >>= 1; crc ^= 0xA001; } else { crc >>= 1; } } } return crc; } /* 通过RS485读取电压数据 */ float read_voltage_via_rs485(void) { uint8_t tx_buf[8]; uint8_t rx_buf[256]; uint8_t rx_len = 0; uint16_t voltage_reg; // 构造Modbus RTU请求帧 tx_buf[0] = DEVICE_ADDR; tx_buf[1] = MODBUS_READ_HOLDING_REG; tx_buf[2] = (VOLTAGE_REG_ADDR >> 8) & 0xFF; tx_buf[3] = VOLTAGE_REG_ADDR & 0xFF; tx_buf[4] = 0x00; tx_buf[5] = 0x01; uint16_t crc = modbus_crc16(tx_buf, 6); tx_buf[6] = crc & 0xFF; tx_buf[7] = (crc >> 8) & 0xFF; rs485_send_data(tx_buf, 8); delay_ms(100); rs485_receive_data(rx_buf, &rx_len); if (rx_len >= 7) { if (rx_buf[0] == DEVICE_ADDR && rx_buf[1] == MODBUS_READ_HOLDING_REG) { voltage_reg = (rx_buf[3] << 8) | rx_buf[4]; float voltage = voltage_reg * 0.01f; return voltage * 10.0f; // 10倍缩放修正 } } return -1.0f; } /* ADS1115读取单次转换 */ float ADS1115_Read_ADC(uint8_t channel) { uint8_t ConfigBuff[2]; uint8_t PGA; int16_t tempData; float voltage; // 配置PGA为2(±2.048V量程) PGA = 2; switch (channel) { case 0: ConfigBuff[0] = (0xC1 & 0xF1) | (PGA << 1); break; case 1: ConfigBuff[0] = (0xD1 & 0xF1) | (PGA << 1); break; case 2: ConfigBuff[0] = (0xE1 & 0xF1) | (PGA << 1); break; case 3: ConfigBuff[0] = (0xF1 & 0xF1) | (PGA << 1); break; default: return -1.0f; } ConfigBuff[1] = 0xE3; // 860 SPS,不使能比较器 HAL_I2C_Mem_Write(&hi2c2, ADS1115_DEV_ADDR, ADS1115_Config, 1, ConfigBuff, 2, 1000); HAL_Delay(2); HAL_I2C_Mem_Read(&hi2c2, ADS1115_DEV_ADDR, ADS1115_Conversion, 1, BYTE_BUF, 2, 1000); tempData = (int16_t)(BYTE_BUF[0] << 8) | (int16_t)BYTE_BUF[1]; switch (PGA) { case 0: voltage = tempData * 0.0001875f; break; case 1: voltage = tempData * 0.000125f; break; case 2: voltage = tempData * 0.0000625f; break; case 3: voltage = tempData * 0.00003125f; break; case 4: voltage = tempData * 0.000015625f; break; case 5: voltage = tempData * 0.0000078125f; break; default: voltage = 0; break; } return voltage; } /* 校准ZMCT103C零点偏移 */ void calibrate_zero_offset(void) { lcd_show_string(10, 210, 200, 16, 16, "Calibrating Zero Offset...", BLUE); // 确保无电流通过互感器 delay_ms(2000); float sum = 0.0f; uint16_t sample_count = 100; for (int i = 0; i < sample_count; i++) { sum += ADS1115_Read_ADC(0); delay_ms(10); } g_zero_offset_voltage = sum / sample_count; g_offset_calibrated = 1; char debug[40]; snprintf(debug, sizeof(debug), "Offset: %.3fV Calibrated", (double)g_zero_offset_voltage); lcd_show_string(10, 210, 200, 16, 16, debug, GREEN); delay_ms(2000); } /* 计算交流电压RMS值(关键函数) */ float calculate_rms_voltage(uint8_t channel) { float sum_squares = 0.0f; float sample; uint32_t start_time = HAL_GetTick(); // 采样多个周期计算RMS for (int i = 0; i < TOTAL_SAMPLES; i++) { sample = ADS1115_Read_ADC(channel); // 减去直流偏置(如果已校准) if (g_offset_calibrated) { sample -= g_zero_offset_voltage; } sum_squares += sample * sample; // 根据采样率控制采样间隔 uint32_t expected_time = start_time + (i * 1000 / SAMPLING_RATE); while (HAL_GetTick() < expected_time) { delay_ms(1); } } return sqrtf(sum_squares / TOTAL_SAMPLES); } /* ZMCT103C交流电压转电流计算(基于技术参数) */ float zmct103c_voltage_to_current(float rms_voltage) { /* * 基于ZMCT103C技术参数计算: * 额定点:输入5A → 输出5mA → 在100Ω负载上产生0.5V RMS电压 * 计算比例系数:K = 5A / 0.5V = 10 A/V * * 物理原理计算: * 1. 次级电流 I_secondary = V_rms / R_burden * 2. 初级电流 I_primary = I_secondary × N */ // 方法1:直接比例计算 float current_direct = rms_voltage * 10.0f; // 方法2:基于物理原理计算(更准确) float secondary_current = rms_voltage / ZMCT103C_BURDEN_RESISTOR; float current_physical = secondary_current * ZMCT103C_TRANSFORMER_RATIO; // 使用方法2,并应用精度修正 float calculated_current = current_physical * (1.0f + ZMCT103C_LINEARITY); return calculated_current; } /* 计算电缆阻抗 */ float calculate_impedance(float voltage, float current) { if (fabsf(current) < 0.001f || voltage < 0 || current < 0) { return -1.0f; } return voltage / current; } /* LCD显示函数 */ void lcd_display_channel(DisplayChannel* channel, uint8_t size) { char buffer[30]; if (strcmp(channel->label, "Impedance") == 0) { if (channel->value < 0) { snprintf(buffer, sizeof(buffer), "%s: N/A", channel->label); } else if (channel->value > 1000) { snprintf(buffer, sizeof(buffer), "%s:%.2fkΩ", channel->label, (double)(channel->value/1000)); } else { snprintf(buffer, sizeof(buffer), "%s:%.2fΩ", channel->label, (double)channel->value); } } else if (strcmp(channel->label, "RMS Voltage") == 0) { snprintf(buffer, sizeof(buffer), "%s:%.3fV", channel->label, (double)channel->value); } else if (strcmp(channel->label, "Offset Voltage") == 0) { snprintf(buffer, sizeof(buffer), "%s:%.3fV", channel->label, (double)channel->value); } else { const char* unit = (strcmp(channel->label, "Voltage") == 0) ? "V" : "A"; if (strcmp(channel->label, "Voltage") == 0) { snprintf(buffer, sizeof(buffer), "%s:%.1f%s", channel->label, (double)channel->value, unit); } else { snprintf(buffer, sizeof(buffer), "%s:%.3f%s", channel->label, (double)channel->value, unit); } } if (strcmp(buffer, channel->last_display) != 0) { uint16_t text_width = strlen(buffer) * size * 6; lcd_fill(channel->x, channel->y, channel->x + text_width, channel->y + size + 2, WHITE); lcd_show_string(channel->x, channel->y, 240, size, size, buffer, channel->color); strncpy(channel->last_display, buffer, sizeof(channel->last_display) - 1); channel->last_display[sizeof(channel->last_display) - 1] = '\0'; } } /* 显示状态信息 */ void lcd_show_status(uint16_t x, uint16_t y, char* status, uint16_t color) { static char last_status[50] = ""; if (strcmp(status, last_status) != 0) { lcd_fill(x, y, 240, y + 16, WHITE); lcd_show_string(x, y, 200, 16, 16, status, color); strncpy(last_status, status, sizeof(last_status) - 1); last_status[sizeof(last_status) - 1] = '\0'; } } /* 显示模块参数信息 */ void lcd_show_module_info(uint16_t x, uint16_t y) { char info[80]; snprintf(info, sizeof(info), "ZMCT103C %d:1 R=%.0fΩ 0.2级", (int)ZMCT103C_TRANSFORMER_RATIO, ZMCT103C_BURDEN_RESISTOR); lcd_show_string(x, y, 200, 16, 16, info, GREEN); } int main(void) { HAL_Init(); sys_stm32_clock_init(RCC_PLL_MUL9); delay_init(72); usart_init(115200); led_init(); lcd_init(); rs485_init(9600); MX_I2C2_Init(); // 初始化显示 lcd_clear(WHITE); lcd_show_string(30, 40, 200, 16, 16, "RMS Measurement System", RED); // 显示模块参数 lcd_show_module_info(30, 60); // 初始化显示通道(增加RMS电压显示) DisplayChannel channels[4] = { {"Voltage", 0.0f, RED, 30, 90, ""}, // RS485读取的线路电压 {"RMS Voltage", 0.0f, MAGENTA, 30, 120, ""}, // ZMCT103C输出的RMS电压 {"Current", 0.0f, BLUE, 30, 150, ""}, // 计算得到的电流RMS值 {"Impedance", 0.0f, GREEN, 30, 180, ""} // 计算得到的阻抗 }; // 显示固定标签 for (int i = 0; i < 4; i++) { char label[30]; snprintf(label, sizeof(label), "%s:", channels[i].label); lcd_show_string(channels[i].x, channels[i].y, 100, 16, 16, label, BLACK); } lcd_show_status(10, 210, "Waiting for module stabilization...", BLUE); // 关键修改1:等待模块稳定(解决缓慢变化问题) delay_ms(5000); // 等待5秒让ZMCT103C模块稳定 // 关键修改2:校准零点偏移(必须在无电流条件下进行) lcd_show_status(10, 210, "Please ensure NO current flow", RED); lcd_show_string(10, 230, 200, 16, 16, "Calibrating in 5 seconds...", RED); delay_ms(5000); calibrate_zero_offset(); lcd_show_status(10, 230, "Starting RMS measurement...", GREEN); delay_ms(1000); uint32_t last_refresh = 0; uint16_t success_count = 0; uint16_t error_count = 0; uint32_t last_calibration_time = HAL_GetTick(); while (1) { uint32_t current_time = HAL_GetTick(); // 定期重新校准(每10分钟) if (current_time - last_calibration_time > CALIBRATION_INTERVAL) { calibrate_zero_offset(); last_calibration_time = current_time; } if (current_time - last_refresh > 1000) // 1秒刷新一次 { float line_voltage, rms_voltage, calculated_current; uint8_t read_success = 1; // 1. 读取线路电压 line_voltage = read_voltage_via_rs485(); // 2. 关键修改3:计算ZMCT103C输出的RMS电压(交流信号) if (read_success) { rms_voltage = calculate_rms_voltage(0); // 验证RMS电压在合理范围内 if (rms_voltage >= 0 && rms_voltage <= 2.0f) // ZMCT103C最大输出约2V { // 3. 将RMS电压转换为电流 calculated_current = zmct103c_voltage_to_current(rms_voltage); success_count++; } else { lcd_show_status(10, 200, "RMS Voltage Out of Range", RED); read_success = 0; error_count++; } } if (read_success) { // 4. 更新显示数据 channels[0].value = line_voltage; channels[1].value = rms_voltage; channels[2].value = calculated_current; channels[3].value = calculate_impedance(line_voltage, calculated_current); // 5. 显示所有数据 for (int i = 0; i < 4; i++) { lcd_display_channel(&channels[i], 16); } // 显示状态信息(包含偏移电压) char status[60]; snprintf(status, sizeof(status), "OK:%d RMS:%.3fV ", success_count, (double)rms_voltage); lcd_show_status(10, 250, status, GREEN); } LED0_TOGGLE(); last_refresh = current_time; } delay_ms(10); } } 你看看我的码还有哪里可以改进的,目前测得的电流数值太不稳定了,我怀疑通电后测得得这个电流数值不是真实的,然后再帮我改改电阻显示部分,让其直接显示具体的数值,而不是显示2k,2.5k这种方式
最新发布
10-11
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值