FOC开环速度控制
DengFOC开环无刷电机控制代码完整解读这是灯哥开源的纯手写ESP32无刷电机开环FOC控制代码不依赖任何第三方FOC库仅使用ESP32原生LED PWM外设实现三相PWM输出是学习FOC原理的绝佳入门代码。一、完整IO配置清单核心问题代码中总共使用了4个GPIO引脚全部配置为输出模式具体如下引脚号功能定义工作模式详细配置GPIO12电机驱动使能引脚数字输出初始电平HIGH高电平使能V4版本电机驱动板GPIO32PWM A相输出LED PWM输出绑定通道0频率30kHz8位分辨率0-255GPIO33PWM B相输出LED PWM输出绑定通道1频率30kHz8位分辨率0-255GPIO25PWM C相输出LED PWM输出绑定通道2频率30kHz8位分辨率0-255IO配置关键说明30kHz PWM频率选择这个频率是为了完全避开人耳听觉范围20Hz-20kHz消除电机运行时的高频啸叫声8位分辨率对应占空比范围0-255对于开环FOC控制已经足够同时能保证30kHz的高频率输出GPIO12使能逻辑DengFOC V4驱动板采用高电平使能低电平会切断电机电源ESP32 LED PWM特性最多支持16个独立PWM通道可任意映射到GPIO引脚非常适合多相电机控制二、代码整体结构与核心逻辑1. 全局变量与宏定义// 三相PWM输出引脚定义intpwmA32;intpwmB33;intpwmC25;// 数值约束宏替代Arduino原生constrain函数#define_constrain(amt,low,high)((amt)(low)?(low):((amt)(high)?(high):(amt)))// 系统参数floatvoltage_power_supply12.6;// 电源电压3S锂电池满电电压floatshaft_angle0;// 电机机械角度开环积分得到floatopen_loop_timestamp0;// 上一次循环的时间戳floatzero_electric_angle0;// 电角度零点偏移开环时无需校准2. 初始化函数setup()voidsetup(){Serial.begin(115200);// 串口初始化用于调试输出// 电机驱动使能pinMode(12,OUTPUT);digitalWrite(12,HIGH);// 开启电机驱动电源// PWM引脚模式设置pinMode(pwmA,OUTPUT);pinMode(pwmB,OUTPUT);pinMode(pwmC,OUTPUT);// LED PWM控制器配置ledcSetup(0,30000,8);// 通道030kHz8位分辨率ledcSetup(1,30000,8);// 通道130kHz8位分辨率ledcSetup(2,30000,8);// 通道230kHz8位分辨率// 将PWM引脚绑定到对应的LED PWM通道ledcAttachPin(pwmA,0);ledcAttachPin(pwmB,1);ledcAttachPin(pwmC,2);Serial.println(完成PWM初始化设置);delay(3000);// 3秒延时方便观察初始化完成}3. 核心数学辅助函数// 机械角度转换为电角度// 电角度 机械角度 × 极对数float_electricalAngle(floatshaft_angle,intpole_pairs){return(shaft_angle*pole_pairs);}// 将任意角度归一化到 [0, 2π] 范围// 解决角度溢出和负数问题float_normalizeAngle(floatangle){floatafmod(angle,2*PI);returna0?a:(a2*PI);}4. PWM输出设置函数voidsetPwm(floatUa,floatUb,floatUc){// 将三相电压转换为占空比0-1// 占空比 相电压 / 电源电压dc_a_constrain(Ua/voltage_power_supply,0.0f,1.0f);dc_b_constrain(Ub/voltage_power_supply,0.0f,1.0f);dc_c_constrain(Uc/voltage_power_supply,0.0f,1.0f);// 写入PWM寄存器8位分辨率对应0-255ledcWrite(0,dc_a*255);ledcWrite(1,dc_b*255);ledcWrite(2,dc_c*255);}5. FOC核心变换函数voidsetPhaseVoltage(floatUq,floatUd,floatangle_el){// 电角度归一化加上零点偏移angle_el_normalizeAngle(angle_elzero_electric_angle);// 帕克逆变换d-q坐标系 → α-β坐标系// 开环控制时Ud0只需要Uq分量Ualpha-Uq*sin(angle_el);UbetaUq*cos(angle_el);// 克拉克逆变换α-β坐标系 → 三相静止坐标系// 这里使用了中心对齐PWM的简化计算加上电源电压的一半作为直流偏置UaUalphavoltage_power_supply/2;Ub(sqrt(3)*Ubeta-Ualpha)/2voltage_power_supply/2;Uc(-Ualpha-sqrt(3)*Ubeta)/2voltage_power_supply/2;// 设置三相PWM输出setPwm(Ua,Ub,Uc);}6. 开环速度控制函数floatvelocityOpenloop(floattarget_velocity){// 获取当前系统时间微秒unsignedlongnow_usmicros();// 计算两次循环之间的时间间隔秒floatTs(now_us-open_loop_timestamp)*1e-6f;// 时间戳溢出保护micros()约70分钟溢出一次if(Ts0||Ts0.5f)Ts1e-3f;// 开环角度积分通过目标速度和时间间隔计算当前机械角度// 这是开环控制的核心没有编码器反馈纯靠时间积分估算角度shaft_angle_normalizeAngle(shaft_angletarget_velocity*Ts);// 设置q轴电压决定输出力矩// 最大安全值为 voltage_power_supply/2超过会导致电压限幅失真floatUqvoltage_power_supply/3;// 计算并输出三相电压// 极对数为7对应DengFOC配套的2208电机setPhaseVoltage(Uq,0,_electricalAngle(shaft_angle,7));// 更新时间戳open_loop_timestampnow_us;returnUq;}7. 主循环函数voidloop(){// 以5rad/s的角速度开环运行// 1rad/s ≈ 9.55rpm5rad/s ≈ 47.75rpm机械转速velocityOpenloop(5);}三、代码关键特性与注意事项纯手写无库依赖代码不依赖SimpleFOC等任何第三方库所有FOC算法都由基础数学运算实现非常适合学习原理开环控制特性不需要编码器或霍尔传感器低速力矩较小高速容易丢步适合入门学习和简单应用可修改参数voltage_power_supply根据实际电源电压修改如12V电源改为12.0pole_pairs根据电机极对数修改代码中为7对应2208电机Uq调整输出力矩最大不超过voltage_power_supply/2target_velocity修改电机目标转速单位rad/s硬件兼容性仅在DengFOC V4开发板上测试过其他ESP32开发板需要根据实际引脚定义修改需要我帮你把这段代码改成支持正反转切换和串口调速的版本吗
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2600677.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!