1

I have a device which sits on pins 10/11 of Arduino UNO. I am trying to send commands from my PC using Arduino to relay my commands to the device via Serial.

The problem is that if I use speed 9600 both for device and USB communication, then my commands gets damaged. Some letters are replaced by strange symbols, etc. The device uses 9600 baud rate.

If I change speed of the PC communication to 4800 (or any speed other than 9600), everything is fine. But I have to use different speeds for the communication.

I am not comfortable with the workaround, because I don't understand what's going on. Could somebody explain why the same serial port speeds causes problems?

Here is my code:

#include <SoftwareSerial.h>

#define rxPin 11
#define txPin 10

SoftwareSerial mySerial =  SoftwareSerial(rxPin, txPin);

 void setup()
 {
   digitalWrite(4,HIGH); // 1 - disable
   mySerial.begin(9600);
   Serial.begin(19200);
   while (!Serial) {;}  // wait for serial port to connect. Needed for native USB port only
   Serial.println("Begin");
 }

 void loop()
 {
  if (mySerial.available()) 
  {
    char c = mySerial.read();
    Serial.write(c);  
  }
  if (Serial.available()) 
  {
    char c = Serial.read();
    mySerial.write(c); 
  }
 }
  • 1
    SoftwareSerial is not my favorite and I didn't have a good taste with it. But, anyway, maybe you should give some more detail about the device you connect on pin 10 and 11. – Sener Sep 6 '18 at 11:08
  • @Sener The device is RMCS 2201 servo: Link to specs It has fixed 9600 baud rate. I connected it directly to COM with a TTL converter and it works fine. So I guess, there is a problem somewhere in my code. Will try your buffering code. Thank you! Maybe you can suggest something to replace SoftwareSerial? – konstantin Sep 6 '18 at 14:37
  • Thank you for the device details. If it is working with USB to TTL module, then we should think about the code. Please give a try the code I mentioned. And even further, try to use hardware serial instead. – Sener Sep 6 '18 at 15:27
  • 1
    But, Arduino Uno has only one hardware serial with pins 0:RX, 1:TX. Then, you can't use PC communication via USB. You may like to consider also Arduino Mega which has 4 Serial ports. – Sener Sep 6 '18 at 15:33
  • Perhaps the interrupt from the incoming byte changes something in the outgoing byte of the SoftwareSerial. It is possible. Perhaps the servo motor has some kind of software serial as well and requires perfect timing of the serial signal. To avoid collisions, you can first read a full line as the answer by @Sener shows. But you better use a hardware serial port of the arduino mega or arduino leonardo. – Jot Sep 6 '18 at 16:52
0

If you are confident with the device you connected to your Arduino Uno in terms of it has a reliable serial communication firmware running on it, You might need some buffering before relaying your commands;

#define RECORD_SIZE 100
void loop()
{
    RelayDataIfAvaliable();
}
void RelayDataIfAvaliable() {
    static char buffer[RECORD_SIZE];
    if (Serial.available())
    {
        if (readline(Serial.read(), buffer, RECORD_SIZE) > 0) {
            mySerial.write(buffer);
        }
    }
}
//Reads entire incoming data into buffer once
int readline(int readch, char *buffer, int len)
{
    static int pos = 0;//This was zero initially. But, it was missing first character!
    int rpos;
    //Serial.print(readch);
    if (readch > 0) {
        switch (readch) {
        case '\n': // Ignore new-lines
            break;
        case '\r': // Return on CR
            rpos = pos;
            pos = 0;  // Reset position index ready for next time
            return rpos;
        default:
            if (pos < len - 1) {
                buffer[pos++] = readch;
                buffer[pos] = 0;
            }
        }
    }
    // No end of line has been found, so return -1.
    return -1;
}
  • I have played with this approach. Buffered read doesn't help. The same problem: everything is fine until I set the same speed for both serials. I have ordered a Mega board. This should solve the problem for sure. :) Thank you very much! – konstantin Sep 7 '18 at 4:55
  • 1
    But, there is another way before going on that road. When I checked that datasheet for the motor, it can also communicate over I2C or SPI. Wouldn't you consider to do that as well? For example, that sample is looking quite promising: RMC220x demo – Sener Sep 7 '18 at 8:25
  • 1
    Ah, one more thing, did you give that down vote for my answer (work in progress)? it was the only place I could place a formatted coding so i did not necessarily a final answer. I believe that at least it deserves some respect. – Sener Sep 7 '18 at 8:32
  • not it's not my down vote. I've marked your answer as useful. Since I don't have enough reputation it's recorded, but not displayed. Your answers help me a lot! – konstantin Sep 7 '18 at 14:06
  • Thank you for your feedback and marking my answer. Good luck with your project. – Sener Sep 7 '18 at 14:24
0

I spent some time playing with your code and it seems your code actually loops the serial therefore if they are both set at 9600 as example and you print what the other one is sending like in your code you end up in a loop if you want to read what your serial is sending it is better put that values in a variable and send it

if you load your code you will get the following message in the arduino IDE once you try to connect to the serial monitor:

Error opening serial port 'COM8'. (Port busy),

your port is busy because the one serial port is reading the other all the time

one more thing I would use the following if you want to repeat a serial port:

 
  if (mySerial.available()) 
  {
    //char c = mySerial.read();
    Serial.write(mySerial.read());  
  }

Hope this hels you

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.