草庐IT

B44 - 基于stm32蓝牙智能语音识别分类播报垃圾桶

小小工程员 2024-12-12 原文

文章目录

任务

题目:基于stm32蓝牙智能语音识别分类播报垃圾桶
实现功能如下:

  1. 语音识别根据使用者发出的指令自动对垃圾进行分类
  2. 根据垃圾的种类实时播报垃圾的类型
  3. 根据垃圾种类驱动对应的舵机进行转动(模拟垃圾桶打开,并在十秒钟自动复位,模拟垃圾桶关闭)
  4. OLED显示屏实时显示四种垃圾桶的状态
  5. 蓝牙app可以控制垃圾桶开关,同时显示四种垃圾桶状态

效果


原理图


指令编码


语音识别模块

简介

LU-ASR01是一款低成本、低功耗、体积小、高性能的离线语音识别系统。本系统集成了语音识别、语音回复、IO控制(多信号输出)、串口输出、温湿度广播等功能。在10米范围内的语音识别率可达98%,远远超过了LD3320等其他模组。
LU-ASR01基本参数:
模块型号:LU-ASRO1尺寸:36mmx36mm
I0口:有8路IO,分别是“IO1~lO8”。其中I01、I02、I03、I04、IO5、IO6可以输出PWM信号,也可以作为普通IO使用。IO7、IO8为普通IO,可以输出高低电平、脉冲信号、舵机信号。有一路串口输出TX管脚,可输出字符或16进制类型数据。一路DHT传感器管脚,可以接DHT11温湿度传感器或DS18B20温度传感器[6],可实现语音控制播报当时温湿度
待机功耗:10mA
供电范围:3.6-5.8V,一般使用5V供电,供电电流大于500mA
工作温度:-20℃~80°C
喇叭参数:8欧姆,3W功率

代码设计

驱动

#ifndef __Lu_ASR01_H
#define __Lu_ASR01_H

#include "stm32f10x.h"
#include "Def_config.h"

#define ASR01_Buffer_Length 50
#define ASR01_Length 5

typedef struct
{
	char ASR01_Rec_Buffer[ASR01_Buffer_Length];
	ENUM_JUDGE isGetData;		//是否获取到数据
	ENUM_JUDGE isParseData;	//是否解析完成
	char ASR01[ASR01_Length];		//字符串形式存储
	ENUM_JUDGE isUsefull;		//信息是否有效
} _ASR01Data;

extern _ASR01Data ASR01_Data;

void ASR01_RecHandle(u8 Res);
void ASR01_Clear_Data(void);
void parseASR01Buffer(void);

#endif 


#include "Lu_ASR01.h"
#include <string.h>
#include <stdio.h>
#include "SG90.h"


_ASR01Data ASR01_Data;
char  ASR01_RX_BUF[ASR01_Buffer_Length]; //接收缓冲,最大ASR01_Buffer_Length个字节.末字节为换行符 
u8 point2 = 0;
void ASR01_RecHandle(u8 Res)
{
	if(Res == '$')
	{
		point2 = 0;	
	}
	ASR01_RX_BUF[point2++] = Res;
	if(Res == '@' || point2 >2)									   
	{
		memset(ASR01_Data.ASR01_Rec_Buffer, 0, ASR01_Buffer_Length);      //清空
		memcpy(ASR01_Data.ASR01_Rec_Buffer, ASR01_RX_BUF, point2); 	//保存数据
		ASR01_Data.isGetData = TRUE; 
		point2 = 0;
		memset(ASR01_RX_BUF, 0, ASR01_Buffer_Length);      //清空
	}		
	if(point2 >= ASR01_Buffer_Length)
	{
		point2 = ASR01_Buffer_Length;
	}	
}
u8 ASR01_Find(char *a)                   // 串口命令识别函数
{ 
    if(strstr(ASR01_Data.ASR01_Rec_Buffer,a)!=NULL)
	    return 1;
	else
		return 0;
}
void ASR01_Clear_Data(void)
{
	ASR01_Data.isGetData = FALSE;
	ASR01_Data.isParseData = FALSE;
	ASR01_Data.isUsefull = FALSE;
	memset(ASR01_Data.ASR01, 0, ASR01_Length);      //清空
	memset(ASR01_Data.ASR01_Rec_Buffer, 0, ASR01_Buffer_Length);      //清空
}
void parseASR01Buffer(void)
{
	if (ASR01_Data.isGetData)  //获得语音模块的数据 --- $1@   : $4@
	{
		ASR01_Data.isGetData = FALSE;
		if(ASR01_Find("$1@"))
		{
			ASR01_Data.isParseData = TRUE;
			ASR01_Data.isUsefull = TRUE;
			
			SG90_Control(1,ANGLE_90);  //控制舵机1 旋转90°
			SG90_Structure.is_num01_open = TRUE;
			printf("$O1@"); //OPEN1  --缩写O1  ---  输出--蓝牙模块--手机同步更改舵机状态
		}
		else if(ASR01_Find("$2@"))
		{
			ASR01_Data.isParseData = TRUE;
			ASR01_Data.isUsefull = TRUE;
			
			SG90_Control(2,ANGLE_90);			
			SG90_Structure.is_num02_open = TRUE;
			printf("$O2@");
		}
		else if(ASR01_Find("$3@"))
		{
			ASR01_Data.isParseData = TRUE;
			ASR01_Data.isUsefull = TRUE;
			
			SG90_Control(3,ANGLE_90);
			SG90_Structure.is_num03_open = TRUE;
			printf("$O3@");
		}
		else if(ASR01_Find("$4@"))
		{  	
			ASR01_Data.isParseData = TRUE;
			ASR01_Data.isUsefull = TRUE;
			
			SG90_Control(4,ANGLE_90);
			SG90_Structure.is_num04_open = TRUE;
			printf("$O4@");
		}
		else
		{
			ASR01_Clear_Data(); //清空接收到的数据---数据帧无效
		}
	}
}





