状态机实现RGB灯跳变

2023-11-11 20:52
文章标签 实现 状态机 rgb 跳变

本文主要是介绍状态机实现RGB灯跳变,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.项目功能梗概

因为原本使用的为for循环进行遍历,然后依次执行代码,但是由于看门狗的存在,不能使用delay_ms这种死延时。所以现在打算定时器回调函数控制状态机状态这种方法。

2.状态机

作用

当系统需要执行某个任务时,可以根据状态机的状态选择不同的操作,例如:

  • 控制系统状态:例如控制器根据状态机的状态选择执行不同的操作,从而控制整个系统的状态,例如开关灯、控制电机等。
  • 系统调度:例如操作系统根据状态机的状态选择执行不同的任务,从而实现系统的调度。
  • 系统事件处理:例如网络通信系统根据状态机的状态选择不同的数据处理方式,例如处理接收到的数据、发送数据等。
  • 系统错误处理:例如系统出现错误时,可以根据状态机的状态选择不同的错误处理方式,例如重新启动系统、输出错误信息等。

总之,状态机可以帮助我们将系统的复杂性分解为多个简单的状态,根据不同的状态选择执行不同的操作,从而更好地实现系统的设计与开发。

主要流程

  1. 定义状态和事件

    首先需要定义系统可能存在的所有状态,通常用枚举类型来表示。同时需要定义可能发生的所有事件,例如输入的数据、定时器到达等。

  2. 初始化状态机

    在程序启动时,需要将状态机初始化为特定的状态。

  3. 定义状态转换和动作

    使用switch-case if-else 函数指针等语句来定义状态转换和动作。当事件发生时,判断当前状态,并根据不同的事件执行相应的动作,并将状态转换为下一个状态。

  4. 事件处理

    当有事件发生时,将事件作为参数传递给状态机,并调用状态转换和动作函数。

  5. 循环执行

    状态机通常作为一个独立的任务运行,并在一个无限循环中等待事件的发生。

3.实现过程相关思考

说实话,尝试了下突然有用标志位的思路了


// 定义全局指针变量
u8 *global_bt_receive_buffer_gradually;
u32 global_length_gradually;
volatile u8 time_flag_gradually = 0;
void handleColor_arrayChange_gradually(u8 *bt_receive_buffer, u32 length)
{printf("通过数组控制灯颜色状态\n");static int j = 0;static int i = 5;u8 STEPS = 30;static u8 i_balance = 3;// 获取初始亮度i-u8 initial_red_value = bt_receive_buffer[i];u8 initial_green_value = bt_receive_buffer[i+1];u8 initial_blue_value = bt_receive_buffer[i+2];for (; (i < (length - 5)) && (time_flag_gradually == 0);){u8 target_red_value = bt_receive_buffer[i + 3];u8 target_green_value = bt_receive_buffer[i + 4];u8 target_blue_value = bt_receive_buffer[i + 5];printf("i的值为-----------i的值为-----------i的值为-----------i的值为-----------i的值为-----------i的值为-----------i的值为-----------i的值为-----------%d\n", i);printf("target_red_value------------------target_red_value---------------target_red_value%d\n", target_red_value);printf("target_red_value------------------target_red_value---------------target_red_value%d\n", target_green_value);printf("target_red_value------------------target_red_value---------------target_red_value%d\n", target_blue_value);// 计算每个颜色通道的增量int red_increment = (target_red_value - initial_red_value) / STEPS;int green_increment = (target_green_value - initial_green_value) / STEPS;int blue_increment = (target_blue_value - initial_blue_value) / STEPS;// 逐步更新颜色值,使其渐变到目标值for (; (j < STEPS) && (time_flag_gradually == 0); j++){u8 current_red_value = initial_red_value + (red_increment * j);u8 current_green_value = initial_green_value + (green_increment * j);u8 current_blue_value = initial_blue_value + (blue_increment * j);handleColorChange(current_red_value, current_green_value, current_blue_value);// delay_2ms(24); // 延时一段时间,控制灯的变化速度printf("initial_red_value----initial_red_value----initial_red_value----initial_red_value----initial_red_value----%d\n", initial_red_value);printf("initial_green_value-----initial_green_value-------initial_green_value-------initial_green_value-------%d\n", initial_green_value);printf("initial_blue_valueinitial_blue_valueinitial_blue_valueinitial_blue_valueinitial_blue_valueinitial_b%d\n", initial_blue_value);printf("红色值每一次增量------红色值每一次增量--------红色值每一次增量--------红色值每一次增量-------红色值每一次增量%d\n", red_increment);printf("绿色值每一次增量------绿色值每一次增量------绿色值每一次增量------绿色值每一次增量------绿色值每一次增量------绿色值每一次增量------%d\n", green_increment);printf("蓝色值每一次增量------蓝色值每一次增量------蓝色值每一次增量------蓝色值每一次增量------蓝色值每一次增量------蓝色值每一次增量------蓝色值每一次增量------%d\n", blue_increment);time_flag_gradually = 1;printf("jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj===================%d\n", j);}if (j >= STEPS){j = 0;i = i + 3;}printf("第一组 RGB 值已经渐变到第二组一样\n");// 更新初始亮度为目标亮度,以便下一组渐变initial_red_value = target_red_value;initial_green_value = target_green_value;initial_blue_value = target_blue_value;}if (i >= (length - 5)){i = 5;}global_bt_receive_buffer_gradually = bt_receive_buffer;global_length_gradually = length;
}
u32 timeout_msec_gradually = 5; // 设置定时时间为10毫秒
void timeout_callback_gradually(void *priv)
{// 每10msstatic u8 i = 5;// printf("回调函数渐变\n");printf("回调函数渐变%d\n", time_flag_gradually);// printf("time_flag_gradually != 0time_flag_gradually != 0time_flag_gradually != 0time_flag_gradually != 0time_flag_gradually != 0\n");i = i + 5;if (i == 50){time_flag_gradually = 0;i = 0;}handleColor_arrayChange_gradually(global_bt_receive_buffer_gradually, global_length_gradually);
}

