Boron Sensor using RS485 via MAX485 Breakout Transceiver

Hi All,

I am trying to get data from a sensor with rs485 output using the max485 breakout transceiver to convert uart to rs485.

Connections:
MAX485 Vcc ==> Boron VUSB (while connected via USB)
MAX485 GND ==> Boron GND & Sensor GND
MAX485 B ==> Sensor RS485-B
MAX485 A ==> Sensor RS485-A
MAX485 DI ==> Boron D9
MAX485 DE ==> Boron D3
MAX485 RE ==> Boron D2
MAX485 RO ==> Boron D10

Sensor Vcc is connected to external 12V w/ common GND with Boron & MAX485.
I am not seeing any output on the serial port when using particle-cli.

#include <Particle.h>
#include <SerialBufferRK.h>

SYSTEM_MODE(MANUAL);
SYSTEM_THREAD(ENABLED);

SerialBuffer<256> rs485Buffer(Serial1); // Use Serial1 for RS485 communication

const int RE = D2;  // Receiver Enable pin connection
const int DE = D3;  // Driver Enable pin connection

const byte nitro[] = {0x01, 0x03, 0x00, 0x1e, 0x00, 0x01, 0xe4, 0x0c};
const byte phos[] = {0x01, 0x03, 0x00, 0x1f, 0x00, 0x01, 0xb5, 0xcc};
const byte pota[] = {0x01, 0x03, 0x00, 0x20, 0x00, 0x01, 0x85, 0xc0};

byte values[11];

byte nitrogen() {
  digitalWrite(DE, HIGH);
  digitalWrite(RE, HIGH);
  delay(10);
  for (byte i = 0; i < sizeof(nitro); i++) {
    rs485Buffer.write(nitro[i]);
  }
  if (rs485Buffer.available() >= sizeof(nitro)) {
    digitalWrite(DE, LOW);
    digitalWrite(RE, LOW);
    for (byte i = 0; i < 7; i++) {
      values[i] = rs485Buffer.read();
      Serial.print(values[i], HEX);
    }
    Serial.println();
  }
  return values[4];
}

byte phosphorous() {
  digitalWrite(DE, HIGH);
  digitalWrite(RE, HIGH);
  delay(10);
  for (byte i = 0; i < sizeof(phos); i++) {
    rs485Buffer.write(phos[i]);
  }
  if (rs485Buffer.available() >= sizeof(phos)) {
    digitalWrite(DE, LOW);
    digitalWrite(RE, LOW);
    for (byte i = 0; i < 7; i++) {
      values[i] = rs485Buffer.read();
      Serial.print(values[i], HEX);
    }
    Serial.println();
  }
  return values[4];
}

byte potassium() {
  digitalWrite(DE, HIGH);
  digitalWrite(RE, HIGH);
  delay(10);
  for (byte i = 0; i < sizeof(pota); i++) {
    rs485Buffer.write(pota[i]);
  }
  if (rs485Buffer.available() >= sizeof(pota)) {
    digitalWrite(DE, LOW);
    digitalWrite(RE, LOW);
    for (byte i = 0; i < 7; i++) {
      values[i] = rs485Buffer.read();
      Serial.print(values[i], HEX);
    }
    Serial.println();
  }
  return values[4];
}

void setup() {
  Serial.begin(9600);
  pinMode(RE, OUTPUT);
  pinMode(DE, OUTPUT);
  digitalWrite(RE, LOW); // Set RE pin to receive mode
  digitalWrite(DE, LOW); // Set DE pin to receive mode
  delay(500);
}

void loop() {
  byte val1, val2, val3;
  val1 = nitrogen();
  delay(250);
  val2 = phosphorous();
  delay(250);
  val3 = potassium();
  delay(250);

  Serial.print("Nitrogen: ");
  Serial.print(val1);
  Serial.println(" mg/kg");
  Serial.print("Phosphorous: ");
  Serial.print(val2);
  Serial.println(" mg/kg");
  Serial.print("Potassium: ");
  Serial.print(val3);
  Serial.println(" mg/kg");

  delay(2000);
}

I am using the SerialBufferRK library (guessing written by @rickkas7) any help is appreciated!
@peekay123 @ScruffR

I'd be surprised about that tho'
Even with the sensor not working at all, you should at least see the static output of your loop().
If that is not the case you have other problems (e.g. code not running, wrong command, defective cable, defective USB port, ...)

However, one issue I see is that you are checking immediately and only once after your write-loops whether all data has arrived and if not (yet), you move on.
I guess you should allow some time for the data to become available after checking and reading.

BTW, you can write and read streams in a single command. You wouldn't need to do it byte by byte.

1 Like

That setup is not safe on the Boron and can damage the UART RX pin. You have the MAX485/breakout board attached to VUSB. That means the MAX485 will output 5V on the RX pin, and GPIO (including RX) is not 5V tolerant on the Boron. Some of the comments on the Amazon page indicate that the breakout board works at 3.3V, and some say it doesn't, but you really need a board that is designed to work at 3.3V to avoid damaging the Boron GPIO.

You're missing two important pieces of initialization in setup():

  • You never call Serial1.begin(9600); or whatever baud rate you are using. The port won't work if you don't initialize it.
  • You're not calling rs485Buffer.setup(); from setup(). If you don't initialize the library, it won't work either.

This is not the cause of your problem, but the MAX485 pins are actually /RE and DE. In other words, receive enable is active low and transmit enable is active high. You normally tie both of them together on a single GPIO and leave the pin LOW except when transmitting.

2 Likes

@babsndeep, these RS485 boards on Amazon seem to have level shifters allowing for operation at 3.3v and 5v. They also support automatic flow-control.

1 Like

Awesome!
Thanks @peekay123 just grabbed those from Amazon, will try when they're delivered and report back!

1 Like

Thanks @rickkas7
I'll try the changes with the new breakout that @peekay123 linked and report back.

1 Like

I'm using ModbusMaster-Particle lib on Argon and that works nicely for me.

I had a terrible time with the cheap amazon RS485 modules burning up after a day or two. At first I thought it was a software issue, but simply swapping a module (with no s/w changes) would see it start working again until the next day.

Instead, I'm using a Gravity Isolated RS485 module from dfrobot, and it's been running flawlessly for more than a year. It's a little more pricey ($20 for 1x instead of $7 for 10x), but it's saved a lot of time and headache for me.

2 Likes

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