【STM32 HAL库】寻迹小车 开环控制 状态机 TB6612+TCRT5000+HC-05

news2024/11/28 22:45:23

【STM32 HAL库】寻迹小车 开环控制 状态机 TB6612+TCRT5000+HC-05

  • 前言
  • 硬件
    • 硬件准备
    • 模块说明
      • 主控 APM32F103VBT6核心板
      • DC/DC降压模块
      • TB6612电机驱动
      • TCRT5000红外循迹模块
      • HC-05蓝牙透传模块
  • 代码逻辑
    • 宏观框架
      • 状态机
    • 框架测试
    • 微观模块
      • 电机模块
      • 循迹模块
      • 蓝牙控制模块

前言

碎碎念一下,本篇博客为个人项目总结,因技术一般且记性较差(笑)故写此博客以供记录与复盘

硬件

硬件准备

模块型号数量碎碎念
主控极海APM32VBT61因原主控指南者VET6故障,中途换成国产板子
电源DC头锂电池1注意电池供电头应与DC/DC降压模块的口一致
DC/DC降压模块XY-36061注意与锂电池的适配性
电机驱动TB66122建议多买几个,TB6612容易炸,一炸等物流就要两三天,一定不要短路!!严重了直接板子电脑主板一块带走
电机+轮子套件JGB37-520霍尔编码器电机2注意,电机架要能固定到小车板子上,最好买带编码器的,否则不能做后续的PID闭环控制
红外循迹传感器TCRT50006+越多越好,反正便宜,只有传感器数量上去了,后续PID循迹时小车速度才能上去,才能更稳
蓝牙透传模块HC-051-2建议备用一个
小车套件酷点机器人小车套件1买哪家的都可,注意最好孔位多,要能适配你的板子以及好安装其他模块
耗材杜邦线,转接线等等充足注意及时补充

模块说明

主控 APM32F103VBT6核心板

