Hello, I am sending an instruction set from MATLAB to an Arduino that tells it which port number on the Arduino to activate (DIGITAL LOW), when to activate it, and how long to keep it activated for (there is also a section that controls a conveyor, but it only runs once and I have not had issues there). The Arduino side of the code, I got some fantastic help on this forum by a poster that responded to my previous (and first) question on here.
There is something weird going on with my serial communication between MATLAB and the Arduino, and after trying many different debugging steps, I cannot figure out what it is. Basically the weird part is that it sometimes works and it sometimes does not, and the issue never happens when running the program for the first time. Below, I am posting the Arduino code, and followed by that I am posting a sample MATLAB code that demonstrates what the issue is, while keeping it short enough such that anyone not familiar with MATLAB will get a pretty clear idea of what's going on. 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 debugging steps I have tried / issues I have tried to think about:
-
Maybe MATLAB is sending the data too fast to the Arduino (though the baud rate is specified on both ends), so I put in a pause, first of 0.5 seconds, then later of 1 second, after every time MATLAB sends instructions (writeline function).
-
Maybe the serial buffer is overflowing, but 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 with the pauses attempted in number 1, before the next one is received, so we never get to 64 bytes
-
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 changed the Arduino out, and got the same results
-
I had MATLAB display for me every instruction set it sends, and it was as expected
-
Just for reference to see how MATLAB is sending the data, here is documentation on the writeline function, which writes data to serial ports. There is nothing that jumps out to me as the data size being anything unexpected --- further, it actually works, it just randomly stops working
Please let me know if anyone has any thoughts on this? Thanks!
Arduino Code
const byte pins [] = {2, 5, 6, 7};
const byte conveyorpin = 3;
char conveyorstring[8];
char speedchar[2];
const int Npin = sizeof(pins);
int speed;
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);
}
}
// 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);
}
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;