MATLAB Arduino Uno Serial Communication Issue (writeline)
18 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
Hi folks,
I have a strange issue using serial communication between MATLAB - Arduino (an Arduino Uno), where it works.... until it doesn't. I posted a question about this on the Arduino forums too, but posting here as well to comment more on the MATLAB side of things, and of course if anyone is also familiar with Arduinos, then both!
Below, I am posting the MATLAB code (shortened sample - where the issue is reproduced), and followed by that I am posting an Arduino code that demonstrates what the issue is. In this instance, MATLAB sends four instructions, first one, later another one, and lastly two together (for two separate ports). What is happening is that I can run the MATLAB code once, and everything works as expected. Then the next time I run it, the Arduino will only respond to the first instruction, and nothing else. I could run it again, and it may still not work. Then I could run it again, and it works. It continues to follow this pattern erratically. Just a note, the writeline function is configured to have a endline character at the end of any string sent. Here are some of the debugging steps (MATLAB side) I have tried / issues I have tried to think about:
- Writeline sends ASCII data, and generally one character is one byte. The Arduino serial buffer can hold 64 bytes. My instruction sets are one character for a relay pin, max four characters for activation time, and four characters for the duration. There are two spaces in between. Each instruction is definitely processed, especially because I tried debugging with a pause(0.5) after each writeline, before the next one is received, so we never get to 64 bytes. It is indeed the case that with a longer pause, it atleast seemed that the issue happened after more runs of the code
- On the Arduino side of things, I put in a Serial.println statement right at the beginning of the serial.available loop, just to see that whenever the issue occurs, is it even entering the loop? ---- therein lies the issue somewhere, it is not entering when the issue starts. So something about the serial data not being stored in the Serial buffer. That could be a MATLAB - Arduino serial connection issue, but then the error pattern, as erratic as it is, is still too specific for that. The issue never happens the first time, and in many cases - the first several times --- I try to run the program.
- I had MATLAB display for me every instruction set it sends, and it was as expected
Thanks in advance for looking at this!:
MATLAB Code:
% Define the COM port and communication settings
comPort = 'COM4'; % Replace 'COMX' with your Arduino's COM port
baudRate = 9600;
% Create a serial port object
s = serialport(comPort, baudRate);
pause(5);
% % Define the instruction set (relay, activation time, and duration)
relayPin = 2; % Control relay on pin 2
relayPin = num2str(relayPin);
activationTime = 500; % Activation time in milliseconds
activationTime = num2str(activationTime);
duration = 250; % Duration in milliseconds
duration = num2str(duration);
% Create the instruction string with the relay, activation time, and duration
instruction = horzcat(relayPin,' ',activationTime,' ',duration);
% Send the instruction to the Arduino
writeline(s,instruction);
% % Define the instruction set (relay, activation time, and duration)
relayPin = 5; % Control relay on pin 2
relayPin = num2str(relayPin);
activationTime = 4000; % Activation time in milliseconds
activationTime = num2str(activationTime);
duration = 250; % Duration in milliseconds
duration = num2str(duration);
% Create the instruction string with the relay, activation time, and duration
instruction = horzcat(relayPin,' ',activationTime,' ',duration);
% Send the instruction to the Arduino
writeline(s,instruction);
% % Define the instruction set (relay, activation time, and duration)
relayPin = 6; % Example: Control relay on pin 2
relayPin = num2str(relayPin);
activationTime = 7000; % Activation time in milliseconds
activationTime = num2str(activationTime);
duration = 250; % Duration in milliseconds
duration = num2str(duration);
% Create the instruction string with the relay, activation time, and duration
instruction = horzcat(relayPin,' ',activationTime,' ',duration);
% Send the instruction to the Arduino
writeline(s,instruction);
% % Define the instruction set (relay, activation time, and duration)
relayPin = 5; % Example: Control relay on pin 2
relayPin = num2str(relayPin);
activationTime = 7000; % Activation time in milliseconds
activationTime = num2str(activationTime);
duration = 250; % Duration in milliseconds
duration = num2str(duration);
% Create the instruction string with the relay, activation time, and duration
instruction = horzcat(relayPin,' ',activationTime,' ',duration);
% Send the instruction to the Arduino
writeline(s,instruction);
% Close the serial port when done
clear s;
clear all;
Arduino Code (Was able to create it thanks to a very helpful poster on Arduino Forums)
const byte pins [] = {2, 5, 6, 7};
const byte conveyorpin = 3;
char conveyorstring[8];
char speedchar[2];
const int Npin = sizeof(pins);
int speed;
float dutycycle;
int roundeddutycycle;
struct Instr {
int state;
int pin;
unsigned long msecStart;
unsigned long msecStop;
};
const int Ninstr = 30;
Instr instr [Ninstr] = {}; // initialize all fields to zero
enum { Available = 0, InUse, Set }; // Available (0) will be default value
enum { Off = HIGH, On = LOW };
char s [80]; // for use with sprintf()
// -----------------------------------------------------------------------------
void
addInstr (
int pin,
unsigned long msecStart,
unsigned long msecStop )
{
sprintf (s, "addIntr: pin %d, %lu start, %lu stop",
pin, msecStart, msecStop);
Serial.println (s);
for (int i = 0; i < Ninstr; i++) {
if (Available == instr [i].state) {
instr [i].state = InUse;
instr [i].pin = pin;
instr [i].msecStart = msecStart;
instr [i].msecStop = msecStop;
return;
}
}
Serial.println ("addIntr: none available");
}
// -----------------------------------------------------------------------------
void loop ()
{
unsigned long msec = millis ();
if (Serial.available () > 0) {
char buf [80];
int n = Serial.readBytesUntil ('\n', buf, sizeof(buf)-1);
buf [n] = '\0';
int pin;
unsigned long msecStart;
unsigned long msecDuration;
for (int j = 0;j<8;j++){
conveyorstring[j]=buf[j];
}
conveyorstring[8] = '\0';
if (strcmp(conveyorstring,"Conveyor") == 0){
sscanf(buf, "Conveyor %d", & speed);
analogWrite(conveyorpin,speed);
}else{
sscanf (buf, "%d %ld %ld", & pin, & msecStart, & msecDuration);
addInstr (pin, msec + msecStart, msec + msecStart + msecDuration);
}
//memset(conveyorstring,0,sizeof(conveyorstring));
}
// Check and execute relay instructions
for (int i = 0; i < Ninstr; i++) {
switch (instr [i].state) {
case InUse:
if (msec >= instr [i].msecStart) {
instr [i].state = Set;
digitalWrite (instr [i].pin, On);
sprintf (s, "loop: set pin %d", instr [i].pin);
Serial.println (s);
}
break;
case Set:
if (msec >= instr [i].msecStop) {
instr [i].state = Available;
digitalWrite (instr [i].pin, Off);
sprintf (s, "loop: clear pin %d", instr [i].pin);
Serial.println (s);
}
break;
}
}
}
// -----------------------------------------------------------------------------
void setup () {
Serial.begin (9600);
for (int i = 0; i < Npin; i++) {
pinMode (pins[i], OUTPUT);
digitalWrite (pins[i], Off);
}
pinMode(conveyorpin,OUTPUT);
}
0 comentarios
Respuestas (1)
Yamilet
el 11 de Nov. de 2023
% Define the COM port and communication settings
comPort = 'COM4'; % Replace 'COMX' with your Arduino's COM port
baudRate = 9600;
% Create a serial port object
s = serialport(comPort, baudRate);
pause(5);
% % Define the instruction set (relay, activation time, and duration)
relayPin = 2; % Control relay on pin 2
relayPin = num2str(relayPin);
activationTime = 500; % Activation time in milliseconds
activationTime = num2str(activationTime);
duration = 250; % Duration in milliseconds
duration = num2str(duration);
% Create the instruction string with the relay, activation time, and duration
instruction = horzcat(relayPin,' ',activationTime,' ',duration);
% Send the instruction to the Arduino
writeline(s,instruction);
% % Define the instruction set (relay, activation time, and duration)
relayPin = 5; % Control relay on pin 2
relayPin = num2str(relayPin);
activationTime = 4000; % Activation time in milliseconds
activationTime = num2str(activationTime);
duration = 250; % Duration in milliseconds
duration = num2str(duration);
% Create the instruction string with the relay, activation time, and duration
instruction = horzcat(relayPin,' ',activationTime,' ',duration);
% Send the instruction to the Arduino
writeline(s,instruction);
% % Define the instruction set (relay, activation time, and duration)
relayPin = 6; % Example: Control relay on pin 2
relayPin = num2str(relayPin);
activationTime = 7000; % Activation time in milliseconds
activationTime = num2str(activationTime);
duration = 250; % Duration in milliseconds
duration = num2str(duration);
% Create the instruction string with the relay, activation time, and duration
instruction = horzcat(relayPin,' ',activationTime,' ',duration);
% Send the instruction to the Arduino
writeline(s,instruction);
% % Define the instruction set (relay, activation time, and duration)
relayPin = 5; % Example: Control relay on pin 2
relayPin = num2str(relayPin);
activationTime = 7000; % Activation time in milliseconds
activationTime = num2str(activationTime);
duration = 250; % Duration in milliseconds
duration = num2str(duration);
% Create the instruction string with the relay, activation time, and duration
instruction = horzcat(relayPin,' ',activationTime,' ',duration);
% Send the instruction to the Arduino
writeline(s,instruction);
% Close the serial port when done
clear s;
clear all;
Ver también
Categorías
Más información sobre MATLAB Support Package for Arduino Hardware en Help Center y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!