RS485 ASCII protocol instead of MODBUS RTU

I’m working on a university project on energy monitoring system and I need to communicate with my digital sensor via RS485 but it use RS485 ASCII protocol instead of MODBUS RTU, As a fact that I hope I’m unable to use ModbusMaster library. has anyone encounter this before ?
I’ll really appreciate if someone can guide me to find code sample or library to fit for RS485 ASCII protocol .

Sensor guidelines for RS 485 ASCII protocol.

Suppose to use this converter to connect Arduino
(http://www.ebay.com/itm/170934217208?ssPageName=STRK:MEWNX:IT&_trksid=p3984.m1439.l2649)

could anyone help me…. :frowning:

You don't say what arduino you have but you will probably need to connect to a spare serial port (Mega) or use software serial port on other arduino's like the UNO. The adaptor needs connecting to arduino using 5V, Gnd, Di, Do and one or two pins for DE & RE. The ASCII protocol is the same as the arduino uses to talk to and reads text from the PC so that's the easy part.
Arduino RS485
5V VCC
GND GND
TX DI
RX DO
DE & RE can be connected to the same arduino pin and are used to tell the RS485 device if it's transmitting or receiving (It can only do one or the other at one time). You could write a simple TX routine that sets the device to transmit mode, send your commands and then switches device to receive mode to read back any results. If there is a possibility you will need to send and receive at the same time then you will need to use two RS485 devices and a hardware serial port.

[/center]

Thank you very much for the help, I’m working with UNO board. I connected my transducer according to this diagram and wrote a simple code to read the values. But it reads -1 as the output(RX LED on the board never blinks) though I expect to read Transducer name (result is same for every transducer commands, Transducer data communication indicator(LED) also not blinked as it should be- once received the command ).
I know my code is so simple but do I in the correct track ? and what is the Err I made here ?
Please guide me.

My code:

#include <SoftwareSerial.h>
SoftwareSerial mySerial(0, 1); // RX, TX
void setup() {

Serial.begin(9600);
Serial.println("Serial Start");
mySerial.begin(9600);
}

void loop() {

digitalWrite(3, HIGH);
mySerial.write("$01M"); // "$01M" is the command to read transducer’s name
digitalWrite(3, LOW);
delay(10);
Serial.println(mySerial.read());

delay(2000);
}

There are a few problems I can see straight away.
You have configured software serial to use the same pins as the hardware serial used to talk to the PC over USB. Change the pins it uses from 0,1 to something like 4,5 and also move the RO & DI pins to these.
The RS485 steering pin (D3) has not been configured as an output pin so all your doing is turning on/off the pins internal pullup resistor and not sending the pin HIGH/LOW.
The command you send ends with but this is only an indication you should be sending a Carriage Return character which is 13 (0x0D) in ASCII. I think you can replace the with \r in the string and it will do the job (\r is a C++ escape sequence code that gets converted to character 13)
You should use code tags (the # character above the smilies) when posting code. The below code may work and allow you to send commands from the serial monitor window (You may need to set CR line ending in the drop down box)

#include <SoftwareSerial.h>
SoftwareSerial mySerial(4, 5); // RX, TX
void setup() {
  pinMode(3,OUTPUT);
  Serial.begin(9600);
  mySerial.begin(9600);
  Serial.println("Serial Start");
  digitalWrite(3, HIGH);
  mySerial.print("$01M\r"); // "$01M<CR>" is the command to read transducer’s name
  delay(10);                // ??Delay to allow Serial to send before turning RS484 output off (may need to be bigger/smaller or not at all if print is blocking)
  digitalWrite(3, LOW);
}

void loop() {
  if (mySerial.available())
  Serial.write(mySerial.read());
  if (Serial.available())
  digitalWrite(3, HIGH);
  mySerial.write(Serial.read());
  delay(10);
  digitalWrite(3, LOW);
}

Thank you very much for the guidance , after changing the code now transducer can receive the signals from Arduino (LED on the Sensor correctly indicate the receipt of correct command) but still I’m getting Null (noting is printed on the Serial monitor) as the response. I changed the delay time several time but it didn’t workout.. what could be the reason behind this?
(my expected return value is “! 01J42”)

Sorry I just noticed the lack of brackets in the loop routine. Try this...

void loop() {
  if (mySerial.available()){
    Serial.write(mySerial.read());
  }
  if (Serial.available()){
    digitalWrite(3, HIGH);
    mySerial.write(Serial.read());
    delay(10);
    digitalWrite(3, LOW);
  }
}

You may still need to adjust (or even remove) the delay time unless someone else can tell you if the SoftwareSerial .print and .write commands are blocking (don't return until completely sent).

I think that transmission from Arduino to transducer is okay, because once transducer get carriage return “\r” green indicator will on (according to the manufacturer, which indicates the data return from transducer) . I have uploaded a video to youtube (Arduino RS485 - YouTube)

My issue is it always returns 0 instead of expected value
Ex :
My command = $01M\r ---> I expected as return = ! 01J421 ---> but my return = 0
Not only to this command but it return 0, for what every the text ending with carriage return “\r”
it’s difficult to find what is the wrong point whether it is with the transducer or in my code. :~

#include <SoftwareSerial.h>
SoftwareSerial mySerial(4, 5); // RX, TX

void setup() {
  pinMode(3,OUTPUT);
  Serial.begin(9600);
  mySerial.begin(9600);
  }

void loop() {

  if (mySerial.available())
   {
     Serial.println(mySerial.read());
   }
  if (Serial.available())
   {
     digitalWrite(3, HIGH);
     mySerial.write(Serial.read());
     delay(10);
     if(!Serial.available())
      {
       digitalWrite(3, LOW);
      }
    }
}

Please post your amended code inside code tags.

Read this before posting a programming question

If you use the below code then I assume your getting the 'READY' text in your serial monitor. I'm just checking the serial between arduino and PC are good.
Does the green LED on the transducer still illuminate if you leave the delay commented out? I am wondering if your missing serial data from the transducer because the RS485 chip is held in send mode for to long after sending the last character.
What happens if you request a longer response with something like #01A do you get some of the data back okay?
Another thing to try is using SoftwareSerial mySerial(4, 5, TRUE); // RX, TX, Inverse Logic as the RS485 adaptor may be using it.
Other than that the only things I could suggest is using a Mega instead of an UNO as it has more than one hardware serial port or maybe try using another RS485 adaptor that can TX and RX at same time without the need of steering.

#include <SoftwareSerial.h>
SoftwareSerial mySerial(4, 5); // RX, TX

void setup() {
  pinMode(3,OUTPUT);
  Serial.begin(9600);
  mySerial.begin(9600);
  Serial.println("READY");
}

void loop() {
  
  if (mySerial.available())
  {
    Serial.println(mySerial.read());
  }
  while (Serial.available())
  {
    digitalWrite(3, HIGH);
    mySerial.write(Serial.read());
  }
  //delay(10);
  digitalWrite(3, LOW);
}

“READY” is printed on the Serial monitor (no issue with the PC & Arduino connection), I even have test the serial using 3rd party serial monitoring tool(C2000 Software- Com Test) but the result is same as Arduino Serial Monitor.

Does the green LED on the transducer still illuminate if you leave the delay commented out?

Command is not recognized as a valid command until I put delay (10) in to the end of the while loop

while (Serial.available())
  {
    digitalWrite(3, HIGH);
    mySerial.write(Serial.read());
    delay(10);
      }

What happens if you request a longer response with something like #01A do you get some of the data back okay?

#01A doesn’t recognized as a valid command but it does for #01A\r (any text ending with \r or \n OR along \r or \n will light up the green led indicating data communication)

SoftwareSerial mySerial(4, 5, TRUE); doesn’t recognize as a valid code.

kasun:
“READY” is printed on the Serial monitor (no issue with the PC & Arduino connection), I even have test the serial using 3rd party serial monitoring tool(C2000 Software- Com Test) but the result is same as Arduino Serial Monitor.
Okay, that's fine. Just wanted to confirm the serial was fine between arduino and PC.

Does the green LED on the transducer still illuminate if you leave the delay commented out?

Command is not recognized as a valid command until I put delay (10) in to the end of the while loop
What if you reduce the delay to nothing but leave it in...

  while (Serial.available())

{
    digitalWrite(3, HIGH);
    mySerial.write(Serial.read());
  }
  delay(0);
  digitalWrite(3, LOW);




#01A<CR> doesn’t recognized as a valid command but it does for #01A\r (any text ending with \r or \n OR along \r or \n will light up the green led indicating data communication)
But are you only sending \r because if your sending \r\n then that will delay the switching of the RS485 module back to receive mode or may cause the transducer to respond in unexpected ways. The PDF you linked to specifically shows commands ending in \r only. What do you get back from this though? Does it look like an expected response but missing a few characters from the beginning or is it still just 0?

SoftwareSerial mySerial(4, 5, TRUE); doesn’t recognize as a valid code.
Sorry I think it should be 'true' and not 'TRUE'. My problem with mixing up languages, I wish I could stick to just one. :(

you are correct… once it change to ‘true’ it recognized as a valid code but once I change, it will return 00 for each character I send as the command.
Ex
command: #01A\r - -> return 000000000000
command: \r - -> return 0000
command: abc - -> return 000000 -->(this is not a valid command, it can be any text)

I found a similar example from RS485 - SoftSerial works, hardware doesn't - Programming Questions - Arduino Forum

void startpomiaru(){ // start measure 
  digitalWrite(pinControl,HIGH);
  delay(1);
  mySerial.write(58); //:
  mySerial.print("0101000111");
  mySerial.write(13); //cr
  mySerial.write(10); //lf
  delay(1);
  digitalWrite(pinControl,LOW);
}

But it it need to be clarified some points
• Pass decimal value of the ASCII characters
• Used binary command with mySerial.print() instead of mySerial.write()
• Sending both CR and LF
Since they say this is working example, I think that I can get something from this (but tested board is not UNO)
Thank you in Advance for further assistance.

kasun:
you are correct… once it change to ‘true’ it recognized as a valid code but once I change, it will return 00 for each character I send as the command.
Okay, lets forget the inversion thing for now. Stick to 'SoftwareSerial mySerial(4, 5);'

I found a similar example from RS485 - SoftSerial works, hardware doesn't - Programming Questions - Arduino Forum

But it it need to be clarified some points
• Pass decimal value of the ASCII characters
When you use Serial.print("M"); you are passing the decimal value of the ASCII character M (decimal 77, hex 0x4D). If you wanted to pass the decimal representation of the ASCII character M then you would print("77") or print("4D") but this is not what you need according to the pdf.
• Used binary command with mySerial.print() instead of mySerial.write()
The other thread you linked to is sending what looks like binary but it's really just ASCII 0 & 1's it sending.
• Sending both CR and LF
Serial.write(13) and Serial.print("\r") will send the same values. The PDF you linked to shows you only need and not ($01M (24H 30H 31H 4DH 0DH) )
Since they say this is working example, I think that I can get something from this (but tested board is not UNO)
Thank you in Advance for further assistance.
Unless I am missing something then the code should work once the delay is tuned. The important bit (as discussed in the other thread) is to ensure the delay is just long enough to allow the last character to fully send before switching the RS485 back to receive mode. To short and you cut off the last character, to long and you may miss some/all of the reply.

Are you sure the PDF is for the device you have (what is the exact device make/model).

I'm kinda stuck in absolutely the same problem, I'm trying to read a relative humidity / temp sensor, (Rotronic, HC2) And I have some trouble even knowing if I have to write jus { 99RDD} \r, everything in hex or what, in the instructions they just tell me to send it like that, so everything I do is to use quotes... and nothing happens... Have you got to any conclussion yet??