[SOLVED] How to send double-sided data with RS485 ?

Hello,

I am trying to make a Nextion remote control screen with RS485. I use Nano for the RS485 control PIN. I use Arduino Mega as a master device. I'm sending data to Nextion through the SoftwareSerial library. My problem is :frowning: I can send data to Nano, but I can't get data from Nano. The TX and RX pins on the mega don't flash.

Mega Sketch :

#define SSerialTxControl 28   //RS485 Direction control
#define RS485Transmit    HIGH
#define RS485Receive     LOW

#define Pin13LED         13



/*-----( Declare Variables )-----*/
int byteReceived;
int byteSend;

void setup()   /****** SETUP: RUNS ONCE ******/
{
  // Start the built-in serial port, probably to Serial Monitor
  Serial.begin(38400);
  Serial.println("SerialRemote");  // Can be ignored

  pinMode(Pin13LED, OUTPUT);
  pinMode(SSerialTxControl, OUTPUT);

  digitalWrite(SSerialTxControl, RS485Receive);  // Init Transceiver

  // Start the software serial port, to another device
  Serial2.begin(38400);   // set the data rate
}//--(end setup )---


void loop()   /****** LOOP: RUNS CONSTANTLY ******/
{
  //Copy input data to output
  if (Serial2.available())
  {
    byteSend = Serial2.read();   // Read the byte

    digitalWrite(Pin13LED, HIGH);  // Show activity
    delay(10);
    digitalWrite(Pin13LED, LOW);

    digitalWrite(SSerialTxControl, RS485Transmit);  // Enable RS485 Transmit
    Serial2.write(byteSend); // Send the byte back
    delay(10);
    digitalWrite(SSerialTxControl, RS485Receive);  // Disable RS485 Transmit
    //    delay(100);
  }// End If RS485SerialAvailable

}//--(end main loop )---

/*-----( Declare User-written Functions )-----*/
//NONE

//*********( THE END )***********

Nano Sketch :

#include <SoftwareSerial.h>
/*-----( Declare Constants and Pin Numbers )-----*/
#define SSerialRX        10  //Serial Receive pin
#define SSerialTX        11  //Serial Transmit pin

#define SSerialTxControl 6   //RS485 Direction control

#define RS485Transmit    HIGH
#define RS485Receive     LOW

#define Pin13LED         13

/*-----( Declare objects )-----*/
SoftwareSerial nextion(SSerialRX, SSerialTX); // RX, TX

/*-----( Declare Variables )-----*/
int byteReceived;
int byteSend;

void setup()   /****** SETUP: RUNS ONCE ******/
{
  // Start the built-in serial port, probably to Serial Monitor
  Serial.begin(38400);
  Serial.println("YourDuino.com SoftwareSerial remote loop example");
  Serial.println("Use Serial Monitor, type in upper window, ENTER");

  pinMode(Pin13LED, OUTPUT);
  pinMode(SSerialTxControl, OUTPUT);

  digitalWrite(SSerialTxControl, RS485Receive);  // Init Transceiver   

  // Start the software serial port, to another device
  nextion.begin(38400);   // set the data rate 

}//--(end setup )---


void loop()   /****** LOOP: RUNS CONSTANTLY ******/
{
  digitalWrite(Pin13LED, HIGH);  // Show activity
  
  if (Serial.available())
  {
    byteReceived = Serial.read();
    
    nextion.write(byteReceived);          // Send byte to Remote Arduino

    digitalWrite(Pin13LED, LOW);  // Show activity    
    
  }

  if (nextion.available())  //Look for data from other Arduino
   {
    digitalWrite(Pin13LED, HIGH);  // Show activity

    byteReceived = nextion.read();    // Read received byte

    digitalWrite(SSerialTxControl, RS485Transmit);  // Enable RS485 Transmit
    Serial.write(byteReceived);        // Show on Serial Monitor
    delay(10);
    digitalWrite(SSerialTxControl, RS485Receive);  // Disable RS485 Transmit 
          
    digitalWrite(Pin13LED, LOW);  // Show activity   
   }

}//--(end main loop )---

