Pages: [1]   Go Down
Author Topic: Serial Repeater  (Read 747 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 27
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I made a cnc where an Arduino is controlling the motors. It works very fine with GRBL flashed to the Arduino. It receives and send serial communication via USB to and from my PC. No problems.

I would like to run my GRBL Arduino (uno rev3) from another Arduino (uno r2) – my control Arduino. The control Arduino should do a number of things but also be able to repeat serial communication from PC to GRBL Arduino. I connected GRBL Arduino's D0 and D1 to my Control Arduino D7 and D8 intending to use SoftwareSerial on these pins. rx->tx, tx->rx

I can't make my Arduinos talk to each other. This is the parts of my code, which should do the job. What I sent from my PC is shown at the LCD. And the initial “Ready ...” arrives at my PC. So the loop is running OK. Can anybody figure out whats wrong.

Code:
#include <SoftwareSerial.h>
#define rxPin 7
#define txPin 8
...
SoftwareSerial mySerial =  SoftwareSerial(rxPin, txPin);
...
void serialRepeater(){
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Serial repeater");
  Serial.begin(9600);
  Serial.println("Ready ...");
  while (!Serial)
  mySerial.begin(9600);
  mySerial.print("$");
  while (mode==3) {   
    if (mySerial.available()>0){
      serData=mySerial.read();
      Serial.write(serData);
      lcd.print(serData);
    }
    if (Serial.available()) {
      serData=Serial.read();
      mySerial.write(serData);
      lcd.print(serData);
      Serial.write(serData);
    }
    if (Button(btnReverse)) {
      while (Button(btnReverse)) {}
      mode=0;
    }
  } 
  lcd.clear();
  mainmenu();
}
 
void loop() {
   mode=3;
   serialRepeater();
}
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 27
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Just got a hole through.

I minimized the code. Now it looks like this:
Code:
void serialRepeater(){
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Serial repeater");
  Serial.begin(9600);
  Serial.println("Ready ...");
  mySerial.begin(9600);
  mySerial.listen();
  while (mode==3) {   
    while (mySerial.available()){
      Serial.write(mySerial.read());
    }
    while (Serial.available()>0) {
      mySerial.write(Serial.read());
    }
    if (Button(btnReverse)) {
      while (Button(btnReverse)) {}
      mode=0;
    }
  } 
  lcd.clear();
  mainmenu();
}

Only problem now is, that it looses characters if message is long.
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 547
Posts: 45973
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
  while (!Serial)
  mySerial.begin(9600);
Why?

snippets-r-us.com is down the internet a ways. Here, we get to see ALL of your code.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 27
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Yes "while (!Serial) " is indeed the error. It must be an error I made when I was copying code from an example. I'm not used to program in C, so my eyes just didn't catch it.
Now my only problem is, that when GRBL dump current settings, the text becomes more and more erroneous. Here's an example of the dump:

Code:
$0 = 200.000 (steps/mm x)
$1 = 200.000 (steps/mm y)
$2 = 200.000 (steps/mm z)
$3 = 50 (microseconds step pulse)
$4 = 250.000 (mm/min default feed rate)
$ = 5000 (m/indeaul sekrae)
$ =0.00(m/ac sgmnt
7  20 ste prtiner msk bnay  100100
8  1.00 aceleatoninmmse^2
9  005 (crnrig untin dvitin n m)
'x=vlu' o etpaamte o jst'$'todup uren sttigs
o

And the failures are not at the same positions each time.
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 168
Posts: 12417
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


The problem is in this code I think as it promotes deadlock
Code:
  while (mode==3) {   
    while (mySerial.available()){   <<<<<<<<<<
      Serial.write(mySerial.read());
    }
    while (Serial.available()>0) { 
      mySerial.write(Serial.read());
    }
    if (Button(btnReverse)) {
      while (Button(btnReverse)) {}
      mode=0;
    }
  } 

If serial is getting data constatntly the second loop gets no time

try to replace it with

Code:
 
while (mode==3)
{   
  if (mySerial.available()) Serial.write(mySerial.read());
  if (Serial.available()>0) mySerial.write(Serial.read());
  if (Button(btnReverse) == HIGH)   // more explicit
  {
    while (Button(btnReverse) == HIGH ) ;  // wait for release
    mode=0;
  }

Now the code check both directions alternatingly
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Offline Offline
Newbie
*
Karma: 0
Posts: 27
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

There must be a more fundamental problem with SoftwareSerial.
I made the tightest possible loop to see how much could be received flawlessly.

This code
Code:
    while (1==1) {
      while (mySerial.available()) Serial.write(mySerial.read());
      while (Serial.available()) mySerial.write(Serial.read());
    };
is better than this code:
Code:
    while (1==1) {
      if (mySerial.available()) Serial.write(mySerial.read());
      if (Serial.available()) mySerial.write(Serial.read());
    };

Errors begin after approximately 175 characters.
For example:
Code:
$0 = 200.000 (steps/mm x)
$1 = 200.000 (steps/mm y)
$2 = 200.000 (steps/mm z)
$3 = 50 (microseconds step pulse)
$4 = 250.000 (mm/min default feed rate)
$5 = 250.000 (mm/min default ee rae)
$ =0.00(m/ac sgmnt
7  20 stp or ivet msk bnay  10000)
8  1.00 acelraioni m/se^2
9  005 (orerig untin evaton n m)
$x=ale'tose praete o jst'$ t dmpcuren sttng
k
Here the errors start at the line beginning with $5.
Logged

Switzerland
Offline Offline
Faraday Member
**
Karma: 96
Posts: 4674
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Do you send anything while receiving? I'm asking because the SoftwareSerial disables interrupts while sending out characters but the reception of characters is depending on a timely handling of an external interrupt. You cannot use SoftwareSerial for sending and receiving characters simultaneously. The hardware serial is able to do that. You might want to change to a Mega, it has 4 hardware serial interfaces.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 27
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

No, I'm not sending and receiving by SoftwareSerial at the same time. In my test I send a $-sign to the GRBL-Ardiono, and then it respond with a dump of current settings ad shown on this page: https://github.com/grbl/grbl/wiki/Configuring-Grbl
Logged

Switzerland
Offline Offline
Faraday Member
**
Karma: 96
Posts: 4674
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

There must be a more fundamental problem with SoftwareSerial.
I made the tightest possible loop to see how much could be received flawlessly.

This code
Code:
    while (1==1) {
      while (mySerial.available()) Serial.write(mySerial.read());
      while (Serial.available()) mySerial.write(Serial.read());
    };
is better than this code:
Code:
    while (1==1) {
      if (mySerial.available()) Serial.write(mySerial.read());
      if (Serial.available()) mySerial.write(Serial.read());
    };


What does "better" mean in this context? The two version differ primarily in the earlier handling of reads from the hardware serial which implies a write to the SoftwareSerial. You're telling that a write does not happen. In this case the two versions act almost identical. What happens if you take out the second if line and write the necessary command to the SoftwareSerial before entering the while loop?
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 168
Posts: 12417
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
while (1==1) {
      while (mySerial.available()) Serial.write(mySerial.read());  <<<<<<<<<<< this line can deadlock
      while (Serial.available()) mySerial.write(Serial.read());  <<<<<<<<<<<<< preventing this to execute which may encounter a buffer overflow....
    };

Sometimes people put a delay(1) in these tight loops to give the serial port time to process.

Have you tried higher baudrates BTW?
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Offline Offline
Newbie
*
Karma: 0
Posts: 27
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@Pylon better in this context is that more data and fewer faults. There's approximately 400 bytes of data received by SoftwareSerial. In best cases I faults begins after 174 bytes. In worst cases I only receive 70 bytes.
@robtillaart I have tried using different baud-rates, then I don't receive anything. I cant change the rate of the GRBL Arduino. If I use delays, I lose data.
I seems that I got to collect the data from SoftwareSerial as quick as possible.
I have tried to collect the data received by  the SoftwareSerial connection in a String in my while loop and then write them back to the computer via Serial. That gave me only 100 bytes out of 400.
My conclusion is that I got to buy a Mega end skip SoftwareSerial.
Logged

Switzerland
Offline Offline
Faraday Member
**
Karma: 96
Posts: 4674
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Do you have a scope? If yes, you could activate the debug feature of SoftwareSerial (line 35-37 of SoftwareSerial.cpp) and get pulses on debug pins when the serial data is being read. This allows you to check the timing of the software implementation and maybe get a sense for what's going wrong.
Logged

Pages: [1]   Go Up
Jump to: