直流无刷电机控制(FOC):电流模式

目录

概述

1 系统框架结构

1.1 硬件模块介绍

1.2 硬件实物图

1.3 引脚接口定义

2 代码实现

2.1 软件架构

2.2 电流检测函数

3 电流环功能实现

3.1 代码实现

3.2 测试代码实现

4 测试


概述

本文主要介绍基于DengFOC的库函数,实现直流无刷电机控制(FOC)的电流环控制。笔者详细介绍了电流环采样电流时用到的函数。DengFOC的软件架构,电流环模式实现的原理等内容。

源代码下载地址:

dengfoctestdemo资源-CSDN文库

1 系统框架结构

1.1 硬件模块介绍

系统硬件框架结构功能如下:

电机模块: 2208直流无刷电机(数量:1)

编码器:  选用AS5600编码器,用于获取当前电机转动的角度,其通过I2C接口与MCU进行通信

驱动板(FOC): 通过接收到MCU传送的PWM芯片,直接作用到MOS管上,以驱动直流无刷电机工作。

主控模块:使用ESP32 ( ESP32-WROOM-32E)

电流检测功能: 使用MCU ADC功能检测INA240的输出电压值

1.2 硬件实物图

1.3 引脚接口定义

 1) 电机驱动板与电机之间的接口

2)编码器与MCU接口

3)电流检测

2 代码实现

2.1 软件架构

2.2 电流检测函数

1)源代码介绍

代码12行: 定义参考电压值

代码13行: ADC的最大值(12bit )

代码16: 计算比率

代码25~26行: 定义ADC的端口

代码28行: 分流电阻

代码29行: 电流放大倍数

代码31行: 电流放大的比率 

代码55~59行: 获取ADC的count值

代码61~66行: 配置ADC的端口模式

​ 

代码69~91行: 获取ADC的均值 

代码93~99行:  读电流参数初始化

代码104~109行:  获取电流值

 2)源代码文件

编写InlineCurrent.c文件的内容

