RS485 ASCII Protocol - No response

I am trying to read a mains frequency from SD037 Frequency Monitor with filter , using ASCII protocol over RS485. I am not getting any response. Please correct if I have done any mistake in the code below. Thank you.

I am using Arduino Mega2560 and DFRobot RS485 shield v1.0

// Sending Command to read frequency is *F?\r\n

#include "ModbusRtu.h"

#define DEBUG 0
#define ID 2
#define UART 3

// assign the Arduino pin that must be connected to RE-DE RS485 transceiver
#define TXEN  4 

Modbus slave(ID, UART, TXEN); // this is slave ID and RS-232 or USB-FTDI


void setup() {
   Serial.begin(38400);
   slave.begin(9600); // baud-rate at 9600
}

void loop() {
   char cmd[5]; 
   cmd[0] = '*';
   cmd[1] = 'F';
   cmd[2] = '?';
   cmd[3] = '\r';
   cmd[4] = '\n';
   int n = sizeof(cmd)/sizeof(cmd[0]);
   Serial.write(cmd,n);
   Serial.println();
   delay(1000);
   if(Serial.available() > 0 ) {
       Serial.println("Receiving:");
       Serial.println(Serial.read());
   }
   delay(1000);
}

Why do you have the following statement:#include "ModbusRtu.h"Get rid of it, you either have the Arduino communicate Modbus or ASCII and I understand you are wanting the Arduino to communicate with ASCII. If so, get rid of all other Modbus related commands while you are at it.

Using simple ASCII commands over IEA-485, you will need to code the operation of the IEA-485 transmitter enable pin, which you have defined as pin 4, otherwise nothing will work, the Arduino will never send data over EIA-485 with the transmitter pin not controlled correctly.

Also, for good programming practice, take the char cmd[5] and the following assignments out of the main loop, you only need to do this once at startup, not each scan of the main loop.

After the Serial.write(cmd,n) the Arduino sends a character of new line, why, it is already being sent with the last few parts of the command, with \r being carriage return and \n being new line, so, get rid of that statement.

Next, the Arduino is always sending the command, without regard that you might be overflowing the buffer of the device, which could be bad depending on how the external device handles incoming data.
Go and look at the learning or reference part of using the Serial port on the Arduino

Basically, your code is a mess !
You are asking the Arduino to write the command out on a serial port and then you are asking the Arduino to do a serial print back to the same port.

I imagine you want the Arduino to communicate to the device on a given port and then back to your computer on another communications port, correct ?

So, program it that way then :slight_smile:


Paul - VK7KPA

Hi Paul,

Thank you very much for your feedback and suggestions. I followed your points and now I am getting the exact response.

But, I am able to read only first few readings and after that Serial monitor goes blank. Could you please help me on this? Thanks..

Hi, glad to hear you have made some progress.
Please post your new code so we can see what you have so far now.

Also, a sample of data of what of what you are getting on the serial monitor would be helpful too.


Paul VK7KPA

Hi Paul,

I fixed the bug. Now I am getting the response continuously. Here is my code and a response. Please let me know if you find any mistakes again.Thank you.

/*Send command to read the frequency*/

char command[4] = {'*', 'F', '?', '\r'}; 
int n = sizeof(command)/sizeof(command[0]); // Number of elements in an array

void setup() {
  // initialize serial ports
  Serial.begin(115200);    // USB serial port 0
  Serial3.begin(9600);   // serial port 3
}

byte rx_byte = 0;        // stores received byte

void loop() {
   
    Serial3.write(command,n);
    Serial.flush();
    delay(250);
    
  // check for data byte on serial port 3
  while (Serial3.available()) {
    // get a byte from serial port 3
    rx_byte = Serial3.read();
    // send the byte to the USB serial port
    Serial.write(rx_byte);
  }
}

FreqMeterReadings.txt (17.4 KB)

It is Serial3.flush(). I changed in my code.

Well done, it looks like you have working code now :slight_smile:
There are a few things I might do differently, but that comes down to coding style.

I guess the next thing you might like to do is put the data into a different data type, either scaled integer or float.
I always tend to use integer, never floats. So, if I want two decimal places I will multiply by a factor of 100.
Then, for example, I will divide by 100 in my SCADA software to represent the actual float at display time only.

Enjoy playing and experimenting with your code to see how you can make it better.
Again, well done, you really made great progress :slight_smile:


Paul VK7KPA

Hi Paul,

I really appreciate your advice.

In my project I have to read the frequency with 4 digits after decimal (Ex: 50.1234)

I have a task to do in which, Arduino should mimic as a frequency meter. So I have to send the command but read the values which are stored in array and the output values should appear with 4 digits after decimal point.

In the above code (previous post) I was reading the values from frequency meter. But now I have to read my own values in the format that gives 4 digits after decimal. From Serial I can get only 2 digits(50.12), I have to get 50.1234. Any pointers how can I achieve this? Thanks in advance.

Finally I managed to get the correct output. Thank you.