/*-----( Declare User-written Functions )-----*/

//NONE
//*********( THE END )***********

Please tell me what I'm doing wrong.

Can you draw a schematic of your connections with pin numbers?

Hold on, what is the plan ? You've seemed to have confused things a little. I'd say the plan should be that the master sends a byte first. That is what masters do. so : in the mega Sketch

void loop()   
{

  if (Serial.available())  // read from the Serial monitor
  {
    byteSend = Serial.read();   // Read the byte

    digitalWrite(Pin13LED, HIGH);  // Show activity
    delay(10);
    digitalWrite(Pin13LED, LOW);

    digitalWrite(SSerialTxControl, RS485Transmit);  // Enable RS485 Transmit
    Serial2.write(byteSend); // Send the byte to the Nano
    delay(1); // for 1 byte at 38400, you need about a quarter of a ms.
    digitalWrite(SSerialTxControl, RS485Receive);  // Disable RS485 Transmit
  }

  if (Serial2.available())  // read from the slave
  {
    byteSend = Serial2.read();   // Read the byte

    digitalWrite(Pin13LED, HIGH);  // Show activity
    delay(10);
    digitalWrite(Pin13LED, LOW);


    
    Serial.write(byteSend); // Send the byte to the Serial Monitor
    // delay(1); // no need to wait for the serial buffer to clear
    
  }

}//--(end main loop )---

and so for the Nano it should receive, send to the nextion, and echo back for now.

void loop()   
{
  digitalWrite(Pin13LED, HIGH);  // Show activity
 
  if (Serial.available())
  {
    byteReceived = Serial.read();   
    
    delay(2); // just a tad more to make sure the RS485 is in receive mode at the other end.
    digitalWrite(SSerialTxControl, RS485Transmit);  // Enable RS485 Transmit
    Serial.write(byteReceived);        // Send to the Mega
    delay(1);  // wait for the buffer to clear
    digitalWrite(SSerialTxControl, RS485Receive);  // Disable RS485 Transmit
    nextion.write(byteReceived);          // Send byte to Nextion
    digitalWrite(Pin13LED, LOW);  // Show activity   
   
  }

  if (nextion.available())  //Look for data from nextion  !!
   {
    digitalWrite(Pin13LED, HIGH);  // Show activity

    byteReceived = nextion.read();    // Read received byte

    digitalWrite(SSerialTxControl, RS485Transmit);  // Enable RS485 Transmit
    Serial.write(byteReceived);        // Send that to the Mega
    delay(1);
    digitalWrite(SSerialTxControl, RS485Receive);  // Disable RS485 Transmit
         
    digitalWrite(Pin13LED, LOW);  // Show activity   
   }

}

That is what you said you want to do.
But in general i never really use a Max485 like that. It cumbersome. For transmission over a RS485 bus i anyway need a shielded twisted pair of wires ideally Cat 5 (or 6) UTP cable, And at the baudrate you are using we ca go a loooong way (upto 450meters !) And UTP cable has 4 pairs, i can use 3 of those (half of one as a common GND) and with 2 more transceivers i have a full-duplex system, without al the directional switching. The RS485 is meant to cover big distances, if you aren't doing that, get rid of the transceivers and hook the Arduinos straight into each other, and lower the Baud-rate until you get a reliable transmission. (9600 should get you at least 30m)

LightuC:
Can you draw a schematic of your connections with pin numbers?

Deva_Rishi:

Hello,
First of all, I apologize for the late reply. The problem was caused by software. I just discovered the problem. I can't read data from Nextion with Nano and send it to Mega.

Nano Sketch :

#include <AltSoftSerial.h>

AltSoftSerial altSerial;

/* RS485 Configurations */
#define RS485ControllerPin 6
#define RS485Transmit   HIGH
#define RS485Receive    LOW

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(38400);

  // set the data rate for the SoftwareSerial port
  altSerial.begin(38400);

  pinMode(RS485ControllerPin, OUTPUT);
  digitalWrite(RS485ControllerPin, RS485Receive);
}

