要点
项目需求:MATLAB向arduino发送亮度和闪烁间隔的信息,arduino控制LED以该亮度和间隔闪烁。
硬件方面就是arduino连一个l298n模块驱动LED,用串口连接电脑。
关于MATLAB扩展包:MATLAB的arduino扩展包可以直接在MATLAB里面写arduino的函数,比如digitalWrite什么的。就好像是给MATLAB外接了一个硬件扩展。如果只是单纯串口通信,则不需要装这个包。
arduino端代码
//2023.4.5
String input = ""; //存储接收的数据,格式,I+间隔L+亮度,ex:‘I60L100’
int luminance = 50; //亮度,0~255,相对亮度,0为灭
int interval = 0; //闪烁间隔,0~∞ ms
//9-12脚为驱动器提供信号,其中9,12作为灯的负极,10,11作为正极
//通过调节正极电压控制相应灯亮度,给引脚起个对应的名字
const int led1 = 10;
const int led2 = 11;
void setup() {
// 初始化设置,只运行一次
//引脚初始化
input.reserve(200);
pinMode(9, OUTPUT);
pinMode(12, OUTPUT);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
digitalWrite(9, LOW);
digitalWrite(12, LOW);
//串口通信初始化
Serial.begin(9600);
Serial.setTimeout(10);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
}
void loop() {
//串口接收程序
//如果串口收到数据,把数据存入input
if (Serial.available() > 0) {
input = "";
while (Serial.available() > 0) {
char inChar = (char)Serial.read();
input += inChar;
delay(2);
}
//在收到的input字符串里搜索I L字符的位置,位置信息分别存到两个index变量里
int indexI = input.indexOf('I');
int indexL = input.indexOf('L');
//根据位置,从’input’字符串里抽取interval和luminance的值分别转成int型,存到对应变量里
String Cinterval = input.substring(indexI + 1, indexL);
String Cluminance = input.substring(indexL + 1, input.length());
interval = Cinterval.toInt();
luminance = Cluminance.toInt();
}
//亮灯程序
//如果interval是0,直接设置灯的正极为对应luminance值,即灯常亮
if (interval == 0) {
analogWrite(led1, luminance);
analogWrite(led2, luminance);
}
//设置灯的正极为对应luminance值,另一个为0(灭),并在interval ms后反转,即灯交替闪烁
else {
analogWrite(led1, luminance);
analogWrite(led2, 0);
delay(interval);
analogWrite(led1, 0);
analogWrite(led2, luminance);
delay(interval);
}
}
在初始化的时候,有一句Serial.setTimeout(10); 是设置arduino收到消息后等待的时间。之前有一个项目需要高刷新率的串口通信,但发现arduino在收到数据后都会顿一下再进行下一步动作。这是arduino默认设置等待下一消息的时间比较长,而且在这段时间内他就等着,别的什么都不干。
MATLAB端代码
MATLAB2018版本后串口函数有一些改动,使用时候注意一下版本,要不然会疑惑到抓狂。
%%
% MATLAB2018前
% 这些放在程序开头执行一次即可
freeports = serialportlist("available");%自动搜索可用端口
arduino=serialport(freeports,9600);%建立端口对象,通信比特率9600
fopen(arduino);%打开端口,打开后可以一直用
pause(2);
% 发送格式:I+闪烁间隔,取值0 ~ +∞,单位ms;L+亮度,取值0 ~ 255,相对亮度
fprintf(arduino,'I60L150');%间隔60ms,亮度150
%放在程序结束时,关闭串口,否则下次运行程序会打不开串口
delete(arduino);%关闭串口
%%
%MATLAB2018后
s = serialport("COM3",9600);
pause(1.8);
%write(s, 'c', "char");
%data = readline(s);
flush(s,"output");
writeline(s,"I60L150");
% Flush output buffer
flush(s,"output");
writeline(s,"I0L0");
% Disconnect and clear serialport connection
delete(s);
clear s;