这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 瑞萨RA4L1实现ADC水位监测

共6条 1/1 1 跳转至

瑞萨RA4L1实现ADC水位监测

助工
2025-05-09 17:43:48     打赏

瑞萨RA4L1 实现 ADC 水位监测

本文介绍了 RA4L1 开发套件和瑞萨 e2 Studio 灵活软件包(FSP)实现 ADC 水位检测的工程设计,工程快速构建等流程。

简介

包括主控和开发板的基本参数和特点介绍。

主控

开发板主控型号为 R7FA4L1BD4CFP

RA4L1 概览

瑞萨电子 RA4L1 MCU 产品组,低功耗 32 位微控制器 (MCU),基于支持 TrustZone® 的 Arm® Cortex®-M33 (CM33) 内核,实现了低工作电压、低功耗与高性能的理想平衡。 RA4L1 的工作电压低至 1.6V,待机电流低至 1.65µA,并具有多种低功耗功能,可根据应用要求实现动态优化功耗/性能。

RA4L1 MCU 具有低功耗功能,例如段码 LCD 显示驱动器和高级安全引擎,以及 RTC、ADC 和定时器。 该系列MCU 集成了 CAN FD、USB 2.0 FS、I2C/I3C 和低功耗 UART 等通信接口,适用于工业自动化、家电、智能家居、消费品、楼宇/家居自动化和医疗等应用。

RA4L1 提供一系列标准 LQFP 和 QFN 封装选项,以及多种节省尺寸的 BGA 和 CSP 选项,可支持 -40 到 125 °C 的工作温度。 支持瑞萨灵活软件包 (FSP) 和整套的软硬件开发工具的全面支持。

详见:RA4L1 - Renesas 瑞萨电子 .

开发套件

RA4L1-SENSOR 套件基于瑞萨 RA4L1 系列微控制器,完美实现了低工作电压、低功耗与高性能之间的理想平衡。RA4L1 微控制器具备多种低功耗功能,包括段码 LCD 显示驱动器、高级安全引擎、RTC、ADC、定时器和低功耗UART 等通信接口,用户可以根据具体应用需求灵活优化功耗与性能的平衡。这使其成为工业自动化、家电、智能家居、消费电子、楼宇自动化以及医疗保健等领域的理想选择。

board_view.jpg

该套件还包括传感器(SENSOR)系列接口、Arduino Uno扩展接口,并提供对微控制器所有引脚的通孔访问,大大提升了系统的扩展性,助力开发者在高效、灵活的开发环境中进行创新设计。

管脚定义

top view

pinout_top.jpg

bottom view

pinout_bottom.jpg


详见:RA4L1: 瑞萨 RA4L1(R7FA4L1BD4CFP#BA0) - Gitee.com

环境搭建

这里使用 Renesas 瑞萨 e2 studio 开发工具,

下载 FSP (flexible software package) 软件包 并安装。

FSP 安装程序内包含 e² studio 集成开发环境、工具链和 FSP 软件包。

ADC 串口输出

介绍了 RA4L1 实现 ADC 模拟电压采集,并通过串口输出。

创建工程

打开 e2 studio 软件

依次点击 文件 - 新建 - 瑞萨 C/C++ 项目 - Renesas RA

依次进行工程命名,路径设置,FSP版本,目标开发板选择,Device 选择 R7FA4L1BD4CFP ,工具链选择 GNU ARM Embedded

完成工程创建

ADC 读取

介绍了工程新建与 ADC 单通道采集电压的实现。

参考:e2studio开发RA4L1(16)----ADC单通道采集电压-CSDN博客

串口配置

新建串口通信堆栈

New Stack - Connectivity - UART (r_sci_uart)

stack_uart.jpg

属性设置

属性 - Module g_uart9 UART (r_sci_uart) - General 、Baud、Interrupts 设置

uart_property.jpg

注意中断 - 回调函数设置

ADC配置

新建ADC堆栈

New Stack - Analog - ADC (r_adc)

stack_adc.jpg

属性配置

General 选项下设置 ADC 单次扫描

adc_property.jpg

Input 选项下勾选 Channel25,配置中断与回调函数

adc_property_callback.jpg

ADC 及串口配置完成后,构建工程,确保无误。

代码

修改主函数代码,实现 ADC 采集与重定向串口打印输出。

完整 hal_entry.c 代码


#include "hal_data.h"
#include <stdio.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)
{
    //宏将告知编译器回调函数不使用参数 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);

    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=%f\n",adc_data25,a25);

        R_BSP_SoftwareDelay (1000, BSP_DELAY_UNITS_MILLISECONDS);
    }


#if BSP_TZ_SECURE_BUILD
    /* Enter non-secure code */
    R_BSP_NonSecureEnter();
#endif
}

void R_BSP_WarmStart(bsp_warm_start_event_t event)
{
    if (BSP_WARM_START_RESET == event)
    {
#if BSP_FEATURE_FLASH_LP_VERSION != 0

        /* Enable reading from data flash. */
        R_FACI_LP->DFLCTL = 1U;
#endif
    }

    if (BSP_WARM_START_POST_C == event)
    {
        /* C runtime environment and system clocks are setup. */

        /* Configure pins. */
        R_IOPORT_Open (&IOPORT_CFG_CTRL, &IOPORT_CFG_NAME);

#if BSP_CFG_SDRAM_ENABLED

        /* Setup SDRAM and initialize it. Must configure pins first. */
        R_BSP_SdramInit(true);
#endif
    }
}