#include <Arduino.h> 
#include "InlineCurrent.h"//  - shunt_resistor  - 分流电阻值
//  - gain  - 电流检测运算放大器增益
//  - phA   - A 相 adc 引脚
//  - phB   - B 相 adc 引脚
//  - phC   - C 相 adc 引脚(可选)#define _ADC_VOLTAGE 3.3f            //ADC 电压
#define _ADC_RESOLUTION 4095.0f      //ADC 分辨率// ADC 计数到电压转换比率求解
#define _ADC_CONV ( (_ADC_VOLTAGE) / (_ADC_RESOLUTION) )#define NOT_SET -12345.0
#define _isset(a) ( (a) != (NOT_SET) )CurrSense::CurrSense(int Mot_Num)
{if(Mot_Num==0){pinA = 39;pinB = 36;//int pinC;_shunt_resistor = 0.01;amp_gain  = 50;volts_to_amps_ratio = 1.0f /_shunt_resistor / amp_gain; // volts to amps// gains for each phasegain_a = volts_to_amps_ratio*-1;gain_b = volts_to_amps_ratio*-1;gain_c = volts_to_amps_ratio;}if(Mot_Num==1){pinA = 35;pinB = 34;//int pinC;_shunt_resistor = 0.01;amp_gain  = 50;volts_to_amps_ratio = 1.0f /_shunt_resistor / amp_gain; // volts to amps// gains for each phasegain_a = volts_to_amps_ratio*-1;gain_b = volts_to_amps_ratio*-1;gain_c = volts_to_amps_ratio;}
}
float CurrSense::readADCVoltageInline(const int pinA)
{uint32_t raw_adc = analogRead(pinA);return raw_adc * _ADC_CONV;
}void CurrSense::configureADCInline(const int pinA,const int pinB, const int pinC)
{pinMode(pinA, INPUT);pinMode(pinB, INPUT);if( _isset(pinC) ) pinMode(pinC, INPUT);
}// 查找 ADC 零偏移量的函数
void CurrSense::calibrateOffsets()
{const int calibration_rounds = 1000;// 查找0电流时候的电压offset_ia = 0;offset_ib = 0;offset_ic = 0;// 读数1000次for (int i = 0; i < calibration_rounds; i++) {offset_ia += readADCVoltageInline(pinA);offset_ib += readADCVoltageInline(pinB);if(_isset(pinC)) offset_ic += readADCVoltageInline(pinC);delay(1);}// 求平均,得到误差offset_ia = offset_ia / calibration_rounds;offset_ib = offset_ib / calibration_rounds;if(_isset(pinC)) offset_ic = offset_ic / calibration_rounds;
}void CurrSense::init()
{// 配置函数configureADCInline(pinA,pinB,pinC);// 校准calibrateOffsets();
}// 读取全部三相电流void CurrSense::getPhaseCurrents()
{current_a = (readADCVoltageInline(pinA) - offset_ia)*gain_a;// ampscurrent_b = (readADCVoltageInline(pinB) - offset_ib)*gain_b;// ampscurrent_c = (!_isset(pinC)) ? 0 : (readADCVoltageInline(pinC) - offset_ic)*gain_c; // amps
}

编写InlineCurrent.h文件的内容

#include <Arduino.h>class CurrSense
{public:CurrSense(int Mot_Num);float readADCVoltageInline(const int pinA);void configureADCInline(const int pinA,const int pinB, const int pinC);void calibrateOffsets();void init();void getPhaseCurrents();float current_a,current_b,current_c;int pinA;int pinB;int pinC;float offset_ia;float offset_ib;float offset_ic;float _shunt_resistor;float amp_gain;float volts_to_amps_ratio;float gain_a;float gain_b;float gain_c;private:int _Mot_Num;
};

3 电流环功能实现

3.1 代码实现

代码29行: 设置电流环的PID参数

代码36行: 创建电流环的Obj

代码57~63行: 设置电流环参数PID函数

代码271~278行: 获取电流数据函数

代码283~293行: 获取IQ电流值

代码295~300行: 电流滤波函数

dengFOC.c 源文件内容:

#include <Arduino.h> 
#include "AS5600.h"
#include "lowpass_filter.h"
#include "pid.h"
#include "InlineCurrent.h"   //引入在线电流检测#define _1_SQRT3 0.57735026919f
#define _2_SQRT3 1.15470053838f
//低通滤波初始化
LowPassFilter M0_Vel_Flt = LowPassFilter(0.01); // Tf = 10ms   //M0速度环
LowPassFilter M0_Curr_Flt = LowPassFilter(0.05); // Tf = 5ms   //M0电流环#define _constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
float voltage_power_supply;
float Ualpha,Ubeta=0,Ua=0,Ub=0,Uc=0;#define _3PI_2 4.71238898038f
float zero_electric_angle=0;int PP=1,DIR=1;
int pwmA = 32;
int pwmB = 33;
int pwmC = 25;//PID
PIDController vel_loop_M0 = PIDController{.P = 2, .I = 0, .D = 0, .ramp = 100000, .limit = voltage_power_supply/2};
PIDController angle_loop_M0 = PIDController{.P = 2, .I = 0, .D = 0, .ramp = 100000, .limit = 100};PIDController current_loop_M0 = PIDController{.P = 1.2, .I = 0, .D = 0, .ramp = 100000, .limit = 12.6};//AS5600
Sensor_AS5600 S0=Sensor_AS5600(0);
TwoWire S0_I2C = TwoWire(0);//初始化电流闭环
CurrSense CS_M0= CurrSense(0);//=================PID 设置函数=================
//速度PID
void DFOC_M0_SET_VEL_PID(float P,float I,float D,float ramp)   //M0角度环PID设置
{vel_loop_M0.P=P;vel_loop_M0.I=I;vel_loop_M0.D=D;vel_loop_M0.output_ramp=ramp;
}//角度PID
void DFOC_M0_SET_ANGLE_PID(float P,float I,float D,float ramp)   //M0角度环PID设置
{angle_loop_M0.P=P;angle_loop_M0.I=I;angle_loop_M0.D=D;angle_loop_M0.output_ramp=ramp;
}void DFOC_M0_SET_CURRENT_PID(float P,float I,float D,float ramp)    //M0电流环PID设置
{current_loop_M0.P=P;current_loop_M0.I=I;current_loop_M0.D=D;current_loop_M0.output_ramp=ramp;
}//M0速度PID接口
float DFOC_M0_VEL_PID(float error)   //M0速度环
{return vel_loop_M0(error);}//M0角度PID接口
float DFOC_M0_ANGLE_PID(float error)
{return angle_loop_M0(error);
}//初始变量及函数定义
#define _constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
//宏定义实现的一个约束函数,用于限制一个值的范围。
//具体来说,该宏定义的名称为 _constrain,接受三个参数 amt、low 和 high,分别表示要限制的值、最小值和最大值。该宏定义的实现使用了三元运算符,根据 amt 是否小于 low 或大于 high,返回其中的最大或最小值,或者返回原值。
//换句话说,如果 amt 小于 low,则返回 low;如果 amt 大于 high,则返回 high;否则返回 amt。这样,_constrain(amt, low, high) 就会将 amt 约束在 [low, high] 的范围内。1// 归一化角度到 [0,2PI]
float _normalizeAngle(float angle)
{float a = fmod(angle, 2*PI);   //取余运算可以用于归一化,列出特殊值例子算便知return a >= 0 ? a : (a + 2*PI);  //三目运算符。格式:condition ? expr1 : expr2 //其中,condition 是要求值的条件表达式,如果条件成立,则返回 expr1 的值,否则返回 expr2 的值。可以将三目运算符视为 if-else 语句的简化形式。//fmod 函数的余数的符号与除数相同。因此,当 angle 的值为负数时,余数的符号将与 _2PI 的符号相反。也就是说,如果 angle 的值小于 0 且 _2PI 的值为正数,则 fmod(angle, _2PI) 的余数将为负数。//例如,当 angle 的值为 -PI/2,_2PI 的值为 2PI 时,fmod(angle, _2PI) 将返回一个负数。在这种情况下,可以通过将负数的余数加上 _2PI 来将角度归一化到 [0, 2PI] 的范围内,以确保角度的值始终为正数。
}// 设置PWM到控制器输出
void setPwm(float Ua, float Ub, float Uc) 
{// 限制上限Ua = _constrain(Ua, 0.0f, voltage_power_supply);Ub = _constrain(Ub, 0.0f, voltage_power_supply);Uc = _constrain(Uc, 0.0f, voltage_power_supply);// 计算占空比// 限制占空比从0到1float dc_a = _constrain(Ua / voltage_power_supply, 0.0f , 1.0f );float dc_b = _constrain(Ub / voltage_power_supply, 0.0f , 1.0f );float dc_c = _constrain(Uc / voltage_power_supply, 0.0f , 1.0f );//写入PWM到PWM 0 1 2 通道ledcWrite(0, dc_a*255);ledcWrite(1, dc_b*255);ledcWrite(2, dc_c*255);
}void setTorque(float Uq,float angle_el) 
{S0.Sensor_update(); //更新传感器数值Uq=_constrain(Uq,-(voltage_power_supply)/2,(voltage_power_supply)/2);float Ud=0;angle_el = _normalizeAngle(angle_el);// 帕克逆变换Ualpha =  -Uq*sin(angle_el); Ubeta =   Uq*cos(angle_el); // 克拉克逆变换Ua = Ualpha + voltage_power_supply/2;Ub = (sqrt(3)*Ubeta-Ualpha)/2 + voltage_power_supply/2;Uc = (-Ualpha-sqrt(3)*Ubeta)/2 + voltage_power_supply/2;setPwm(Ua,Ub,Uc);
}void DFOC_Vbus(float power_supply)
{voltage_power_supply=power_supply;pinMode(pwmA, OUTPUT);pinMode(pwmB, OUTPUT);pinMode(pwmC, OUTPUT);ledcSetup(0, 30000, 8);  //pwm频道, 频率, 精度ledcSetup(1, 30000, 8);  //pwm频道, 频率, 精度ledcSetup(2, 30000, 8);  //pwm频道, 频率, 精度ledcAttachPin(pwmA, 0);ledcAttachPin(pwmB, 1);ledcAttachPin(pwmC, 2);Serial.println("完成PWM初始化设置");//AS5600S0_I2C.begin(19,18, 400000UL);S0.Sensor_init(&S0_I2C);   //初始化编码器0Serial.println("编码器加载完毕");//PID 加载vel_loop_M0 = PIDController{.P = 2, .I = 0, .D = 0, .ramp = 100000, .limit = voltage_power_supply/2};//初始化电流传感器CS_M0.init();}float _electricalAngle()
{return  _normalizeAngle((float)(DIR *  PP) * S0.getMechanicalAngle()-zero_electric_angle);
}void DFOC_alignSensor(int _PP,int _DIR)
{  PP=_PP;DIR=_DIR;setTorque(3, _3PI_2);  //起劲delay(1000);S0.Sensor_update();  //更新角度,方便下面电角度读取zero_electric_angle=_electricalAngle();setTorque(0, _3PI_2);  //松劲(解除校准)Serial.print("0电角度:");Serial.println(zero_electric_angle);
}float DFOC_M0_Angle()
{return DIR*S0.getAngle();
}//无滤波
//float DFOC_M0_Velocity()
//{
//  return DIR*S0.getVelocity();
//}//有滤波
float DFOC_M0_Velocity()
{//获取速度数据并滤波float vel_M0_ori=S0.getVelocity();float vel_M0_flit=M0_Vel_Flt(DIR*vel_M0_ori);return vel_M0_flit;   //考虑方向
}//==============串口接收==============
float motor_target;
int commaPosition;
String serialReceiveUserCommand() {// a string to hold incoming datastatic String received_chars;String command = "";while (Serial.available()) {// get the new byte:char inChar = (char)Serial.read();// add it to the string buffer:received_chars += inChar;// end of user inputif (inChar == '\n') {// execute the user commandcommand = received_chars;commaPosition = command.indexOf('\n');//检测字符串中的逗号if(commaPosition != -1)//如果有逗号存在就向下执行{motor_target = command.substring(0,commaPosition).toDouble();            //电机角度Serial.println(motor_target);}// reset the command buffer received_chars = "";}}return command;
}float serial_motor_target()
{return motor_target;
}//================简易接口函数================
void DFOC_M0_set_Velocity_Angle(float Target)
{setTorque(DFOC_M0_VEL_PID(DFOC_M0_ANGLE_PID((Target-DFOC_M0_Angle())*180/PI)),_electricalAngle());   //角度闭环
}void DFOC_M0_setVelocity(float Target)
{setTorque(DFOC_M0_VEL_PID((serial_motor_target()-DFOC_M0_Velocity())*180/PI),_electricalAngle());   //速度闭环
}void DFOC_M0_set_Force_Angle(float Target)   //力位
{setTorque(DFOC_M0_ANGLE_PID((Target-DFOC_M0_Angle())*180/PI),_electricalAngle());
}void DFOC_M0_setTorque(float Target)
{setTorque(Target,_electricalAngle());
}void runFOC()
{//====传感器更新====// S0.Sensor_update();CS_M0.getPhaseCurrents();//====传感器更新====
}//=========================电流读取=========================//通过Ia,Ib,Ic计算Iq,Id(目前仅输出Iq)
float cal_Iq_Id(float current_a,float current_b,float angle_el)
{float I_alpha=current_a;float I_beta = _1_SQRT3 * current_a + _2_SQRT3 * current_b;float ct = cos(angle_el);float st = sin(angle_el);//float I_d = I_alpha * ct + I_beta * st;float I_q = I_beta * ct - I_alpha * st;return I_q;
}float DFOC_M0_Current()
{  float I_q_M0_ori=cal_Iq_Id(CS_M0.current_a,CS_M0.current_b,_electricalAngle());float I_q_M0_flit=M0_Curr_Flt(I_q_M0_ori);return I_q_M0_flit;  
}

dengFOC.h 源文件内容:

//灯哥开源,遵循GNU协议,转载请著名版权!
//GNU开源协议(GNU General Public License, GPL)是一种自由软件许可协议,保障用户能够自由地使用、研究、分享和修改软件。
//该协议的主要特点是,要求任何修改或衍生的作品必须以相同的方式公开发布,即必须开源。此外,该协议也要求在使用或分发软件时,必须保留版权信息和许可协议。GNU开源协议是自由软件基金会(FSF)制定和维护的一种协议,常用于GNU计划的软件和其他自由软件中。
//仅在DengFOC官方硬件上测试过,欢迎硬件购买/支持作者,淘宝搜索店铺:灯哥开源
//你的支持将是接下来做视频和持续开源的经费,灯哥在这里先谢谢大家了
//函数声明void setPwm(float Ua, float Ub, float Uc);
float setTorque(float Uq,float angle_el);
float _normalizeAngle(float angle);
void DFOC_Vbus(float power_supply);
void DFOC_alignSensor(int _PP,int _DIR);
float _electricalAngle();float serial_motor_target();
String serialReceiveUserCommand();
//传感器读取
float DFOC_M0_Velocity();
float DFOC_M0_Angle();
//PID
void DFOC_M0_SET_ANGLE_PID(float P,float I,float D,float ramp);
void DFOC_M0_SET_VEL_PID(float P,float I,float D,float ramp);
float DFOC_M0_VEL_PID(float error);
float DFOC_M0_ANGLE_PID(float error);
void DFOC_M0_SET_CURRENT_PID(float P,float I,float D,float ramp);//接口函数
void DFOC_M0_set_Velocity_Angle(float Target);
void DFOC_M0_setVelocity(float Target);
void DFOC_M0_set_Force_Angle(float Target);
void DFOC_M0_setTorque(float Target);float DFOC_M0_Current();
float cal_Iq_Id(float current_a,float current_b,float angle_el);void runFOC();

3.2 测试代码实现

代码37行: 设置供电电压

代码38行: 设置电极数和编码器的方向

代码57行: 获取电流参数

代码58行: 设置PID参数

代码59行:设置执行单元

源代码如下:

/* USER CODE BEGIN Header */
/**
******************************************************************************
* File Name    : foc_function_test.c
* Description  : FOC 闭环各种模式测试
******************************************************************************
* @attention
*
* COPYRIGHT:    Copyright (c) 2025 tangmingfei2013@126.com * CREATED BY:   Alan.tang
* DATE:         JAN 7th, 2025
*  参考代码:    Deng FOC
*
******************************************************************************
*/
/* USER CODE END Header */#include "DengFOC.h"
const int LED_PIN = 2;int Sensor_DIR=-1;    //传感器方向
int Motor_PP=7;       //电机极对数
float Sensor_Vel;/*0: 电流模式   1: 速度模式2: 位置模式
*/
#define SELECT_MODE        0void setup() 
{pinMode(LED_PIN, OUTPUT);digitalWrite(LED_PIN, LOW);digitalWrite(LED_PIN, HIGH);// put your setup code here, to run once:Serial.begin(115200);DFOC_Vbus(11.6);            //设定驱动器供电电压DFOC_alignSensor(Motor_PP,Sensor_DIR);#if SELECT_MODE == 0// 设置电流模式闭环PIDDFOC_M0_SET_CURRENT_PID(5,200,0,100000);#elif SELECT_MODE == 1// 设置速度闭环PIDDFOC_M0_SET_VEL_PID(0.01,0.00,0,0);#elif SELECT_MODE == 2//设置位置模式闭环PIDDFOC_M0_SET_VEL_PID(0.01,0.00,0,0);DFOC_M0_SET_ANGLE_PID(0.5,0,0,0);
#endif }void postion_Mode_test( void )
{//设置速度DFOC_M0_set_Velocity_Angle(serial_motor_target());
}void velocity_Mode_test( void )
{//设置速度DFOC_M0_setVelocity(serial_motor_target());
}void current_Mode_test( void )
{static int count=0;// 电流模式runFOC();DFOC_M0_setTorque(serial_motor_target());count++;if(count>30){count=0;Serial.printf("%0.2f \n", DFOC_M0_Current());}
}void loop() 
{
#if SELECT_MODE == 0current_Mode_test(); 
#elif SELECT_MODE == 1velocity_Mode_test();
#elif SELECT_MODE == 2postion_Mode_test();
#endif//接收串口serialReceiveUserCommand();
}

4 测试

1) 设置电流值为0时,电流的输出波形

2)设置电流为2

 3)设置电流值为-2

