Boron Sensor using RS485

Hi @rickkas7 @ScruffR @peekay123

The last post got locked before I had the chance to reply / report back.
I grabbed the boards @peekay123 recommended for talking to RS485 sensor using Boron.

Code is compiling and I am getting data from the sensor but want to run the schematic and updated code by you guys for a sanity check :slight_smile:

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

// SYSTEM_MODE(MANUAL);
// SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(AUTOMATIC);
SYSTEM_THREAD(DISABLED);

SerialBuffer<256> rs485Buffer(Serial1); // use serial1 (D9/D10 tx/rx) for rs485 communication

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() {
  delay(100);
  for (byte i = 0; i < sizeof(nitro); i++) {
    rs485Buffer.write(nitro[i]);
  }
  delay(100);
  if (rs485Buffer.available() >= sizeof(nitro)) {
    for (byte i = 0; i < 7; i++) {
      values[i] = rs485Buffer.read();
      //Serial.print(values[i], HEX);
    }
    //Serial.println();
  }
  return values[4];
}

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

byte potassium() {
  delay(100);
  for (byte i = 0; i < sizeof(pota); i++) {
    rs485Buffer.write(pota[i]);
  }
  delay(100);
  if (rs485Buffer.available() >= sizeof(pota)) {
    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);
  delay(2500); // allow time to open serial port

  Serial1.begin(9600);
  rs485Buffer.setup();
  delay(1000);
  Serial.println();
}

void loop() {
  // turn on power to rs485 via D11
  pinMode(D11, OUTPUT);
  digitalWrite(D11, HIGH);
  delay(1500);

  // turn on step-up-converter by setting enable to low via D8
  pinMode(D8, OUTPUT);
  digitalWrite(D8, HIGH);
  delay(1500);

  for (int counter = 0; counter <= 5; counter++){
      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");
  Serial.println();

  // convert values to strings
  String nitrogenValue = String(val1);
  String phosphorousValue = String(val2);
  String potassiumValue = String(val3);
  delay(2500);

    if (counter == 5) {
      Particle.publish("NPK-Nitrogen", nitrogenValue, PRIVATE);
      Particle.publish("NPK-Phosphorous", phosphorousValue, PRIVATE);
      Particle.publish("NPK-Potassium", potassiumValue, PRIVATE);
  
      Serial.println("[ULTRA-LOW-POWER-SLEEP]");
      Serial.println("Going to Sleep.....");
      Particle.disconnect();
      delay(5000);
      SystemSleepConfiguration config;
      config.mode(SystemSleepMode::ULTRA_LOW_POWER).duration(1440min);
      System.sleep(config);
      Serial.println("Awake from Sleep, Restarting Device.....");
      System.reset(); // code execution starts back in void setup()
    }
  }
}

I am using a step-up-converter since the sensor requires 12V.

@babsndeep, some thoughts:

Regarding the schematic:

  • Does the Boost w/EN (3.3-12v) have a built-in pull-up resistor on the EN pin. If not, you should add one.
  • How is the unit powered? Only via the CR123A? If so, at 3V it will not be enough to power the Boron. You show 3.3v-4.2v so not sure what battery you intend to use and if it is being charged via USB or other method.
  • I assume the NPK RS485 box is your sensor powered via 12Vdc, correct? How far is the sensor from the Boron?
  • Why is D11 powering Vcc of the TTL-RS485 module? The GPIO output current on the Boron is likely not high enough to power the module.

Regarding the code:

  • You have pinMode() in loop() which is not necessary since ULTRA_LOW_POWER sleep mode maintains GPIO settings and states. However, since you so a System.reset() after sleeping, it is "good form" to put single run code, such as the pinMode() commands in setup().
  • You should consider a single function for sending/receiving to the sensor. The function should have two arguments: a pointer to the command bytes array and a pointer to a values array. The function would use the command pointer to output the command and then use the values pointer to receive the data. However, I notice you only return values[4] indicating that the other received bytes may be response bytes such as address or ack/nack. You don't validate any of that before "accepting" the last byte.
  • To reduce cloud operations, you may want to have a single publish and combine the values into a single c-string using snprintf() for example.
  • You may want to wait for 'Particle.disconnected()` before sleeping. Alternatively, you could use Particle.setDisconnectOptions() to disconnect gracefully before sleeping.
3 Likes

@peekay123 @ScruffR @rickkas7

Schematic

  • No datasheet for the Boost unfortunately but I can see EN connected to an SMD resistor which I assume is the pull-up resistor.
  • Boron is powered by a 4.2V battery with its own charging circuit that's separate from the additional 4.2V that powers the Boost and NPK sensor with Boron I/O pins (D8) controlling the EN of the Boost.
  • Correct, NPK RS485 is sensor powered via 12VDC, less than 1FT from Boron.
  • (D11) is powering the TTL-RS485 chip for controlling ON/OFF. Should I switch the power for TTL-RS485 from Boron OI (can't find the current draw of the TTL-RS485) to Battery and control it using Boron IO using Transistor like for the Boost?

Code

  • Thanks for the single run code pointer, moving to setup().
  • Will do on single function with command and values array as well as validating.
  • The final code will combine publish.
  • Will do on disconnect before sleeping.

Thanks again for taking the time to help.
Looking forward to the response to above updates.

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