基于RISC-V MCU为核心的智能电能表,及有人云物联网平台监控数据
一、预想功能
基于32 位通用增强型 RISC-V MCU CH32V103开发板作为核心控制主板,通过接收和处理单相电能检测模块实时获取的单相数据,包括对电压、电流、有功功率、无功功率、电能、功率因数、二氧化碳含量、频率、芯片温度等相关数据进行计算和整理,同时驱动OLED 屏幕实时刷新显示单相电能数据,并将数据进行打包后通过串口向以太网模块发送数据包,以太网模块将数据包上传至云端,实现远距离在有人云平台对数据进行监控及上下发指令功能。
二、系统框架
三、硬件介绍
该智能电表硬件部分主要由RISC-V MCU CH32V103开发板、电能计模块、以太网模块、驱动模块、OLED 屏幕以及排插等器件组成。
RISC-V MCU CH32V103开发板:作为核心主板。负责对电能检测模块下发收集指令,以及对电能检测模块响应的数据进行处理,一方 面对接收的单相数据进行转换后驱动OLED 屏幕对相关数据进行显示,另一方面对单相数据进行重新打包并通过串口对以太网模块进行数据传输。
电能计模块:通过排插连接电器,并实时检测外接电器的单相数据。若接收主板发来的接收指令,则将检测到的数据上发到主板。
以太网模块:作为开发板与云端进行数据传输的媒介。当模块接收主板下发的数据包时,会将数据包通过路由器上传到云端,有人云平台通过对数据进行接收并显示到监控界面上,用户也可通过在有人云的监控界面对主板下发数据和指令。
驱动模块:按照主板指令驱动散热器开关以及转动的速度等。
OLED屏幕:显示相关数据。
排插:可外接电器,支持220V交流供电,接入排插的电器运行时的单相数据不断被电能检测模块进行收集。
四、软件介绍
1.主函数
int main(void)
{
uint8_t OLED_Show_Change = 0;
uint8_t OLED_Show_First_In = 0;
DisableGlobalIRQ();
board_init();
gpio_init(B2, GPO, 0, GPIO_PIN_CONFIG);
gpio_init(C0, GPO, 1, GPIO_PIN_CONFIG);
gpio_init(C1, GPO, 1, GPIO_PIN_CONFIG);
gpio_init(C3, GPO, 0, GPIO_PIN_CONFIG);
gpio_init(C4, GPO, 0, GPIO_PIN_CONFIG);
uart_init(UART_1, 4800, UART1_TX_A9, UART1_RX_A10);
uart_init(UART_2, 115200, UART2_TX_A2, UART2_RX_A3);
uart_rx_irq(UART_1, ENABLE);
uart_rx_irq(UART_2, ENABLE);
U_OLED_Init();
U_OLED_Clear();
timer_pit_interrupt_ms(TIMER_1, 10);
EnableGlobalIRQ(0);
while (1)
{
if (U_Tim_Count > 250)
{
U_Tim_Count = 0;
OLED_Show_Change++;
if (OLED_Show_Change > 2)
{
OLED_Show_Change = 0;
OLED_Show_First_In = 0;
}
}
switch (OLED_Show_Change)
{
case 0:
U_Show_IM1253B_Data1(OLED_Show_First_In, U_IM1253B_Data);
OLED_Show_First_In = 1;
break;
case 1:
U_Show_IM1253B_Data2(OLED_Show_First_In, U_IM1253B_Data);
OLED_Show_First_In = 0;
break;
case 2:
U_Show_IM1253B_Data3(OLED_Show_First_In, U_IM1253B_Data);
OLED_Show_First_In = 1;
break;
default:
break;
}
if (MCU_Interrupt0_Timer_1S_End)
{
U_Send_RendCommand_IM1253B();
MCU_Interrupt0_Timer_1S_End = 0;
U_Send_Ethernet_Data();
systick_delay_ms(100);
U_Send_Ethernet_Data2();
}
U_Calculation_IM1253B_Data();
receive_key();
}
}
2.电能计量模块相关驱动函数
串口1中断函数
void USART1_IRQHandler(void)
{
static uint8_t U_GetData;
uart_query(UART_1, &U_GetData);
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
U_MCU_UART1_GetData_End = U_Get_IM1253B_Data(U_GetData);
}
读取电能计上发的数据,进行判断后存入特定数组中
uint8_t U_Get_IM1253B_Data(uint8_t Get_Data)
{
static uint8_t i = 0;
static uint8_t Get_Data_Buf[37] =
{ 0 };
Get_Data_Buf[i++] = Get_Data;
if (Get_Data_Buf[0] != 0x01)
{
i = 0;
}
if ((i == 2) && (Get_Data_Buf[1] != 0x03))
{
i = 0;
}
if ((i == 3) && (Get_Data_Buf[2] != 0x20))
{
i = 0;
}
if (i > 2)
{
if (i != (Get_Data_Buf[2] + 5))
{
return 0;
}
if (Get_Data_Buf[2] == 0X20)
{
memcpy(IM1253B_Data_Buf, Get_Data_Buf, 37);
return 1;
}
}
return 0;
}
向电能计发送读取相关寄存器命令函数
void U_Send_RendCommand_IM1253B(void)
{
static uint8_t ReadCommad[8] =
{ 0x01, 0x03, 0x00, 0x48, 0x00, 0x08, 0xc4, 0x1a };
uint8_t i = 0;
for (i = 0; i < 8; i++)
{
uart_putchar(UART_1, ReadCommad[i]);
systick_delay_ms(1);
}
}
3.以太网模块相关驱动函数
对电能相关数据进行打包并发送给以太网模块函数
void U_Send_Ethernet_Data(void)
{
uint8_t U_Send_Ethernet_Data[45] =
{ 0x01, 0x46, 0x00, 0x00, 0x00, 0x10, 0x20 };
Float_Data_Arry_Change_uchar(U_Send_Ethernet_Data, U_IM1253B_Data_Float,10);
U_GetCrcData(U_Send_Ethernet_Data, 39);
uart_putbuff(UART_2, U_Send_Ethernet_Data, 41);
}
向以太网发送设备开关指令函数
void U_Send_Ethernet_Data2(void)
{
uint8_t U_Send_Ethernet_Data2[12] =
{ 0x01, 0x45, 0x00, 0x00, 0x00, 0x10, 0x02 };
U_Send_Ethernet_Data2[7] = U_Ethernet_Data_Float[0];
U_Send_Ethernet_Data2[8] = U_Ethernet_Data_Float[1];
U_GetCrcData(U_Send_Ethernet_Data2, 9);
uart_putbuff(UART_2, U_Send_Ethernet_Data2, 11);
}
对以太网模块返回到主板的数据进行判断后把特定数据存入数组中
uint8_t U_MCU_UART2_GetData_End = 0;
uint8_t Ethernet_Data_Buf[8] = { 0 };
uint8_t U_Get_Ethernet_Data(uint8_t Get_Data)
{
static uint8_t i = 0;
static uint8_t E_Data_Buf[8] =
{ 0 };
E_Data_Buf[i++] = Get_Data;
if (E_Data_Buf[0] != 0x01)
{
i = 0;
}
if ((i == 2) && (E_Data_Buf[1] != 0x05))
{
i = 0;
}
if ((i == 3) && (E_Data_Buf[2] != 0x00))
{
i = 0;
}
if ((i == 4) && (E_Data_Buf[3] != 0x00))
{
i = 0;
}
if(i == 8)
{
memcpy(Ethernet_Data_Buf, E_Data_Buf, 9);
}
}
计算校验位函数
static void U_GetCrcData(uint8_t *U_Data_Buffer, uint8_t len)
{
uint16_t wcrc = 0XFFFF;
uint8_t temp;
uint8_t CRC_L, CRC_H;
uint8_t i = 0, j = 0;
for (i = 0; i < len; i++)
{
temp = *U_Data_Buffer & 0X00FF;
U_Data_Buffer++;
wcrc ^= temp;
for (j = 0; j < 8; j++)
{
if (wcrc & 0X0001)
{
wcrc >>= 1;
wcrc ^= 0XA001;
}
else
{
wcrc >>= 1;
}
}
}
CRC_L = wcrc & 0xff;
*U_Data_Buffer = CRC_L;
CRC_H = wcrc >> 8;
*(U_Data_Buffer + 1) = CRC_H;
}
五、有人云平台控制面板
在有人云平台对控制界面进行编辑排版,定义相关变量及协议。
六、功能验证
1.完整成品展示
2.OLED 屏幕显示测试
将设备接入负载,打开电源。 如上所示,OLED 屏幕显示正常,且数据无错误。
3.有人云平台测试
接通电源和电器后在电脑端打开有人云平台 如上所示,数据能够正常显示且实时更新。
打开手机有人云平台小程序 如上所示,数据能正常显示且实时更新。
正常状态下散热器未打开
打开下发指令开关 如上所示,可见散热器开始转动,云平台下发指令成功,开发板执行指令成功。
综合上面几项测试,以RISC-V MCU CH32V103芯片为核心的开发板实现了对电能数据的收发和处理以及通过OLED正常显示,对云平台实现数据交换以及远程无线指令上发下发和执行功能,达到预想功能,测试成功。
|