当前位置: 首页 > news >正文

stm32平衡车

目录

一.所需材料

二.PID算法(简单说明)

直立环

速度环

串级PID 

三.使用到的外设 

         1.定时器输出比较-PWM

2.定时器编码器模式 

3.编码器读取速度 

4.电机驱动函数

5.外部中断

四、小车

        调试 


一.所需材料

1.陀螺仪MPU6050--读取三轴的加速度和角速度,然而我们平衡车需要的不是加速度和角速度,而是需要实时的角度,即我们还需要进行姿态角转换,可以直接移植正点原子的DMP函数

2.TB6612电机驱动,l298N也可,我用的是TB6612,点击查看接线

3.OLED,用来显示姿态角,可以直接移植

4.12v锂电池和DCDC降压模块给电机和单片机供电

5.编码电机,点击查看接线

6.c8t6单片机

二.PID算法(简单说明)

P(比例)算法:Kp*误差。

        可以看出,误差越大,P的输出就越大,所以P的作用是减小误差,但是只有P算法会发生超调现象,即在不受外力下可以看作简谐运动,一直震荡

I(积分)算法:Ki*误差的积分。

        可以看出,只要存在误差(一般叫做稳态误差,比如小车在平衡位置偏左或右一点点,但是又不会倒下等等的情况下产生的角度误差)就会一直累加,累加累加的总误差就变的很大,滚雪球一样,越来越大,所以I可以消除稳态误差

D(微分):Kd*误差的微分。

        可以看出,两次误差之差反映的是系统的反应速度,响应越快,误差之差越大,D输出很大,反之很小,所以D算法会抑制过冲,消弱系统的反应速度。例如简谐运动,以最下点为期望点,小球从空中开始速度很小,后面越来越快,即可以理解为误差微分越来越大,且为负的,所以D输出就越来越大,力的方向与小球运动方向相反,若没有D算法,小球就会继续简谐运动,若此时有了D算法,小球的运动就会收到阻碍而令小球到达的高度降低,长此以往,小球就会静止在最低点

        也可以这样看,在水中挥拳,挥的速度越大,受到的阻尼越大

直立环

PWM_OUT=Kp*误差+Kd*误差的微分

误差=真实角度-期望角度

误差的微分=角速度,姿态角转换得到

作用:让小车保持短时间的平衡,但是推一下就可能倒下

