AT32F421驱动BLDC 配合上位机控制与调参

AT32F421驱动BLDC 配合上位机控制与调参


  • 🔧AT32 电机控制与调参上位机软件:ArteryMotorMonitorhttps://www.arterytek.com/cn/support/motor_control.jsp?index=0
  • 🌿测试电机参数:2204-12N14P,无感BLDC,极对数7
  • 📘测试工程:bldc_1shunt_sensorless(在上面页可以下载到AT32F421_MC_Library_Project_V2.1.2
    在这里插入图片描述

👉 个人也是初始使用该调参上位机软件,在探索使用过程中,遇到不少问题,例如状态不正常,电机不转等问题。建议初次使用先仔细阅读相关文档和原理图,如果使用官方提供的驱动板可以略过,直接参照文档测试即可,对于采用自制驱动板的需要参考官方的原理图进行连接,软件工程也需要做相对应修改。

  • 🍁官方提供的驱动原理图部分参考:AT-MOTOR-EVB-V2.0_SCH.pdf(个人采用的EG2133,和官方使用的驱动芯片功能一样,下桥臂低电平开启)
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 🌿控制引脚:(参考AT-MOTOR-EVB-V2.0_SCH.pdf原理图)
    在这里插入图片描述
    在这里插入图片描述

==== 3相PWM控制 ====
U  	上桥臂 PA8
V   上桥臂 PA9
W   上桥臂 PA10
----------------
U  	下桥臂 PB13
V   下桥臂 PB14
W   下桥臂 PB15
BRK  刹车 PB12  PB8
------------
==== HALL ====
PB4
PB5
PB0
==== 比较器反电动势检测 ====
PA5
PA6
PA7
=== VBUS电压 ====
PA4
--- 温度 ---
PB1

🛠工程参数设定

  • 🔖电机主要参数在设置文件motor_control_drive_param.h中配置:
  • 🌿驱动电机参数:
/* choose sensor */
//#define HALL_SENSORS  //带霍尔传感器检测
#define SENSORLESS    //无传感器控制的模式(通用)
#define BLDC_SENSORLESS_ADC		//六步方波无传感器控制以 ADC 检测反电势的模式
//#define BLDC_SENSORLESS_COMP		//六步方波无传感器控制以比较器检测反电势的模式......./* Motor parameters  */
#define RS_LL                        (1.89)           /* Stator resistance, ohm 电机线间电阻值(unit: Ω)*/
#define LS_LL                        (0.002387)       /* Stator inductance, H 电机线间电感值(unit: H)*/
#define POLE_PAIRS                   (14/2)              //电机极对数
#define KE                           (1.0)            /* Back EMF constant(line-to-line, peak voltage), V/rpm 电机 KE 值(unit: V/rpm)*/
#define NOMINAL_CURRENT              (1.7)	//电机额定电流 (unit: ampere)
  • 🌿反电势检测模式:(决定调参控制上位机软件控制界面)
/* choose how to start up */
//#define INIT_ANGLE_STARTUP	//无传感器之初始角度检测启动(通用)
#define ALIGN_AND_GO_STARTUP  //无传感器之对齐启动(通用)
//#define OPENLOOP_STARTUP    //无传感器之开环启动(通用)

在这里插入图片描述

📗启动步骤和条件

  • 以下内容和官方提供的AT32F421_MC_Library_Project中相关文档说明基本相同。
    在这里插入图片描述

在这里插入图片描述

    1. 加载工程配置
      在这里插入图片描述
      在这里插入图片描述
    1. 打开对应串口,连接目标板串口1引脚(PB6/Tx1,PB7/Rx1)
      在这里插入图片描述
    1. 按下播放键(4.)即可周期性更新 UI 接口的数据以及与目标板通过串口实时通信, 如发送启动/停止电机
      的命令、实时调速、调试电流 PID 参数以及监控参数绘制波形等。
      在这里插入图片描述
    1. 发波启动条件:ESC_STATE_SAFTY_READY
      在这里插入图片描述
  • 🌟如果不是使用的官方的驱动板,像我采用自制的驱动板,硬件参数不一样,可以在对应的驱动程序中,对相关参数。进行修改或检测内容进行屏蔽。(屏蔽位置:滴答定时器回调中SysTick_Handler
void SysTick_Handler(void)
{int16_t sp_value = 0;flag_status mode_switch1 = SET;sp_value = adc_in_tab[ADC_POTENTIO_IDX] - SP_OFFSET;mode_switch1 = gpio_input_data_bit_read(MODE1_BUTTON_PORT, MODE1_BUTTON_PIN);switch(esc_state_old){case ESC_STATE_IDLE:if(ctrl_source == CTRL_SOURCE_EXTERNAL){if((sp_value <= 0) && (param_initial_rdy == SET) && (curr_offset_rdy == SET)){esc_state = ESC_STATE_SAFETY_READY;}else{esc_state = ESC_STATE_IDLE;}}else{if((param_initial_rdy == SET) && (curr_offset_rdy == SET)){esc_state = ESC_STATE_SAFETY_READY;}else{esc_state = ESC_STATE_IDLE;}}break;case ESC_STATE_SAFETY_READY:if(ctrl_mode == ID_MANUAL_TUNE || ctrl_mode == IQ_MANUAL_TUNE){if(start_stop_btn_flag == SET){esc_state = ESC_STATE_I_TUNE;}}else if(ctrl_mode == SPEED_CTRL){if(ctrl_source == CTRL_SOURCE_EXTERNAL){if(sp_value >= SP_RUN_POINT){if (mode_switch1 == SET)  /* CCW*/{hall_ccw_ctrl_para();rotor_speed.dir = CCW;current.volt_sign = -1;}else  /* CW*/{hall_cw_ctrl_para();rotor_speed.dir = CW;current.volt_sign = 1;}esc_state = ESC_STATE_ANGLE_INIT;}else{esc_state = ESC_STATE_SAFETY_READY;}}else if(ctrl_source == CTRL_SOURCE_SOFTWARE){if((speed_ramp.cmd_final != 0) && (start_stop_btn_flag == SET)){if(speed_ramp.cmd_final > 0)        /* CW*/{hall_cw_ctrl_para();rotor_speed.dir = CW;current.volt_sign = 1;}else if(speed_ramp.cmd_final < 0)   /* CCW*/{hall_ccw_ctrl_para();rotor_speed.dir = CCW;current.volt_sign = -1;}esc_state = ESC_STATE_ANGLE_INIT;}else{esc_state = ESC_STATE_SAFETY_READY;}}}else if(ctrl_mode == TORQUE_CTRL){if(ctrl_source == CTRL_SOURCE_EXTERNAL){if(sp_value >= SP_RUN_POINT){if (mode_switch1 == SET)   /* CCW*/{hall_ccw_ctrl_para();rotor_speed.dir = CCW;current.volt_sign = -1;}else  /* CW*/{hall_cw_ctrl_para();rotor_speed.dir = CW;current.volt_sign = 1;}esc_state = ESC_STATE_ANGLE_INIT;}else{esc_state = ESC_STATE_SAFETY_READY;}}else if(ctrl_source == CTRL_SOURCE_SOFTWARE){if((current.Ibus.Iref != 0) && (start_stop_btn_flag == SET)){if(current.Ibus.Iref > 0)        /* CW*/{hall_cw_ctrl_para();rotor_speed.dir = CW;current.volt_sign = 1;}else if(current.Ibus.Iref < 0)   /* CCW*/{hall_ccw_ctrl_para();rotor_speed.dir = CCW;current.volt_sign = -1;}esc_state = ESC_STATE_ANGLE_INIT;}else{esc_state = ESC_STATE_SAFETY_READY;}}}else if(ctrl_mode == OPEN_LOOP_CTRL){if(ctrl_source == CTRL_SOURCE_EXTERNAL){if(sp_value >= SP_RUN_POINT){openloop.period_ref = openloop.olc_init_period;openloop.volt_ref = openloop.olc_init_volt;esc_state = ESC_STATE_STARTING;}else{esc_state = ESC_STATE_SAFETY_READY;}}else if(ctrl_source == CTRL_SOURCE_SOFTWARE){if(start_stop_btn_flag == SET){openloop.period_ref = openloop.olc_init_period;openloop.volt_ref = openloop.olc_init_volt;esc_state = ESC_STATE_STARTING;}else{esc_state = ESC_STATE_SAFETY_READY;}}}if(I_auto_tune.state_flag == PROCESSING){current_auto_tuning(&I_auto_tune);set_current_pid_param(&I_auto_tune, &pid_is);I_auto_tune.state_flag = SUCCEED;}break;case ESC_STATE_ANGLE_INIT:/* Determine the initial position at the beginning(BLDC sensor-less) */angle_init_func();/* Stop motor */if((ctrl_source == CTRL_SOURCE_SOFTWARE && start_stop_btn_flag == RESET) ||(ctrl_source == CTRL_SOURCE_EXTERNAL && sp_value <= SP_STOP_POINT)){esc_state = ESC_STATE_FREE_RUN;}break;case ESC_STATE_STARTING:if(ctrl_mode == OPEN_LOOP_CTRL){esc_state = ESC_STATE_RUNNING;}else{if (sense_hall_steps < SENSE_HALL_TIMES){sys_counter++;if (sys_counter >= REBOOT_PERIOD_MS){esc_state = ESC_STATE_SAFETY_READY;}}else{esc_state = ESC_STATE_RUNNING;start_state = START_STATE_STABLE_RUN;sys_counter = 0;/* Set parameter for switching to closed-loop control */rdy_to_close_loop_param();}}/* Stop motor */if((ctrl_source == CTRL_SOURCE_SOFTWARE && start_stop_btn_flag == RESET) ||(ctrl_source == CTRL_SOURCE_EXTERNAL && sp_value <= SP_STOP_POINT)){esc_state = ESC_STATE_FREE_RUN;}break;case ESC_STATE_RUNNING:if(ctrl_mode == SPEED_CTRL){if(ctrl_source == CTRL_SOURCE_EXTERNAL){if (sp_value <= SP_STOP_POINT){speed_ramp.cmd_final = 0;if(rotor_speed.filtered <= MIN_CONTROL_SPEED){esc_state = ESC_STATE_FREE_RUN;}}else{if (mode_switch1 == SET)  /* CCW*/{if (sp_value >= SP_RUN_POINT){speed_ramp.cmd_final = -MIN_CONTROL_SPEED - (((sp_value << 1) * SP_TO_SPD_CMD) >> 15);}else{speed_ramp.cmd_final = -MIN_CONTROL_SPEED;}}else                     /* CW*/{if (sp_value >= SP_RUN_POINT){speed_ramp.cmd_final = MIN_CONTROL_SPEED + (((sp_value << 1) * SP_TO_SPD_CMD) >> 15);}else{speed_ramp.cmd_final = MIN_CONTROL_SPEED;}}}command_ramp(&speed_ramp);
#if defined WITHOUT_CURRENT_CTRLvolt_cmd = pid_controller(&pid_spd_volt, (speed_ramp.command - rotor_speed.filtered));
#elsecurrent.Ibus.Iref = pid_controller(&pid_spd, (speed_ramp.command - rotor_speed.filtered));
#endif}else if(ctrl_source == CTRL_SOURCE_SOFTWARE){if (start_stop_btn_flag == RESET){esc_state = ESC_STATE_FREE_RUN;}else{if(abs(speed_ramp.cmd_final) < MIN_CONTROL_SPEED){if(rotor_speed.dir == CW)speed_ramp.cmd_final = MIN_CONTROL_SPEED;elsespeed_ramp.cmd_final = -MIN_CONTROL_SPEED;}command_ramp(&speed_ramp);#if defined WITHOUT_CURRENT_CTRLvolt_cmd = pid_controller(&pid_spd_volt, (speed_ramp.command - rotor_speed.filtered));
#elsecurrent.Ibus.Iref = pid_controller(&pid_spd, (speed_ramp.command - rotor_speed.filtered));
#endif}}}else if(ctrl_mode == TORQUE_CTRL){if(ctrl_source == CTRL_SOURCE_EXTERNAL){if (sp_value <= SP_STOP_POINT){current.Ibus.Iref = 0;if(rotor_speed.filtered <= MIN_CONTROL_SPEED){esc_state = ESC_STATE_FREE_RUN;}}else if (sp_value >= SP_RUN_POINT){if (mode_switch1 == SET)    /* CCW*/{current.Ibus.Iref = -(sp_value * SP_TO_I_CMD) >> 15;}else                        /* CW*/{current.Ibus.Iref = (sp_value * SP_TO_I_CMD) >> 15;}}}else if(ctrl_source == CTRL_SOURCE_SOFTWARE){if (start_stop_btn_flag == RESET){esc_state = ESC_STATE_FREE_RUN;}else{esc_state = ESC_STATE_RUNNING;}}}else if(ctrl_mode == OPEN_LOOP_CTRL){if(ctrl_source == CTRL_SOURCE_EXTERNAL){if(sp_value <= SP_STOP_POINT){esc_state = ESC_STATE_FREE_RUN;}else{closeloop_rdy = RESET;/* 5 ms inc openloop volt & spd */open_loop_cmd_ramp(&openloop);}}else if(ctrl_source == CTRL_SOURCE_SOFTWARE){if (start_stop_btn_flag == RESET){esc_state = ESC_STATE_FREE_RUN;}else{closeloop_rdy = RESET;/* 5 ms inc openloop volt & spd */open_loop_cmd_ramp(&openloop);}}}break;case ESC_STATE_FREE_RUN:if (rotor_speed.filtered == 0){esc_state = ESC_STATE_SAFETY_READY;}else{esc_state = ESC_STATE_FREE_RUN;}break;case ESC_STATE_BRAKING:break;case ESC_STATE_ERROR:if(error_code == MC_NO_ERROR){esc_state = ESC_STATE_IDLE;}break;case ESC_STATE_ENC_ALIGN:break;case ESC_STATE_I_TUNE:if (start_stop_btn_flag == SET){I_tune_manual();}else{current.Ibus.Iref = 0;esc_state = ESC_STATE_FREE_RUN;}break;case ESC_STATE_AUTO_LEARN:break;
#ifdef MOTOR_PARAM_IDENTIFYcase ESC_STATE_WINDING_PARAM_ID:if (motor_param_ident.state_flag == PROCESSING){param_id_process(&motor_param_ident);}else{if (motor_param_ident.Ls.f <= 0 || motor_param_ident.Rs.f <= 0){motor_param_ident.state_flag = FAILED;error_code |= error_code_mask & MC_PARAM_IDENT_ERROR;motor_param_ident.Rs.f = motor_param_ident.Rs_Old.f;motor_param_ident.Ls.f = motor_param_ident.Ls_Old.f;}else{motor_param_ident.state_flag = SUCCEED;motor_param_ident.Rs_Old.f = motor_param_ident.Rs.f;motor_param_ident.Ls_Old.f = motor_param_ident.Ls.f;}tmr_output_enable(PWM_ADVANCE_TIMER, FALSE);disable_pwm_timer();tmr_pwm_init();adc_preempt_config();PWM_ADVANCE_TIMER->cval = 0;enable_pwm_timer();esc_state = ESC_STATE_FREE_RUN;}break;
#endifcase ESC_STATE_NONE:break;}fMosTemperature = (((adc_in_tab[ADC_MOS_TEMP_IDX] * ADC_REFERENCE_VOLT / ADC_DIGITAL_SCALE_12BITS) - V0_V) / dV_dT) + T0_C;ui_wave_param.iMosTemperature_meas = (int16_t)(fMosTemperature * 100);ui_wave_param.iBusVoltage_meas = (int16_t)(adc_in_tab[ADC_BUS_VOLT_IDX]);ui_wave_param.speed_meas_filter_pu = (int16_t)(rotor_speed.filtered * RPM_TO_SPEED_PU >> 15);ui_wave_param.speed_reference_pu = (int16_t)(speed_ramp.command * RPM_TO_SPEED_PU >> 15);adc_sample.emf.emf_half_vdc_val = (int16_t)(adc_in_tab[ADC_BUS_VOLT_IDX] * EMF_HALF_VDC_GAIN);zcp_highspd_fall = (adc_sample.emf.emf_half_vdc_val) + (adc_sample.emf.emf_high_spd_offset_falling);zcp_highspd_rise = (adc_sample.emf.emf_half_vdc_val) + (adc_sample.emf.emf_high_spd_offset_rising);
#if 1/* Over/under voltage protection 屏蔽过电压*/
//  if (adc_in_tab[ADC_BUS_VOLT_IDX] < UNDERVOLTAGE_THRESHOLD_d)
//  {
//    error_code |= error_code_mask & MC_UNDER_VOLT_ERROR;
//  }
//  else if (adc_in_tab[ADC_BUS_VOLT_IDX] > OVERVOLTAGE_THRESHOLD_d)
//  {
//    error_code |= error_code_mask & MC_OVER_VOLT_ERROR;
//  }/* MOS Temperature protection 屏蔽温度*/
//  if (adc_in_tab[ADC_MOS_TEMP_IDX] > TEMPERATURE_THRESHOLD_d)
//  {
//    error_code |= error_code_mask & MC_OVER_TEMP_ERROR;
//  }
#endif/* Enter error state handler */if (error_code != MC_NO_ERROR){esc_state = ESC_STATE_ERROR;}}
  • 🌿AT32官方驱动板提供的母线电压采集电路:
    在这里插入图片描述
  • 🌿AT32官方MOS管温度采集电路:
    在这里插入图片描述

🛠调参步骤

在这里插入图片描述

开环控制模式下调参:(✨推荐配合可调电源,能直观的看到电机在运转时,电流大小。)

调参原则:先小,然后逐渐递增。

  • 🌿在电机能转动情况下,从初始速度开始调。
  • 🌿电机能平稳启动后,调节最终的速度 ,最快速度时,电机运转不卡顿为止。
  • 🌿调节循环周期,电机转动流畅,电流最小。
  • 📐将最终整定后的参数,修改到工程中:
    在这里插入图片描述
  • 👉需要注意,部分参数不是直接照抄,有偏置补偿的。(修改后,重新烧录程序,再连接上位机软件,可以查看到修改后的参数以及运行效果)
    在这里插入图片描述
  • 🌿其他运行模式,进行调参方式,类似操作即可。
📒其他相关控制电路
  • 官方提供的外部定位器调试电路:
    在这里插入图片描述
    在这里插入图片描述
AT32官方提供的例程并不适合新手移植,不管是从AT32提供的开源驱动硬件还是软件实现代码,都是比较复杂的。成本比较高。
  • 🌿驱动硬件,从驱动板原理图可以看出,设计的物料比较多和控制方法相对比较复杂。虽然可以针对不同mcu和驱动电机进行优化,但是按照现成的软件驱动实现的方案,成本还是高。
  • 🌿软件实现,不方便移植。如果想将这套代码移植到其他品牌单片机上,几乎是行不通的。

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

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

相关文章

LVS(Linux Virtual Server)

简介 LVS&#xff08;Linux Virtual Server&#xff09;是一个高性能的开源负载均衡解决方案&#xff0c;它通过在Linux内核中实现IPVS&#xff08;IP Virtual Server&#xff09;模块来提供负载均衡功能。LVS能够将外部请求根据特定的算法分发到后端的多个服务器上&#xff0c…

百度文心一言API调用,千帆大模型获取API Key和API Secret图解

百度文心一言大模型调用教程&#xff0c;获取文心一言API Key和API Secret的方法&#xff0c;码笔记mabiji.com告诉大家在百度智能云的千帆大模型平台创建应用&#xff0c;即可获取文心一言的API Key和API Secret&#xff0c;详细流程如下&#xff1a; 1、在百度智能云的千帆大…

gitlab项目添加新成员

gitlab项目添加新成员 1、进入项目&#xff0c;找到settings----->点击Members 2、手动输入要添加成员的账号或者搜索&#xff0c;最后点击Add to project就可以了 choose a role permission 是为要添加的成员选择角色权限 补充&#xff1a; ‌Maintainer&#xff1a;拥…

同态加密和SEAL库的介绍(八)性能

本篇会对比三种加密方案&#xff0c;同时每种方案配置三种参数。即九种情况下的各个操作的性能差异&#xff0c;为大家选择合适的方案和合适的参数提供参考。表格中所有时长的单位均为微妙&#xff0c;即 。 当然数据量比较大&#xff0c;为了方便大家查找&#xff0c…

[BSidesCF 2019]Kookie1

打开题目&#xff0c;看到 根据提示&#xff0c;账号&#xff1a;cookie。密码&#xff1a;monster。试一下登录&#xff0c;登陆成功 抓包看看信息 根据提示&#xff0c; 看一下返回包 账号要加username要改成admin&#xff0c;改一下试试 构造cookie 直接得到flag flag{c…

Redis远程字典服务器(3)——常用数据结构和单线程模型

目录 一&#xff0c;常用数据结构 1.0 前言 1.1 string 1.2 hash 1.3 list 1.4 set 1.5 zset 1.6 演示 二&#xff0c;关于单线程模型 2.1 关于Redis的单线程 2.2 Redis为什么快 一&#xff0c;常用数据结构 1.0 前言 Redis是采用键值对的方式来存储数据的&#…

探索算法系列 - 前缀和算法

目录 一维前缀和&#xff08;原题链接&#xff09; 二维前缀和&#xff08;原题链接&#xff09; 寻找数组的中心下标&#xff08;原题链接&#xff09; 除自身以外数组的乘积&#xff08;原题链接&#xff09; 和为 K 的子数组&#xff08;原题链接&#xff09; 和可被 …

Java—抽象类和接口 (´▽`)ノ

目录&#xff1a; 一、抽象类&#xff1a; 1、概念: 在面向对象中&#xff0c;所有对象都是由类来创建的&#xff0c;但是呢&#xff0c;并不是所有的类都用来创建类&#xff0c;如果一个类不能描述一个具体的对象&#xff0c;那么这个类就是抽象类。 可以看到&#xff0c;我们…

kotlin简介

Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言&#xff0c;被称之为 Android 世界的Swift&#xff0c;由 JetBrains 设计开发并开源。 Kotlin 可以编译成Java字节码&#xff0c;也可以编译成 JavaScript&#xff0c;方便在没有 JVM 的设备上运行。 在Google I/O 2017…

嵌入式软件中状态机的几种操作

嵌入式软件中状态机的几种操作 1、状态机的术语 现态&#xff1a;是指当前所处的状态。 条件&#xff1a;又称为“事件”&#xff0c;当一个条件被满足&#xff0c;将会触发一个动作&#xff0c;或者执行一次状态的迁移。 动作&#xff1a;条件满足后执行的动作。动作执行完…

Animate软件基本概念:遮罩层和引导层

这里简单讲一下Animate软件中关于遮罩层和引导层的基本概念。 FlashASer&#xff1a;AdobeAnimate2021软件零基础入门教程https://zhuanlan.zhihu.com/p/633230084 FlashASer&#xff1a;实用的各种Adobe Animate软件教程https://zhuanlan.zhihu.com/p/675680471 FlashASer&…

Hadoop集群安装配置,spark集群安装配置

前提&#xff1a;准备3台linux服务器&#xff0c;并保证其网络可进行相互通信 假设三台机器IP分别为&#xff1a; 192.168.88.101 192.168.88.102 192.168.88.103一.配置三台服务器之间SSH免密登录,关闭防火墙&#xff0c;时间同步 三台服务器均执行以下1,2,3,4,5,6,8命令 1…

【MongoDB 】MongoDB 介绍及应用,设计到4个案例

MongoDB 介绍概述 基础概念 MongoDB 是非关系型数据库&#xff0c;也就是nosql&#xff0c;存储json数据格式会非常灵活&#xff0c;要比数据库mysql/MariaDB更好&#xff0c;同时也能为mysql/MariaDB分摊一部分的流量压力。 对于经常读写的数据他会存入内存&#xff0c;如此…

视频剪辑SDK,人脸美化与滤镜特效,焕发直播新活力

在数字化浪潮席卷全球的今天&#xff0c;直播已成为连接品牌与消费者、创作者与观众的重要桥梁。为了在激烈的直播竞争中脱颖而出&#xff0c;提供高质量、富有创意的直播内容成为关键。美摄科技&#xff0c;作为视频处理技术的先行者&#xff0c;携手其强大的视频剪辑SDK解决方…

2024年计算机类学术会议有哪些

随着科技的飞速发展&#xff0c;计算机科学与技术领域正以前所未有的速度进步&#xff0c;各类学术会议成为了交流最新研究成果、探讨前沿技术趋势的重要平台。2024年&#xff0c;全球范围内将举办多场计算机类学术会议&#xff0c;这些会议不仅汇聚了顶尖的专家学者&#xff0…

一六三、go多版本安装与切换

如何安装多版本 官方安装方法 参考链接 当已安装某个版本后&#xff0c;执行如下命令 go install golang.org/dl/go1.19.7latest go1.19.7 download执行第一行命令后&#xff0c;会在GOPATH中新增go1.19.7。执行第二行命令后&#xff0c;会在sdk目录下载完整的包。 通过sm…

制造知识普及(十)-- 常见的工业软件介绍

「 1. ERP」 企业资源计划&#xff08;enterprise resource planning&#xff0c;ERP&#xff09;是制造企业的核心管理软件。ERP系统的基本思想是以销定产&#xff0c;协同管控企业的产、供、销、人、财、物等资源&#xff0c;帮助企业按照销售订单&#xff0c;基于产品的制造…

gitlab-runner /var/run/docker.sock connect permission denied

usermod -aG docker gitlab-runner sudo service docker restart参考&#xff1a;https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3492

如何在 Android 手机/平板电脑上恢复误删除的 DCIM 文件夹

DCIM 文件夹是智能手机和平板电脑上最重要的文件夹之一。许多人报告说他们在 Android 设备上遇到了 DCIM 文件夹为空的问题。实际上&#xff0c;这种情况大多数情况下都会发生&#xff0c;当您意外从 Android 设备中删除 DCIM 文件夹或因病毒攻击、应用程序问题和意外格式化等原…

1-5 C语言 - 类型修饰符关键字const和volatile的概念及使用(超详细)

本节重点讲述类型修饰符关键字const和volatile的概念及使用&#xff0c;如果想详细了解关键字的同学点击下方链接进行跳转 1-1 C语言 - 关键字及其使用(数据类型)-CSDN博客 1-2 C语言 - 控制语句关键字-CSDN博客 1-3 C语言 - 控制语句的使用注意事项&#xff08;这些绝对是您…