void loop() { // run over and over
static uint8_t buffer[8];
  static uint8_t receivedByteCounter;
  uint8_t byteHolder;

  while (altSerial.available() > 0)
  {
    byteHolder = altSerial.read();
    
    buffer[receivedByteCounter] = byteHolder;
    
    if (receivedByteCounter == 7)
    {
      for(int i = 0; i < 8; i++) {
          digitalWrite(RS485ControllerPin, RS485Transmit);
          Serial.print((byte)buffer[i], HEX);
          delay(1);
          digitalWrite(RS485ControllerPin, RS485Receive);
      }
      receivedByteCounter = 0;
    }

    ++receivedByteCounter;
  }
}

Serial Monitor : Expected : A5A5A501000 | Result : A5A5A501000 The result is displayed on the serial screen as I want. But Mega seems like he doesn't understand the data type. I think there is a problem with the data type I sent to Mega.

Mega Sketch :

void serialEvent2()
{
  static uint8_t buffer[10];
  static uint8_t receivedByteCounter;
  static uint8_t startByteCounter;
  uint8_t byteHolder;

  while (Serial2.available() > 0)
  {
    byteHolder = Serial2.read();

    if (byteHolder == 0xa5)
    {
      ++startByteCounter;

      if (startByteCounter > 2)
      {
        startByteCounter = 0;
        receivedByteCounter = 0;
      }
    }
    else
    {
      startByteCounter = 0;
    }
    
    buffer[receivedByteCounter] = byteHolder;
    
    if (receivedByteCounter == 5)
    {

      switch (buffer[1])
      {
        case 0:

            switch (buffer[2])
            {
			.....
			..... Integer Statements
			.....
			}
      }
    }

    ++receivedByteCounter;
    if (receivedByteCounter > 9) {
      receivedByteCounter = 9;
    }
  }
}

The TX and RX pins on the mega don't flash.

If you're talking about the LEDs, you are aware that they will only flash when communicating over USB (Serial, not Serial1 and so on?

Start with lower baudrates on software serial connection, 38400 is at the limit as far as I know.

Start with lower baudrates on software serial connection, 38400 is at the limit as far as I know

for transmit up to 115200, and both ways 57600 are reliable.
But that is not the issue. Actually the reception is as expected on the altswSerial.
You send it from the nano as a HEX representation of a byteSerial.print((byte)buffer[i], HEX); which makes it easy to read on the serial monitor, but then you try to receive it on the Mega as if they are still individual bytes (rather than their HEX representation)

    byteHolder = Serial2.read();

    if (byteHolder == 0xa5)

You should be trying to read what you send (or send what you want to read) which is a 14-byte char - array "A5A5A501000" So if you want to compare the first byte, you need to read the first 2 characters and compare them to "A5".
Also using   while (Serial2.available() > 0) within a Serial event, chances are you will empty the buffer before the transmission is complete.

sterretje:
1)If you're talking about the LEDs, you are aware that they will only flash when communicating over USB (Serial, not Serial1 and so on?

Start with lower baudrates on software serial connection, 38400 is at the limit as far as I know.

1-) Yes, you're right. I was printing the same data on the serial monitor and Serial2. I noticed it later. It wasn't in Sketch. Sorry.

2-) I've tried sending data from Nano to Nextion via AltSoftSerial Library and it's working. AltSoftSerial Library, for an extra serial port The library does its job very well. The baudrate limit is higher than it says.

I thank you for your advice and help. But I'm sure it's about the data type. I just don't understand what kind of data I have to send.

Deva_Rishi:
for transmit up to 115200, and both ways 57600 are reliable.
But that is not the issue. Actually the reception is as expected on the altswSerial.
You send it from the nano as a HEX representation of a byteSerial.print((byte)buffer[i], HEX); which makes it easy to read on the serial monitor, but then you try to receive it on the Mega as if they are still individual bytes (rather than their HEX representation)

    byteHolder = Serial2.read();