测试视频如下:

直流无刷电机控制(FOC):电流模式测试视频

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在 Flownex 网络中创建传热元件

本文探讨了在 Flownex 仿真中集成新传热元件的步骤&#xff0c;以增强热系统管理能力。 了解 Flownex 中的传热元件 Flownex 中的传热元件复制传导、对流和辐射&#xff0c;从而深入了解系统的热流体行为。准确建模复杂系统需要了解这些单元的特性和功能。Flownex 的高级功能…

《OpenCV计算机视觉实战项目》——银行卡号识别

文章目录 项目任务及要求项目实现思路项目实现及代码导入模块设置参数对模版图像中数字的定位处理银行卡的图像处理读取输入图像&#xff0c;预处理找到数字边框使用模版匹配&#xff0c;计算匹配得分 画出并打印结果 项目任务及要求 任务书&#xff1a; 要为某家银行设计一套…

PyCharm文档管理

背景&#xff1a;使用PyCharmgit做文档管理 需求&#xff1a;需要PyCharm自动识别docx/xslx/vsdx等文件类型&#xff0c;并在PyCharm内点击文档时唤起系统内关联应用(如word、excel、visio) 设置步骤&#xff1a; 1、file -》 settings -》file types 2、在Files opened i…

景联文科技提供高质量多模态数据处理服务,驱动AI新时代