舵机模块

简介

本设计使用了4台舵机用来控制垃圾桶的开合,都是SG90型舵机。舵机是一种位置(角度)伺服驱动器,适用于那些需要角度不断变化并可以保持的闭环控制执行模块[13]。舵机主要由电机、电位器、控制电路、减速齿轮组、外壳、以及舵盘组成。

所述舵机的控制信号周期是一个20ms的脉宽调制(PWM)信号,在该PWM信号中,在0.5至2.5ms之间,在0至180°之间具有线性变化。舵机的输入信号为PWM信号,由PWM调制,并根据不同的占空比来控制舵机的转动角度和方向。

本设计选用STM32单片机的PB8-PB11四个引脚为舵机输入PWM信号来控制舵机旋转的角度从而实现控制垃圾桶盖的开关。其工作原理是:STM32单片机的PB8-PB11四个引脚分别连接4个舵机的输入端,通过定时器产生PWM信号控制舵机工作,舵机驱动电路内置基准电压,对信号的要求是20ms周期、0.5ms宽度,通过对比输入的信号与基准电压,可以得到偏差结果,从而控制了外部设备的转动角度。比如:电压差为正时,电机正向旋转,电压差为负时,电机反向旋转,电压差为零时,电机处于静止状态,从而达到带动垃圾桶盖开关的目的。

驱动

#ifndef __SG90_H
#define __SG90_H

#include "stm32f10x.h"
#include "Def_config.h"

#define SG90_RCC_APB2Periph_GPIOX  RCC_APB2Periph_GPIOB
#define SG90Num01_GPIOX_PinX  GPIO_Pin_8
#define SG90Num01_GPIOX       GPIOB

#define SG90Num02_GPIOX_PinX  GPIO_Pin_9
#define SG90Num02_GPIOX       GPIOB

#define SG90Num03_GPIOX_PinX  GPIO_Pin_10
#define SG90Num03_GPIOX       GPIOB

#define SG90Num04_GPIOX_PinX  GPIO_Pin_11
#define SG90Num04_GPIOX       GPIOB

//Turn_angle: 1---0度  2---45度 3---90 4--- 135度  5---180度     
typedef enum {
	ANGLE_0 = 1,
	ANGLE_45 = 2,
	ANGLE_90 = 3,
	ANGLE_135 = 4,
	ANGLE_180 = 5
}ENUM_ANGLE;

typedef struct {
	ENUM_JUDGE is_num01_start;  //启动
	ENUM_JUDGE is_num02_start;
	ENUM_JUDGE is_num03_start;
	ENUM_JUDGE is_num04_start;
	ENUM_ANGLE num01_angleX;  //转动角度
	ENUM_ANGLE num02_angleX;
	ENUM_ANGLE num03_angleX;
	ENUM_ANGLE num04_angleX;
	ENUM_JUDGE is_num01_finish;  //到达指定角度
	ENUM_JUDGE is_num02_finish;
	ENUM_JUDGE is_num03_finish;
	ENUM_JUDGE is_num04_finish;
	
	ENUM_JUDGE is_num01_open;
	ENUM_JUDGE is_num02_open;
	ENUM_JUDGE is_num03_open;
	ENUM_JUDGE is_num04_open;
}STRUCT_SG90;
extern STRUCT_SG90 SG90_Structure;

