Serial RX and USB data

Hello guys I feel kinda bad asking so much questions I hope this is the final one :).

I’m using Arduino UNO bord. I already know from this post : http://forum.arduino.cc/index.php?topic=27436.0

That pin 0 (RX) and pin 1 (TX) are used for the USB connections. But I want to use the RX pin to connect my receiver with.

Well I hear you think just disconnect or don’t disconnect the USB and use the receiver on pin 0 without caring. But it doesn’t work like that. The code that I have works fine thanks to all you guys.

So for example I can receive all my strings on pin 0 without any problem , So it does receive my data. But when in my code I ask for this

if (Richting=“V”){
digitalWrite(13,HIGH);
analogWrite(E1,255);
}

. It does make the LED on pin 13 HIGH when I receive a “V” but it doesn’t set the PWM to my motor. Meanwhile when I go the the serial monitor and I type my strings manually like “V” It makes the LED HIGH and ALSO SET THE PWM TO MY MOTOR … How do I SOLVE THIS ?

Thank you in advanced !

#define E1 10  // Enable Pin for motor 1
#define E2 11  // Enable Pin for motor 2

#define I1 8  // Control pin 1 for motor 1 for L293D it changes the direction of the motor
#define I2 9  // Control pin 2 for motor 1 for L293D it changes the direction of the motor
#define I3 12  // Control pin 1 for motor 2 for L293D it changes the direction of the motor
#define I4 13  // Control pin 2 for motor 2 for L293D it changes the direction of the motor


String Richting;  // Direction
int Axis;                 // Numbers (the speed I want to set on the motors)
const byte numChars = 75;
char receivedChars[numChars]; // an array to store the received data
boolean newData = false;

void setup() {

Serial.begin(2400);
  pinMode(13, OUTPUT);
  pinMode(E1, OUTPUT);
  pinMode(E2, OUTPUT);

  pinMode(I1, OUTPUT);
  pinMode(I2, OUTPUT);
  pinMode(I3, OUTPUT);
  pinMode(I4, OUTPUT);
  Serial.println("<Arduino is ready>");
}

void loop() {
  if (recievedMessage())
  {
    parseMessage();
    Calculation();
    showNewMessage();
  }
}

bool recievedMessage() {
  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++;
      Richting = receivedChars[1];
      if (ndx >= numChars) {
        ndx = numChars - 1;
      }
    }
    else {
      receivedChars[ndx] = '\0'; // terminate the string
      ndx = 0;
      newData = true;
      return true;
    }
  }
  return false;
}

void showNewMessage() {
  if (newData == true) {
    
    Serial.print("De richting=");
    Serial.println(Richting);
    Serial.print("De snelheid=");
    Serial.println(Axis);
    newData = false;
    
  }
}

void parseMessage()
{
  strtok(receivedChars, ",");
  Axis = atoi(strtok(NULL, ","));
}

void Calculation()
{
  if (Richting="V"){
    digitalWrite(13,HIGH);
    analogWrite(E1,255);
  }
}

  if (Richting = "V")That sets Richting to "V" rather than testing it. Not quite what you want, I think.

The USB serial is connected to pin 0 and 1 via some resistors. These resistors are weak enough that something else plugged into the pins will be able to override the USB.

But it doesn't always work. If the driver from your receiver isn't very strong (maybe it's a 3.3V device) then it can't override the USB.

But you said it's setting pin 13 high. That would indicate that that part of the code is working.

I do see one potential problem: You have two names for pin 13. You named it I4 and you are also calling that number directly in digitalWrite(13,HIGH); Once you give it a name, always use that name.

You are setting your variable Richting inside the message-receiver, before it even gets the second character of the message. receivedChars[1] is the second char. When you are parsing data out of a message like this, you must wait until the message is complete before you can make sense of the contents of the message.

MorganS: You are setting your variable Richting inside the message-receiver, before it even gets the second character of the message. receivedChars[1] is the second char. When you are parsing data out of a message like this, you must wait until the message is complete before you can make sense of the contents of the message.

this is just one of the pitfalls of using (nearly all) global variables like this... assigning or getting them from anywhere. yucky.

@MrKrabs....

what went wrong? you had the parsing working! ;)

Don’t use String™. You are correctly using a character array, so there is no reason to copy it into the wasteful String class.

The main problem is using the assignment ‘=’ instead of the comparison ‘==’, like others have said, but you don’t need the String Richting;

You may also have a problem with the EndMarker. The ‘\n’ character is a line feed character on the Arduino, with an ASCII value of 10. Originally, this meant to advance the paper one line. New characters would be printed one line lower on the page (now screen), but in the same horizontal position.

To start printing at the left margin, the program had to send a carriage return character, ASCII value 13. This can also be specified as ‘\r’.

The Serial Monitor window can send one, both, or neither character(s) when you press Send. There’s a pull-down choice in the bottom-right corner of the Serial Monitor window. For your sketch, you may have the wrong setting. Choose “Newline”.

