Advice needed for most efficient way to parse a byte array

This is basically my first post on the Arduino forum so hello everyone. I am currently working on my first Arduino project and have come to a point where my head is a bit spinning, too many ways to do something. So I am looking for some suggestions on the most efficient way to send and receive byte arrays to and from the Nano and PC.

Background:
Project is a coil winder using 2 stepper motors (winder & carriage), 2 x TB6600's, USB port, C# PC program for the grunt work, Arduino Nano (old bootloader), AccelStepper library.
There are 2 arrays going to the Nano and 1 coming back to the PC. The 3 arrays are Settings, Commands, and Indicators. I want to keep everything or as much as I can as simply as possible for others to use my project.

What I've done so far:
I've read all the basic serial stuff, read the more advanced stuff, researched on here and the internet and have come up with a mish-mash of ideas. I know that C# and the Nano transmit the ASCII byte values as integers and each converts them into characters for representation.

Main problem: Parsing the bytes.
My basic program flow; do all the heavy calculations on the PC, send those calculations(Settings to the Nano), jog the carriage into position and set the home location, start the coil build and have the Nano report on it's status/progress as the Indicator array. Speed of communications is NOT a major factor because the Nano will be handling the actual coil build. The arrays will be like this below:

Start of string, either - setting (S) or command (C) or indicator (I) char, data, end of string. All coma delimited.

Settings:
string StartS = "<";
string Sts = "S";
string strPPR_WindingM;
strPPR_WindingM = Convert.ToString(PPR_WindingM);
string EndS = ">";

String unicodeString = StartS + "," + Sts + "," + strPPR_WindingM + "," + dblPPR + "," + PPWind + "," + WPLayer + "," + STEP_RATIO + "," + PPLayer + "," + Speed + "," + Accel + "," + radBtnDir + "," + EndS;

For a total of 38 bytes.

Commands:
string StartS = "<";
string CMD = "C";
string strCarLEFT;
strCarLEFT = "Lft";
string EndS = ">";

//prep byte string
String unicodeString = StartS + "," + CMD + "," + strCarLEFT + "," + EndS;

Total of 9 bytes per separate command which is sent one command at a time as needed.

Indicators to PC:
LED Left, LED Right, LED Paused, LED Home Set, WINDER PULSE, CARRIAGE PULSE, WORKING ON WINDING #, WORKING ON LAYER #

-mixed binary like string.
eg. I,100111,######,###

So what I mainly need to do is to determine is the incoming data is a Setting or a Command. If a setting then store these values including the home position (command). Commands are mostly do until (Jogging). I have looked into and tried the strtok method a couple of different uses anyway. I was thinking of using a 'if' statement for the 'S'/'C' part and a switch statement for the 'C' commands part.

This code seems promising:

char* subStr (char* input_string, char *separator, int segment_number)
{
char *act, *sub, *ptr;
static char copy[100];
int i;

strcpy(copy, input_string);
for (i = 1, act = copy; i <= segment_number; i++, act = NULL)
{
sub = strtok_r(act, separator, &ptr);
if (sub == NULL) break;
}
return sub;
}

All suggestions welcome on making an efficient byte array parse. Thank you in advance. I hope I gave enough info.

Ray

P.S. I have found that setting the COM in C# to Xon/Xoff the fastest and no programming of wait states. This is really weird.

Xon/Xoff is a bilateral protocol, you can't use it only on one side.

Is your data just a comma separated string? It is ridiculous to concatenate all that stuff using the String class when you can just send it out sequentially. The String class is notorious for crashing small processors like the Arduino.

You can not return sub; it's a local parameter that vanishes when the function subStr returns and can be overwritten at anytime after that. You can make sub static which will solve that problem.

The updated serial input basics thread will show you how you can use nul-terminated character arrays (including use of startmarker and endmarker); just make the array big enough to hold the maximum text plus one character (nul-terminator).

aarg:
Xon/Xoff is a bilateral protocol, you can't use it only on one side.

I know and that's the weird part. I'm not sure if it has something to do with either the FTDI or C#/Windows 10 USB hardware layer. DTE & RTS are off also, 115200 8N1 also.