void SG90_Init(void);
void SG90_ControlAngleX(void);
void SG90_Control(u8 numX,ENUM_ANGLE angleX);

#endif


/******************************
SG90 舵机驱动程序
PB8 - PB11  四个舵机
******************************/
#include "SG90.h"
#include "led.h"
#include "bsp_timer3.h"  

void SG90_GPIO_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	/* GPIOx clock enable */
	RCC_APB2PeriphClockCmd(SG90_RCC_APB2Periph_GPIOX, ENABLE);
	GPIO_InitStructure.GPIO_Pin = SG90Num01_GPIOX_PinX | SG90Num02_GPIOX_PinX | SG90Num03_GPIOX_PinX | SG90Num04_GPIOX_PinX;  
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

	GPIO_Init(SG90Num01_GPIOX, &GPIO_InitStructure);
}
void SG90_Init(void)
{
	SG90_GPIO_Init();
	
	SG90_Structure.is_num01_start = FALSE;
	SG90_Structure.is_num02_start = FALSE;
	SG90_Structure.is_num03_start = FALSE;
	SG90_Structure.is_num04_start = FALSE;
	SG90_Structure.num01_angleX = ANGLE_0;
	SG90_Structure.num02_angleX = ANGLE_0;
	SG90_Structure.num03_angleX = ANGLE_0;
	SG90_Structure.num04_angleX = ANGLE_0;
	
	SG90_Structure.is_num01_open = FALSE;
	SG90_Structure.is_num02_open = FALSE;
	SG90_Structure.is_num03_open = FALSE;
	SG90_Structure.is_num04_open = FALSE;
	
	SG90_Structure.is_num01_finish = FALSE;
	SG90_Structure.is_num02_finish = FALSE;
	SG90_Structure.is_num03_finish = FALSE;
	SG90_Structure.is_num04_finish = FALSE;
	
	SG90_Control(1,ANGLE_0);
	SG90_Control(2,ANGLE_0);
	SG90_Control(3,ANGLE_0);
	SG90_Control(4,ANGLE_0);
}
u8 Counter_01 = 0;
#define PWM_Cycle 40            //40*500us  = 20ms	
u8 Duoji_WaitTime01=0;	
u8 Duoji_WaitTime02=0;	
u8 Duoji_WaitTime03=0;	
u8 Duoji_WaitTime04=0;	
#define Duoji_WaitTime_Max 36  //设置转动等待时间  36个信号周期---500us/1周期
STRUCT_SG90 SG90_Structure;
void SG90_ControlAngleX(void)  //uint16_t SG90NumX_GPIOX_PinX,ENUM_ANGLE angle
{
	Counter_01++;
	if(Counter_01>=PWM_Cycle)                   //一个周期20ms    //LED_Control(REVERSE);
	{
		Counter_01=0;	
		if(SG90_Structure.is_num01_start == TRUE)  
		{
			Duoji_WaitTime01++;
			if(Duoji_WaitTime01>Duoji_WaitTime_Max)
			{
				Duoji_WaitTime01=0;
				SG90_Structure.is_num01_finish = TRUE;
				
				SG90_Structure.is_num01_start = FALSE;
			}	
		}
		else
		{
			Duoji_WaitTime01=0;
//			SG90_Structure.is_num01_finish = FALSE;
		}
		
		if(SG90_Structure.is_num02_start == TRUE)  
		{
			Duoji_WaitTime02++;
			if(Duoji_WaitTime02>Duoji_WaitTime_Max)
			{
				Duoji_WaitTime02=0;
				SG90_Structure.is_num02_finish = TRUE;
				
				SG90_Structure.is_num02_start = FALSE;
			}	
		}
		else
		{
			Duoji_WaitTime02=0;
//			SG90_Structure.is_num02_finish = FALSE;
		}

		if(SG90_Structure.is_num03_start == TRUE)  
		{
			Duoji_WaitTime03++;
			if(Duoji_WaitTime03>Duoji_WaitTime_Max)
			{
				Duoji_WaitTime03=0;
				SG90_Structure.is_num03_finish = TRUE;
				
				SG90_Structure.is_num03_start = FALSE;
			}	
		}
		else
		{
			Duoji_WaitTime03=0;
//			SG90_Structure.is_num03_finish = FALSE;
		}

		if(SG90_Structure.is_num04_start == TRUE)  
		{
			Duoji_WaitTime04++;
			if(Duoji_WaitTime04>Duoji_WaitTime_Max)
			{
				Duoji_WaitTime04=0;
				SG90_Structure.is_num04_finish = TRUE;
				
				SG90_Structure.is_num04_start = FALSE;
			}	
		}
		else
		{
			Duoji_WaitTime04=0;
//			SG90_Structure.is_num04_finish = FALSE;
		}		
	}		
	if(SG90_Structure.is_num01_start == TRUE)
	{
		if(Counter_01 <= SG90_Structure.num01_angleX)
		{
			GPIO_SetBits(SG90Num01_GPIOX,SG90Num01_GPIOX_PinX);
		}
		else
		{
			GPIO_ResetBits(SG90Num01_GPIOX,SG90Num01_GPIOX_PinX);
		}
	}
	if(SG90_Structure.is_num02_start == TRUE)
	{
		if(Counter_01 <= SG90_Structure.num02_angleX)
		{
			GPIO_SetBits(SG90Num02_GPIOX,SG90Num02_GPIOX_PinX);
		}
		else
		{
			GPIO_ResetBits(SG90Num02_GPIOX,SG90Num02_GPIOX_PinX);
		}
	}
	if(SG90_Structure.is_num03_start == TRUE)
	{
		if(Counter_01 <= SG90_Structure.num03_angleX)
		{
			GPIO_SetBits(SG90Num03_GPIOX,SG90Num03_GPIOX_PinX);
		}
		else
		{
			GPIO_ResetBits(SG90Num03_GPIOX,SG90Num03_GPIOX_PinX);
		}
	}
	if(SG90_Structure.is_num04_start == TRUE)
	{
		if(Counter_01 <= SG90_Structure.num04_angleX)
		{
			GPIO_SetBits(SG90Num04_GPIOX,SG90Num04_GPIOX_PinX);
		}
		else
		{
			GPIO_ResetBits(SG90Num04_GPIOX,SG90Num04_GPIOX_PinX);
		}
	}
}
void SG90_Control(u8 numX,ENUM_ANGLE angleX)
{
	switch(numX)
	{
		case 1:
			SG90_Structure.is_num01_start = TRUE;
			SG90_Structure.is_num01_finish = FALSE;
			SG90_Structure.num01_angleX = angleX;
			while(SG90_Structure.is_num01_finish == FALSE);	
			time3_struct.Counter_01 = 0;
			time3_struct.is_5000MS_01Arrive = FALSE;
		break;
		case 2:
			SG90_Structure.is_num02_start = TRUE;
			SG90_Structure.is_num02_finish = FALSE;
			SG90_Structure.num02_angleX = angleX;
			while(SG90_Structure.is_num02_finish == FALSE);	
			time3_struct.Counter_02 = 0;
			time3_struct.is_5000MS_02Arrive = FALSE;
		break;
		case 3:
			SG90_Structure.is_num03_start = TRUE;
			SG90_Structure.is_num03_finish = FALSE;
			SG90_Structure.num03_angleX = angleX;
			while(SG90_Structure.is_num03_finish == FALSE);	
			time3_struct.Counter_03 = 0;
			time3_struct.is_5000MS_03Arrive = FALSE;
		break;
		case 4:
			SG90_Structure.is_num04_start = TRUE;
			SG90_Structure.is_num04_finish = FALSE;
			SG90_Structure.num04_angleX = angleX;
			while(SG90_Structure.is_num04_finish == FALSE);	
			time3_struct.Counter_04 = 0;
			time3_struct.is_5000MS_04Arrive = FALSE;
		break;
		default:break;
	}
}