优点
啊这,实际上是手头没板子了,只能先用这个过度下
缺点
1.板载资源较少(4个定时器,不足以完成驱动电机以及编码器测速的功能
2.国产平替的板子再怎么说兼容性都不能100%等于STM32,且开源资料有限,谨慎考虑
建议
建议买个资源多点的板子,建议vet6起步,硬件资源有限真的有点难绷

DC/DC降压模块

功能
将锂电池输入进DCDC的12v转换为12v与5v输出

TB6612电机驱动

功能
本质上讲,TB6612是一个电子开关,它根据接收到的PWM信号,来控制”开“与”关“时间的比例,根据“占空比”,输出特定的电压,以此电压来驱动电机

TCRT5000红外循迹模块

功能
发射红外光到反射面,若反射面吸收,则接收不到反射回的红外光,则led熄灭,D0口输出高电平
所以在合适的阈值下,根据D0口的电平高低,就能判断处是否检测到黑线(黑线吸收红外线)

HC-05蓝牙透传模块

功能
将复杂的蓝牙协议简化为串口透传,本质上就是无线的串口通信

代码逻辑

宏观框架

状态机

状态机图
在这里插入图片描述
状态机伪代码

void fsm(void)
{
	switch(当前状态)
{
    case 空闲状态:
	{
		//电机停止 
        switch(当前事件)
        {
			case 空闲事件:
				当前状态 = 空闲状态;
				break;
            case 循迹事件:
                当前状态 = 循迹状态; 
                break;			
            default:
				当前状态 = 运动状态;
                break;
        }
	}
    break;

    case 循迹状态:
	{
		//循迹 
        switch(当前事件)
        {
            case 空闲事件:
                当前状态 = 空闲状态; 
                break;
            case 循迹事件:
                当前状态 = 循迹状态; 
                break;	
            default:
				  当前状态 = 运动状态;
                break;
        }
	}
    break;	

    case 运动状态:
	{
        switch(当前事件)
        {
            case 空闲事件:
                当前状态 = 空闲状态; 
                break;
            case 循迹事件:
                当前状态 = 循迹状态; 
                break;
			case 直走事件:
				//直走 
				break;
            case 后退事件:
				//后退 
                break;
			case 左转事件:
                //左转 
                break;
            case 右转事件:
                //右转 
                break;
            case 加速事件:
                //加速 
                break;
            case 减速事件:
                //减速 
                break;
            case 速度最大事件:
                //速度最大 
				break;
            case 停止事件:
                //停止 
                break;
        }
	}
    break;

	}
}

状态机代码

void fsm(void)
{
	switch(cur_state)
{
    case S0_IDLE:
	{
		stop();
        switch(EvntID)
        {
			case E0_IDLE:
				cur_state = S0_IDLE;
				break;
            case E1_TRACK:
                cur_state = S1_TRACK; 
                break;			
            default:
				cur_state = S2_SPORT;
                break;
        }
	}
    break;

    case S1_TRACK:
	{
		track();
        switch(EvntID)
        {
            case E0_IDLE:
                cur_state = S0_IDLE; 
                break;
            case E1_TRACK:
                cur_state = S1_TRACK; 
                break;	
            default:
				  cur_state = S2_SPORT;
                break;
        }
	}
    break;	

    case S2_SPORT:
	{
        switch(EvntID)
        {
            case E0_IDLE:
                cur_state = S0_IDLE; 
                break;
            case E1_TRACK:
                cur_state = S1_TRACK; 
                break;
			case E2_GO:
				go1();
				break;
            case E3_BACK:
				back();
                break;
			case E4_LEFT:
                left();
                break;
            case E5_RIGHT:
                right();
                break;
            case E6_SPEED_UP:
                speed_up();
                break;
            case E7_SPEED_DOWN:
                speed_down();
                break;
            case E8_SPEED_MAX:
                speed_max();
				break;
            case E9_STOP:
                stop();
                break;
        }
	}
    break;

	}
}

框架测试

以HC-05蓝牙透传模块控制小车为例

HC-05初始化

void hc05_init(void)
{
	HAL_UART_Receive_IT(&huart3, &receiveData,1);
}

接收完成中断回调函数中实现“当前事件”的更新,从而实现状态机的切换

/*
简述:重定义接收完成中断回调函数
详解:根据接收到蓝牙调试助手发送的数据,更新事件(以供状态机切换
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart == &huart3)
	{
		//用以调试(判断是否进入中断,判断当前receiveData值
//		printf("OK\n");
//		printf("receiveData = %d\n",receiveData-48);

		switch(receiveData-48)
		{
			case 0:
				EvntID = E0_IDLE;
				printf("STOP\n");
				break;
			case 1:
				EvntID = E1_TRACK;
				printf("TRACK\n");
				break;
			case 2:
				EvntID = E2_GO;
				printf("GO\n");			
				break;
			case 3:
				EvntID = E3_BACK;
				printf("BACK\n");				
				break;
			case 4:
				EvntID = E4_LEFT;
				printf("LEFT\n");	
				break;
			case 5:
				EvntID = E5_RIGHT;
				printf("RIGHT\n");
				break;
			case 6:
				EvntID = E6_SPEED_UP;
				printf("SPEED_UP\n");
				break;
			case 7:
				EvntID = E7_SPEED_DOWN;
				printf("SPEED_DOWN\n");
				break;
			case 8:
				EvntID = E8_SPEED_MAX;
				printf("SPEED_MAX\n");
				break;
			case 9:
				EvntID = E9_STOP;
				printf("STOP\n");
				break;
			default:
				EvntID = E0_IDLE; // 默认情况下返回到空闲状态
				printf("ERROR_STOP\n");
				break;
		}
		HAL_UART_Receive_IT(&huart3, &receiveData, 1);
	}
} 

微观模块

也就是状态机伪代码中的基本的功能代码

电机模块

motor.c

#include "motor.h"

uint16_t pulse_l,pulse_r;
float speed_l,speed_r;

/*
简述:启动电机函数
详解:开启TIM定时器的PWM模式,开始产生PWM波,启动电机
*/
void Motor_Start(void)
{
	//启动左侧A相电机
	HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_1);
	//启动右侧B相电机	
	HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_4);

}


