A0221A4 ultrasonic sensor of RS-485 comm

Hello all, i am using the a RS485 ultrasonic sensor module "A0221A4". I connected the sensor to a TTL to RS-485 module and connected the module to the arduino uno over pin 10 and 11 to act as RX-TX pins.
I am trying to send a command to the RS485 module to get the distance via softwareserial and failing. is there a specific library or an arduino uno example to use for that sensor. You can find the rs485 command data sheet for that sensor in this link https://www.aliexpress.com/item/1005003691760080.html

The following is the circuit used:

The code used to get the address from the A0221A4 is as follow:

#include <Arduino.h>
#include <SoftwareSerial.h>

byte GET_ADDRESS[8] = {0xFF, 0x03, 0x02, 0x00, 0x00, 0x01, 0x90, 0x6C};

SoftwareSerial mySerial(10, 11);
bool requested = false;

void setup()
{
    Serial.begin(115200);
    mySerial.begin(9600);
    Serial.println("Begin Program...");
}

void loop()
{
    if (!requested)
    {
        Serial.print("Getting Address: ");
        for (int i = 0; i < 8; i++)
        {
            Serial.print(GET_ADDRESS[i], HEX);
            Serial.print(" ");
            mySerial.print(GET_ADDRESS[i], HEX);
        }
        Serial.println();
        mySerial.flush();
        requested = true;
    }
    if (mySerial.available() > 0 && requested)
    {
        for (int i = 0; i < 7; i++)
        {
            Serial.print(mySerial.read(), HEX);
            Serial.print(" ");
        }
        requested = false;
        Serial.println();
    }
}

Thanks in advance

Welcome to the forums. Please read this tutorial: How to get the best out of this forum - Using Arduino / Installation & Troubleshooting - Arduino Forum

And then post your code, using code tags. Otherwise, folks won't be able to help.

2 Likes

All of those ground pins need to be tied together so you have a common ground across the entire system.

What you are seeing on the serial monitor when your program runs?

Thanks for the reply. As you mentioned i tried connecting the ground together and it was the same thing. Also after sending the 8byte hex code of get_address i am not getting anything as a reply.

This is the serial monitor log:

Begin Program...
Getting Address: FF 3 2 0 0 1 90 6C

N.B. I tried the sensor by directly connecting it to pc vial usb-rs485 adapter and did get a reply from the sensor using a serial monitor software. The modbus hex sent was ff 03 02 00 00 01 90 6c and the received data was 01 03 02 00 01 79 84 which is correct.

The bus transceiver controls RE and DO are not connected. In that case, the transceiver can't change the bus data direction. As well as connecting them, they have to be controlled in software.

yes.
and the transmitter needs to be enabled during transmission. flush() can be called to wait for transmission to complete and the transmitted disabled allowing reception of a response

other questions

  • presumably GET_ADDRESS [] is the command requesting a response from your sensor. are you sure the sensor expects ASCII chars, if so does each ASCII value need a space between it and the next
  • why not always process any available data from the sensor (i.e. mySerial)? why make it contingent on requested?
  • why not print everything received from mySerial, why limit it to 7 characters? if there is a specific end character in the response, consider using Serial.readBytesUntil()

i don't believe that's necessary for the balance pair rs-485 signal. there's no common ground between a USB rs-485 adapter and rs-485 bus

There should be some common ground, at least through safety ground. But it isn't part of the signal path at all. It will operate without it.

From what the datasheeet of the sensor mentioned, the sensor expects an 8 hex code request and a response of 7 hex codes.
e.g. Host (TX): FF 03 02 00 00 01 90 6C
The sensor replies:
(RX): 01 03 02 00 01 79 84
The space is just for debugging. The actual code that is sent to the sensor is from the SoftwareSerial via "mySerial" variable.

I've connected the RE and DE to pin 5 on the arduino. The code now is the following:

#include <Arduino.h>
#include <SoftwareSerial.h>

byte GET_ADDRESS[8] = {0xFF, 0x03, 0x02, 0x00, 0x00, 0x01, 0x90, 0x6C};

SoftwareSerial mySerial(10, 11);
#define TRN_PIN PIN5

void setup()
{
    Serial.begin(115200);
    mySerial.begin(9600);
    Serial.println("Begin Program...");
    pinMode(TRN_PIN, OUTPUT);
}

void loop()
{
    digitalWrite(TRN_PIN, 1);
    Serial.print("Getting Address: ");
    for (int i = 0; i < 8; i++)
    {
        Serial.print(GET_ADDRESS[i], HEX);
        Serial.print(" ");
        mySerial.print(GET_ADDRESS[i], HEX);
    }
    Serial.println();
    mySerial.flush();
    digitalWrite(TRN_PIN, 0);
    delay(100);
    if (mySerial.available() > 0)
    {
        for (int i = 0; i < 7; i++)
        {
            Serial.print(mySerial.read(), HEX);
            Serial.print(" ");
        }
        Serial.println();
    }
    delay(1000);
}

