MATLAB - Arduino Uno Serial Communication Issue

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:

  1. 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).

  2. 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

  3. 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.

  4. I changed the Arduino out, and got the same results

  5. I had MATLAB display for me every instruction set it sends, and it was as expected

  6. 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;

strncpy() is your friend here

Write is out of bounds. You can only write to 0..7. After this, ALL bets are off

If there are any spurious chars left in your input buffer, Serial.readBytesUntil() will timeout yet you process it anyway. Much, much better to know you have received an entire line before processing Serial Input Basics - updated

You might want to consider sending all your data a comma separated values and then parsing them with strtok(). Again, probably more reliable.

Thanks for the response blh64

Responding off of my phone and will try messing with this more from my computer.

I hadn’t included that I can send two types of instructions as the other type of instruction is not in the MATLAB code sample I posted - sorry for any confusion. They are: 1) the character array “Conveyor” followed by a duty cycle for the prespecified PWM pin a conveyor is connected to (for example: “Conveyor 255” will run the applicable PWM Pin at a 100% duty cycle) OR - 2) The instruction set I described in my question.

The thing is I haven’t had an issue of the code entering the wrong part of the if statement. Rather, my issue is that after the Arduino “stops responding” - it’s not even entering the Serial.Available() as discovered by a serial.println debugging statement I placed there. I definitely see your point about potential spurious inputs, however it’s not taking any inputs after it stops working it seems. Further as far as spurious inputs - the write line function from MATLAB automatically appends a line ending at the end of all data, and with the Serial.ReadBytesUntil() function, and because data is programmatically sent, I shouldn't have a start character issue

I will certainly look into your suggestion of strtok(), I used that previously before switching to sscanf, but as of right now- it seems before it gets to data parsing, it’s something with the input buffer. Two questions for you:

  • Could you elaborate on the 0-7 being the limits for the write? The data I’m sending is all more than 9 characters (8 index points), and it is the index number 8 in the array which I try to put in the NULL character to use the strcmp()

  • I reread through the serial input tutorial. The confusion I came away with is that when he’s reading ASCII data in the last Example, he’s comparing his strings to the ASCII values. MATLAB’s writeline function writes ASCII values to the serial port, but this entire time I have been comparing characters not their ASCII values. But then I begin to wonder, why does it work in the first place? Before my error begins, the conveyor and relay pins work as expected

Thanks again for taking the time to look at this!

Valid array indices are 0 to 7 (8 elements, which would include the terminating zero byte of a valid C-string).

In other words, the above reserves space for seven ASCII characters plus the terminating zero byte.

Hi jremington,

Thanks for taking the time to respond

So the command I am looking to compare in the strcmp function is to check if the first seven characters of my command are the string "Conveyor". So does this mean that line I have

conveyorstring[8] = '\0';

is unnecessary as the 8th index position already has the NULL character? And me attempting to write to it, is what is making, as blh64 pointed out, a situation where all bets are off.

I can certainly take that out, and part of me is thinking that perhaps some error that happened while the out of bounds write happened, is causing the program to malfunction on the next loop. However, would it be possible that the malfunction is so that it's not even showing something available in the serial port?

Thanks!

This
char conveyorstring[8];
allocates space for 8 bytes. They are accessed with an index that runs from 0 to 7.
This
conveyorstring[8] = '\0';
places a byte, 0x00, at the next location beyond those allocated for the string. That space will likely belong to some other variable, but you have no way of knowing which one, or what effect that overwrite may have.
Does that make it more clear?

Quite possibly, this is not the source of that problem, but it is most certainly incorrect, and will definitely cause problems. Often, resolving these "unrelated" problems result in behaviour that is more easily recognized for what it is, and what it is caused by.
By the way,

check if the first seven characters of my command are the string "Conveyor".

No, because the first seven characters will only be "Conveyo". That may seem like a nitpick, but your wording may be revealing a residual miscomprehension of the issue, so I'm pointing it out. Clear and consistent communication by all participants in a thread usually results in more swiftly resolving the core issue.

Good thinking.

is unnecessary as the 8th index position already has the NULL character

No, the contents of the "8th index position" are unpredictable, and that memory is probably used for something else.

You MUST make sure that the zero byte is present, or other errors will occur. Most people either make the array a few bytes larger than necessary, and/or are extremely careful never to write outside of the array bounds.