/*
简述:设置小车速度
详解:根据PWM占空比与小车速度关系,改变PWM比较寄存器值,从而改变占空比控制小车速度
*/
void Motor_SetSpeed(MotorDirection Mode,float speed_l,float speed_r)
{
	if(0 <= speed_l && speed_l <= 356)
	pulse_l = 1000 - 2.8086*speed_l;
	if(0 <= speed_r && speed_r <= 356)
	pulse_r = 1000 - 2.8086*speed_r;	
	
	if(Mode == FORWARD)
	{
	HAL_GPIO_WritePin(AIN1_GPIO_Port,AIN1_Pin,GPIO_PIN_RESET);
	HAL_GPIO_WritePin(AIN2_GPIO_Port,AIN2_Pin,GPIO_PIN_SET);
	HAL_GPIO_WritePin(BIN1_GPIO_Port,BIN1_Pin,GPIO_PIN_RESET);
	HAL_GPIO_WritePin(BIN2_GPIO_Port,BIN2_Pin,GPIO_PIN_SET);
	}
	else if(Mode == BACKWARD)
	{
	HAL_GPIO_WritePin(AIN1_GPIO_Port,AIN1_Pin,GPIO_PIN_SET);
	HAL_GPIO_WritePin(AIN2_GPIO_Port,AIN2_Pin,GPIO_PIN_RESET);	
	HAL_GPIO_WritePin(BIN1_GPIO_Port,BIN1_Pin,GPIO_PIN_SET);
	HAL_GPIO_WritePin(BIN2_GPIO_Port,BIN2_Pin,GPIO_PIN_RESET);	
	}	
	
	__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,pulse_l);
	__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_4,pulse_r);	

	
	
}

/*
简述:小车基本运动模式
详解:设置小车左右轮速度,从而改变小车运动方式
*/
void go(void)
{
	Motor_SetSpeed(FORWARD,52,50);
}
void go1(void)
{
	Motor_SetSpeed(FORWARD,100,95);
}
void stop(void)
{
	Motor_SetSpeed(FORWARD,5,5); 
}

void back(void)
{
	Motor_SetSpeed(BACKWARD,100,100);
	
}
void left(void)
{
	Motor_SetSpeed(FORWARD,1,70);
}

void left1(void)
{
	Motor_SetSpeed(FORWARD,5,50);
}
void left2(void)
{
	Motor_SetSpeed(FORWARD,5,150);
}
void left3(void)
{
	Motor_SetSpeed(FORWARD,5,200);
}

void right(void)
{
	Motor_SetSpeed(FORWARD,70,1);
}
void right1(void)
{
	Motor_SetSpeed(FORWARD,50,5);
}
void right2(void)
{
	Motor_SetSpeed(FORWARD,150,5);
}
void right3(void)
{
	Motor_SetSpeed(FORWARD,200,5);
}
/*
简述:小车加速函数
详解:获取小车1、2相电机对应的定时器的比较寄存器的当前值,并定义最小比较寄存器值,用以控制小车加速后速度上限
*/
void speed_up(void)
{

	uint16_t motor_a_compare,motor_b_compare;
	uint16_t min_compare = 700;
	uint16_t max_change_i;
	
	motor_a_compare = __HAL_TIM_GET_COMPARE(&htim4,TIM_CHANNEL_1);
	motor_b_compare = __HAL_TIM_GET_COMPARE(&htim4,TIM_CHANNEL_4);
	
	if(motor_a_compare>motor_b_compare)
		 max_change_i = motor_b_compare - min_compare;
	else
		 max_change_i = motor_a_compare - min_compare;
	for(float i = 0;i <= max_change_i;i+=0.001)
	{
		__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,motor_a_compare - i);
		__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_4,motor_b_compare - i);
	}
}

/*
简述:小车减速函数
详解:获取小车1、2相电机对应的定时器的比较寄存器的当前值,并定义最大比较寄存器值,用以控制小车减速后速度下限
*/
void speed_down(void)
{
	uint16_t motor_a_compare,motor_b_compare;
	uint16_t max_compare = 999;
	uint16_t max_change_i;
	
	motor_a_compare = __HAL_TIM_GET_COMPARE(&htim4,TIM_CHANNEL_1);
	motor_b_compare = __HAL_TIM_GET_COMPARE(&htim4,TIM_CHANNEL_4);
	
	if(motor_a_compare>motor_b_compare)
		 max_change_i = max_compare - motor_a_compare;
	else
		 max_change_i = max_compare - motor_b_compare;
	for(float i = 0;i <= max_change_i;i+=0.001)
	{
		__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,motor_a_compare + i);
		__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_4,motor_b_compare + i);
	}
}
/*
简述:小车加速到最大速度函数
详解:for循环中比较寄存器值自减,实现小车速度自增(设置并控制速度上限(减速比较小,最大速度过大))
*/
void speed_max(void)
{
	uint16_t max_i = 270;
	static float i = 0;
	for(;i <= max_i;i+=0.001)
	{
		__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,1000 - i);
		__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_4,1000 - i);
	}	
}