/*
直立环
PWM_OUT = Kp*角度偏差+Kd*角度偏差的微分
角度偏差求微分就是对角度偏差求导,即为角速度
gyro_Y:俯仰角的角速度
*/int Vertical(float Expect_Angle,float Angle,float gyro_Y)
{int PWM_out1=0;PWM_out1 = Vertical_Kp*(Expect_Angle-Angle)+Vertical_Kd*(gyro_Y-0);return PWM_out1;
}
/*

速度环

PWM_OUT=Kp*误差+Ki*误差的积分 

误差:期望速度-真实速度

误差的积分=误差累加

作用:消除稳态误差,加强系统的反应速度

极性问题:

速度环在平衡一类的基本上都是用正反馈,即积分误差,放大误差,先注释掉直立环,则极性正确的现象就是转动一下轮子,立刻就会加速到最大,因为我们速度理论值是0,我们转了一下,产生了误差,速度环不断放大误差,使速度环输出越大,就会让轮子不断加速到最大速度,若是负反馈,我们很难转动轮子

int Velocity(int Target,int left,int right)
{	static int Encoder_S,EnC_Err_Lowout_last,PWM_out3,Encoder_Err,EnC_Err_Lowout;float a = 0.7;Encoder_Err = left+right-Target;//速度偏差//对速度偏差进行一阶低通滤波EnC_Err_Lowout = a*EnC_Err_Lowout_last+(1-a)*Encoder_Err;EnC_Err_Lowout_last=EnC_Err_Lowout;//积分Encoder_S+=EnC_Err_Lowout;//限幅Encoder_S=I_Limit(Encoder_S);PWM_out3 = Velocity_Kp*EnC_Err_Lowout + Velocity_Ki*Encoder_S;return PWM_out3;	
}
int I_Limit(int Encoder_S)
{if(Encoder_S>10000)Encoder_S=10000;else if(Encoder_S<-10000)Encoder_S=-10000;else Encoder_S=Encoder_S;return Encoder_S;
}

速度环必须滤波,因为速度会突变,突变的速度会对系统产生很大影响 

        滤波:编码器测到的数据(速度)是存在一些突变的,这些突变会导致系统的不稳定,所以我们要滤除这些突变,这就是滤波,类似于模电里面的“滤除电路中的高频信号”

一阶低通滤波:把权重给到上次滤波后的速度,另一个这次的速度为(1-a)倍,0.5<a<1

积分限幅:误差的积分在一直累加,若没有限幅,积分会越来越大,举个例子:小车倒下了,我们为了保护电机而关掉了电机,但是单片机的电源并没有关掉,误差一直在累加,很大很大了,当我们把小车放好并打开电机后,由于I的作用根本无法平衡。所以要限幅。

串级PID 

 串级,顾名思义,就是一个环的输出作为另一个环的输入,例如速度环的输出作为直立环的输入,或者直立环的输出作为速度环的输入

速度环输入:1.给定速度。2.速度反馈。

输出:角度值(直立环的期望速度输入)

直立环输入:1.给定角度(速度环输出)。2.角度反馈

输出:PWM(直接控制小车)

Vertical_out=Kp1*(Angle-Expect_Angle)+Kd* gyro_y

直立环输出=Kp1*(真实角度-期望角度+机械中值)+Kd*角度偏差的微分

Velocity_out =Kp2*(Encoder_ real- Encoder_ expect)+Ki*(Encoder_ real- Encoder_ expect)的积分

速度环输出=Kp2*(反馈编码器值-期望编码器值)+Ki*编码器偏差的积分

合并推导:Expect_Angle   =     Velocity_out

Vertical_out = Kp1*{ Angle-[ Kp2*(Encoder_ real- Encoder_ expect)+Ki*Σ(Encoder_ real- Encoder_ expect) ]}+Kd*gyro_y

          =Kp1*真实角度+ Kd*角度偏差的微分-Kp1* [Kp2*编码器偏差- Ki *编码器偏差的积分]

                         

三.使用到的外设 

      1.定时器输出比较-PWM

void PWM_Init_TIM1(uint16_t Psc,uint16_t Per)
{//开时钟,AFIORCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_TIM1 | RCC_APB2Periph_AFIO,ENABLE);GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽GPIO_InitStruct.GPIO_Pin  = GPIO_Pin_8 | GPIO_Pin_11;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStruct);TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct);//因为没有将所有的结构体内容全部配置,所以这里先初始化一下TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//不分频----滤波器的采样频率,可以由内部时钟直接提供,//也可以由内部时钟加一个时钟分频而来,//分频系数就是由TIM_ClockDivision决定TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//向上计数TIM_TimeBaseInitStruct.TIM_Period = Per;//ARR的值TIM_TimeBaseInitStruct.TIM_Prescaler = Psc;//PSC的值//TIM_TimeBaseInitStruct.TIM_RepetitionCounter  重复计数器,这里不需要TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStruct);TIM_OCInitTypeDef  TIM_OCInitStruct;TIM_OCStructInit(&TIM_OCInitStruct);//初始化输出比较结构体TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;//输出比较模式 TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; //极性,有效电平为高电平TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//输出使能TIM_OCInitStruct.TIM_Pulse = 0;//CCRTIM_OC1Init(TIM1,&TIM_OCInitStruct);TIM_OC4Init(TIM1,&TIM_OCInitStruct);TIM_CtrlPWMOutputs(TIM1,ENABLE);//高级定时器特有的,必须使能//使能ARR影子寄存器TIM_ARRPreloadConfig(TIM1,ENABLE);//使能输出比较预装载值寄存器TIM_OC4PreloadConfig(TIM1,TIM_OCPreload_Enable);TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);TIM_Cmd(TIM1,ENABLE);
}

2.定时器编码器模式 

//配置编码器
//编码器1-PA0/PA1-TIM2
//编码器2-PB6/PB7-TIM4
void Encoder_TIM2_Init()
{//开启GPIO时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//开启定时器时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//初始化GPIOGPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_InitStruct.GPIO_Pin  = GPIO_Pin_0 | GPIO_Pin_1;GPIO_Init(GPIOA,&GPIO_InitStruct);//初始化定时器	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct);//因为没有将所有的结构体内容全部配置,所以这里先初始化一下TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//滤波分频系数TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//向上计数TIM_TimeBaseInitStruct.TIM_Period = 65535;//ARR的值TIM_TimeBaseInitStruct.TIM_Prescaler = 0;//PSC的值//TIM_TimeBaseInitStruct.TIM_RepetitionCounter  重复计数器,这里不需要TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);//编码器特有的配置函数,配置模式TIM_EncoderInterfaceConfig(TIM2,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);//初始化输入捕获TIM_ICInitTypeDef TIM_ICInitStruct;TIM_ICStructInit(&TIM_ICInitStruct);//因为没有将所有的结构体内容全部配置,所以这里先初始化一下TIM_ICInitStruct.TIM_ICFilter = 10;// 滤波器,范围是 0x0 and 0xFTIM_ICInit(TIM2,&TIM_ICInitStruct);//清除定时器溢出中断标志位TIM_ClearFlag(TIM2,TIM_FLAG_Update);//配置溢出中断TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//设置计数器初始值为0TIM_SetCounter(TIM2,0);//开启定时器TIM_Cmd(TIM2,ENABLE);
}void Encoder_TIM4_Init()
{//开启GPIO时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//开启定时器时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);//初始化GPIOGPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_InitStruct.GPIO_Pin  = GPIO_Pin_6 | GPIO_Pin_7;GPIO_Init(GPIOB,&GPIO_InitStruct);//初始化定时器	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct);//因为没有将所有的结构体内容全部配置,所以这里先初始化一下TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;//外部时钟滤波分频系数TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//向上计数TIM_TimeBaseInitStruct.TIM_Period = 65535;//ARR的值TIM_TimeBaseInitStruct.TIM_Prescaler = 0;//PSC的值//TIM_TimeBaseInitStruct.TIM_RepetitionCounter  重复计数器,这里不需要TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStruct);//编码器特有的配置函数TIM_EncoderInterfaceConfig(TIM4,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);//配置IC输入TIM_ICInitTypeDef TIM_ICInitStruct;TIM_ICStructInit(&TIM_ICInitStruct);//因为没有将所有的结构体内容全部配置,所以这里先初始化一下TIM_ICInitStruct.TIM_ICFilter = 10;// 滤波器TIM_ICInit(TIM4,&TIM_ICInitStruct);//清除定时器溢出中断标志位TIM_ClearFlag(TIM4,TIM_FLAG_Update);//配置溢出中断TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);//设置计数器初始值为0TIM_SetCounter(TIM4,0);//开启定时器TIM_Cmd(TIM4,ENABLE);
}

3.编码器读取速度 

/*******************
编码器速度读取函数*入口参数:定时器2/4
*******************/
int Read_Speed(int TIMx)
{int value_1;switch(TIMx){//int ? shortcase 2:value_1=(short)TIM_GetCounter(TIM2);TIM_SetCounter(TIM2,0);break; //先读取编码器的计数值,然后清零计数值,目的是直接获得速度,而不用计数值相减来算速度case 4:value_1=(short)TIM_GetCounter(TIM4);TIM_SetCounter(TIM4,0);break;default :value_1 = 0;}//这里TIM_GetCounter()函数的返回值是uint16_t ,而我们的返回值是有符号的int类型,所以这里强制类型转化一下return value_1;
}

4.电机驱动函数


//电机初始化函数
void Motor_Init()
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;//复用推挽GPIO_InitStruct.GPIO_Pin  = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15 ;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIO_InitStruct);
}//限幅函数
void Limit(int *motorA ,int *motorB)
{if(*motorA > PWM_MAX)*motorA=PWM_MAX;if(*motorA < PWM_MIN)*motorA=PWM_MIN;if(*motorB > PWM_MAX)*motorB=PWM_MAX;if(*motorB < PWM_MIN)*motorB=PWM_MIN;
}//绝对值函数
int abs(int p)
{int q;q = p>0?p:(-p);return q;
}//电机驱动函数
//入口参数:PID运算完成后最终PWM值
void Load(int moto1,int moto2)
{//判断正反转if(moto1>0)Ain1=1,Ain2=0;else 			 Ain1=0,Ain2=1;//输入PWM的绝对值TIM_SetCompare1(TIM1,abs(moto1));if(moto2>0)Bin1=1,Bin2=0;else 			 Bin1=0,Bin2=1;TIM_SetCompare4(TIM1,abs(moto2));
}
//电机为10KHZ
//72000000/7200 = 10 000 HZ
#define PWM_MAX		 7200	
#define PWM_MIN		-7200extern int MOTO1,MOTO2;
#define Ain1	PBout(14)
#define Ain2	PBout(15)#define Bin1	PBout(13)
#define Bin2	PBout(12)

