MATLAB+Arduino控制小车直行+转向

1 硬件

两轮车+arduino板子

硬件连接

注意:电机连线。

这个小车的电机电流小,可以用arduino板子直接驱动,如果是大电流的,需要你自带电池,供电用用你的电池(如移动电源),控制信号,PWM接arduino的pwm口。

端口分配:

D10: 左轮 PWM

D11:右轮PWM

2 servo信号校正

按理0.5V应该是电机停止命令,但我的小车不标准。

用资源管理器调整

左右轮的零点分别你是0.55 和0.51. 所以发中位时,需要用实际的0点值。

其次:两个电机的方向还需要注意。如 左轮为顺时针,右轮为逆时针。

|----|--------|--------|
| 轮 | 顺时针 | 逆时针 |
| 左轮 | >0.55 | <0.55 |
| 右轮 | <0.51 | >0.51 |

在 MATLAB 中控制 Arduino 板的伺服电机(Servo Motor)是通过 MATLAB 的 Arduino 支持包实现的。

控制原理

  1. 伺服电机

    • 伺服电机是一种可以精确控制角度的电机,通常角度范围为 0° 到 180°。

    • 通过 PWM(脉宽调制)信号控制伺服电机的位置,PWM 信号的占空比决定了电机的角度。

  2. Arduino 控制伺服电机

    • Arduino 通过数字引脚输出 PWM 信号来控制伺服电机。

    • MATLAB 通过 Arduino 支持包与 Arduino 通信,发送控制命令。

  3. MATLAB 控制原理

    • MATLAB 通过串口与 Arduino 通信,发送指令来控制伺服电机。

    • MATLAB 的 servo 函数封装了底层 PWM 信号生成的细节,用户只需指定角度即可。

MATLAB 函数

以下是 MATLAB 中用于控制伺服电机的主要函数:

  1. servo

    • 创建一个伺服电机对象。

    • 语法:s = servo(a, pin)

      • a:Arduino 对象。

      • pin:伺服电机连接的引脚(例如 'D9')。

  2. writePosition

    • 设置伺服电机的位置(角度)。

    • 语法:writePosition(s, position)

      • s:伺服电机对象。

      • position:目标位置,范围为 [0, 1],对应 180°

  3. readPosition

    • 读取伺服电机的当前位置。

    • 语法:position = readPosition(s)

      • s:伺服电机对象。

      • position:当前位置,范围为 [0, 1]

  4. clear

    • 清理伺服电机对象。

    • 语法:clear s

    % MATLAB 代码:控制伺服电机

    % 创建 Arduino 对象
    a = arduino('COM3', 'Uno'); % 根据实际情况修改 COM 端口

    % 创建伺服电机对象
    s = servo(a, 'D9'); % 伺服电机连接到 D9

    % 主循环
    disp('控制伺服电机:');
    disp('输入角度(0-180),或输入 q 退出');

    try
    while true
    % 获取用户输入
    command = input('请输入角度(0-180):', 's');

    复制代码
         % 退出条件
         if strcmpi(command, 'q')
             break;
         end
    
         % 将输入转换为角度
         angle = str2double(command);
         if isnan(angle) || angle < 0 || angle > 180
             disp('无效输入,请输入 0-180 之间的角度');
             continue;
         end
    
         % 设置伺服电机位置
         position = angle / 180; % 将角度转换为 [0, 1] 范围
         writePosition(s, position);
    
         % 读取当前角度
         currentPosition = readPosition(s);
         currentAngle = currentPosition * 180;
         fprintf('当前角度:%.1f°\n', currentAngle);
     end

    catch
    % 清理
    clear s;
    clear a;
    disp('程序结束');
    end

3 小车行走控制代码

用键盘来选择前进后退。

由于两个轮子是相对安装的,给同一个增量值时,它们的转向是反向的。因此,我们需要在代码中对左右电机的增量值进行反向处理。

具体代码如下:

复制代码
% MATLAB 代码:控制小车行驶
clear
% 创建 Arduino 对象
a = arduino('COM5', 'Uno'); % 根据实际情况修改 COM 端口

% 定义电机零转速
leftMotorZero = 0.55; % 左电机零转速
rightMotorZero = 0.51; % 右电机零转速

% 创建伺服电机对象(用于生成 PWM 信号)
leftMotor = servo(a, 'D10'); % 左电机连接到 D10
rightMotor = servo(a, 'D11'); % 右电机连接到 D11

% 初始化电机速度
writePosition(leftMotor, leftMotorZero); % 左电机停止
writePosition(rightMotor, rightMotorZero); % 右电机停止

% 主循环
disp('控制小车行驶:');
disp('1 - 前进');
disp('2 - 后退');
disp('3 - 左转');
disp('4 - 右转');
disp('0 - 停止');
disp('q - 退出');

try
    while true
        % 获取用户输入
        command = input('请输入命令:', 's');

        % 根据命令控制小车
        switch command
            case '1' % 前进
                % 左电机正转,右电机正转(增量值反向)
                writePosition(leftMotor, leftMotorZero + 0.1); % 左电机正转
                writePosition(rightMotor, rightMotorZero - 0.1); % 右电机正转
                disp('小车前进');

            case '2' % 后退
                % 左电机反转,右电机反转(增量值反向)
                writePosition(leftMotor, leftMotorZero - 0.1); % 左电机反转
                writePosition(rightMotor, rightMotorZero + 0.1); % 右电机反转
                disp('小车后退');

            case '3' % 左转
                % 左电机反转,右电机正转(增量值反向)
                writePosition(leftMotor, leftMotorZero - 0.1); % 左电机反转
                writePosition(rightMotor, rightMotorZero - 0.1); % 右电机正转
                disp('小车左转');

            case '4' % 右转
                % 左电机正转,右电机反转(增量值反向)
                writePosition(leftMotor, leftMotorZero + 0.1); % 左电机正转
                writePosition(rightMotor, rightMotorZero + 0.1); % 右电机反转
                disp('小车右转');

            case '0' % 停止
                writePosition(leftMotor, leftMotorZero); % 左电机停止
                writePosition(rightMotor, rightMotorZero); % 右电机停止
                disp('小车停止');

            case 'q' % 退出
                break;

            otherwise
                disp('无效命令');
        end
    end
catch
    % 清理
    writePosition(leftMotor, leftMotorZero); % 左电机停止
    writePosition(rightMotor, rightMotorZero); % 右电机停止
    clear leftMotor rightMotor a;
    disp('程序结束');
end

结果

能按照要求做基本的控制,只是没有做运动学关系的控制,因为我的小车没有速度反馈。

把小车立起来调试,结果表明可以实现小车前进后退和转向控制。实际使用时,可以在电机输出部分做一个斜坡,避免速度突变。

相关推荐
西岸行者6 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意6 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码6 天前
嵌入式学习路线
学习
毛小茛7 天前
计算机系统概论——校验码
学习
babe小鑫7 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms7 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下7 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。7 天前
2026.2.25监控学习
学习
im_AMBER7 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
CodeJourney_J7 天前
从“Hello World“ 开始 C++
c语言·c++·学习