主程序源代码

/*******************************************************************************

\* 文件名称:基于stm32蓝牙智能语音识别分类播报垃圾桶

\* 实验目的:1.

\* 2.

\* 程序说明:完整程序Q:277 227 2579;@: itworkstation@ hotmail.com

\* 日期版本:本项目分享关键细节,熟悉使用单片机的可做参考代码。完整讲解+源代码工程可联系获取,可定制。

*******************************************************************************/
/*******************************************************************************  
* 适配工程:最小系统板STM32C8T6镀金板
* 舵机占空比与运行角度的关系
0.5ms--------------0度;

1.0ms------------45度;

1.5ms------------90度;

2.0ms-----------135度;

2.5ms-----------180度;
*******************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include "main.h"  
#include "SG90.h"
#include "bsp_timer4.h" 
#include "usart1.h"
#include "Lu_ASR01.h"
#include "usart2.h" 
#include "bsp_timer3.h" 
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
extern const unsigned char BMP1[];

/**
  * @说明     主函数
  * @参数     None 
  * @返回值   None
  */
STRUCT_NVICPriority NVICPriority_Structure;
void sysInit(void)
{
	/*---------------------初始化中断顺序,0:最优先---------------------*/
	NVICPriority_Structure.Tim4 = 1;  
	NVICPriority_Structure.Usart1 = 2;
	NVICPriority_Structure.Usart2 = 3;
	NVICPriority_Structure.Tim3 = 0;
	
	/*----------------------外设初始化,配置参数-------------------------------------*/
	TIM4_Init();  
	SG90_Init();
	USART1_Init();  
	USART2_Init();
	
	/*-----------------------舵机控制:归0------------------------------------*/
	SG90_Control(1,ANGLE_0);
	SG90_Control(2,ANGLE_0);
	SG90_Control(3,ANGLE_0);
	SG90_Control(4,ANGLE_0);
	
	LED_Init();
	
	/*------------------------屏幕初始,IO等-----------------------------------*/
	OLED_Init();
	LCD_Display();  //显示---欢迎界面
	Delay_ms(5000); //延时5S
	LCD_Menu = LCD_SHOWMESSAGE;LCD_refresh = TRUE;	//变换界面
	
	//			LED_Control(ON);
//			Delay_ms(5000);
//			LED_Control(OFF);
//			Delay_ms(5000);
	TIM3_Init();
}
int main(void)
{	
	sysInit();	
    while(1){				
		parseASR01Buffer(); 
		if (ASR01_Data.isUsefull)
		{
			ASR01_Data.isUsefull =  FALSE;
			LCD_refresh=TRUE; 				//屏幕同步刷新状态
		}
		if(SG90_Structure.is_num01_finish)  //舵机转动结束
		{
			if(time3_struct.is_5000MS_01Arrive) //5s标志位
			{
				time3_struct.is_5000MS_01Arrive = FALSE;
				SG90_Structure.is_num01_finish = FALSE;
				if(SG90_Structure.num01_angleX != ANGLE_0)  //若舵机角度不等于0°,说明在90°状态--
				{
					SG90_Control(1,ANGLE_0);  //舵机归0
					SG90_Structure.is_num01_open = FALSE;
					printf("$C1@");  //CLOSE1  -- 缩写C1  同步状态给手机
					LCD_refresh=TRUE; 	
				}
			}
		}
		if(SG90_Structure.is_num02_finish)
		{
			if(time3_struct.is_5000MS_02Arrive)
			{
				time3_struct.is_5000MS_02Arrive = FALSE;
				SG90_Structure.is_num02_finish = FALSE;
				if(SG90_Structure.num02_angleX != ANGLE_0)
				{
					SG90_Control(2,ANGLE_0);
					SG90_Structure.is_num02_open = FALSE;
					printf("$C2@");  //CLOSE2  -- 缩写C1
					LCD_refresh=TRUE; 	
				}
			}
		}
		if(SG90_Structure.is_num03_finish)
		{
			if(time3_struct.is_5000MS_03Arrive)
			{
				time3_struct.is_5000MS_03Arrive = FALSE;
				SG90_Structure.is_num03_finish = FALSE;
				if(SG90_Structure.num03_angleX != ANGLE_0)
				{
					SG90_Control(3,ANGLE_0);
					SG90_Structure.is_num03_open = FALSE;
					printf("$C3@");  //CLOSE3  -- 缩写C1
					LCD_refresh=TRUE; 	
				}
			}
		}
		if(SG90_Structure.is_num04_finish)
		{
			if(time3_struct.is_5000MS_04Arrive)
			{
				time3_struct.is_5000MS_04Arrive = FALSE;
				SG90_Structure.is_num04_finish = FALSE;
				if(SG90_Structure.num04_angleX != ANGLE_0)
				{
					SG90_Control(4,ANGLE_0);
					SG90_Structure.is_num04_open = FALSE;
					printf("$C4@");  //CLOSE4  -- 缩写C1
					LCD_refresh=TRUE; 	
				}
			}
		}
		LCD_Display();
    }     
}