aarg:
Is your data just a comma separated string? It is ridiculous to concatenate all that stuff using the String class when you can just send it out sequentially. The String class is notorious for crashing small processors like the Arduino.

Yes it is a string. So far with all my testing it seems fine. The actual bytes sent for the settings transfer looks like this:
String out:
<,S,800,800,143,218,6,31174,650,400,,>

ASCII bytes out:
[60][44][83][44][56][48][48][44][56][48][48][44][49][52][51][44][50][49][56][44][54][44][51][49][49][55][52][44][54][53][48][44][52][48][48][44][44][62]

When I send the command to jog left:
String unicodeString = StartS + "," + CMD + "," + strCarLEFT + "," + EndS

I get this going out.
Text string out:
"<,C,Lft,>"

ASCII bytes out :
[60][44][67][44][76][102][116][44][62]

Received from Nano:
C Lft

Which is correct but, that is just using a simple send-back-what-it-sees routine.

Ray

Surely you can see the danger of using xon/xoff unilaterally... if an xoff is received, communications will permanently freeze.

If you use Xon/Xoff, the Arduino should send those characters; the PC should have the protocol enabled and basically adhere to it without you having to interfere in code at the PC side.

For short messages like yours, Xon/Xoff should not be needed. It's used to slow the transmission down when e.g. the buffer in a printer gets full or writing to EEPROM in an Arduino can't keep up with the receiving of the data.

Also note that you can't use Xon/Xoff in a full binary data stream as the Xon/Xoff bytes can actually be valid data.

A simple way to implement a kind of handshake is to let the receiver echo a received byte; the transmitter is not allowed to send the next byte before the echo is received.

I fully understand what both of you are saying about Xon/Xoff, I've been using serial coms for about 35 years now but, this is my first USB attempt that is mine. I usually use the DB9 serial port. I have used a lot of others(manufacturers) with embedded devices with either serial ports usually DB9 or USB. If I use 9600 to 115200 with DTE & RTS 8N1 no flow control (the usual setup), then I must add a 1.5 sec wait after I open a port and another 0.5 sec. after a serial port write in the C# program, not really acceptable.

If I need to add time to allow a EEPROM transfer that is not a problem. Because of what I'm allowed in C# I prefer to stay with the ASCII bytes.

Anyway, any ideas on parsing bytes, like maybe a byte array?

Ray

Good luck with the serial kludge. It's a little weird that you're asking how to parse a byte array, when you have an example of it in your first post... is there a specific problem or obstacle that is blocking you?

Ray_Richter:
If I use 9600 to 115200 with DTE & RTS 8N1 no flow control (the usual setup), then I must add a 1.5 sec wait after I open a port and another 0.5 sec. after a serial port write in the C# program, not really acceptable.

I assume that the 'wait' is due to the reset of the Arduino. Play with the DTR/RTS settings in your C# code to prevent that. No example at hand ( different PC :frowning: ), I'm reasonably sure that I've done it before.

aarg:
Good luck with the serial kludge. It's a little weird that you're asking how to parse a byte array, when you have an example of it in your first post... is there a specific problem or obstacle that is blocking you?

Yes, but i'm working on it and getting closer. As for the serial kludge it has been my experience with USB serial coms that it's best to be prepared for the stupid, weird, and makes no sense stuff. People are use to the straight forward standard serial port stuff and forget that there are extra hardware/firmware involved that we don't see but must be taken into account.

As I stated in my first post above I need to break the received bytes into 2 cateriorges, Settings and Commands, this is done by parsing the first byte. Settings (variables) are sent once and are the parameters for making the coil. Commands can be sent several times but, only some commands are allowed to be passed to the Nano once the Nano is commanded to start building, ie. terminate build or pause. I have 2 sketches going right now the main program and a test program that was close to working. I have most of my test program working now or did. I just have come up with a way to put the bytes together to form separate string values like these below.

Text string sent:
<S,800,800,143,218,6,31174,650,400,CCW>

