利用手机蓝牙发送串口数据对直流无刷电机进行控制

电机控制代码基于simplefoc库

硬件使用:

  1. 电机:直流无刷电机2804
  2. 单片机MCU:ESP32 lolin D32
  3. 编码器:AS5600
  4. 驱动板:simplefoc mini
  5. 导线:杜邦线若干
  6. 安卓手机,安装蓝牙串口助手app
  7. 使用平台:arduino ide或者vscode+platform io

以上硬件,除手机外,均可以在M创动工坊采购到

代码如下:

#include <Arduino.h>

#include <Wire.h>

#include <SimpleFOC.h>

#include <iostream>

#include <sstream>

#include "BluetoothSerial.h" //蓝牙库

// SDA 21

// SCL 22

// magnetic sensor instance - I2C

MagneticSensorI2C sensor = MagneticSensorI2C(AS5600_I2C);

BluetoothSerial SerialBT; // 实例化蓝牙

BLDCMotor motor = BLDCMotor(7);

BLDCDriver3PWM driver = BLDCDriver3PWM(32, 33, 25, 12);

float target_angle = 0;   // 位置、速度、扭矩值

char model = 'a';         // 模式控制,默认位置模式

float change_value = 0.5; // 变化值

void setup()

{

    // initialise magnetic sensor hardware

    Wire.setClock(400000);

    sensor.init();

    // link the motor to the sensor

    motor.linkSensor(&sensor);

    // power supply voltage [V]

    driver.voltage_power_supply = 12;

    driver.init();

    // link the motor and the driver

    motor.linkDriver(&driver);

    // choose FOC modulation (optional)

    motor.foc_modulation = FOCModulationType::SpaceVectorPWM;

    // set motion control loop to be used

    motor.controller = MotionControlType::angle;

    // velocity PI controller parameters

    motor.PID_velocity.P = 0.1;

    motor.PID_velocity.I = 0.02;

    //  motor.PID_velocity.D = 0.01;

    // maximal voltage to be set to the motor

    motor.voltage_limit = 6;

    // velocity low pass filtering time constant

    // the lower the less filtered

    motor.LPF_velocity.Tf = 0.01f;

    // angle P controller

    motor.P_angle.P = 20; // 位置PID的P值

    // maximal velocity of the position control

    motor.velocity_limit = 10;

    motor.PID_velocity.output_ramp = 1200; // 调整这个值可以影响电机的加速和减速性能。较高的值会使电机加速和减速更快,但可能导致振动或电流峰值。

    motor.LPF_velocity.Tf = 0.01f;         // 这可以滤除电机的噪声和高频振动,从而使速度控制更加稳定。

    Serial.begin(115200);

    // comment out if not needed

    motor.useMonitoring(Serial);

    // initialize motor

    motor.init();

    // align sensor and start FOC

    motor.initFOC();

    SerialBT.begin("ESP32 Motor Control"); // 蓝牙设备的名称

    Serial.println(F("电机准备就绪。"));

    Serial.println(F("通过串口发送命令, 角度Axx, 速度Vxx, 扭矩Txx:"));

    _delay(1000);

}

// 蓝牙串口调试函数

int commaPosition;

void serial_debug() // 蓝牙控制字段

{

    if (SerialBT.available() > 0)

    {

        char DATA = SerialBT.read();

        if (!isdigit(DATA))

        {

            delay(5);

            switch (DATA)

            {

            /*---模式控制-----*/

            case 'a': // 位置模式

                model = 'a';

                target_angle = sensor.getAngle();

                break;

            case 'v':

                model = 'v';

                break;

            case 't':

                model = 't';

                break;

            /*----速度控制-----*/

            case '+':

                target_angle = target_angle + change_value;

                break;

            case '-':

                target_angle = target_angle - change_value;

                break;

            /*-----位置控制-----*/

            case 's':

                target_angle = 0;

                break;

            case 'f': // 前进

                model = 'v';

                target_angle = 20;

                break;

            case 'b': // 后退

                model = 'v';

                target_angle = -20;

                break;

            }

            SerialBT.print("model:");

            SerialBT.print(model);

            SerialBT.print("   target:");

            SerialBT.println(target_angle);

            SerialBT.println("--------------------");

        }

    }

}

String received_chars = ""; // 初始化接收到的字符变量

void receive_number()

{

    while (Serial.available()>0)

    {

        char inChar = (char)Serial.read(); // 从串口读取数据

        // 检查是否是回车或换行字符

        if (inChar == '\n' || inChar == '\r')

        {

            // 执行用户命令

            String command;

            // 检查命令是否仅由数字字符组成

            bool isNumeric = true;

            for (size_t i = 0; i < command.length(); i++)

            {

                if (!isdigit(command.charAt(i)) && command.charAt(i) != '.' && command.charAt(i) != '-')

                {

                    isNumeric = false;

                    break;

                }

            }

            if (isNumeric)

            {

                motor.controller = MotionControlType::angle;

                std::string str = command.c_str(); // 将 String 转换为 std::string

                std::istringstream ss(str);        // 使用 std::istringstream 解析命令

                ss >> target_angle;

                // 用于调试的打印目标角度

                Serial.print("Target Angle:");

                Serial.println(target_angle);

                motor.move(target_angle);

            }

            else

            {

                Serial.println("无效命令:不是数字值");

            }

            received_chars = ""; // 为下一个命令重置 received_chars

        }

        else

        {

            received_chars += inChar;

        }

    }

}

void loop()

{

    motor.loopFOC(); // 给上劲

    serial_debug();  //

    receive_number();

    // 读取不同的命令,实现位置模式、速度模式、扭矩模式的切换

    if (model == 'a')

    {

        motor.controller = MotionControlType::angle;

        motor.move(target_angle);

    }

    else if (model == 'v')

    {

        motor.controller = MotionControlType::velocity;

        motor.move(target_angle);

    }

    else if (model == 't')

    {

        motor.controller = MotionControlType::torque;

        motor.move(target_angle);

    }

}

以上代码,亲测可行。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

M创动工坊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值