有关B44 - 基于stm32蓝牙智能语音识别分类播报垃圾桶的更多相关文章

  1. 叮咚买菜基于 Apache Doris 统一 OLAP 引擎的应用实践 - 2

    导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵

  2. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  3. STM32读取串口传感器数据(颗粒物传感器,主动上传) - 2

    文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,

  4. kvm虚拟机安装centos7基于ubuntu20.04系统 - 2

    需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc

  5. ruby-on-rails - (Ruby,Rails) 基于角色的身份验证和用户管理...? - 2

    我正在寻找用于Rails的优质管理插件。似乎大多数现有的插件/gem(例如“restful_authentication”、“acts_as_authenticated”)都围绕着self注册等展开。但是,我正在寻找一种功能齐全的基于管理/管理角色的解决方案——但不是简单地附加到另一个非基于角色的解决方案。如果我找不到,我想我会自己动手......只是不想重新发明轮子。 最佳答案 RyanBates最近做了两个关于授权的railscast(注意身份验证和授权之间的区别;身份验证检查用户是否如她所说的那样,授权检查用户是否有权访问资源

  6. ruby - 在 Rakefile 中动态生成 Rake 测试任务(基于现有的测试文件) - 2

    我正在根据Rakefile中的现有测试文件动态生成测试任务。假设您有各种以模式命名的单元测试文件test_.rb.所以我正在做的是创建一个以“测试”命名空间内的文件名命名的任务。使用下面的代码,我可以用raketest:调用所有测试require'rake/testtask'task:default=>'test:all'namespace:testdodesc"Runalltests"Rake::TestTask.new(:all)do|t|t.test_files=FileList['test_*.rb']endFileList['test_*.rb'].eachdo|task|n

  7. ruby - 如何使用 Ruby 基于字母数字字符串生成颜色? - 2

    我想要像“嘿那里”这样的东西变成,例如,#316583。我希望将任意长度的字符串“归结”为十六进制颜色。我不知道从哪里开始。我在想,每个字符串的MD5散列都是不同的-但如何将该散列转换为十六进制颜色数字? 最佳答案 你可以只取几位前几位:require'digest/md5'color=Digest::MD5.hexdigest('Mytext')[0..5] 关于ruby-如何使用Ruby基于字母数字字符串生成颜色?,我们在StackOverflow上找到一个类似的问题:

  8. 【自动驾驶环境感知项目】——基于Paddle3D的点云障碍物检测 - 2

    文章目录1.自动驾驶实战:基于Paddle3D的点云障碍物检测1.1环境信息1.2准备点云数据1.3安装Paddle3D1.4模型训练1.5模型评估1.6模型导出1.7模型部署效果附录show_lidar_pred_on_image.py1.自动驾驶实战:基于Paddle3D的点云障碍物检测项目地址——自动驾驶实战:基于Paddle3D的点云障碍物检测课程地址——自动驾驶感知系统揭秘1.1环境信息硬件信息CPU:2核AI加速卡:v100总显存:16GB总内存:16GB总硬盘:100GB环境配置Python:3.7.4框架信息框架版本:PaddlePaddle2.4.0(项目默认框架版本为2.3

  9. STM32的HAL和LL库区别和性能对比 - 2

    LL库和HAL库简介LL:Low-Layer,底层库HAL:HardwareAbstractionLayer,硬件抽象层库LL库和hal库对比,很精简,这实际上是一个精简的库。LL库的配置选择如下:在STM32CUBEMX中,点击菜单的“ProjectManager”–>“AdvancedSettings”,在下面的界面中选择“AdvancedSettings”,然后在每个模块后面选择使用的库总结:1、如果使用的MCU是小容量的,那么STM32CubeLL将是最佳选择;2、如果结合可移植性和优化,使用STM32CubeHAL并使用特定的优化实现替换一些调用,可保持最大的可移植性。另外HAL和L

  10. ruby - 规范测试基于 EventMachine 的(Reactor)代码 - 2

    我正在尝试整个BDD方法并想测试AMQP基于Vanilla的方面Ruby我正在写的应用程序。选择Minitest后作为与其他名副其实的蔬菜框架不同的平衡功能和表现力的测试框架,我着手编写此规范:#File./test/specs/services/my_service_spec.rb#Requirementsfortestrunningandconfigurationrequire"minitest/autorun"require"./test/specs/spec_helper"#Externalrequires#MinitestSpecsforEventMachinerequire

随机推荐