【RA4L1-SENSOR】Home Assistant 物联网ADC电压表
本文介绍了瑞萨 RA4L1-SENSOR 开发板由 ADC 采集引脚电压数据,通过串口发送数据至 ATK D20 WiFi 模块,ATK-D20 模块将 MQTT 消息透传至 Home Assistant 平台,实现 HA 物联网电压表的项目设计。
项目介绍
介绍了瑞萨 RA4L1-SENSOR 开发板结合 ADC 功能实现电压测量,进一步结合 ATK-D20 模块实现物联网电压表的项目设计。
项目方案
- 硬件连接:RA4L1-SENSOR 开发板和 ATK-D20 WiFi 模块的接线;
- 流程图:代码和项目流程;
- 工程代码:ADC 配置和主程序;
- MQTT透传:包括 ATK-D20 模块 MQTT 透传配置、软件测试等;
- 效果演示:包括接入 Home Assistant 平台、YAML 配置等。
项目框架

硬件连接
- 使用 Type-C 数据线连接开发板串口接线端和电脑,用以串口通信;
- 使用 J-LINK 调试器连接板载 SWD 调试端口;
- 连接 ATK-D20 模块
| RA4L1 | ATK-D20 | Note |
|---|---|---|
| RXD1 (P608) | TX | Receive data |
| TXD1 (P115) | RX | Transmit data |
| GND | GND | Ground |
实物图

流程图

工程创建
- 使用 e^2^ studio 软件和 FSP 快速创建目标工程,配置 UART、 ADC 和 LCD 堆栈,生成工程的基本架构;
- 打开 e2 studio 软件,依次点击
文件-新建-瑞萨 C/C++ 项目-Renesas RA; - 依次进行工程命名,路径设置,FSP版本,目标开发板选择,Device 选择
R7FA4L1BD4CFP,工具链选择GNU ARM Embedded,完成工程创建。
时钟配置
- 根据 MCU 外部硬件配置,设置晶振及时钟树;
LCD 堆栈
- 新建数码管 LCD 堆栈
New Stack-Graphics-Segment LCD (r_slcdc);
属性设置
- 选中 Segment LCD 堆栈,修改属性配置;
- 设置名称、LOCO 时钟源、(LOCO/SOSC)256 分频器、1/3偏压驱动、COM公共端、波形A、内部电压升压、VL1或VCC参考电压、0对比度。
引脚配置
- LCD 引脚配置;
- VL(Voltage Level)引脚用于提供 LCD 偏置电压,控制 LCD 的对比度和驱动电压。
- 在内部电压提升模式(Internal Voltage Boosting) 下,RA MCU 会自动产生 VL1、VL2、VL3、VL4 并提供给 LCD 作为驱动电压。
- 点击
Generate Project Content,构建工程,确认 0 报错。
详见:【RA4L1-SENSOR】ADC温度的LCD 显示 .
工程代码
添加 LCD 数字显示库文件和主函数代码;
电压 LCD 显示
添加串口打印和ADC电压采集关键代码;
#include "hal_data.h"
#include <stdio.h>
#include "LCD_ShowNum.h"
FSP_CPP_HEADER
void R_BSP_WarmStart(bsp_warm_start_event_t event);
FSP_CPP_FOOTER
fsp_err_t err = FSP_SUCCESS;
volatile bool uart_send_complete_flag = false;
void user_uart_callback (uart_callback_args_t * p_args)
{
if(p_args->event == UART_EVENT_TX_COMPLETE)
{
uart_send_complete_flag = true;
}
}
#ifdef __GNUC__ //串口重定向
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#endif
PUTCHAR_PROTOTYPE
{
err = R_SCI_UART_Write(&g_uart9_ctrl, (uint8_t *)&ch, 1);
if(FSP_SUCCESS != err) __BKPT();
while(uart_send_complete_flag == false){}
uart_send_complete_flag = false;
return ch;
}
int _write(int fd,char *pBuffer,int size)
{
for(int i=0;i<size;i++)
{
__io_putchar(*pBuffer++);
}
return size;
}
volatile bool scan_complete_flag = false;
void adc_callback (adc_callback_args_t * p_args)
{
FSP_PARAMETER_NOT_USED(p_args);
scan_complete_flag = true;
}
void hal_entry(void)
{
/* TODO: add your own code here */
/* Open the transfer instance with initial configuration. */
err = R_SCI_UART_Open(&g_uart9_ctrl, &g_uart9_cfg);
assert(FSP_SUCCESS == err);
printf("hello world!\n");
/* Initializes the module. */
err = R_ADC_Open(&g_adc0_ctrl, &g_adc0_cfg);
/* Handle any errors. This function should be defined by the user. */
assert(FSP_SUCCESS == err);
/* Enable channels. */
err = R_ADC_ScanCfg(&g_adc0_ctrl, &g_adc0_channel_cfg);
assert(FSP_SUCCESS == err);
/* Open SLCDC driver */
err = R_SLCDC_Open(&g_slcdc0_ctrl, &g_slcdc0_cfg);
/* Handle any errors. This function should be defined by the user. */
assert(FSP_SUCCESS == err);
/* When using internal boost mode this delay is required to allow the boost circuit to charge. See RA4M1 User's
* Manual (R01UH0887EJ0100) 8.2.18 "Segment LCD Source Clock Control Register (SLCDSCKCR)" for details. */
R_BSP_SoftwareDelay(5, BSP_DELAY_UNITS_MILLISECONDS);
/* Start SLCDC output */
err = R_SLCDC_Start(&g_slcdc0_ctrl);
assert(FSP_SUCCESS == err);
while(1)
{
uint16_t adc_data25 = 0;
double a25;
/* Enable scan triggering from ELC events. */
(void) R_ADC_ScanStart(&g_adc0_ctrl);
scan_complete_flag = false;
while (!scan_complete_flag)
{
/* Wait for callback to set flag. */
}
err = R_ADC_Read(&g_adc0_ctrl, ADC_CHANNEL_25, &adc_data25);
assert(FSP_SUCCESS == err);
a25 = (double)(adc_data25/4095.0)*3.3;
printf("P510(AN25) = %d, Voltage = %fV\n",adc_data25,a25);
uint16_t Num = a25 * 100; // convert to uint16_t style
LCD_ShowNum(Num);
R_BSP_SoftwareDelay (500, BSP_DELAY_UNITS_MILLISECONDS);
LCD_Clear();
}
#if BSP_TZ_SECURE_BUILD
R_BSP_NonSecureEnter();
#endif
}
- 保存代码,构建工程;
- 调试、上传固件。
效果
板载 LCD 屏显示 A5 引脚实时电压值