Does that make it more clear?

Thank you --- Yes this cleared it up, I was declaring the size as if I had to specify the index it goes up to, not the actual length of the string. In this instance, I was treating

char conveyorstring[8]

as something that would give me 9 spaces, which is not the case. Thanks for clearing this up. I will fix this and try on my hardware within the next 1-2 days. I am hoping my out of bounds write was happening on memory space allocated for the serial input buffer or something, and after I wrote enough instructions, it was not taking more. Wishful thinking....

Clear and consistent communication by all participants in a thread usually results in more swiftly resolving the core issue.

Agreed --- I meant to write seven characters again in terms of "upto index # 7", but even reading one day later, me the author would be confused by that. It's been a long time since I used C, which was brief to begin with, and since then most of my use has been of MATLAB (where size and index match), so it seems I am "half-adapting".... thanks for pointing it out

Thanks! Cleared up the concept on the out of bounds write, I kept jumping back and forth between the size & index value. I will fix the declaration and try this again on my hardware soon and write on here if it solved the issue. Thanks again for taking the time to look at this

Hi All,

I tried increasing the array size of the "conveyorstring" variable to see any difference. Unfortunately it did not cause a difference. I also completely commented it out just to see, and it did not work. For reference, the amended arduino code is pasted below. The only change is the increased size (I did more than one spot just to have some extra space) and commented the code so that only the Serial.println that shows if serial buffer was detecting the data prints (though of course it does not really matter I take them out):

Serial.println("Serial received");

On the MATLAB code, after every writeline function, I added a

pause(0.1)
readline(s)

Readline reads the same thing that Arduino's Serial Monitor displays. I am not sure that the pause is necessary, but just incase MATLAB goes to read the readline faster than the data is transmitted.

One thing I noticed is, that upon executing the MATLAB function, the first go around works just fine. On the second go around, the erratic behavior starts again, but the constant is that it never entered the Serial.available loop. Meaning, MATLAB is sending data, and somehow the relays are activating without a pattern without actually entering the Serial.available loop.

Please let me know if anyone has any idea on what could be going on

Thanks!

Arduino Code:

const byte pins [] = {2, 5, 6, 7};
const byte conveyorpin = 3;
char conveyorstring[10];
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) {
	Serial.println("Serial received");
        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);


   
}

You should really check out: Serial Input Basics - updated - #3 by Robin2

Also, you are not testing to see that you have received a valid pin # so your code will change any pin.

Check this out: relays - Wokwi ESP32, STM32, Arduino Simulator

Hi blh64,

Thanks for the response again, and for setting up the Wokwi project. When I first saw your post, I didn't realize that you had actually written the code in the simulator to try, I thought it was just a link to the Wokwi tool as a resource. I had used it at the very beginning of this project, but not for the existing code I have currently, so before coming back to the forum, I was trying to simply run that existing code on the simulator, and I am unable to reproduce the error I get in real life. While there can be a big difference in me typing the instructions in the Serial Monitor on Wokwi, and MATLAB programmatically writing to the serial port, maybe it's still insight?

I will try your code on the actual hardware likely by tomorrow or day after and see if it works.

I also rewrote my code using strtok() as you mentioned in your first post for reliability, and on the simulator - works, but on the hardware - same issues.

Finally, as far following Robin2's example#4, theoretically is there any reliability difference between

Serial.readBytesUntil()

and the method in that example? Of course I will be trying your code on hardware so we can see if it makes any difference.

For the pins, the exact array declared at the beginning of the code is a copy of the array MATLAB has available to send from - so that's why I was not checking

I tried a variety of other troubleshooting steps, I am posting them in my next post.

Thanks!

const byte pins [] = {2, 5, 6, 7};
const byte conveyorpin = 3;
char conveyorstring[10];
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) {
	      Serial.println("Serial received");
        char buf [80];
        const char delim[] = {' '};
        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{
        char *portion1 = strtok(buf,delim);
        pin = atoi(portion1);
        char *portion2 = strtok(NULL,delim);
        msecStart = atol(portion2);
        char *portion3 = strtok(NULL,delim);
        msecDuration = atol(portion3);
        //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);


   
}

Hi All,

I tried a few other troubleshooting steps. Out of all of them, writing two that give any new insight. Let me know if this gives any ideas:

  • In case of something weird happening (spurious characters in serial input, etc), I rewrote the MATLAB code such that after sending the data to the Arduino, wait a bit, and read the two lines I was having the Arduino print: 1) It received the data, and 2) How many bytes are sitting in the serial port, just to see if anything gets leftover and it crosses 64. Nothing unexpected, and as usual when the program stops working, the Arduino does not enter the loop under:

if Serial.available() > 0

  • Only interesting thing was, that if I waited a few minutes between executing the MATLAB script, then the error disappeared. So maybe it's something about the way MATLAB is setting up the serial connection to the Arduino ("desperation explanations"). So I wrapped the MATLAB function in a for loop that iterates 10 times without setting up a new serial connnection or clearing it. It worked six times before cutting off. What was interesting was what the Arduino printed when it entered its loop against the sixth iteration from MATLAB, following which it stopped working. I have attached screenshot of our MATLAB "Serial monitor" on the sixth iteration. Note, the outputs follow this format, first it prints "Serial received", next it prints the number of bytes sitting there.

  • Thought exercise: The Arduino is not powering the Songle brand Relays, only the inputs. I read logic input current is 2-4 mA. Having multiple relays on, and before when I used to have the conveyor one on (20 mA current to a VFD), I don't think I have enough current demand to cause issues on the hardware. Let me know if this sounds right.

Arduino & MATLAB codes below - barely any changes except what is described

Arduino:

const byte pins [] = {2, 5, 6, 7};
const byte conveyorpin = 3;
char conveyorstring[10];
char speedchar[2];
const int  Npin = sizeof(pins);
int speed;
int bytecount = 0;

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) {
	Serial.println("Serial received");
        delay(64);
        bytecount = Serial.available();
	Serial.println(bytecount);
        char buf [80];
        const char delim[] = {' '};
        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{
        char *portion1 = strtok(buf,delim);
        pin = atoi(portion1);
        char *portion2 = strtok(NULL,delim);
        msecStart = atol(portion2);
        char *portion3 = strtok(NULL,delim);
        msecDuration = atol(portion3);
        //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);
for i = 1:10
% % Define the instruction set (relay, activation time, and duration)
relayPin = 2; % Example: Control relay on pin 
relayPin = num2str(relayPin);
activationTime = 500; % Activation time in milliseconds 
activationTime = num2str(activationTime);
%activationTime = activationTime*1000;
duration = 10; % Duration in milliseconds 
duration = num2str(duration);
%duration = duration*1000;

% 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);
pause(0.5);
readline(s)
readline(s)

% % Define the instruction set (relay, activation time, and duration)
relayPin = 5; % Example: Control relay on pin 
relayPin = num2str(relayPin);
activationTime = 2000; % Activation time in milliseconds 
activationTime = num2str(activationTime);
%activationTime = activationTime*1000;
duration = 10; % Duration in milliseconds 
duration = num2str(duration);
%duration = duration*1000;

% 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);
pause(0.5);
readline(s)
readline(s)

% % Define the instruction set (relay, activation time, and duration)
relayPin = 7; % Example: Control relay on pin 
relayPin = num2str(relayPin);
activationTime = 4000; % Activation time in milliseconds 
activationTime = num2str(activationTime);
%activationTime = activationTime*1000;
duration = 10; % Duration in milliseconds 
duration = num2str(duration);
%duration = duration*1000;

% 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);
pause(0.5);
readline(s)
readline(s)

% % Define the instruction set (relay, activation time, and duration)
relayPin = 5; % Example: Control relay on pin 
relayPin = num2str(relayPin);
activationTime = 4000; % Activation time in milliseconds 
activationTime = num2str(activationTime);
%activationTime = activationTime*1000;
duration = 10; % Duration in milliseconds 
duration = num2str(duration);
%duration = duration*1000;

% 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);
pause(0.5);
readline(s)
readline(s)
end


% Close the serial port when done
pause(5)
clear s;
clear all;

Yes, the Serial class has a timeout which defaults to 1000 milliseconds so that function will wait a maximum of 1 second before returning, possibly without finding the ending char. Robin's example will wait indefinitely for the ending char.

How is everyting wired up? Are the grounds connected? You could be having a power issue.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.