在当今快速发展的AI时代&#xff0c;多模态数据标注成为推动人工智能技术进步的关键环节。景联文科技作为行业领先的AI数据服务提供商&#xff0c;专注于为客户提供高质量、高精度的多模态数据标注服务&#xff0c;涵盖图像、语音、文本、视频及3D点云等多种类型的数据。通过专…

django基于Python的智能停车管理系统

1.系统概述 1.定义&#xff1a;Django 基于 Python 的智能停车管理系统是一个利用 Django 框架构建的软件系统&#xff0c;用于高效地管理停车场的各种事务&#xff0c;包括车辆进出记录、车位预订、收费管理等诸多功能。 2.目的&#xff1a;它的主要目的是提高停车场的运营效…

【Rust】切片类型

目录 思维导图 1. 切片类型概述 2. 函数示例&#xff1a;获取字符串中的第一个单词 2.1 问题描述 2.2 初步实现 2.3 代码实现 3. 切片的引入 3.1 切片的定义 3.2 切片的优势 3.3 改进后的函数 4. 函数参数的通用性 4.1 改进函数签名 4.2 示例代码 5. 其他切片类型…

微信小程序-Docker+Nginx环境配置业务域名验证文件

在实际开发或运维工作中&#xff0c;我们时常需要在 Nginx 部署的服务器上提供一个特定的静态文件&#xff0c;用于域名验证或第三方平台验证。若此时使用 Docker 容器部署了 Nginx&#xff0c;就需要将该验证文件正确地映射&#xff08;挂载&#xff09;到容器中&#xff0c;并…