Same thing only in ASCII bytes, shown delimited:
[60][83][44][56][48][48][44][56][48][48][44][49][52][51][44][50][49][56][44][54][44][51][49][49][55][52][44][54][53][48][44][52][48][48][44][67][67][87][62]

ASCII integer byte/s is the default format for both serial com ports (C# and Arduino), the conversion to text is done internally by both.

ASCII byte [44] is the comma delimiter, [60] & [62] are the start & end markers. I would post my test code but, I lost it and have to rebuild the semi-working version. So right now or was, at the point where I need to add each byte together until the program see's a comma. In which case the bytes are transferred to a variable and then get the next byte string. So I'm going to have to do a byte stream to delimited string conversion I think.

Ray

sterretje:
I assume that the 'wait' is due to the reset of the Arduino. Play with the DTR/RTS settings in your C# code to prevent that. No example at hand ( different PC :frowning: ), I'm reasonably sure that I've done it before.

Nope the Arduino is fine, it's C# that has the problem with the USB driver. Serial monitor works excellent with no delay problems. I've played with all the parameters that are allowed in C# with no luck. So I just decided "what the hell, I'll give it a stupid try", and it worked, go figure. So I think that either the C#/Windows 10 driver or the Nano FTDI driver has something to do with it, most likely the C#/Windows 10 driver, oh well, it's FM.

Ray

This is the test code I'm modifying, it was written by Robin2.

// adapted from Serial Input Basics
// char data type replaced by byte
const byte numBytes = 32;
byte receivedBytes[numBytes];
byte numReceived = 0;

boolean newData = false;

void setup() {
    Serial.begin(9600);
    Serial.println("<Arduino is ready>");
    Serial1.begin(9600);
}

void loop() {
    recvBytesWithStartEndMarkers();
    showNewData();
}

void recvBytesWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    byte startMarker = 0x80;
    byte endMarker = 0x40;
    byte rb;
   

    while (Serial1.available() > 0 && newData == false) {
        rb = Serial1.read();

        if (recvInProgress == true) {
            if (rb != endMarker) {
                receivedBytes[ndx] = rb;
                ndx++;
                if (ndx >= numBytes) {
                    ndx = numBytes - 1;
                }
            }
            else {
                receivedBytes[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                numReceived = ndx;  // save the number for use when printing
                ndx = 0;
                newData = true;
            }
        }

        else if (rb == startMarker) {
            recvInProgress = true;
        }
    }
}

void showNewData() {
    if (newData == true) {
        Serial.print("This just in ... ");
        for (byte n = 0; n < numReceived; n++) {
            Serial.print(receivedBytes[n], HEX);
            Serial.print(' ');
        }
        Serial.println();
        showGroupsOfBytes();
        newData = false;
    }
}

void showGroupsOfBytes() {
    for (byte n = 0; n < numReceived; n++) {
        Serial.print(receivedBytes[n], HEX);
        Serial.print(' ');
        if ((n + 1) % 5 == 0) {
            Serial.println();
        }
    }
    Serial.println();
}

Ray

As for the serial kludge it has been my experience with USB serial coms that it's best to be prepared for the stupid, weird, and makes no sense stuff. People are use to the straight forward standard serial port stuff and forget that there are extra hardware/firmware involved that we don't see but must be taken into account.

I'm always prepared for unexpected problems. I've seen things that almost made me believe in the supernatural. My idea of "taking them into account" is systematically fixing them. The whole program of engineering is to corral the useless randomness and uncertainty of the universe into reliable patterns that we can depend on.

A fix with no obvious risks would be fine, but using Xon/Xoff is leaving a huge reliability hole in your project. I say this here, not for you, because you don't seem to care. I say it for other people who might read it and think that it's really an adequate fix.

It's the same thing with your use of the String class. There is a long history of problems with it on Arduino platform. Yet, you are completely satisfied with it, just because today it works.

Did you try, "no flow control" on the PC side?

aarg:
It's the same thing with your use of the String class. There is a long history of problems with it on Arduino platform. Yet, you are completely satisfied with it, just because today it works.

The String class is the C# side.

aarg:
I'm always prepared for unexpected problems. I've seen things that almost made me believe in the supernatural. My idea of "taking them into account" is systematically fixing them. The whole program of engineering is to corral the useless randomness and uncertainty of the universe into reliable patterns that we can depend on.

A fix with no obvious risks would be fine, but using Xon/Xoff is leaving a huge reliability hole in your project. I say this here, not for you, because you don't seem to care. I say it for other people who might read it and think that it's really an adequate fix.

It's the same thing with your use of the String class. There is a long history of problems with it on Arduino platform. Yet, you are completely satisfied with it, just because today it works.

Did you try, "no flow control" on the PC side?

aarg I'm sorry if I'm coming across as i don't care but, I do care. In 35 years of programming industrial equipment the standard serial port settings has almost always been 9600, 8N1, and no flow control. I can't ever remember having to use Xon/Xoff to get a reliable fast connection, except for 1 oddball serial modem. I made a serial com form in my C# program that allows the settings to be quickly changed but, I would have to add in the program delays.

serialPort_M.Open();
System.Threading.Thread.Sleep(1500); // wait for USB port to open

serialPort_M.Write(unicodeString);
System.Threading.Thread.Sleep(500); // wait before enabling receive

That code above is a total of a 2 second delay to see what the Arduino sees and that is using 9600 or 115200, 8N1, and no flow control. I have never seen any program having to wait 1.5 seconds to send data.

As for the String class in Arduino I can't say much because I have no experience with it, I hope I don't have problems with it. Mind you I don't know exactly what you mean by the string class, do you mean the String() object? and if so what should I be looking out for?

Ray

Okay, I will re-read the entire thread later and see if I missed anything. It's not clear to me, why a 2 second delay in the PC code startup would ever make any difference - don't you just start the PC app and leave it running? Why would there be any association between PC app startup time and Arduino sketch startup time? Isn't there handshaking between the PC and Arduino to avoid any data loss in communications between them?

You could try lifting the jumper on the Arduino that connects DTR to reset... after you program the sketch. I think that is the cause of the delay.

Anyway, if this aspect isn't your focus right now, it's okay...

Below demo code for a C# console application and matching Arduino code (Serial Input Basics, slightly modified). Tested against a SparkFun RedBoard with FTDI chip as well as an original Uno with 16U2.

C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.IO.Ports;


namespace ArduinoComms
{
    class Program
    {
        static SerialPort _serialPort = new SerialPort();
        static string portName;
        static string message = "<S,800,800,143,218,6,31174,650,400,CCW>";

        static void Main(string[] args)
        {
            if (args.Length != 0)
            {
                portName = args[0];
            }
            else
            {
                Console.WriteLine("Please specify com port");
                Console.ReadLine();
                return;
            }

            Console.WriteLine("Opening port");
            if (connect(portName, false) == false)
            {
                return;
            }
            Console.WriteLine("Port open");


            int cnt = 0;

            char[] received = new char[256];
            if (_serialPort.IsOpen == true)
            {
                DateTime dtStart = DateTime.Now;
                DateTime dtEnd = dtStart;
                while (cnt++ < 10)
                {
                    _serialPort.Write(message);

                    int max = received.Length;
                    int numBytes = 0;

                    try
                    {
                        while (true)
                        {
                            int n = _serialPort.Read(received, numBytes, max - numBytes);
                            numBytes += n;
                            Console.WriteLine("numBytes = {0}", numBytes);
                            if (received[numBytes - 1] == '\n')
                            {
                                break;
                            }
                        }
                        string x = new String(received).Substring(0, numBytes);
                        Console.WriteLine(x);
                        dtEnd = DateTime.Now;

                        Console.WriteLine((dtEnd - dtStart).TotalMilliseconds);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                    Console.Write("Average time: ");
                    Console.Write((dtEnd - dtStart).TotalMilliseconds / 10);
                    Console.WriteLine(" ms");

                }


                _serialPort.Close();
            }

            Console.ReadLine();
        }


        /// <summary>
        /// Open serial port
        /// </summary>
        /// <param name="portName">COMxx</param>
        /// <param name="reset">reset arduino if true</param>
        /// <returns></returns>
        static bool connect(string portName, bool reset)
        {
            try
            {
                _serialPort.PortName = portName;
                _serialPort.BaudRate = 57600;
                _serialPort.DataBits = 8;
                _serialPort.Parity = Parity.None;
                _serialPort.StopBits = StopBits.One;
                _serialPort.Handshake = Handshake.None;
                _serialPort.ReadTimeout = 2000;
                _serialPort.DtrEnable = reset;

                _serialPort.Open();
                Console.WriteLine("{0} opened", portName);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return false;
            }

            return true;
        }
    }
}

You can play with the reset parameter; application requires that you pass the com port as a parameter. Please note that there is no Sleep().

Arduino

// Example 3 - Receive with start- and end-markers

const byte numChars = 128;
char receivedChars[numChars];

boolean newData = false;
const byte ledPin = LED_BUILTIN;


void setup()
{
  Serial.begin(57600);
  //Serial.println("<Arduino is ready>");
  pinMode(ledPin, OUTPUT);
}

void loop()
{
  static uint32_t lastBlinkTime;
  if (millis() - lastBlinkTime >= 350)
  {
    lastBlinkTime = millis();
    digitalWrite(ledPin, !digitalRead(ledPin));
  }
  recvWithStartEndMarkers();
  showNewData();
}

void recvWithStartEndMarkers() {
  static boolean recvInProgress = false;
  static byte ndx = 0;
  char startMarker = '<';
  char endMarker = '>';
  char rc;

  while (Serial.available() > 0 && newData == false) {
    rc = Serial.read();

    if (recvInProgress == true) {
      if (rc != endMarker) {
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars) {
          ndx = numChars - 1;
        }
      }
      else {
        receivedChars[ndx] = '\0'; // terminate the string
        recvInProgress = false;
        ndx = 0;
        newData = true;
      }
    }

    else if (rc == startMarker) {
      recvInProgress = true;
    }
  }
}

void showNewData() {
  if (newData == true) {
    Serial.print("This just in ... ");
    Serial.println(receivedChars);
    newData = false;
  }
}

Code fully based on Serial Input Basics.

I've increased numChars because the message that the C# code sends is bigger than the original 32 bytes.
I've added a blink-without-delay so a board reset can visibly be picked up.

I got it working - yippy

aarg - thank you for your input, I welcome all comments and input, I have learned to listen.

sterretje - also thank you for your input and work. I really didn't expect anyone to go as far as you did. Anyway I got my Arduino code to work parsing the settings & commands now. I really don't know why I had to put threads on hold to get something back from the Nano, I will investigate this more later on. Maybe it's because I'm using a Chinse Nano knock-off. But the chip does say FTDI FT232RL. Also I have the same situation when using my Hp notebook. Would the fact that my Nano has the older bootloader matter?

I'm really disappointed in the reference page for the switch function, it says to use a variable and says nothing about the variable having to be a integer. It seems that they have had years to fix it up.

My Arduino parsing test code:

// Receive with start- and end-markers combined with parsing by Robin2
// Test program parsing for th UMT Coil Winder

const byte numChars = 39;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use by strtok() function

      // variables to hold the parsed data
char message[numChars] = {0};
int integerFromPC = 0;
float floatFromPC = 0.0;

boolean newData = false;

//SETTINGS
String inType = "";   // Type of input
int PPR_WindingM = 0; // Winder Pulses per rev
int PPR_C = 0;        // Carriage Pulses Per rev
long PPWind_C = 0;    // Carriage Pulses Per Winding
int WPLayer = 0;      // WINDINGS PER LAYER
int STEP_RATIO = 0;   // WINDER TO CARRIAGE RATIO
long PLayer_C = 0;    // Carriage steps per layer
int Speed = 0;        // Speed Motors
int Accel = 0;        // Acceleration
int radBtnDir = 0;    // Direction
char ByteToChar = "";

//COMMANDS
String receivedCommand;
int WME = 0;    // Winder Motor Enable
int CME = 0;    // Carriage Motor  Enable
int Lft = 0;    // Left
int Rit = 0;    // Right
int Pas = 0;    // Pause
int Con = 0;    // Continue
int W1r = 0;    // Wind_1_rev
int Sth = 0;    // Set_home
int Str = 0;    // Start
int Stp = 0;    // Terminate/Stop
int Clr = 0;    // Clear


//============

void setup() {
    Serial.begin(115200);
}

//============

void loop() {
    recvWithStartEndMarkers();
    if (newData == true) {
        strcpy(tempChars, receivedChars);
            // this temporary copy is necessary to protect the original data
            //   because strtok() replaces the commas with \0
        parseData();
        newData = false;
    }
}

//============

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;

    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

//============

void parseData() {

      // split the data into its parts
    char * strtokIndx; // this is used by strtok() as an index

    strtokIndx = strtok(tempChars,",");      // get the first part - the string
    strcpy(message, strtokIndx); // copy it to message
          Serial.println(" ");
          Serial.print("message ");
          Serial.println(message);
          Serial.println(" ");
    inType = message;         //char to string
          Serial.print("inType ");
          Serial.println(inType);
          Serial.println(" ");
    if(inType == "S")
    {
      strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
      PPR_WindingM = atoi(strtokIndx);     // convert this part to an integer
      Serial.print("PPR_WindingM ");
          Serial.println(PPR_WindingM);
          Serial.println(" ");

      strtokIndx = strtok(NULL, ",");
      PPR_C = atoi(strtokIndx);
      Serial.print("PPR_C ");
          Serial.println(PPR_C);
          Serial.println(" ");     

      strtokIndx = strtok(NULL, ",");
      PPWind_C = atol(strtokIndx);  // convert this part to a long
      Serial.print("PPWind_C ");
          Serial.println(PPWind_C);
          Serial.println(" ");

      strtokIndx = strtok(NULL, ",");
      WPLayer = atoi(strtokIndx);
      Serial.print("WPLayer ");
          Serial.println(WPLayer);
          Serial.println(" ");

      strtokIndx = strtok(NULL, ",");
      STEP_RATIO = atoi(strtokIndx);
      Serial.print("STEP_RATIO ");
          Serial.println(STEP_RATIO);
          Serial.println(" ");

      strtokIndx = strtok(NULL, ",");
      PLayer_C = atol(strtokIndx);
      Serial.print("PLayer_C ");
          Serial.println(PLayer_C);
          Serial.println(" ");

      strtokIndx = strtok(NULL, ",");
      Speed = atoi(strtokIndx);
      Serial.print("Speed ");
          Serial.println(Speed);
          Serial.println(" ");

      strtokIndx = strtok(NULL, ",");
      Accel = atoi(strtokIndx);
      Serial.print("Accel ");
          Serial.println(Accel);
          Serial.println(" ");

      strtokIndx = strtok(NULL, ",");
      radBtnDir = atoi(strtokIndx);
      Serial.print("radBtnDir ");
          Serial.println(radBtnDir);
          Serial.println(" ");
   }

    if(inType == "C")
    {
      strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
      strcpy(message, strtokIndx);
      
      //strcpy(receivedCommand, strtokIndx);
      //receivedCommand = atoi(strtokIndx);
      String receivedCommand = String(message);
      

      if (receivedCommand == "WME")
        {
          Serial.print("WME ");
          Serial.println(WME);
          //DO SOMETHING
        }
          
      if (receivedCommand ==  "CME")
        {
          Serial.print("CME ");
          Serial.println(CME);
          //DO SOMETHING
        }
        
      if (receivedCommand ==  "Lft")
        {
          Serial.print("Lft ");
          Serial.println(Lft);
          //DO SOMETHING
        }

      if (receivedCommand ==  "Rit")
        {
          Serial.print("Rit ");
          Serial.println(Rit);
          //DO SOMETHING
        }

      if (receivedCommand ==  "Pas")
        { 
          Serial.print("Rit ");
          Serial.println(Rit);
          //DO SOMETHING
        }
      
      if (receivedCommand ==  "Con")
        {
          Serial.print("Con ");
          Serial.println(Con);
          //DO SOMETHING
        }
        
      if (receivedCommand ==  "W1r")
         {
          Serial.print("W1r ");
          Serial.println(W1r);
          //DO SOMETHING
         }
        
      if (receivedCommand ==  "Sth")
         {
          Serial.print("Sth ");
          Serial.println(Sth);
          //DO SOMETHING
         }
        
      if (receivedCommand ==  "Str")
         {
          Serial.print("Str ");
          Serial.println(Str);
          //DO SOMETHING
         }
        
      if (receivedCommand ==  "Stp")
         {
          Serial.print("Stp ");
          Serial.println(Stp);
          //DO SOMETHING
         }
        
      if (receivedCommand ==  "Clr")
         {
          Serial.print("Clr ");
          Serial.println(Clr);
          //DO SOMETHING
         }
   }
   if(inType == "t")
    {
      Serial.print("com test ");
      Serial.println("CONNECTION IS GOOD");
      //DO SOMETHING
    }
}

I tried posting my C# serial com form code but, it says I exceeded the 9000 character rule. I can post it later if you want.

Once again thank you everyone. Now I have some code to merge and clean up.

Ray

There are two reasons why I'm hanging around here; trying to help people and trying to learn. The C# code was both.

I'm always interested in other people's PC code; doesn't matter for which OS and which language.

Your original code possibly did not work due to memory issues; pitty that you never posted it completely. I pointed one out in my first post, there might have been others like buffer overflows.

Your new Arduino code has a receivedChars that's just big enough; not sure if all messages will fit in there. Although I'm against wasting memory, I would play it safe and later reduce if needed.

Next, get rid of that String receivedCommand; one day it will bite you.

    if (receivedCommand == "WME")
    {
      Serial.print("WME ");
      Serial.println(WME);
      //DO SOMETHING
    }

Below is equivalent using the character array that you already have.

    if(strcmp(message, "WME") == 0)
    {
      Serial.print("WME ");
      Serial.println(WME);
      //DO SOMETHING
    }

Lastly, use functions to process the individual inTypes; long functions are a nightmare to maintain. There is a basic rule-of-thumb that you should be able to print a function on a single page of A4 using a standard font size :wink:

sterretje:
2)
I'm always interested in other people's PC code; doesn't matter for which OS and which language.