其实就是把第一个for循环里的数组移位转移到了小的for循环里,只有当小的for循环里面已经将颜色渐变全部实现了,才允许i++实现移位。不过有个问题就是颜色渐变完成后,会从最后一个颜色突变到第一个颜色。这里应该是在设置代码初始化时的重新赋值的原因,导致缺失了一段颜色变化。

 

  • 将所要的颜色数据数据提取出来,作为一个数组。每一次颜色渐变完成,就将数组的后三位赋值到前三位,以此类推,重新执行函数。
  • 第二种,写死,每次多执行一段最后一个颜色渐变到第一个颜色的代码。

疑惑,有没有使用更简洁的方法,或者说环形数组对这种循环显示的是不是更好。

贴一下目前代码图片

u16 timer_id_color_change_suddenly = 0;
u16 timer_id_color_change_gradually = 0;
void *private_data = NULL; // 设置私有参数为NULL
u32 timeout_msec = 10;     // 设置定时时间为10毫秒
u8 priority = 1;           // 设置优先级为1
void timeout_callback(void *priv)
{static u16 i = 0;printf("回调函数跳变\n");i = i + 10;if (i == 1000){printf("ifififiifiifififiififififi\n");time_flag_suddenly = 1;i = 0;}handleColor_arrayChange_suddenly(global_bt_receive_buffer, global_length, global_color_mode_record, global_color1);
}// 定义全局指针变量
u8 *global_bt_receive_buffer_gradually;
u32 global_length_gradually;
volatile u8 time_flag_gradually = 0;
void handleColor_arrayChange_gradually(u8 *bt_receive_buffer, u32 length)
{printf("通过数组控制灯颜色状态\n");static int j = 0;static int i = 5;u8 STEPS = 30;static u8 i_balance = 3;static flag = 1;// 获取初始亮度i-u8 initial_red_value = bt_receive_buffer[i];u8 initial_green_value = bt_receive_buffer[i + 1];u8 initial_blue_value = bt_receive_buffer[i + 2];for (; (i < (length - 5)) && (time_flag_gradually == 0);){u8 target_red_value = bt_receive_buffer[i + 3];u8 target_green_value = bt_receive_buffer[i + 4];u8 target_blue_value = bt_receive_buffer[i + 5];printf("i的值为-----------i的值为-----------i的值为-----------i的值为-----------i的值为-----------i的值为-----------i的值为-----------i的值为-----------%d\n", i);printf("target_red_value------------------target_red_value---------------target_red_value%d\n", target_red_value);printf("target_red_value------------------target_red_value---------------target_red_value%d\n", target_green_value);printf("target_red_value------------------target_red_value---------------target_red_value%d\n", target_blue_value);// 计算每个颜色通道的增量int red_increment = (target_red_value - initial_red_value) / STEPS;int green_increment = (target_green_value - initial_green_value) / STEPS;int blue_increment = (target_blue_value - initial_blue_value) / STEPS;// 逐步更新颜色值,使其渐变到目标值for (; (j < STEPS) && (time_flag_gradually == 0); j++){u8 current_red_value = initial_red_value + (red_increment * j);u8 current_green_value = initial_green_value + (green_increment * j);u8 current_blue_value = initial_blue_value + (blue_increment * j);handleColorChange(current_red_value, current_green_value, current_blue_value);// delay_2ms(24); // 延时一段时间,控制灯的变化速度printf("initial_red_value----initial_red_value----initial_red_value----initial_red_value----initial_red_value----%d\n", initial_red_value);printf("initial_green_value-----initial_green_value-------initial_green_value-------initial_green_value-------%d\n", initial_green_value);printf("initial_blue_valueinitial_blue_valueinitial_blue_valueinitial_blue_valueinitial_blue_valueinitial_b%d\n", initial_blue_value);printf("红色值每一次增量------红色值每一次增量--------红色值每一次增量--------红色值每一次增量-------红色值每一次增量%d\n", red_increment);printf("绿色值每一次增量------绿色值每一次增量------绿色值每一次增量------绿色值每一次增量------绿色值每一次增量------绿色值每一次增量------%d\n", green_increment);printf("蓝色值每一次增量------蓝色值每一次增量------蓝色值每一次增量------蓝色值每一次增量------蓝色值每一次增量------蓝色值每一次增量------蓝色值每一次增量------%d\n", blue_increment);time_flag_gradually = 1;printf("jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj===================%d\n", j);}if (j >= STEPS){j = 0;i = i + 3;}printf("第一组 RGB 值已经渐变到第二组一样\n");// 更新初始亮度为目标亮度,以便下一组渐变initial_red_value = target_red_value;initial_green_value = target_green_value;initial_blue_value = target_blue_value;}if (i >= (length - 5)){i=5;}global_bt_receive_buffer_gradually = bt_receive_buffer;global_length_gradually = length;
}

        