You could make this a little more robust in your code. Instead of watching for a ‘\n’, you could watch for any characters >= a space character, ’ ':

    if (rc >= ' ') { // not a CR or LF

This matches numbers, letters, punctuation… any printable/visible character.

I would also suggest testing the bool types without the == operator. Instead of

    if (newdata == true) {

… you can simply write

    if (newdata) {

This is a little easier to read, IMO, and certainly less to type. Testing for false can be performed with the logical NOT operator, ‘!’ or ‘not’:

    if (not newdata) {

… or

    if (!newdata) {

Here’s your sketch with those suggested changes:

#define E1 10  // Enable Pin for motor 1
#define E2 11  // Enable Pin for motor 2

#define I1 8  // Control pin 1 for motor 1 for L293D it changes the direction of the motor
#define I2 9  // Control pin 2 for motor 1 for L293D it changes the direction of the motor
#define I3 12  // Control pin 1 for motor 2 for L293D it changes the direction of the motor
#define I4 13  // Control pin 2 for motor 2 for L293D it changes the direction of the motor


int Axis;                 // Numbers (the speed I want to set on the motors)
const byte numChars = 75;
char receivedChars[numChars]; // an array to store the received data
boolean newData = false;

void setup() {

  Serial.begin(2400);
  // pinMode(13, OUTPUT); <-- This is the same as I4!
  pinMode(E1, OUTPUT);
  pinMode(E2, OUTPUT);

  pinMode(I1, OUTPUT);
  pinMode(I2, OUTPUT);
  pinMode(I3, OUTPUT);
  pinMode(I4, OUTPUT);
  Serial.println("<Arduino is ready>");
}

void loop() {
  if (recievedMessage())
  {
    parseMessage();
    Calculation();
    showNewMessage();
  }
}

bool recievedMessage() {
  static byte ndx = 0;

  while (Serial.available()) {
    char rc = Serial.read();

    if (rc >= ' ') { // Not a CR orLF

      if (ndx < numChars) {  // if there's room...
        receivedChars[ndx] = rc;  //  ... save another char
        ndx++;
      }

    } else if (ndx > 0) { // not an empty string

      receivedChars[ndx] = '\0'; // terminate the string
      ndx     = 0;
      newData = true;
      return true;

    }
  }
  return false;
}

void showNewMessage() {
  if (newData) {

    Serial.print("De richting=");
    Serial.println(receivedChars);
    Serial.print("De snelheid=");
    Serial.println(Axis);
    newData = false;

  }
}

void parseMessage()
{
  strtok(receivedChars, ",");
  Axis = atoi(strtok(NULL, ","));
}

void Calculation()
{
  if ( strcmp( receivedChars, "V" ) == 0 ){
    digitalWrite(I4,HIGH); // <-- use I4, not 13
    analogWrite(E1,255);
  }
}

It also ignores empty lines, and uses the pin name I4 instead of the pin number 13.

Notice how it uses the strcmp function to require the exact 1-character command, “V”. If you want a longer command, it’s ok to put more characters in there, like “Vol”. You cannot compare receivedChars to a string like this:

  if (receivedChars == "V") {   // NO!

You must use the strcmp function:

    if ( strcmp( receivedChars, "V" ) == 0 ) { // Yes, two C strings (char arrays) compared

Optionally, you could do this 1-character comparison:

  if (receivedChars[0] == 'V') { // starts with a 'V' char

Note the single quotes instead of double quotes. This would accept “VOL,120” or “V,123” or “Voodoo,40”, because they all start with V.

There are many string functions. Official strcmp description here, decent summaries here and here.

Cheers,
/dev

@UKHeliBob : Thanks for noticing I'm gonna change that to "==".

@MorganS : Yes I know , Thanks for noticing and responding. I know it's the same but in this case it doesn't matter :). Yes but I have no choice , Before my actual string comes CHAR 22 wich is a sync if you gonna look it the ASCII-table. And I needed to filter it out So acctual receivedChars[0]= CHAR 22 (sync) if you know what I mean ? How do I make it that CHAR 22 gets filtered out ?

@BulldogLowell : Yes it WORKS AWSOME thank you so much for rewriting the code and helpfull tips !

@-dev : I understand what you mean I set it to 'New line" always. But you should see my send code it exists out of this SEND CHAR 22 + Direction + Axis (speed) + CHAR 13 + CHAR 10. So I know what you mean but I have no trouble receiving the signal anymore for a weird reason it just worked suddenly :).

MrKrabs: @MorganS : Yes I know , Thanks for noticing and responding. I know it's the same but in this case it doesn't matter :). Yes but I have no choice , Before my actual string comes CHAR 22 wich is a sync if you gonna look it the ASCII-table. And I needed to filter it out So acctual receivedChars[0]= CHAR 22 (sync) if you know what I mean ? How do I make it that CHAR 22 gets filtered out ?

When newData is true, then you can look at the second char of the message. If it's always going to be SYNC, then you should use revcWithStartAndEndMarkers() and use SYNC as the start marker. (How you type this character on the serial monitor is another question.)