循迹模块

tcrt5000.c

#include "tcrt5000.h"


DIRECTION mode;
DIRECTION LEFTMAX;
DIRECTION RIGHTMAX;

/*
简述:判断当前位置状态
详解:根据红外传感器的D0值-->判断当前小车偏移量(LEFT1左一级偏移,LEFT2左二级偏移以此类推)
基本逻辑:先判断左右侧感应到黑线的最远端传感器,若左侧没感应到黑线,则以右侧感应到黑线的最远端传感器作为偏移程度;若右侧没感应到黑线则同理;若两侧都没感应到黑线或都感应到黑线,则直行
举例:若左1左2感应到黑线,左3没感应到黑线,则左MAX=左2。若右1右2右3都没感应到黑线,则右MAX=GO。此时偏移量mode=左MAX=左2,在循迹处左转程度为LEFT2对应的左转程度
*/
void GetDirection(void)
{
	
	//判断左侧传感器中感应到黑线的最远端传感器
	if(L3 == 1)
		LEFTMAX = LEFT3;
	else if(L2 == 1)
		LEFTMAX = LEFT2;
	else if(L1 == 1)
		LEFTMAX = LEFT1;
	else 
		LEFTMAX = GO;
	
	
	//判断右侧传感器中感应到黑线的最远端传感器
	if(R3 == 1)
		RIGHTMAX = RIGHT3;
	else if(R2 == 1)
		RIGHTMAX = RIGHT2;
	else if(R1 == 1)
		RIGHTMAX = RIGHT1;
	else 
		RIGHTMAX = GO;
	
	
	//判断偏移量
	if((LEFTMAX == GO) && (RIGHTMAX == GO))
		mode = GO;
	else if((LEFTMAX != GO) && (RIGHTMAX == GO))
		mode = LEFTMAX;
	else if((LEFTMAX == GO) && (RIGHTMAX != GO))
		mode = RIGHTMAX;
	else
		mode = GO;
}


/*
简述:循迹函数
详解:先更新当前位置状态,根据当前小车偏移量执行对应纠正偏移的动作
*/
void track(void)
{
	//先更新当前偏移量
	GetDirection();		

	//根据偏移量执行循迹操作(偏移量越大,转弯程度越大
	switch(mode)
	{
		case GO:
			go();
			break;
			
		case LEFT1:
			left1();
			break;
		
		case LEFT2:
			left2();
			break;

		case LEFT3:
			left3();
			break;
		
		case RIGHT1:
			right1();
			break;
		
		case RIGHT2:
			right2();
			break; 

		case RIGHT3:
			right3();
			break; 	
	}
}

蓝牙控制模块

#include "hc05.h"
uint8_t receiveData;
/*
简述:hc05蓝牙透传模块初始化函数
详解:开启中断接收
*/
void hc05_init(void)
{HAL_UART_Receive_IT(&huart3, &receiveData,1);}