5.外部中断

dmp读取是用的中断读取,10ms读取一次,所以我们要配置MPU6050的外部中断

void MPU6050_EXTI_Init(void)
{//开启时钟//因为是复用功能,所以开启AFIORCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO,ENABLE);//配置GPIOGPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;//GPIO_Mode_AF_PP;复用推挽GPIO_InitStruct.GPIO_Pin  = GPIO_Pin_5;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIO_InitStruct);	//映射GPIO和外部中断GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource5);//配置EXTI结构体EXTI_InitTypeDef  EXTI_InitStruct;EXTI_InitStruct.EXTI_Line = EXTI_Line5;//中断线EXTI_InitStruct.EXTI_LineCmd = ENABLE;//使能中断线EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;//中断模式EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling;//下降沿触发EXTI_Init(&EXTI_InitStruct);}void NVIC_Config()
{NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//外部中断NVIC_InitTypeDef  NVIC_InitStruct;NVIC_InitStruct.NVIC_IRQChannel = EXTI9_5_IRQn;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;NVIC_Init(&NVIC_InitStruct);//串口NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority =0;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;NVIC_Init(&NVIC_InitStruct);
}void EXTI9_5_IRQHandler(void)
写中断服务函数,里面做的是PID算法
void EXTI9_5_IRQHandler(void)
{		if(EXTI_GetITStatus(EXTI_Line5) == SET)//MPU6050外部中断是PB5{if(PBin(5) == 0)//引脚定义为外部上拉,而外部中断触发模式是下降沿,这里就是再进行下降沿的检测{EXTI_ClearITPendingBit(EXTI_Line5);//1.采集编码器数据和MPU6050的角度信息Encoder_Left  = -Read_Speed(2);//因为电机是相对安装的,即左右电机相差180度,为了让编码器输出极性一致,Encoder_Right = Read_Speed(4);//所以需要取反,或者调转一下极性也可以mpu_dmp_get_data(&Pitch,&Roll,&Yaw);		MPU_Get_Gyroscope(&gyrox,&gyroy,&gyroz);MPU_Get_Accelerometer(&aacx,&aacy,&aacz);//2.将数据压入闭环控制中,计算输出控制量			Velocity_out = Velocity(Target_Speed,Encoder_Left,Encoder_Right);Vertical_out = Vertical(Velocity_out+Med_Angle,Pitch,gyroy);Turn_out = Turn(gyroz);	PWM_out = Vertical_out;//3.把控制量加载到电机上MOTO1 = PWM_out-Turn_out;//这里一加一减是因为两个电机是反向安装的,实际上就是同向加减了MOTO2 = PWM_out+Turn_out;Limit(&MOTO1,&MOTO2);Load(MOTO1,MOTO2);}}
}

四、小车

本人不会打板,所以选择了做一回杜邦线战神!

调了直立环和速度环,但是不理想,不能很好的回位

 

调试 

串级的PID调试时应该断掉两个环的连接

机械中值把平衡小车放在地面上,从前向后以及从后向前绕电机轴旋转平衡小车,两次的向另一边倒下的角度的中值,就是机械中值。

直立环

Kp极性:

极性错误:小车往哪边倒,车轮就往反方向开,会使得小车加速倒下。

极性正确:小车往哪边倒,车轮就往哪边开,以保证小车有直立的趋势。

Kp大小:

Kp一直增加,直到出现大幅低频震荡

Kd极性:

极性错误:拿起小车绕电机轴旋转,车轮反向转动,无跟随。

极性正确:拿起小车绕电机轴旋转,车轮同向转动,有跟随。

Kd大小:

Kd一直增加,直到出现高频震荡

直立环调试完毕后,对所有确立的参数乘以0.6作为最终参数。

原因:之前得到的参数都是Kp、Kd最大值,根据工程经验平衡小车的理想参数为最大参数乘以0.6求得。

结果:乘以0.6后,小车的抖动消失,但同时直立效果也变差。待下面加入速度环就能得到更好的性能。

在调试速度环参数极性时:需要去掉(注释掉)直立环运算

在调试速度环参数大小时:再次引入(取消注释)直立环运算

Kp&Ki

线性关系、Ki=(1/200)*Kp、仅调Kp即可。

Kp&Ki极性:

极性错误:手动转动其中一个车轮,另一车轮会以同样速度反向旋转——典型负反馈。

极性正确:手动转动其中一个车轮,两个车伦会同向加速,直至电机最大速度——典型正反馈。

Kp&Ki大小:

增加Kp&Ki,直至:小车保持平衡的同时,速度接近于零。且回位效果较好。

转向环

Kp极性:

极性错误:拿起小车,并将小车绕Z轴旋转,两车轮旋转的趋势与小车旋转趋势一致——典型正反馈。

极性正确:拿起小车,并将小车绕Z轴旋转,两车轮旋转的趋势与小车旋转趋势相反——典型负反馈。

Kp大小:

加大Kp,直至走直线效果较好,且无剧烈抖动。 

参考于b站up主天下行走的平衡车教学 

相关文章:

stm32平衡车

目录 一.所需材料 二.PID算法&#xff08;简单说明&#xff09; 直立环 速度环 串级PID 三.使用到的外设 1.定时器输出比较-PWM 2.定时器编码器模式 3.编码器读取速度 4.电机驱动函数 5.外部中断 四、小车 调试 一.所需材料 1.陀螺仪MPU6050--读取三轴的加速度…...

google浏览器下载文件提示无法安全地下载怎么解决?

在使用google浏览器下载文件的时候,弹出了“无法安全下载”的提示,搞了文件都下载不下来,网上查了一下,是因为chrome认为使用非https链接下载文件是不安全的,在新版本中阻止了用户下载。 目录 1、打开google浏览器的设置...

Navicat 干货 | 通过检查约束确保 PostgreSQL 的数据完整性

数据完整性对于任何数据库系统来说都是很重要的一方面&#xff0c;它确保存储的数据保持准确、一致且有意义的。在 PostgreSQL 中&#xff0c;维护数据完整性的一个强大工具是使用检查约束。这些约束允许你定义数据必须遵守的规则&#xff0c;以防止无效数据的插入或修改。本文…...

FPGA时钟资源详解(2)——Clock-Capable Inputs

FPGA时钟系列文章总览&#xff1a;FPGA原理与结构&#xff08;14&#xff09;——时钟资源https://ztzhang.blog.csdn.net/article/details/132307564 目录 一、概述 1.1 为什么使用CC 1.2 如何使用CC 二、Clock-Capable Inputs 2.1 SRCC 2.2 MRCC 2.3 其他用途 2.3.1…...

使用JMeter的JSON提取器:通过递归下降查找,从接口响应中提取特定字段

在接口测试中&#xff0c;我们经常需要从返回的JSON数据中提取特定字段以便后续使用。JMeter提供了JSON提取器&#xff0c;可以帮助我们实现这一目标。本文将介绍如何使用JMeter的JSON提取器通过递归下降查找的方式从接口响应中提取特定字段&#xff0c;并通过示例解释JSON表达…...

Js全部循环方法解析

forEach方法 没有返回值&#xff0c;与 for 循环没有什么区别。 [1,2,3,4,5,6,7,8,9,0].forEach(item > {console.log(item); })map方法 返回一个新数组&#xff0c;不改变原数组。通过return内的操作后的数据 const newArr [1,2,3,4,5,6,7,8,9,0].map(item > {retu…...

高阶SQL语句(二)

一 子查询 也被称作内查询或者嵌套查询&#xff0c;是指在一个查询语句里面还嵌套着另一个查询语 句。子查询语句 是先于主查询语句被执行的&#xff0c;其结果作为外层的条件返回给主查询进行下一 步的查询过滤。 ①子语句可以与主语句所查询的表相同&#xff0c;也可以是不…...

Phoenix伪分布安装

引言 Phoenix是构建在HBase上的一个SQL层&#xff0c;能让我们用标准的JDBC APIs而不是HBase客户端APIs来创建表&#xff0c;插入数据和对HBase数据进行查询。Phoenix完全使用Java编写&#xff0c;作为HBase内嵌的JDBC驱动。Phoenix查询引擎会将SQL查询转换为一个或多个HBase扫…...

Python算法100例-4.6 歌星大奖赛

完整源代码项目地址&#xff0c;关注博主私信源代码后可获取 1.问题描述2.问题分析3.算法设计4.确定程序框架5.完整的程序6.问题拓展7.知识点补充 1&#xff0e;问题描述 在歌星大奖赛中&#xff0c;有10个评委为参赛的选手打分&#xff0c;分数为1&#xff5e;100分。选手最…...

静态路由表学习实验

实验要求&#xff1a;各个pc设备可以通信&#xff0c;并且可以访问外网&#xff0c;假设R1已连接外网 拓扑结构 思路&#xff1a;配置pc机ip地址&#xff0c;子网掩码&#xff0c;和网关&#xff08;网关地址是上层路由接口的地址&#xff09;&#xff0c;配置路由各个接口地址…...

客户端测试 可测性改进-学习记录

客户端测试面临的挑战 难点&#xff1a; 业务复杂&#xff0c;产品多&#xff0c;技术栈多样 测试过程的痛点&#xff1a; 配置-》执行-〉检查-》结果 手工测试前置配置操作极其繁琐&#xff1a;安装测试包-〉进入debug页面-》设置h-〉设置AB test-》锁定rn包-〉进入业务页…...

机器学习和神经网络9

通过前几次学习,相信对机器学习和神经网络已经有了较为深入的了解。 让我们从一些经典的机器学习算法和实际代码示例开始。: 线性回归:用于预测连续输出的基本算法。你可以从这里找到详细的原理和代码示例。 K-近邻算法 (k-Nearest Neighbors, kNN):一种简单但有效的分类和…...

http模块—http请求练习

题目要求&#xff1a;搭建如下http服务&#xff1a; 1.当浏览器向我们的服务器发送请求时&#xff0c;当请求类型是get请求&#xff0c;请求的url路径地址是/login。响应体结果是登录页面 2.当浏览器向我们的服务器发送请求时&#xff0c;当请求类型是get请求&#xff0c;请求…...

视频号原视频下载使用方法?新人都在用

视频号已经成为我们生活中不可或缺的一种方式&#xff0c;让更多人跃跃欲试&#xff0c;分享自己的生活瞬间或专业知识。然而&#xff0c;有时我们可能需要从视频号中提取原视频&#xff0c;无论是为了备份、编辑还是其他用途。本文将详细解析如何有效、安全地从视频号提取原视…...

用html画一个烟花特效

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>烟花特效</title><link rel"stylesheet" href"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/css/fontawesom…...

SQL-CRUD-1

第一关任务描述 本关任务&#xff1a; 用insert给数据库添加数据 相关知识 有关系student(sno,sname,ssex,sage,sdept)&#xff0c;属性对应含义&#xff1a;学号&#xff0c;姓名&#xff0c;性别&#xff0c;所在系。现有的部分元组如下所示 insert 向数据库表插入数据的…...

linux 命令行下的计算器

!!! author 文章目录 1. echo 运算器, 推荐2. bc 计算器, 不推荐3. dc 计算器, 不推荐4. awk计算器. 推荐5. python. 推荐 1. echo 运算器, 推荐 限制是仅能在整数运算时使用 $ echo $((10534)) 70 优点,输入简洁, 支持运算表达式,支持16进制,10进制混合输入. 缺点,不支持浮点…...

Available platform plugins are: linuxfb, minimal, offscreen, vnc.

说明&#xff1a; buildroots根文件中已经移植好了QT的库&#xff0c;但是运行QT交叉编译之后的可执行文件报错&#xff1a; qt.qpa.plugin: Could not find the Qt platform plugin "eglfs" in "" This application failed to start because no Qt platf…...

C++中string容器的修改操作

目录 1.push_back() 尾插字符 2.append() 尾插字符串 3.operator 4.assign 覆盖 5.insert() 指定位置插入 6.erase() 删除 7.replace() 替换 8.swap() 交换 9.pop_back() 尾删 1.push_back() 尾插字符 void push_back (char c) string s("i miss gjj"); s…...

Elasticsearch:虚拟形象辅助和对话驱动的语音到 RAG 搜索

作者&#xff1a;来自 Elastic Sunile Manjee 搜索的演变 搜索已经从产生简单结果的简单文本查询发展成为容纳文本、图像、视频和问题等各种格式的复杂系统。 如今的搜索结果通过生成式人工智能、机器学习和交互式聊天功能得到增强&#xff0c;提供更丰富、更动态且与上下文相…...

python打卡day49

知识点回顾&#xff1a; 通道注意力模块复习空间注意力模块CBAM的定义 作业&#xff1a;尝试对今天的模型检查参数数目&#xff0c;并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

作者&#xff1a;来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗&#xff1f;了解下一期 Elasticsearch Engineer 培训的时间吧&#xff01; Elasticsearch 拥有众多新功能&#xff0c;助你为自己…...

反射获取方法和属性

Java反射获取方法 在Java中&#xff0c;反射&#xff08;Reflection&#xff09;是一种强大的机制&#xff0c;允许程序在运行时访问和操作类的内部属性和方法。通过反射&#xff0c;可以动态地创建对象、调用方法、改变属性值&#xff0c;这在很多Java框架中如Spring和Hiberna…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

#Uniapp篇:chrome调试unapp适配

chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器&#xff1a;Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

免费PDF转图片工具

免费PDF转图片工具 一款简单易用的PDF转图片工具&#xff0c;可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件&#xff0c;也不需要在线上传文件&#xff0c;保护您的隐私。 工具截图 主要特点 &#x1f680; 快速转换&#xff1a;本地转换&#xff0c;无需等待上…...