[SOLVED] Receiving Serial Data from VB Application

Hello community. Once again I'm up against the wall and I need your help. First I want to mention that I already read all the general serial communication tips, guides and the basic's page. Yes, I'm a beginer, this is only my second project.
Last year I did a motor control with VB.NET application and I had troubles reading the incoming serial data as String. Huge mistake, thanks to you I switched to char with only 1 symbol and it worked perfectly in timely manner.
This year I need the same, so I stepped on my previous project and I wanted simply to change the action after a command. It turned the communication is no longer working properly, again, using the very very simple 1 symbol char commands. It freezes after the first received command. As in later stage, I'd have a SIM900 chip connected and I'd need to send phone numbers, I decided directly to go for the multi-character solution with '\n', just like it's explained and written in Serial Basics tutorial. It didn't work so I simplified and simplified and simplified so right now all I have the exact copied program from the tutorial with the only addition of adding a diode so I can debug.

int gLed = 13;
int yLed = 12;
int rLed = 11;

const byte numChars = 32;
char receivedChars[numChars];
boolean newData = false;

void recvWithEndMarker() {
    static byte ndx = 0;
    char endMarker = '\n';
    char rc;
   
    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

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

void dataTest() {
    if (newData == true && receivedChars == 'red') {
          digitalWrite(rLed,HIGH);
          delay(2000);
          newData = false; }
    else if (newData == true && receivedChars == 'green') {
          digitalWrite(gLed,HIGH);
          delay(2000);
          newData = false; }
    else {
          digitalWrite(yLed,HIGH);
          delay(2000); }
          //newData = false; }
}

void setup() {
  Serial.begin(9600);
  //Serial.setTimeout(200);
  pinMode(gLed, OUTPUT);
  pinMode(yLed, OUTPUT);
  pinMode(rLed, OUTPUT);
}

void loop() {
  recvWithEndMarker();
  dataTest();
}

My VB.NET commands are pretty simple as well:

spArduino.Open()
spArduino.WriteLine("red\n")
spArduino.Close()

I debugged recvWithEndMarker() and it's working. It looks like I do receive the data but I cannot read it.

I assume this communication represents at least half the issues you're dealing with here.

  if (newData == true && receivedChars == 'red')

receivedChars is a C style string, ie an array of chars terminated with a '\0'
You are trying to test what it holds uisng ==, which you cannot do
Even if you could then single quotes are used for single characters so 'red' is wrong

Use

  if (newData == true && strcmp(receivedChars, "red") == 0)  //0 indicates a match

I am pretty sure that Robin did not do the comparison using == in his example programs

Thank you.

You're right, this part was not in the tutorial, I added it for testing as I assumed it holds the same string. I was sure I'm doing something wrong reading the data.

I switched as suggested:

void dataTest() {
    if (newData == true && strcmp(receivedChars, "red") == 0) {
          digitalWrite(yLed,HIGH);
          delay(2000);
          newData = false; }
    else if (newData == true && strcmp(receivedChars, "green") == 0) {
          digitalWrite(gLed,HIGH);
          delay(2000);
          newData = false; }
    else {
          digitalWrite(rLed,HIGH);
          delay(2000); }
          //newData = false; }
}

Unfortunatelly, no change. It's staying at the 'else' case constantly, yet the command is coming through the serial. :frowning:

Step 1 when having problems testing values is to print what you are testing before the test. Are the values as expected ?

It may have no bearing on the problem but note that every time you open teh serial connection from VB the Arduino will reboot

Note that Robin's recvWithEndMarker() function reads up till the '\n'. Depending on your terminal program (Serial Monitor?) or its settings, you might receive '\r' followed by '\n'. So your

if (newData == true && strcmp(receivedChars, "red") == 0)

will fail because you receive more than just e.g. "red".

Change your serial monitor settings to Newline (right bottom, dropdown) and try again.

Alternatively, use

if (newData == true && strcmp(receivedChars, "red\r") == 0)

And to prevent all those line ending issues, use the approach with startmarker and endmarker.

UKHeliBob:
Step 1 when having problems testing values is to print what you are testing before the test. Are the values as expected ?

It may have no bearing on the problem but note that every time you open teh serial connection from VB the Arduino will reboot

In VB I used a couple of 'MsgBox' to determine if the code there is working as intended and it is.
In Arduino I cannot use the serial monitor as the port is 'busy' by the VB application. So I'm using these diodes for testing in each case and after each line. I just simplifed it back to 1 symbol commands and now it's working perfectly as well:

char val;

void serialMonitor() {
  while (Serial.available()) {
    val = Serial.read();
    if (val == 'R') {
      digitalWrite(rLed,HIGH);
      digitalWrite(yLed,LOW);
      digitalWrite(gLed,LOW); 
      delay(2000); }
    else if (val == 'G') {
      digitalWrite(rLed,LOW);
      digitalWrite(yLed,LOW);
      digitalWrite(gLed,HIGH);
      delay(2000);}
    else {
      digitalWrite(rLed,LOW);
      digitalWrite(yLed,HIGH);
      digitalWrite(gLed,LOW); }
   }
}

With VB write being:

spArduino.Open()
spArduino.WriteLine("G")
spArduino.Close()

Yet I'll have to make it able to recieve char data suitable for a phone number, +359123456789 for example or at least 123456789 which I can combine with +359 in Arduino.
So at this point I reach the conclusion that VB is sendind the data, Arduino is recieving the data but I fail to read it and work with it.

sterretje:
Note that Robin's recvWithEndMarker() function reads up till the '\n'. Depending on your terminal program (Serial Monitor?) or its settings, you might receive '\r' followed by '\n'. So your

if (newData == true && strcmp(receivedChars, "red") == 0)

will fail because you receive more than just e.g. "red".

Change your serial monitor settings to Newline (right bottom, dropdown) and try again.

Alternatively, use

if (newData == true && strcmp(receivedChars, "red\r") == 0)

And to prevent all those line ending issues, use the approach with startmarker and endmarker.

That looks nice. I'm not using the Serial Monitor though so I don't have this option 'New Line'. I'm writing via VB.NET application and the simple write code is just above. With sending spArduino.WriteLine("red\n") in VB, I expect Arduino to see only "red". This is how I assume I can recreate a serial monitor command.

I tried if (newData == true && strcmp(receivedChars, "red\r") == 0) as well but it's still the same no matter if in VB I write spArduino.WriteLine("red") or spArduino.WriteLine("red\n")

WriteLine is going to add a newline to your string. Print out what you actually get, preferably with a prefix and suffix so you can detect that there was a newline. Perhaps use strlen to see how many characters you received.

Or forget about it and use strncmp.

Consider using strstr() rather than strcmp()

...R

wildbill:
WriteLine is going to add a newline to your string. Print out what you actually get, preferably with a prefix and suffix so you can detect that there was a newline. Perhaps use strlen to see how many characters you received.

Or forget about it and use strncmp.

That's it!

spArduino.WriteLine("red")
(newData == true && strcmp(receivedChars, "red") == 0)

...did the magic! Big thanks for that.

Is there anyway though to save that current array value to a different char/string? For example:

char command = receivedChars;

Will that line work? I will need to send phone numbers and work with those and I read char type is the best for this.

Is there anyway though to save that current array value to a different char/string?

strcpy()

Robin2:
Consider using strstr() rather than strcmp()

...R

Thank you for the advise. That would be easier as I'm only sending few commands that have nothing incommon in terms of symbols.

UKHeliBob:
strcpy()

Ah, I'm embarrassed. Self-learner here.

Thank you all. I'm continuing on my own now. I might have troubles simultaneously reading and writing the serial and communicating with SIM900 also via SoftwareSerial but that's slightly ahead of time. One step at a time.

Huge appreciations. I'm marking the topic [SOLVED].

Hi guys,

Just an update if someone has similar problems. The serial transfer in direction VB->Arduino was just fine yesterday. Today It turned out though that the direction Arduino->VB had issues. After few hours of bumping my head at the wall I read some advises here and there so I'm presenting my mistakes:

First of all, I changed the Arduino reading from '\n' new line to < start and > end maker. I realized this allow much more room for improvements.

Then, it turned out that this:

spArduino.Open()
spArduino.WriteLine("R")
spArduino.Close()

is wrong. Apparently this repeative opening and closing the port after each command is really not a good idea and it brings nothing good. So, it's just spArduino.WriteLine("") now.
And third, in VB properties of the Serial Port object, there are options - DtrEnable and RtsEnable. For Arduino Uno they both have to be False. If you've experiment with any of it being True, Arduino has to be rebooted before trying again with False.

Works like a charm now.

Once again, thank you all.

bongo_bg:
Apparently this repeative opening and closing the port after each command is really not a good idea and it brings nothing good.

Your PC program causes the Arduino to reset when it opens the serial port. Your PC program needs to allow time for that before sending anything and it should keep the serial port open until it is completely finished with the Arduino.

In my PC-Arduino projects I have my Arduino send a message from setup() - something like Serial.println(""); - and my PC program waits to receive that before trying to send anything to the Arduino.

...R

Apparently this repeative opening and closing the port after each command is really not a good idea and it brings nothing good.

If only you had taken note of reply #3

note that every time you open teh serial connection from VB the Arduino will reboot

Robin2:
In my PC-Arduino projects I have my Arduino send a message from setup() - something like Serial.println(""); - and my PC program waits to receive that before trying to send anything to the Arduino.

...R

Yes, I did that now.

UKHeliBob:
If only you had taken note of reply #3

Sorry about that. I read it but I had no idea what you mean until I wasted few hours testing it symbol by symbol and I saw only one or two ocasinal characters managed to go through. Now it's clear. Ah if only I knew this year ago...