- 2024-12-15
-
回复了主题帖:
【Follow me第二季第3期】作品提交
Jacktang 发表于 2024-12-15 09:57
两个定时器实现的,不方便画如流程图的原因是
目前没想到如何画才能表达清楚
- 2024-12-14
-
发表了主题帖:
【Follow me第二季第3期】作品提交
首先非常感谢电子工程世界论坛和得捷举办的Follow me活动,感谢第二季第三期任务讲解的老师。通过一个月的学习让我学到很多有关瑞萨芯片开发的相关知识。
入门任务
环境搭建
万事开头难,单片机的开发第一步就是搭建开发环境。瑞萨的开发软件是e2Studio,离线安装包有多重下载方式,GitHub的下载链接为:Release v5.5.0 · renesas/fsp · GitHub。当然官网也有下载链接,在此不再贴上去了。软件版本有很多,建议下载5.5最新版本,我也是用这个版本完成任务的。打开GitHub的下载链接点击如下图的红框就可以进行下载
下载好的安装包安装方式也是比较简单的,点击后就可平常的安装方式一样。以下是安装过程,画红框是需要自己勾选的,其他的就按照默认选择就可以。
瑞萨也推出支持MDK和IAR的工程创建软件,可以下载如下图的方框安装使用,使用方式和e2Studio的方式差不多,只是在新建工程时需要选择MDK或IAR做编译软件,MDK也需要进行一些配置,配置方式可以在网上查找。本次使用的板卡是EK-RA6M5,板上带有JLink仿真器,所以e2Studio软件完全够用。
下载调试示例程序
安装好后需要在开始菜单中找到e2Studio的快捷链接,我是找到后拖到桌面,这样方便后续的使用。也可以在安装软件的文件夹中找到,如果没有自定义安装路径的话会安装在C盘的Renesas文件夹下。
瑞萨针对官方多个开发板都提供了丰富的例程,例程的链接是GitHub - renesas/ra-fsp-examples: Example projects for Renesas RA MCU family。可以通过下载压缩包方式下载,也可以直接下载下来。打开安装好的e2Studio软件后导入工程的方法有两种。一种是点击左上角的文件-->从文件系统中打开项目;另外一种是点击项目资源管理器的导入或者点击左上角的文件-->导入,选择常规下的来自文件夹或归档的文件项目。如下图
然后选择导入工程的文件夹路径,建议是e2studio文件夹下的路径,因为创建工程的一些配置文件是放在e2studio文件夹下的,如果选择其他的文件夹路径会出现软件识别多个配置文件,不过也没有影响。本次以_quickstart文件夹下的例程为例。
文件导入后可能是因为版本的问题,直接编译会出现错误,解决方法是打开configuration.xml文件,虽然会有一些警告,但是直接点击确定就可以,然后编译就会没有问题。对其他的例程也是适用的,只不过有些例程还是编译会有问题,这一点就没有办法了。编译的方式是可以点击下图的编译按钮
编译过程和结果会在下方的控制台中显示,编译成功会显示如下内容
接下来是下载程序到板卡上,需要一根microUSB线,需要插入一端只有一个microUSB接口上。然后通过软件下载程序,方式如下图
下载后会提示是否切换仿真界面,如果选择切换会进入仿真界面;选择否还是会在工程文件界面。切换这两个界面的方式如下图
红框是工程文件界面,右侧是仿真界面。程序下载成功后需要点击运行才会运行程序或者USB拔掉重新接上也可以启动程序(该方式适合不用仿真或用J-Link RTT Viewer软件通信用)。启动和仿真按钮如下图所示
本例程的程序下载成功后可以将microUSB线接入J11(USB Full Speed)丝印的接口上。然后可以用串口软件或e2studio的串口插件进行交互,这里我选择串口软件进行交互,波特率是115200,8Bit数据位,1个停止位,无奇偶校验进行连接。连接后出现如下界面
然后可以输入4进行Flash读写测试,测试结果如下
新建工程
在开始Blink和按键任务前,其实刚才介绍的示例程序就可以实现,但是为了更清楚的了解程序是如何实现的,所以从空的工程一步一步进行配置和编写程序实现任务要求的效果。新建工程的方法是点击左上角的文件-->新建-->瑞萨C/C++项目-->Renesas RA。如下图
然后可以双击Renesas RA C/C++ Project,如下图
接下来是命名工程名和选择工程文件保存路径,可以用默认的文件夹路径,也可以取消勾选使用缺省值前的√自定义保存工程文件路径。设置好后点击下一步进入设备型号配置,可以只需修改Device选项即可。在Device选项框的后面点三个点图标找到EK-RA6M5的选项便可。如下图
然后就是多次点击下一步,其中有选择是否添加操作系统的选项。这里没有用到,所以可以多次点击下一步。最后是选择是否创建基础工程还是空的。我这里选择的是空的工程来进行任务效果的实现。
Blink和按键
原理图
Blink和按键的实现需要先看一下原理图,知道LED灯控制引脚和按键引脚接到那个I/O口上。原理图可以在瑞萨官网下载。按键和LED灯控制引脚对应的原理图如下
流程图
因为Blink的实现主要是靠两个定时器实现的,不方便画如流程图中,所以只画了按键处理的流程图
配置
在创建工程是e2studio已经将对应的I/O口进行配置了,所以不需要配置对应引脚。
应用程序代码编写
首先是添加控制LED灯闪烁频率和亮灭程度的两个定时器,创建方法是打开configuration.xml文件,在stacks中点击New stack,在Timers先后创建两个Timer General PWM(r_gpt),如下图
然后分别点击对应的Timer Stack后点击下方的属性,按照如下图的修改进行修改
然后按快捷键Ctrl+S保存修改的配置,点击右上角的Generate Project Content生成对应的程序到工程文件中。
之后是应用程序的编写,首先是创建控制LED灯亮灭的.h文件,这里定义成bsp_led.h,主要是对三个LED灯的亮灭控制,打开后可以发现都是宏定义。宏定义BLUE、GREEN和RED是三个LED灯对应的控制引脚端口号;TURN_GREEN_ON、TURN_GREEN_OFF和TURN_GREEN_TOGGLE分别是控制绿灯亮、灭和状态翻转的。
接下来是新建自己编写的.c和.h文件,可以在src文件夹中直接创建.c和.h文件。软件会自动识别并放入到工程当中一并进行编译。src文件夹一般是用户程序文件夹,hal_entry.c文件也在该文件夹下。
按键对应的文件有bsp_key.c和.h文件。其中.h文件宏定义KEY2_SW1_PIN和KEY1_SW2_PIN是对应两个按键引脚的端口号;KEY_ON和KEY_OFF分别表示按键按下和没有按下。.c文件定义按键扫描函数,入口参数是两个按键的宏定义KEY2_SW1_PIN和KEY1_SW2_PIN,返回的是按键是否被按下(KEY_ON和KEY_OFF)。
两个定时器的回调函数定义在gpt_blinker.c和.h文件中,函数led_duty_frequency_update和led_duty_cycle_update分别是更新控制LED闪烁频率和亮灭程度的定时器设置值;gpt_blinker_Init是两个定时器的初始化;gpt_blinker_callback和gpt_green_callback分别是两个定时器的回调函数。
hal_entry.c是用户函数的入口函数定义的.c文件。和其他的厂家不一样的就是用户函数的入口不是main而是hal_entry。在hal_entry函数中自己编写的函数如下。
gpt_blinker_Init();
while (1)
{
/* Enable access to the PFS registers. If using r_ioport module then register protection is automatically
* handled. This code uses BSP IO functions to show how it is used.
*/
if( Key_Scan(KEY1_SW2_PIN) == KEY_ON )
{
g_board_status.led_intensity = (uint16_t) ((g_board_status.led_intensity + 1) % BLINK_INTENSITY_SUM);
key_press_down_flag = 1;
}
if( Key_Scan(KEY2_SW1_PIN) == KEY_ON )
{
g_board_status.led_frequency = (uint16_t)((g_board_status.led_frequency + 1) % BLINK_FREQ_SUM);
key_press_down_flag = 1;
}
if (key_press_down_flag)
{
key_press_down_flag = 0;
led_duty_frequency_update();
led_duty_cycle_update();
}
}
首先是初始化两个定时器,然后是不断判断两个按键是否被按下。如果被按下就分别控制闪烁频率和亮度的定时器设置值,最后是根据按键被按下标志key_press_down_flag是否被置1来更新两个定时器的设置值。
两个按键分别修改的是g_board_status.led_intensity和g_board_status.led_frequency的值,这两个变量是取值于gpt_blinker.c文件中的g_pwm_dcs和g_pwm_rates数组的值。如果想修改闪烁频率和亮度的可选项,则可以在gpt_blinker.h文件中进行定义,并修改宏定义BLINK_INTENSITY_SUM和BLINK_FREQ_SUM的值就可以在两个数组中进行添加。
验证
编译和下载成功后的效果如下
[localvideo]9871776905e6c5731e1880063b7449cf[/localvideo]
对应程序源码
基础任务
quad-spi flash和octo-spi flash配置及读写速度测试
原理图
SPI和OSPIFlash对应的原理图如下所示
流程图
测试QSPI和OSPIFlash读写速度的方法是用定时器计算Flash读写一定数据量的时间,对应的简易流程图如下
配置
在新建工程中打开Stacks,按照如下顺序创建stack和属性配置,以及时钟的配置。首先是取消引脚的复用,如下图所示
配置好后依然是按Ctrl+S进行保存并点击Generate Project Content。
应用程序代码编写
这里参考ospi的例程,用J-Link RTT Viewer进行交互,所以可以把ospi例程下的SEGGER_RTT文件夹和common_utils.h。ospi_commands.c和.h文件、ospi_ep.c和.h文件、ospi_test.c和.h文件和qspi_test.c和.h文件是从_quickstart例程中复制下来并做了适当的修改的。
在hal_entry函数中编写如下代码
/* TODO: add your own code here */
fsp_err_t fsp_err;
uint32_t ospi_read_result = 0;
uint32_t ospi_write_result = 0;
uint32_t qspi_read_result = 0;
uint32_t qspi_write_result = 0;
timer_info_t timer_info;
uint32_t block_size_actual = 0;
APP_PRINT("\r\nenter the text block size specifying a 2K boundary (eg 24):");
while (1)
{
block_size_actual = process_input_data();
if ((block_size_actual >= 2) && (block_size_actual <= 64))
{
APP_PRINT("%d\r\n",block_size_actual);
fsp_err = R_GPT_Open(g_memory_performance.p_ctrl, g_memory_performance.p_cfg);
uint32_t ospi_performance_write_result = 0;
uint32_t ospi_performance_read_result = 0;
uint32_t timer_frequency;
R_GPT_InfoGet(g_memory_performance.p_ctrl, &timer_info);
timer_frequency = timer_info.clock_frequency;
ospi_performance_test (block_size_actual, &ospi_performance_write_result, &ospi_performance_read_result);
/* Multiply uSec calcs by 100, to avoid losses due to small results in integer maths
* * Scaled to fit within uint32_t */
ospi_write_result = ((100000000 / timer_frequency) * ospi_performance_write_result) / 100;
qspi_write_result = ((100000000 / timer_frequency) * qspi_write_test(block_size_actual)) / 100;
APP_PRINT("Writing to flash completed\r\n");
APP_PRINT("Reading the text block from external Quad-SPI and Octo-SPI flash memories...\r\n");
ospi_read_result = ((100000000 / timer_frequency) * ospi_performance_read_result) / 100;
qspi_read_result = ((100000000 / timer_frequency) * qspi_read_test(block_size_actual)) / 100;
APP_PRINT("Reading from flash completed\r\n");
R_GPT_Close(g_memory_performance.p_ctrl);
/* Handle error */
if (FSP_SUCCESS != fsp_err)
{
/* Fatal error */
APP_PRINT("ospi qspi read test failed\r\n");
}
APP_PRINT("block_size_actual Value is:%d",block_size_actual);
APP_PRINT("\r\n-------------------------------------------------");
APP_PRINT("\r\nOperation/Flash Quad-SPI Octa-SPI");
APP_PRINT("\r\n-------------------------------------------------");
APP_PRINT("\r\nWrite %6ld %6ld", qspi_write_result , ospi_write_result);
APP_PRINT("\r\nRead %6ld %6ld", qspi_read_result , ospi_read_result);
APP_PRINT("\r\n-------------------------------------------------");
APP_PRINT("\r\nNote: Times are in microseconds");
}
else
{
APP_PRINT("\r\nInvalid size, nenter the text block size specifying a 2K boundary (eg 24):");
}
}
逻辑和例程中的一样,只是用J-Link RTT打印输出信息和获取测试需要的数据。
验证
烧写到板卡后可以用J-Link RTT Viewer软件进行测试,目前输入两位数测试数据时需要通过复制才可以,输入一个数值后就会立马进行测试,这也是第一次使用J-Link RTT Viewer软件造成的。测试完成后可以继续输入数值进行测试。
对应程序源码
DAC配置生成波形及性能测试
配置
在新建工程的基础上进行如下图的配置
应用程序代码编写
在hal_entry函数编写如下代码
fsp_err_t err = FSP_SUCCESS;
/* Open the DAC channel */
err = R_DAC_Open (&g_dac_ctrl, &g_dac_cfg);
double w = 0,dac_value = 0;
/* handle error */
if (FSP_SUCCESS != err)
{
/* DAC module open failed */
while(1)
{
}
}
while (1)
{
w += (PI / 30);
if (w >= (2 * PI))
{
w = 0;
}
dac_value = (sin(w) + 1) / 2 * 4095;
R_DAC_Write(&g_dac_ctrl, (uint16_t)dac_value);
R_DAC_Start(&g_dac_ctrl);
R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_MILLISECONDS);
}
代码也是参考直播时记录的代码。
验证
对应输出的引脚是P014,所以用示波器查看输出波形如下
对应程序源码
进阶任务
示例程序中新增命令打印信息
添加步骤
在s_menu_items数组中添加如下内容
{"followme" , Followme_display_menu},
最终的数组定义如下
/* Table of menu functions */
static st_menu_fn_tbl_t s_menu_items[] =
{
{"followme" , Followme_display_menu},
{"Kit Information" , kis_display_menu},
{"Web Server" , eth_emb_display_menu},
{"Network Name Lookup" , eth_www_display_menu},
{"Quad-SPI and Octo-SPI Speed Comparison" , ext_display_menu},
{"Cryptography and USB High speed (MSC)" , enc_display_menu},
{"Next Steps", ns_display_menu },
{"", NULL }
};
在menu_kis.c文件中添加如下函数的定义
/**********************************************************************************************************************
* Function Name: Followme_display_menu
* Description : .
* Return Value :
*********************************************************************************************************************/
test_fn Followme_display_menu(void)
{
int8_t c = -1;
//uint32_t value = 0;
sprintf (s_print_buffer, "%s%s", gp_clear_screen, gp_cursor_home);
/* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
print_to_console((void*)s_print_buffer);
print_to_console((uint8_t *)"Please enter a number(0~9):");
/* provide small delay so board_status should be up to date */
vTaskDelay (s_ticks_to_wait);
//xEventGroupSetBits (g_update_console_event, STATUS_DISPLAY_MENU_KIS);
while (CONNECTION_ABORT_CRTL != c)
{
c = input_from_console ();
if ((MENU_EXIT_CRTL == c) || (CONNECTION_ABORT_CRTL == c))
{
break;
}
else
{
sprintf (s_print_buffer, "%s%s", gp_clear_screen, gp_cursor_home);
/* ignoring -Wpointer-sign is OK when treating signed char_t array as as unsigned */
print_to_console((void*)s_print_buffer);
sprintf (s_print_buffer, "You entered:%d", c - '0');
print_to_console((void*)s_print_buffer);
print_to_console((uint8_t *)"\r\n\r\n> Press space bar to return to MENU Or Continue entering numbers\r\n");
}
}
//xEventGroupClearBits (g_update_console_event, STATUS_DISPLAY_MENU_KIS);
return (0);
}
/**********************************************************************************************************************
End of function Followme_display_menu
*********************************************************************************************************************/
在menu_kis.h文件中添加如下函数的声明
extern test_fn Followme_display_menu(void);
验证
实现的效果是用串口软件打开后,先输入1进入自己编写的程序中,然后通过数值键输入任意的数字,输入后就立马打印输入的数值。目前没有做到输入更多的字符进行打印。效果如下图
对应程序源码
扩展任务
设计一个类似信号发生器功能的例程。可在示例程序上修改。通过命令或按键,设置DAC输出波形,可通过flash存储历史波形等信息
配置
配置和基础任务的配置一样,只不过基础任务是分成两个任务,需要合成一个作为扩展任务的使用,在此省略配置过程。
流程图
实现扩展任务的方式比较简单,首先是上电检查Flash中的数据是否是有效的,如果有效就按读取的值进行输出,否则可以按默认值或不输出。当有按键或串口有输入时就做对应的修改。流程图如下
应用程序代码编写
首先是用了基础任务的src文件夹下的程序。也添加了按键的.c和.h文件(和入门任务的程序一样)。hal_entry函数写的自定义函数如下
fsp_err_t err = FSP_SUCCESS;
double w = 0,dac_value = 0;
double freq = 10;
uint8_t dac_freq = 10;
/* Open the DAC channel */
err = R_DAC_Open (&g_dac_ctrl, &g_dac_cfg);
if (FSP_SUCCESS != err)
{
/* DAC module open failed */
APP_PRINT("DAC open falied\r\n");
R_DAC_Close(&g_dac_ctrl);
}
getDACsetferq(flash_value);
if (flash_value[0] != 0)
{
freq = flash_value[0];
}
APP_PRINT("read DAC value is:%d\r\n",dac_freq);
/* handle error */
while (1)
{
//qspi_DAC_input_value = process_input_data();
if( Key_Scan(KEY1_SW2_PIN) == KEY_ON )
{
dac_freq += 10;
freq = dac_freq;
flash_value[0] = freq;
saveDACfreq(flash_value);
APP_PRINT("read DAC value is:%d\r\n",dac_freq);
}
if( Key_Scan(KEY2_SW1_PIN) == KEY_ON )
{
dac_freq -= 10;
if (dac_freq <= 0)
{
dac_freq = 10;
}
flash_value[0] = freq;
saveDACfreq(flash_value);
APP_PRINT("read DAC value is:%d\r\n",dac_freq);
}
w += (PI / freq);
if (w >= (2 * PI))
{
w = 0;
}
dac_value = (sin(w) + 1) / 2 * 4095;
R_DAC_Write(&g_dac_ctrl, (uint16_t)dac_value);
R_DAC_Start(&g_dac_ctrl);
R_BSP_SoftwareDelay(1, BSP_DELAY_UNITS_MICROSECONDS);
}
验证
实现的效果是一个按键按下会增加正玄波的频率;另一个按键被按下会减少频率值,且最小值为10。效果如下图
对应程序源码
- 2024-12-13
-
回复了主题帖:
【入围名单】《大规模语言模型:从理论到实践》
邮寄信息已确认,阅读计划可以完成
阅读计划:学习第一章和第二章了解大语言模型的概念、训练类型和架构等。通过第三章和第四章的学习,学习大语言模型的学习过程和分布式训练的步骤和过程。通过第五章的学习了解大预言模型在训练过程中如何进行校正。通过第六章的的学习强化模型训练的强度。通过第七章和第八章的学习认识模型的运用和模型效果的评价。
- 2024-12-12
-
加入了学习《FollowMe 第二季:3 - EK_RA6M5 开发板入门》,观看 EK-RA6M5 开发板入门
- 2024-12-11
-
加入了学习《【Follow me第二季第3期】》,观看 【Follow me第二季第3期】入门任务
- 2024-12-07
-
上传了资料:
Follow me第二季第三期EK-RA6M5入门任务
- 2024-11-21
-
回复了主题帖:
【2024 DigiKey创意大赛】养老护理作品总结和提交
- 2024-11-19
-
加入了学习《【Follow me第二季第3期】LED程序修改及编译,Blink及按键测试》,观看 【Follow me第二季第3期】LED程序修改及编译,Blink及按键测试
- 2024-11-15
-
加入了学习《正点原子手把手教你学STM32-M7》,观看 手把手教你写跑马灯实验-HAL库版本
- 2024-10-30
-
发表了主题帖:
【2024 DigiKey创意大赛】养老护理作品总结和提交
作品名称:养老护理
作者:1084504793
一、作品功能介绍
本作品在原有的按键呼救的基础上变成通过手势进行多种功能的操作,简单易用且功能强大。将只能家居系统搬进养老院中,使广大的老年人员可以体验到科技的进步和家居的只能化。同时也方便老人进行操作,即通过简单的挥手便可进行,告别语音控制识别的低准确带来的麻烦。
二、使用方式
ESP32驱动AHT20获取温湿度数据,并将温湿度数据实时显示在0.96寸OLED屏上。若温湿度数值比较大时会上报给服务器端(树莓派5运行的HomeAssistant)。通过TCS3200颜色识别器可以识别出不同的颜色,通过颜色可以进行标记,如医院的普通病人或重症人员等。通过手势可以简单的进行交互,如向左挥手可以进入灯控界面,向上挥手可以开启灯;向下挥手可以关闭。再向右挥手可以进入呼救界面,向上是发出呼救,呼救信号是通过ESP32无线的MQTT报给树莓派5,向下可以取消呼救。若不需要使用的时候可以遮挡PAJ7620模块前的识别芯片。
三、硬件连接图
四、系统框图
五、功能界面
1、温湿度显示界面(默认界面)
设备上电默认显示温湿度数据,显示效果如下图所示:
2、LED控制界面
在温湿度显示界面(默认界面)下向右挥手进入LED控制界面,或者在求救界面向左挥手,效果如下图
LED状态默认是关闭的,向上挥手可以开启LED,效果显示如下图所示
在此界面向下挥手可以关闭LED灯,显示效果和LED状态默认显示是一样的。
3、求救界面
在LED设置界面向右挥手可以进入求救界面,在温湿度显示界面向左挥手也可以进入。求救界面默认是没有发出的,效果如下
向上挥手可以发出求救,效果如下
向下挥手可以取消求救,效果如默认界面。
六、代码解析
1、初始化部分
Serial.begin(UART_BAUD_SET); /* 串口0初始化 */
Wire.begin(SDA_PORT, SCL_PORT, 400000); /* 初始化IIC连接 */
//pinMode(LED_PORT, OUTPUT); /* 初始化LED引脚 */
//digitalWrite(LED_PORT, LOW); /* LED默认熄灭,即LEN引脚输出低电平 */
//digitalWrite(LED_PORT, HIGH);
strip.begin();
strip.setBrightness(10);
for (int j = 0; j < 5; j++)
{
for (int i = 0; i < strip.getLedCount(); i++)
{
strip.setLedColorData(i, 255, 255, 255);
strip.show();
}
}
OLED_Init(); /* OLED模块初始化 */
if(Gesture.init()) /* 初始化PAJ7620 */
{
Serial.println("PAJ7620U2 initialization failed");
}
else
{
Serial.println("PAJ7620U2 initialization success");
}
Serial.println("Please input your gestures:\n");
if (aht.begin()) /* 初始化AHT20 */
{
Serial.println("Found AHT20");
}
else
{
Serial.println("Didn't find AHT20");
}
/* 初始化TSC3200 */
pinMode(S0_PIN,OUTPUT); //设定引脚输入输出模式
pinMode(S1_PIN,OUTPUT);
pinMode(S2_PIN,OUTPUT);
pinMode(S3_PIN,OUTPUT);
pinMode(OUT_PIN,INPUT);//控制器采集传感器信号
digitalWrite(S0_PIN,HIGH); //频率缩放20% S0-HIGH,S1-LOW
digitalWrite(S1_PIN,LOW);
初始化部分主要初始化各个模块
2、逻辑处理
/* 获取颜色传感器颜色值 */
int r_RGB, g_RGB, b_RGB;
float k_R=7.6, k_G=6.8, k_B=7.3;
int r_H, g_H, b_H;
int r_L, g_L, b_L;
int data_RGB_TFT16;
digitalWrite(S2_PIN, LOW);//只采集红光
digitalWrite(S3_PIN, LOW);
r_L = pulseIn(OUT_PIN, LOW);
r_H = pulseIn(OUT_PIN, HIGH);
r_RGB=calcRGB(r_L,r_H,k_R);
Serial.print("r_RGB = ");
Serial.print(r_RGB);
Serial.print(" ");
delay(200);
digitalWrite(S2_PIN, HIGH);//只采集绿光
digitalWrite(S3_PIN, HIGH);
g_L = pulseIn(OUT_PIN, LOW);
g_H = pulseIn(OUT_PIN, HIGH);
g_RGB=calcRGB(g_L,g_H,k_G);
Serial.print("g_RGB = ");
Serial.print(g_RGB);
Serial.print(" ");
delay(200);
digitalWrite(S2_PIN, LOW);//只采集蓝光
digitalWrite(S3_PIN, HIGH);
b_L = pulseIn(OUT_PIN, LOW);
b_H = pulseIn(OUT_PIN, HIGH);
b_RGB=calcRGB(b_L,b_H,k_B);
Serial.print("b_RGB = ");
Serial.print(b_RGB);
Serial.print(" ");
Serial.println();
delay(200);
/* 手势数据获取 */
paj7620_gesture_t result;
if (Gesture.getResult(result))
{
switch (result)
{
case UP:
delay(GES_QUIT_TIME);
Gesture.getResult(result);
if (result == PUSH)
{
Serial.println("Forward");
delay(GES_QUIT_TIME);
}
else if (result == POLL)
{
Serial.println("Backward");
delay(GES_QUIT_TIME);
}
else
{
Serial.println("Up");
}
break;
case DOWN:
delay(GES_QUIT_TIME);
Gesture.getResult(result);
if (result == PUSH)
{
Serial.println("Forward");
delay(GES_QUIT_TIME);
}
else if (result == POLL)
{
Serial.println("Backward");
delay(GES_QUIT_TIME);
}
else
{
Serial.println("Down");
}
break;
case LEFT:
delay(GES_QUIT_TIME);
Gesture.getResult(result);
if (result == PUSH)
{
Serial.println("Forward");
delay(GES_QUIT_TIME);
}
else if (result == POLL)
{
Serial.println("Backward");
delay(GES_QUIT_TIME);
}
else
{
Serial.println("Left");
}
break;
case RIGHT:
delay(GES_QUIT_TIME);
Gesture.getResult(result);
if (result == PUSH)
{
Serial.println("Forward");
delay(GES_QUIT_TIME);
} else if (result == POLL)
{
Serial.println("Backward");
delay(GES_QUIT_TIME);
} else
{
Serial.println("Right");
}
break;
case PUSH:
Serial.println("Forward");
delay(GES_QUIT_TIME);
break;
case POLL:
Serial.println("Backward");
delay(GES_QUIT_TIME);
break;
case CLOCKWISE:
Serial.println("Clockwise");
break;
case ANTI_CLOCKWISE:
Serial.println("anti-clockwise");
break;
case WAVE:
Serial.println("wave");
break;
default:
break;
}
}
/* 温湿度数据获取 */
sensors_event_t humidity, temp;
aht.getEvent(&humidity, &temp);// populate temp and humidity objects with fresh data
/*Serial.print("Temperature: ");
Serial.print(temp.temperature);
Serial.println(" degrees C");
Serial.print("Pressure: ");
Serial.print(humidity.relative_humidity);
Serial.println(" RH %");*/
/* 手势处理 */
switch (result)
{
case UP:
if (OLEDNextSel == OLED_MENU_SEL_LED_SET)
{
LEDSta = 1;
}
else if (OLEDNextSel == OLED_MENU_SEL_CALL_HELP)
{
CallHelpSta = 1;
}
break;
case DOWN:
if (OLEDNextSel == OLED_MENU_SEL_LED_SET)
{
LEDSta = 0;
}
else if (OLEDNextSel == OLED_MENU_SEL_CALL_HELP)
{
CallHelpSta = 0;
}
break;
case LEFT:
if (OLEDNextSel == OLED_MENU_SEL_TEM)
{
OLEDNextSel = OLED_MENU_SEL_CALL_HELP;
}
else
{
OLEDNextSel = static_cast<OLEDMenuSel>((static_cast<int>(OLEDNextSel) - 1) % 3);
}
break;
case RIGHT:
OLEDNextSel = static_cast<OLEDMenuSel>((static_cast<int>(OLEDNextSel) + 1) % 3);
if (OLEDNextSel == OLED_MENU_SEL_LAST)
{
OLEDNextSel = OLED_MENU_SEL_TEM;
}
break;
default:
break;
}
/* LED状态实现 */
if (LEDSta)
{
for (int j = 0; j < 5; j++)
{
for (int i = 0; i < strip.getLedCount(); i++)
{
strip.setLedColorData(i, 255, 255, 255);
strip.show();
}
}
}
else
{
for (int j = 0; j < 5; j++)
{
for (int i = 0; i < strip.getLedCount(); i++)
{
strip.setLedColorData(i, 0, 0, 0);
strip.show();
}
}
}
/* OLED显示处理 */
if ((OLEDNextSel != OLEDPerSel) || (LEDSta != LEDStaRec) || (CallHelpStaRec != CallHelpSta) ||
((HumiRec > ((uint32_t)humidity.relative_humidity + 1)) || (HumiRec < ((uint32_t)humidity.relative_humidity - 1))
||(TempRec > ((uint32_t)temp.temperature + 1)) || (TempRec < ((uint32_t)temp.temperature - 1))))
{
if (OLEDNextSel != OLEDPerSel)
{
OLEDPerSel = OLEDNextSel;
}
HumiRec = humidity.relative_humidity;
TempRec = temp.temperature;
OLED_Clear();
//Serial.println("next");
switch (OLEDPerSel)
{
case OLED_MENU_SEL_TEM:
{
OLED_ShowString(6,1,"Temp:",16);
OLED_ShowString(6,3,"Humi:",16);
//OLED_ShowNum(43,1,30,3,16);
OLED_ShowNum(43,1,(uint32_t)temp.temperature,3,16);
OLED_ShowNum(43,3,(uint32_t)humidity.relative_humidity,3,16);
break;
}
case OLED_MENU_SEL_LED_SET:
{
LEDStaRec = LEDSta;
if (LEDSta)
{
OLED_ShowString(6,2,"LED: On",16);
}
else
{
OLED_ShowString(6,2,"LED: Off",16);
}
break;
}
case OLED_MENU_SEL_CALL_HELP:
{
CallHelpStaRec = CallHelpSta;
if (CallHelpSta)
{
OLED_ShowString(6,2,"Already Called",16);
OLED_ShowString(18,4,"for Help!",16);
}
else
{
OLED_ShowString(6,2,"Call for Help? ",16);
}
break;
}
default:
break;
}
}
逻辑处理主要包括各个模块数据的获取,数据处理和OLED显示刷新等。
七、源码文件
源码链接:2024_DigiKey_创意大赛_养老护理
源码文件主要包含工程文件、OLED驱动代码和OLED字库。
八、效果视频
[localvideo]d8b891c3af364f900d1402e781114c4c[/localvideo]
九、总结
三个月如白驹过隙那样过得那么快。从刚开始不知道如何使用Arduino开发软件,不知道ESP32如何编程,树莓派如何使用等到现在对其都有了一定的了解。虽然最后作品并没有完美呈现出来,但是其中学到的知识却是无比宝贵的。感谢得捷提供的舞台,感谢得捷的支持。
十、文档
- 2024-10-29
-
上传了资料:
2024_DigiKey_创意大赛_养老护理
- 2024-10-16
-
加入了学习《DigiKey 应用说:Raspberry Pi 5 在视频直播中的应用》,观看 Raspberry Pi 5 在视频直播中的应用
- 2024-09-19
-
回复了主题帖:
下载MPS AI电源资料包,赢【Keep体脂秤、按摩眼罩、电脑支架】
已参加
- 2024-09-12
-
回复了主题帖:
【2024 DigiKey 创意大赛】环境搭建
Jacktang 发表于 2024-8-25 21:42
最后无意见将擦除完的内存卡烧写一下boot修复文件试试,竟然发现烧写成功了。
之前哪些失败是怎么回事呢 ...
内存卡已经安装好系统后是不能刷boot修复文件的,必须是空卡才可以。
- 2024-08-25
-
回复了主题帖:
继续留在大城市打拼还是回家乡从头再来?
如果下定决心,并且也感到能接受的话就可以回去,不管怎样都会有出路的。
-
发表了主题帖:
【2024 DigiKey 创意大赛】环境搭建
在收到开发板前就开始准备一些配件,如树莓派需要的内存卡、HDMI线和电源。由于之前没有接触过树莓派和ESP32,所以环境搭建比较曲折,尤其是树莓派系统的烧录。
先来说一下树莓派系统烧录遇到的问题。在网上也查了很多的资料或视频,都是按照教程的方式使用官方软件制作系统,但是上电后发现树莓派的指示灯先亮红灯,之后红灯灭绿灯闪烁4次,熄灭一段时间后,绿灯又再次闪烁4次,就这样反反复复的,和网上说的长亮是不一样的。树莓派接上HDMI线后,发现屏幕不亮,显示的是没有信号。刚开始以为是接的显示器是电脑显示器,没有网上常用的7英寸专用显示器,所以怀疑是树莓派识别的显示器是不支持的,没有输出HDMI信号,所以在网上查了如何强制显示。后来根据网上的教程修改config.txt文件的内容,但是还是没有任何效果。后来不断地换其他的系统,如32位的(刚开始制作的是64位的),无桌面版的等等,换完之后也是修改config.txt文件内容进行尝试,但是没有任何的变化。就这样浪费了很多的时间。后来感觉灯闪烁是有规律的,随意也查了下指示灯亮或闪烁表示什么,在这个文章中树莓派 ACT LED 指示灯闪烁模式代表的状态 | 树莓派实验室 (nxez.com)也终于知道是因为start*.elf 文件未找到。有了眉目就开始找解决办法,无意见知道制作系统的软件可以修复boot文件,我还以为是我制作的内存卡的文件是boot文件且因为损坏才导致的,所以就在系统烧写完成后就点击boot修复功能,但是一直失败。不过文章写的最多的是内存卡的格式必须是FAT32的,但我买的是64G,FAT32最大支持32G,所以也用了技术文档的内存卡格式设置软件再重新制作系统,但是还是没有效果。所以又在网上买了32G的内存卡,并且也是带有系统的。收到货后就立马试了一下,但是和之前的现象也是一样的,然后就问售后该如何解决,说是接上网线试试,但是接上网线后网口的灯是没有亮的。中间也想着用串口试试,看看打印是什么内容。但是串口不能用杜邦线接,引出的针脚也有串口,所以试了一下,一直打印乱码,换了所有的波特率也是显示乱码。
最后无意见将擦除完的内存卡烧写一下boot修复文件试试,竟然发现烧写成功了。内存卡用的是64G的,用官方软件擦除的。烧写成功后,没有做其他的事,就直接装到树莓派上,发现指示灯频繁闪烁,直至因闪烁频繁而感觉一直是长亮,因为有些文章说树莓派读取内存卡的文件绿灯会闪烁。在烧写完修复文件后,也是好奇看了文件内容,发现没有多少的文件。打开config.txt文件后写有若boot修复成功后,HDMI接的显示屏会显示绿色。所以接个显示屏看看效果,发现果真是显示绿色的。然后拔出内存卡,烧写正式的64为Raspberry Pi OS系统。树莓派插上内存卡,接上显示器上电后发现指示灯长亮,显示器正常显示树莓派的桌面。写了这么多就是想分享一下自己解决问题的思路和经验,也希望对大家有所帮助。不过现在回想起来要是刚开始就擦除完内存卡数据后就烧写boot修复文件就不会这么曲折了,但是第一次接触树莓派,以为boot引导系统是在内存卡上的,因为我看设备芯片也没发现有什么存储数据的芯片,所以一直以为是内存卡的问题,还以为树莓派不支持这种内存卡。后来才在一些技术文档中才知道boot引导程序是在树莓派上的EEPROM上,可能是在散热片下,这个就以后考究了。
树莓派烧写boot引导系统的方法。
接下来是ESP32环境的搭建。这次我选择Arduino环境开发ESP32,因为觉得该环境相对来说比较简单,上手快。之前也是没有接触ESP32和Arduino,所以Arduino环境支持ESP32开发也是用了两天的时间,主要消耗在ESP32支持包的下载。不过可以借鉴某个机构的ESP32开发教程,其中就有快速搭建Arduino环境的教程,可以说是分分钟的事。
ESP32的Arduino环境搭建如下图
- 2024-08-09
-
发表了主题帖:
【2024 DigiKey 创意大赛】ESP32-C6、树莓派5和TCS3200传感器开箱
期待已久的板卡终于到了。包装非常好,没有任何的磕碰。板卡也都用了防静电袋进行二次包装。