still no reply coming from the sensor.

Is the device guaranteed to respond within 100ms? If it doesn't, your code ignores it.

You could check that by accessing it via the USB adapter and sniffing the serial lines.

Or, make the interval longer for testing.

The best way would be a very short bus turn around delay, start accepting characters immediately, subject to a much longer time out.

I've removed the 100ms delay and added a 5 seconds timeout delay instead but still no response.

#include <Arduino.h>
#include <SoftwareSerial.h>

byte GET_ADDRESS[8] = {0xFF, 0x03, 0x02, 0x00, 0x00, 0x01, 0x90, 0x6C};

SoftwareSerial mySerial(10, 11);
#define TRN_PIN PIN5

#define TIMEOUT_DELAY 5000

void setup()
{
    Serial.begin(115200);
    mySerial.begin(9600);
    Serial.println("Begin Program...");
    pinMode(TRN_PIN, OUTPUT);
}

unsigned long time = 0;

void loop()
{
    time = millis();
    digitalWrite(TRN_PIN, 1);
    Serial.print("Getting Address: ");
    for (int i = 0; i < 8; i++)
    {
        Serial.print(GET_ADDRESS[i], HEX);
        Serial.print(" ");
        mySerial.print(GET_ADDRESS[i], HEX);
    }
    Serial.println();
    digitalWrite(TRN_PIN, 0);
    while (mySerial.available() == 0)
    {
        if (millis() - time > TIMEOUT_DELAY)
        {
            Serial.println("Request Timed Out...");
            break;
        }
    }
    if (mySerial.available() > 0)
    {
        for (int i = 0; i < 7; i++)
        {
            Serial.print(mySerial.read(), HEX);
            Serial.print(" ");
        }
        Serial.println();
    }
}

Also this is an example from the serial monitor on pc of how the messaging happened in the serial monitor software:

I'm not digging deeply, but shouldn't it be

        mySerial.write(GET_ADDRESS[i], HEX);

in the case that the device accepts raw data, not ASCII hex?

1 Like

After reading through the AliExpress page and what you've told us so far, one of your problems could to be in this bit of code.

Modbus expects a stream of bytes as it monitors the time between the bytes to spot a new message. Try removing (or commenting out) the 2 Serial.print() commands.

Also note that you can write out the command without the use of the loop by doing:

mySerial.write( GET_ADDRESS, sizeof( GET_ADDRESS ) );

And, a delay of around 1 second should be enough for a reply whilst testing.

1 Like

Yes that was the problem. I should have used write instead of print. The problem was with the print and the RE and DE not being controlled. Thanks alot and here is the working code:

#include <Arduino.h>
#include <SoftwareSerial.h>

byte GET_ADDRESS[8] = {0xFF, 0x03, 0x02, 0x00, 0x00, 0x01, 0x90, 0x6C};
byte GET_DISTANCE[8] = {0x01, 0x03, 0x01, 0x00, 0x00, 0x01, 0x85, 0xF6};

SoftwareSerial mySerial(10, 11);
#define TRN_PIN PIN5

#define TIMEOUT_DELAY 5000

unsigned long time = 0;

void sendData(String note, byte *data)
{
    time = millis();
    digitalWrite(TRN_PIN, 1);
    Serial.print(note);
    for (int i = 0; i < 8; i++)
    {
        Serial.print(data[i], HEX);
        Serial.print(" ");
    }
    Serial.println();
    Serial.flush();
    mySerial.write(data, 8);
    mySerial.flush();
    digitalWrite(TRN_PIN, 0);
    delay(10);
}

void receiveData()
{
    byte data[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    while (mySerial.available() == 0)
    {
        if (millis() - time > TIMEOUT_DELAY)
        {
            Serial.println("Request Timed Out...");
            break;
        }
    }
    if (mySerial.available() > 0)
    {
        mySerial.readBytes(data, 7);
        for (int i = 0; i < 7; i++)
        {
            Serial.print(data[i], HEX);
            Serial.print(" ");
        }
        Serial.println();
    }
    delay(10);
}

void setup()
{
    Serial.begin(115200);
    mySerial.begin(9600);
    Serial.println("Begin Program...");
    pinMode(TRN_PIN, OUTPUT);
    sendData("Getting Address: ", GET_ADDRESS);
    receiveData();
}

void loop()
{
    sendData("Getting Distance: ", GET_DISTANCE);
    receiveData();
    delay(1000);
}
1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.