这篇关于状态机实现RGB灯跳变的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/392780

相关文章

SpringBoot集成XXL-JOB实现任务管理全流程

《SpringBoot集成XXL-JOB实现任务管理全流程》XXL-JOB是一款轻量级分布式任务调度平台,功能丰富、界面简洁、易于扩展,本文介绍如何通过SpringBoot项目,使用RestTempl... 目录一、前言二、项目结构简述三、Maven 依赖四、Controller 代码详解五、Service

Python 基于http.server模块实现简单http服务的代码举例

《Python基于http.server模块实现简单http服务的代码举例》Pythonhttp.server模块通过继承BaseHTTPRequestHandler处理HTTP请求,使用Threa... 目录测试环境代码实现相关介绍模块简介类及相关函数简介参考链接测试环境win11专业版python

GO语言短变量声明的实现示例

《GO语言短变量声明的实现示例》在Go语言中,短变量声明是一种简洁的变量声明方式,使用:=运算符,可以自动推断变量类型,下面就来具体介绍一下如何使用,感兴趣的可以了解一下... 目录基本语法功能特点与var的区别适用场景注意事项基本语法variableName := value功能特点1、自动类型推

基于Python实现自动化邮件发送系统的完整指南

《基于Python实现自动化邮件发送系统的完整指南》在现代软件开发和自动化流程中,邮件通知是一个常见且实用的功能,无论是用于发送报告、告警信息还是用户提醒,通过Python实现自动化的邮件发送功能都能... 目录一、前言:二、项目概述三、配置文件 `.env` 解析四、代码结构解析1. 导入模块2. 加载环

使用shardingsphere实现mysql数据库分片方式

《使用shardingsphere实现mysql数据库分片方式》本文介绍如何使用ShardingSphere-JDBC在SpringBoot中实现MySQL水平分库,涵盖分片策略、路由算法及零侵入配置... 目录一、ShardingSphere 简介1.1 对比1.2 核心概念1.3 Sharding-Sp

Java+AI驱动实现PDF文件数据提取与解析

《Java+AI驱动实现PDF文件数据提取与解析》本文将和大家分享一套基于AI的体检报告智能评估方案,详细介绍从PDF上传、内容提取到AI分析、数据存储的全流程自动化实现方法,感兴趣的可以了解下... 目录一、核心流程:从上传到评估的完整链路二、第一步:解析 PDF,提取体检报告内容1. 引入依赖2. 封装

Java实现复杂查询优化的7个技巧小结

《Java实现复杂查询优化的7个技巧小结》在Java项目中,复杂查询是开发者面临的“硬骨头”,本文将通过7个实战技巧,结合代码示例和性能对比,手把手教你如何让复杂查询变得优雅,大家可以根据需求进行选择... 目录一、复杂查询的痛点:为何你的代码“又臭又长”1.1冗余变量与中间状态1.2重复查询与性能陷阱1.

python 线程池顺序执行的方法实现

《python线程池顺序执行的方法实现》在Python中,线程池默认是并发执行任务的,但若需要实现任务的顺序执行,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋... 目录方案一:强制单线程(伪顺序执行)方案二:按提交顺序获取结果方案三:任务间依赖控制方案四:队列顺序消

Redis实现分布式锁全过程

《Redis实现分布式锁全过程》文章介绍Redis实现分布式锁的方法,包括使用SETNX和EXPIRE命令确保互斥性与防死锁,Redisson客户端提供的便捷接口,以及Redlock算法通过多节点共识... 目录Redis实现分布式锁1. 分布式锁的基本原理2. 使用 Redis 实现分布式锁2.1 获取锁

Linux实现查看某一端口是否开放

《Linux实现查看某一端口是否开放》文章介绍了三种检查端口6379是否开放的方法:通过lsof查看进程占用,用netstat区分TCP/UDP监听状态,以及用telnet测试远程连接可达性... 目录1、使用lsof 命令来查看端口是否开放2、使用netstat 命令来查看端口是否开放3、使用telnet