#if BSP_TZ_SECURE_BUILD

FSP_CPP_HEADER
BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ();

BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ()
{

}
FSP_CPP_FOOTER

#endif


保存文件,构建工程,使用 J-Link 调试和上传固件。

效果演示

分别演示了 A0 引脚悬空、接地、接 3V3 的 ADC 采集与电压串口输出。

A0 悬空

adc_uart_print.gif

A0 接地

A0 连接 GND,输出电压值约为 0

adc_uart_GND.jpg


可见此时 P510(AN25) 输出最小值为 0

A0 接 3V3

A0 连接 3V3 ,输出电压值为 3.30 V

adc_uart_3V3.jpg

可见此时 P510(AN25) 输出最大值为 4095

水位传感器

水位传感器(Water Sensor)可以检测水位高度(检测高度:0 - 40 mm),亦可用作雨滴传感器,用于各种天气状况的监测,检测是否下雨及雨量的大小,广泛应用于汽车自动刮水系统、智能灯光系统和智能天窗系统等。

模块简介

当模块上电,电源指示 LED 点亮;

工作电压:DC 3.3V - 5V ;

输出类型:模拟信号;

water_level_sensor.jpg

传感器具有 10 条裸露的铜线,其中 5 条是电源铜线,另外 5 条是感测铜线。

走线隔行平行排列,每两条电源铜线间有一条感测铜线。

引脚定义

S(信号)为模拟输出;

+(VCC)为传感器供电;

–(GND)为接地。

运行原理

当平行铜线之间有水时,水浸没的高度不同,电流不同。 铜线间的电阻根据水位的变化而变化。

电阻与水的高度成反比(传感器浸水越深,导电性越好,电阻越小,电流越大)。

water_level_sensor_resistance.gif

参考:水位传感器如何工作并与Arduino接口 - 知乎

因此根据 ADC 测量传感器输出的电压,便可以确定水位。

water_sensor_length.jpg

模块原理图

SCH_water-sensor2.jpg


硬件连接

将水位传感器的模拟输出引脚 S 与开发板的 A0 相连,正负极分别与开发板的 3V3 和 GND 相连,示意图如下

board_water_sensor_connect.jpg


A0 引脚对应 MCU 的 adc_channel_25

绘图工具:Cirkit Designer IDE , Fritzing .

水位校准

由于各地的水质差异,导电性能不同,因此需要根据实际情况进行校准。

多次校准,取平均值;

每次校正前,需将 PCB 表面的平行铜线擦干,待测得电压为 0 时再置入水中,记录水位值和电压值。

校准数据采集

水位 10 毫米,相应的串口输出电压为 1.25 伏特

water_level_adjust_10mm.jpg

实际水位 22 毫米,相应的串口输出电压为 1.65 伏特

water_level_adjust_22mm.jpg


实际水位 37 毫米,相应的串口输出电压为 1.84 伏特

water_level_adjust_37mm.jpg

假设 ADC 读取电压(V)与水位高度(mm)为线性相关关系,对上述数据进行拟合

water_level_linear_fit.jpg

获得拟合表达式 y = 41.774 x - 38.686

这里使用 Excel 软件对数据进行拟合

代码

在代码中添加相应的水位高度定义

while(1)
{
        uint16_t adc_data25=0;
        double a25,wl; // define wl (water level)
        (void) R_ADC_ScanStart(&g_adc0_ctrl);
        scan_complete_flag = false;
        while (!scan_complete_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;
        wl = (double)(41.774 * a25 - 38.686); // water level definition equation
        printf("P510(AN25)=%d, voltage=%f, water level=%f mm\n",adc_data25,a25,wl); // print water level (mm)

        R_BSP_SoftwareDelay (1000, BSP_DELAY_UNITS_MILLISECONDS);
}

保存代码,重新构建工程,调试工程,上传工程至开发板;

打开串口助手,连接目标串口对应的设备端口号,打开串口,获取实时 ADC 电压值和水位值。

效果演示

adc_uart_water_level.gif

结果分析

经过多次测量,可以获得较为理想的检测结果。

此外,校准和测量过程中发现 ADC 采集的电压值会随时间逐渐减小,可能原因是

PCB 板被液体浸润,液体表面张力导致初始时刻覆盖更大面积的铜板,电阻较小,输出电压较大;

随着时间推移,表面张力被克服,PCB板液面覆盖面积逐渐平稳下降,此时电压也逐渐减小,最后趋于稳定(类似“海水退潮”)。


总结

本文介绍了 RA4L1 开发套件和瑞萨 e2 Studio 灵活软件包(FSP)实现 ADC 水位检测的工程设计,工程快速构建,包括 ADC 采集、串口打印电压值、水位传感器、运行原理、硬件连接、水位校准、代码、效果展示等流程,为瑞萨单片机 ADC 的相关产品设计和快速应用提供了参考。





关键词: 瑞萨     串口     ADC     RA4L1    

高工
2025-05-09 19:57:30     打赏
2楼

很好奇,这种两个铜皮方式的水位检测,原理是啥?


专家
2025-05-09 22:18:06     打赏
3楼

感谢分享


工程师
2025-05-17 14:48:47     打赏
4楼

高工
2025-05-19 11:14:42     打赏
5楼

实现的效果比较完整,从瑞萨工具端的配置到代码的实现。


专家
2025-05-19 17:22:07     打赏
6楼

期待楼主更多佳作。



共6条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]