鸿蒙UI(ArkUI-方舟UI框架)

参考&#xff1a;https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V13/arkts-layout-development-overview-V13 ArkUI简介 ArkUI&#xff08;方舟UI框架&#xff09;为应用的UI开发提供了完整的基础设施&#xff0c;包括简洁的UI语法、丰富的UI功能&#xff…

图片和短信验证码(头条项目-06)

1 图形验证码接口设计 将后端⽣成的图⽚验证码存储在redis数据库2号库。 结构&#xff1a; {img_uuid:0594} 1.1 创建验证码⼦应⽤ $ cd apps $ python ../../manage.py startapp verifications # 注册新应⽤ INSTALLED_APPS [django.contrib.admin,django.contrib.auth,…

SpringCloud系列教程:微服务的未来(十二)OpenFeign连接池、最佳实践、日志、微服务拆分

本篇博客将讨论如何优化 OpenFeign 的连接池配置&#xff0c;如何使用最佳实践提升服务间通信的效率和可维护性&#xff0c;并探讨如何通过拆分服务来提升微服务架构的灵活性和可扩展性&#xff0c;具体涵盖了用户服务和交易服务的拆分。 目录 前言 OpenFeign 连接池 最佳实…

进阶——十六届蓝桥杯嵌入式熟练度练习(LED的全开,全闭,点亮指定灯,交替闪烁,PWM控制LED呼吸灯)