Me too.

sterretje:
3)
Your original code possibly did not work due to memory issues; pitty that you never posted it completely. I pointed one out in my first post, there might have been others like buffer overflows.

Your new Arduino code has a receivedChars that's just big enough; not sure if all messages will fit in there. Although I'm against wasting memory, I would play it safe and later reduce if needed.

Next, get rid of that String receivedCommand; one day it will bite you.

I kept the receivedCommand and got rid of the message (swapped them). I was thinking about using a string compare and was my next option, your snippet works well. I also don't like wasting memory, any ideas on how I could make all those strtok statements go away without taking up more memory? Maybe an array for the settings and a For loop?

sterretje:
Lastly, use functions to process the individual inTypes; long functions are a nightmare to maintain. There is a basic rule-of-thumb that you should be able to print a function on a single page of A4 using a standard font size :wink:

Yup I agree, it's on my todo list for the main (real sketch). I went back and tried 115200, 8N1, none, DTR=off, RTS=off, no thread waiting and now works fine. I really can't say why but, with it now working my chances of finding out why it was so slow is almost nil. I checked my anti-virus & anti-malware program logs and there is nothing. Windows system logs also show nothing. I also have the same programs running in the background as before. I even upgraded to the latest VS and that didn't help. I also made sure that my Windows 10 was fully upgraded. I played with that slow com response for a week, with no luck and bang now it works. I hate when that happens, I learn nothing.

From what I can tell between the 2 sketches I should have enough memory/s to make this work. I know how to save to eeprom with Microchip and their IDE, now I just have to figure it out with Arduino. Not because I have to but, because I want to. LOL

Thanks again
Let me know if you have any more suggestions.

Ray

Returned message.png