同时终端打印 ADC 原始值和相应的电压转换值

JSON
为了后面 MQTT 透传,将电压数据整理为 JSON 格式,代码如下
printf("{\"adc\": %u, \"volt\": %.3f}\r\n", adc_data25, a25);
效果

双串口输出
- 在工程配置中新增串口 Stacks 堆栈,回调函数命名为
user_uart1_callback; - 串口 1 对应引脚为 P608 (RXD) 和 P115 (TXD)
代码
/* 新增串口1回调 */
volatile bool uart1_send_complete_flag = false;
void user_uart1_callback(uart_callback_args_t *p_args)
{
if (p_args->event == UART_EVENT_TX_COMPLETE)
uart1_send_complete_flag = true;
}
while(1)
{
printf("{\"adc\": %u, \"volt\": %.3f}\r\n", adc_data25, a25);
/* 新增:串口1打印 ****************/
char buf[32];
int len = snprintf(buf, sizeof(buf), "{\"adc\": %u, \"volt\": %.3f}\r\n", adc_data25, a25);
uart1_send_complete_flag = false;
R_SCI_UART_Write(&g_uart1_ctrl, (uint8_t *)buf, len);
while (!uart1_send_complete_flag) ; // 等待发完
}
效果

Home Assistant
为了实现物联网 ADC 电压表的设计,使用 ATK-D20 WiFi 模块,结合 MQTT 透传功能,实现 JSON 格式消息上传至 Home Assistant 智能家居平台。
ATK D20
这里使用 ATK-D20 WiFi DTU 模块实现串口 MQTT 透传。
ATK-D20 是由正点原子团队(ALIENTEK)自主研发的一款高性能 2.4GHz WiFi DTU 模块,主要用于实现串口设备通过 WiFi 无线方式接入网络。
- 模块支持 TCP、UDP、HTTP、MQTT、原子云等多种通信协议,支持 AT 指令控制、注册包、心跳包、Modbus 采集等功能,极大地方便了二次开发与系统集成。
详见:D20 WiFi DTU | 文档 .
MQTT 配置
- 检查硬件连接,打开 ATK-D2x 配置软件,打开串口;
- 进入左侧
模式配置界面,工作模式选择 MQTT; - 填写 MQTT 服务器用户名、密码、ip地址、订阅主题、发送主题等信息;
- 点击上方
保存所有参数按钮,此时上位机自动发送 AT 指令,完成 MQTT 配置并自动重启;

详见:正点原子 D20 WiFi 模块 .
MQTTX
使用 MQTTX 软件测试串口透传与服务器转发。
- 打开 MQTTX 软件,新建连接;
- 填写 MQTT 服务器地址、用户名信息等,点击 Connect 按钮;
- 新建订阅主题,输入 ATK-D20 上位机对应的发布主题信息,如
homeassistant/sensor/adc/state; - 窗口不断弹出接收到的 MQTT 服务器转发的电压等信息;

YAML 配置
配置 HA 平台的 YAML 文件,根据主题添加相关参数;
YAML 文件代码
mqtt:
sensor:
- name: "ADC 数值"
state_topic: "homeassistant/adc/state"
unit_of_measurement: "%"
value_template: "{{ value_json.adc }}"
- name: "ADC 电压"
state_topic: "homeassistant/adc/state"
unit_of_measurement: "%"
value_template: "{{ value_json.volt }}"
进入 HA 概览页面,编辑仪表盘,添加对应的卡片即可;

总结
本文介绍了瑞萨 RA4L1-SENSOR 开发板由 ADC 采集引脚电压数据,通过串口发送数据至 ATK D20 WiFi 模块,ATK-D20 模块将 MQTT 消息透传至 Home Assistant 平台,实现 HA 物联网电压表的项目设计,为该产品在物联网领域的开发设计和快速应用提供了参考。

全部评论