点亮灯的函数 void led_show(unsigned char upled) { HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOC,upled<<8,GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RE…

动态规划【打家劫舍】

今天和大家分享一下动态规划当中的打家劫舍题目&#xff0c;希望在大家刷题的时候提供一些思路 打家劫舍1&#xff1a; 题目链接&#xff1a; 198. 打家劫舍 - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋…

Jaeger UI使用、采集应用API排除特定路径

Jaeger使用 注&#xff1a; Jaeger服务端版本为&#xff1a;jaegertracing/all-in-one-1.6.0 OpenTracing版本为&#xff1a;0.33.0&#xff0c;最后一个版本&#xff0c;停留在May 06, 2019。最好升级到OpenTelemetry。 Jaeger客户端版本为&#xff1a;jaeger-client-1.3.2。…

Vue-Cli

一.vue.js 1.优点 1)体积小,压缩后33K 2)更高的运行效率 3)双向数据绑定 4)生态丰富,学习成本低 2.Vue指令 指令带有前缀 v- 开头&#xff0c;以表示它们是 Vue 提供的特殊属性。 1)v-text (1)作用 &#xff1a;设置标签的文本内容 默认写法会替换全部内容&#xff0c…

【源码解析】Java NIO 包中的 ByteBuffer

文章目录 1. 前言2. ByteBuffer 概述3. 属性4. 构造器5. 方法5.1 allocate 分配 Buffer5.2 wrap 映射数组5.3 slice 获取子 ByteBuffer5.4 duplicate 复刻 ByteBuffer5.5 asReadOnlyBuffer 创建只读的 ByteBuffer5.6 get 方法获取字节5.7 put 方法往 ByteBuffer 里面加入字节5.…

