Go Down

Topic: [SOLVED] Receiving Serial Data from VB Application (Read 213 times) previous topic - next topic

bongo_bg

May 26, 2020, 11:38 am Last Edit: May 26, 2020, 02:40 pm by bongo_bg
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.

Code: [Select]
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:

Code: [Select]
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.

UKHeliBob

Code: [Select]
 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
Code: [Select]

  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
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

bongo_bg

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:

Code: [Select]
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. :(

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
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

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
Code: [Select]
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
Code: [Select]
if (newData == true && strcmp(receivedChars, "red\r") == 0)


And to prevent all those line ending issues, use the approach with startmarker and endmarker.
If you understand an example, use it.
If you don't understand an example, don't use it.

Electronics engineer by trade, software engineer by profession. Trying to get back into electronics after 15 years absence.

bongo_bg

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:

Code: [Select]
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:
Code: [Select]
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.

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
Code: [Select]
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
Code: [Select]
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")

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.

Robin2

Two or three hours spent thinking and reading documentation solves most programming problems.

bongo_bg

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!

Code: [Select]
spArduino.WriteLine("red")
+
Code: [Select]
(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:
Code: [Select]
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.

UKHeliBob

Quote
Is there anyway though to save that current array value to a different char/string?
strcpy()
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

bongo_bg

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.

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

bongo_bg

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:
Code: [Select]
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("<RED>") 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.

Robin2

#12
May 27, 2020, 03:02 pm Last Edit: May 27, 2020, 03:03 pm by Robin2
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("<Arduino is ready>"); - and my PC program waits to receive that before trying to send anything to the Arduino.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

UKHeliBob

Quote
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
Quote
note that every time you open teh serial connection from VB the Arduino will reboot
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

bongo_bg

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

...R
Yes, I did that now.

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

Go Up