/*
简述:重定义接收完成中断回调函数
详解:根据接收到蓝牙调试助手发送的数据,更新事件(以供状态机切换
*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart == &huart3)
	{
//		用以调试(判断是否进入中断,判断当前receiveData值
//		printf("OK\n");
//		printf("receiveData = %d\n",receiveData-48);

		switch(receiveData-48)
		{
			case 0:
				EvntID = E0_IDLE;
				printf("STOP\n");
				break;
			case 1:
				EvntID = E1_TRACK;
				printf("TRACK\n");
				break;
			case 2:
				EvntID = E2_GO;
				printf("GO\n");			
				break;
			case 3:
				EvntID = E3_BACK;
				printf("BACK\n");				
				break;
			case 4:
				EvntID = E4_LEFT;
				printf("LEFT\n");	
				break;
			case 5:
				EvntID = E5_RIGHT;
				printf("RIGHT\n");
				break;
			case 6:
				EvntID = E6_SPEED_UP;
				printf("SPEED_UP\n");
				break;
			case 7:
				EvntID = E7_SPEED_DOWN;
				printf("SPEED_DOWN\n");
				break;
			case 8:
				EvntID = E8_SPEED_MAX;
				printf("SPEED_MAX\n");
				break;
			case 9:
				EvntID = E9_STOP;
				printf("STOP\n");

				break;
			default:
				EvntID = E0_IDLE; // 默认情况下返回到空闲状态
				printf("ERROR_STOP\n");
				break;
		}
		HAL_UART_Receive_IT(&huart3, &receiveData, 1);
	}
} 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2060133.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

keepalived安装-centos7

一、yum安装 1、安装Keepalived&#xff1a; yum install -y keepalived 2、启动Keepalived服务&#xff1a; systemctl start keepalived 3、设置Keepalived服务开机自启 systemctl enable keepalived 4、检查Keepalived服务状态&#xff1a; systemctl status keepal…

VAuditDemo常规漏洞

VAuditDemo常规漏洞 一、留言类功能漏洞 messageDetail.php - 存在数字型SQL注入&#xff0c;反射型XSS SQL注入 sqlwaf修改措施 反射型XSS messageSub.php search.php - 存在反射型xss 二、用户操作类漏洞 1、登录功能 logCheck.php - 空验证码绕过漏洞 2、编辑用户信息类 upd…

秘密指南!浮毛会危害人体健康吗?宠物空气净化器帮助解决危害

每当立秋一到&#xff0c;对于我这样的重度鼻炎患者而言&#xff0c;无疑是又一轮掉毛季的预警。家中猫咪的毛发仿佛永远扫不尽&#xff0c;皮屑也无处不在&#xff0c;让人头疼不已。好在&#xff0c;两年前我采纳了宠物医生的建议&#xff0c;用上了宠物空气净化器&#xff0…

Element-plus el-input 添加图标

案例图 根据官方文档来&#xff0c;我们需要先注册图标并应用到全局。 import { createApp } from "vue" import App from "./App.vue"const app createApp(App) //创建VUE对象import * as ElementPlusIconsVue from "element-plus/icons-vue"f…

竞争和冒险

竞争和冒险 文章目录 竞争和冒险总结 产生原因 数字电路中&#xff0c;信号传输与状态变换时都会有一定的延时。 在组合逻辑电路中&#xff0c;不同路径的输入信号变化传输到同一点门级电路时&#xff0c;在时间上有先有后&#xff0c;这种先后所形成的时间差称为竞争&#xf…

【方法】如何给ZIP压缩文件添加密码?

如果想要保护ZIP压缩文件不被他人随意打开&#xff0c;可以设置密码保护&#xff0c;那要如何设置呢&#xff1f;下面推荐两种方法&#xff0c;一起来看看吧&#xff01; 方法1&#xff1a; 如果想在压缩文件的时候&#xff0c;同时设置密码&#xff0c;可以使用WinRAR或者7-…

Qt 系统相关 - 文件

目录 1. 文件概述 2. 输入输出设备类 3. 文件读写类 4. 文件和目录信息类 1. 文件概述 文件操作是应用程序必不可少的部分。Qt 作为一个通用开发库&#xff0c;提供了跨平台的文件操作能力。 Qt 提供了很多关于文件的类&#xff0c;通过这些类能够对文件系统进行操作&#x…

04.震动控制灯

vibrate 的意思就是震动 #include "reg52.h" #include <intrins.h>sbit led1 P3^7; sbit vibrate P3^3;void Delay2000ms() //11.0592MHz {unsigned char i, j, k;_nop_();i 15;j 2;k 235;do{do{while (--k);} while (--j);} while (--i); }void main()…

1块钱的家用桶装水抽水泵方案开发

目录 背景介绍需求分析 背景介绍 2024年8月&#xff0c;接到惠州大亚湾客户一个开发桶装水的一个PCB方案开发&#xff0c;要求成本控制在1万套&#xff0c;Bom成本在一块钱。 说干就干&#xff0c;先在网上搜索一下目前市面上的方案。 需求分析 想这种传统的桶装水是手动的…

DVWA综合靶场漏洞讲解

目录 综合靶场漏洞讲解 Brute Force Low Medium High Command Injection Low Medium High File Inclusion Low,Medium,High File Upload Low Medium High SQL Injection Low Medium High SQL Injection (Blind) Low Medium High XSS&#xff08;DOM&am…

未来购物新境界:商品样机3D展示可视化引领潮流

在这个日新月异的数字时代&#xff0c;科技的每一次飞跃都在深刻改变着我们的生活方式&#xff0c;尤其是购物体验。从传统的实体店选购到线上商城的便捷浏览&#xff0c;再到如今商品样机3D展示可视化的兴起&#xff0c;消费者正逐步踏入一个前所未有的沉浸式购物新时代。 想象…

layui table表单 checkbox选中一个其它也要选中

当我们选中其中一个商品的时候同类型的商品状态也要跟着改变 所以要在表单加载完成后去监听checkbox ,done:function (res) {console.log(详情表格数据,res)tableDetailList res.data;// 监听表格复选框选择table.on(checkbox( INST_SELECTORS.instLayFilters.unpaidTableDe…

亚马逊erp开子账号上百种权限,个人货代选品商标分配

亚马逊全功能 ERP 选品商标分配&#xff0c;上百种权限分配。 说说 ERP 子账号的相关操作&#xff01; 1. 哈喽大家好&#xff01;对于需要子账号多开的卖家来说&#xff0c;多个子账号进行智能分配可以减少个人操作的时间&#xff0c;提升团队的工作效率。今天就来和我一起看…

黄热病疫苗市场调研:预计到 2030 年全球市场规模将达到 1.8 亿美元

一、黄热病疫苗市场研究 &#xff08;一&#xff09;发展趋势 1. 市场规模增长&#xff1a;据调研团队报告所示&#xff0c;预计到 2030 年全球黄热病疫苗市场规模将达到 1.8 亿美元&#xff0c;年复合增长率为 3.0%。这表明市场在未来几年将保持稳定增长态势。增长的原因主要…

MESI 协议:多核处理器的一致性解决方案

文章目录 概述MESI 协议的基本原理概念协议状态 工作机制缓存行状态转移状态转换图状态转换表典型的状态转换示例详细的状态转换说明 写缓冲区 & 失效队列写缓冲区&#xff08;Store Buffer&#xff09;失效队列&#xff08;Invalidation Queue&#xff09; Java内存模型应…

vue实现卡片遮罩层交互式功能

前言 在前端开发中&#xff0c;卡片遮罩层是一种常见的交互设计元素&#xff0c;用于强调某个区域或内容&#xff0c;并提供用户操作的入口。本文将带大家在 vue 中结合实际案例实现此功能。 实现效果 完整代码 html <template><!-- 主容器 --><div class&quo…

[C++] map、set 的 封装 (二):map、set和红黑树的双向奔赴

标题&#xff1a;[C] map、set 的 封装 &#xff08;二&#xff09; 水墨不写bug 前言 在正式深入进map、set封装之前&#xff0c;我有一些话想说&#xff0c;map和set的封装在初次理解时可能会比较困难&#xff0c;仅仅是模板&#xff0c;仿函数引起的回调就会把你拌入无底深…

【从Qwen2,Apple Intelligence Foundation,Gemma 2,Llama 3.1看大模型的性能提升之路】

从早期的 GPT 模型到如今复杂的开放式 LLM&#xff0c;大型语言模型 (LLM) 的发展已经取得了长足的进步。最初&#xff0c;LLM 训练过程仅侧重于预训练&#xff0c;但后来扩展到包括预训练和后训练。后训练通常包括监督指令微调和校准&#xff0c;这是由 ChatGPT 推广的。 自 …

redis AOF机制

在redis运行期间&#xff0c;不断将redis执行的写命令写到文件中&#xff0c;redis重启之后&#xff0c;只要将这些命令重复执行一遍就可以恢复数据。因为AOF只是将少量的写命令写入AOF文件中&#xff0c;因此其执行效率高于RDB&#xff0c;开启AOF即使Redis发生故障&#xff0…

Redis缓存场景

Redis缓存场景 文章目录 Redis缓存场景Redis做缓存旁路缓存缓存异常缓存穿透缓存击穿缓存雪崩 缓存一致性先写缓存再写数据库先写数据库再写缓存先删除缓存再写数据库先写数据库再删缓存缓存双删Binlog异步更新总结 Redis做缓存 部分图解来自于&#xff1a;https://www.miansh…