if (byteHolder == 0xa5)


You should be trying to read what you send (or send what you want to read) which is a 14-byte char - array **"A5A5A501000"** So if you want to compare the first byte, you need to read the first 2 characters and compare them to "A5".
Also using `  while (Serial2.available() > 0)` within a Serial event, chances are you will empty the buffer before the transmission is complete.

I get it, okay, I see, but would it make any difference if I sent the data with "serial.write(temp, length)" OR "serial.print((byte)temp)" ? I think I need to write the data byte by byte from the static buffer. I don't have to turn it into HEX, do I ?

As far as I know, when variable is defined with byte data type : A5 to 165 or 0xa5 all values are the same. I hope I didn't misunderstand what you wrote. Thank you.

"serial.print((byte)temp)" ? I think I need to write the data byte by byte from the static buffer. I don't have to turn it into HEX, do I ?

No you don't have to, but you did so you could read it on the Serial Monitor. if you change Serial.print((byte)buffer[i], HEX); to
Serial.write((byte)buffer[i]); You won't recognize it probably since it will look like this : '¥'

As far as I know, when variable is defined with byte data type : A5 to 165 or 0xa5 all values are the same

, yes but you are calling a function which does have some overloaded versions, but print() 0xA5 as 165, and will convert that to 3 bytes being '1', '6' & 5' and converts 0xA5 to HEX if you specify that would make it "A5", which at the other end will come out as 2 bytes values 65 & 35.
write() is the function you want that actually sends the value.

Deva_Rishi:
No you don't have to, but you did so you could read it on the Serial Monitor. if you change Serial.print((byte)buffer[i], HEX); to
Serial.write((byte)buffer[i]); You won't recognize it probably since it will look like this : '¥', yes but you are calling a function which does have some overloaded versions, but print() 0xA5 as 165, and will convert that to 3 bytes being '1', '6' & 5' and converts 0xA5 to HEX if you specify that would make it "A5", which at the other end will come out as 2 bytes values 65 & 35.
write() is the function you want that actually sends the value.

Hello again, I have a new problem right now. Serial2 does not trigger SerialEvent2. But serialEvent1 is running fine. I don't know why. Although I write Serial.print ("Test") in the SerialEvent2 function, I don't see anything. But it works in SerialEvent1. Only the problem seems to be in SerialEvent2.

I'm sure that's my last problem. Once we figure this out, it's gonna work. I thank you again and again for everything.

I don't see anything. But it works in SerialEvent1. Only the problem seems to be in SerialEvent2.

I can not re-create your issue, I uploaded to my Uno

void setup() {
  Serial.begin(250000);
}

void loop() {
  Serial.println("YUP");
  delay(1000);
}

and to a Mega i bought for a project (that i may as well start on)

void setup() {
  Serial.begin(250000);
  Serial.println("Serial Started");
  Serial2.begin(250000);
}

void loop() {
}

void serialEvent2() {
  while (Serial2.available()) {
    Serial.write(Serial2.read());
  }
}

And that works

Deva_Rishi:
I can not re-create your issue, I uploaded to my Uno

void setup() {

Serial.begin(250000);
}

void loop() {
  Serial.println("YUP");
  delay(1000);
}




and to a Mega i bought for a project (that i may as well start on)


void setup() {
  Serial.begin(250000);
  Serial.println("Serial Started");
  Serial2.begin(250000);
}

void loop() {
}

void serialEvent2() {
  while (Serial2.available()) {
    Serial.write(Serial2.read());
  }
}


And that works

Thank you for your help. Yes, the code sample you provided worked successfully. The problem was that the MAX485's RX leg was faulty. The RX pin was pulling to LOW because it was faulty. For this reason, serialEvent2 was not triggered even though there was a signal. We noticed when we examined it with an oscilloscope. In short, the problem is not in Mega. The problem was at MAX485. I can not thank you enough.