HTML5实现好看的中秋节网页源码

HTML5实现好看的中秋节网页源码 前言一、设计来源1.1 网站首页界面1.2 登录注册界面1.3 节日由来界面1.4 节日习俗界面1.5 节日文化界面1.6 节日美食界面1.7 节日故事界面1.8 节日民谣界面1.9 联系我们界面 二、效果和源码2.1 动态效果2.2 源代码 源码下载结束语 HTML5实现好看…

OA项目登录

导入依赖,下面的依赖是在这次OA登录中用到的 <!--web依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.sprin…

YangQG 面试题汇总

一、交叉链表 问题&#xff1a; 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 解题思想&#xff1a; 双指针 备注&#xff1a;不是快慢指针&#xff0c;如果两个长度相…

【面试题】技术场景 4、负责项目时遇到的棘手问题及解决方法

工作经验一年以上程序员必问问题 面试题概述 问题为在负责项目时遇到的棘手问题及解决方法&#xff0c;主要考察开发经验与技术水平&#xff0c;回答不佳会影响面试印象。提供四个回答方向&#xff0c;准备其中一个方向即可。 1、设计模式应用方向 以登录为例&#xff0c;未…

WEB前端-3.2

目录 css 【例】飙升榜 【源码】 css 【例】飙升榜 【源码】 <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width, initial-scale1.0"&g…