SDI-12 on WisBlock

I want to use the WisBlock to read out an SDI-12 sensor. Does anyone know if it is possible using the RS485 interface (Transmit data efficiently with the LoRa®-powered RAK5802 module – RAKwireless Store)? I saw somewhere on the internet that someone used only the one connection from the RS485 differential pair, and connected that to the SDI-12 sensor. The other connection from the differential pair is then either left floating, grounded, or pulled to Vcc.

Or does RAK maybe plan to make an SDI-12 interface card for the WisBlock?

Hello JP,
I doubt that it will work with the RAK5802 module, but could be worth a try.

We are collecting customer feedback about interfacs/sensors that they would like to see supported by WisBlock and I will add your request to our list. But I cannot promise you anything.

I tried to speak SDI-12 using the RS485 connector board (RAK5802) today. So far I’m not successful. I’m not sure if I should use A or B, and if it’s fine to pull the other terminal to 3.3V or to GND. And I can’t find the Arduino forum post that described the setup.

Next step would be to try Arduino-SDI-12 but I’m not sure if the WisBlock has a free GPIO I can use for this. And then I’m also not sure if the library needs interrupts or not.

I’ll update here if I find anything. If you have any ideas, please let me know.

Following your need of an SDI interface module I put it on the list of new WisBlock modules for this year. But I cannot promise any availability date. We are planning at least 3 events this year where we will present new WisBlock modules.

At this point I need to find a way to test the viability of using the WisBlock to read out SDI-12 soil moisture probes. It needs to happen asap, as it influences business decisions.

We can’t wait for RAK to release a new comms module every time we want to do something new/custom. In this case the best is to find a way to directly interface with the WisBlock without a connectivity module. I’ll search for the docs and see if there is a GPIO which can be used.

I understand your problem.

If I might recommend something, look at

  • the RAK1920, which has several GPIO’s, SPI and I2C exposed on the Click! connector.
    image
  • or the 5804 which has all available GPIO’s, I2C, Serial and SPI exposed on a small connector. It comes with a matching connector and cable to connect external devices.
    image
1 Like

Yes, that is a good idea. What do you think about the J10 and J11 headers on the base board? I see J11 has a free GPIO on pin 2. That might work. I’m still looking through the documentation of the WisBlock to figure out exactly how to use these pin from Arduino.

IO1 on J11 would be available to use.

We know about the confusing different naming of GPIO’s on the RAK5005-O and the RAK4631.
In the next release of the Arduino BSP we will have all RAK5005-O GPIO’s predefined and linked to the correct GPIO numbers of the RAK4631.

For now you can use this list as a start:

	/*
 * WisBlock Base GPIO definitions
 */
	static const uint8_t WB_IO1 = 17;	   // SLOT_A SLOT_B
	static const uint8_t WB_IO2 = 34;	   // SLOT_A SLOT_B
	static const uint8_t WB_IO3 = 21;	   // SLOT_C
	static const uint8_t WB_IO4 = 4;	   // SLOT_C
	static const uint8_t WB_IO5 = 9;	   // SLOT_D
	static const uint8_t WB_IO6 = 10;	   // SLOT_D
	static const uint8_t WB_SW1 = 33;	   // IO_SLOT
	static const uint8_t WB_A0 = 5;		   // IO_SLOT
	static const uint8_t WB_A1 = 31;	   // IO_SLOT
	static const uint8_t WB_I2C1_SDA = 13; // SENSOR_SLOT IO_SLOT
	static const uint8_t WB_I2C1_SCL = 14; // SENSOR_SLOT IO_SLOT
	static const uint8_t WB_I2C2_SDA = 24; // IO_SLOT
	static const uint8_t WB_I2C2_SCL = 25; // IO_SLOT
	static const uint8_t WB_SPI_CS = 26;   // IO_SLOT
	static const uint8_t WB_SPI_CLK = 3;   // IO_SLOT
	static const uint8_t WB_SPI_MISO = 29; // IO_SLOT
	static const uint8_t WB_SPI_MOSI = 30; // IO_SLOT

WB_IOx refers to the IO name used on the RAK5005-O and on the modules.

I was able to get SDI-12 working on the Wisblock using SoftwareSerial. The ArduinoSDI12 library didn’t work, even after I hacked it to use the micros() timer for timing.

SoftwareSerial does not support any other serial mode than SERIAL_8N1. But SDI-12 uses SERIAL_7E1. I therefore manually add a parity bit to every byte before I transmit, and I ignore the parity bit on rx.

Example code below:

#include <SoftwareSerial.h>

SoftwareSerial sdi12rx(17, -1, true);
SoftwareSerial sdi12tx(-1, 17, true);

uint8_t command[] = "?I!";

uint8_t rxBuffer[64];

void setup() {
  Serial.begin(57600);
  while(!Serial);
  Serial.println("Startup");

  addParityBits(command, sizeof(command)-1);
}

void loop() {
  
  Serial.println("loop");

  Serial.print("Request: ");
  for(int i=0; i<sizeof(command); i++) {
    if(command[i] < 0x10) Serial.print("0");
    Serial.print(command[i], HEX);
    Serial.print(" ");
  }
  Serial.println();
  
  pinMode(17, OUTPUT);
  digitalWrite(17, HIGH);
  delay(12);
  digitalWrite(17, LOW);
  delay(9);
  
  sdi12tx.begin(1200);
  sdi12tx.write(command, sizeof(command)-1);

  delay(6);
  sdi12tx.end();
  pinMode(17, INPUT_PULLDOWN);
  
  sdi12rx.begin(1200);
  sdi12rx.setTimeout(2000);

  Serial.print("Response: ");
  unsigned long startTime = millis();
  int bytesRead = 0;
  while(millis()-startTime < 2000) {
    if(sdi12rx.available()) {
      uint8_t response = sdi12rx.read() & 0b01111111; // ignore parity bit
      rxBuffer[bytesRead++] = response;
      if(response == 0x0A) {
        break;
      }
    }
  }

  delay(6);
  sdi12rx.end();
  while(sdi12rx.available()) sdi12rx.read();
  
  pinMode(17, INPUT_PULLDOWN);
  Serial.println("RX closed");

  Serial.write(rxBuffer, bytesRead);

  delay(2000);
}

void addParityBits(uint8_t* dataBuffer, size_t bufferLength) {
  for(int i=0; i<bufferLength; i++) {
    uint8_t parity = calcParityBit(dataBuffer[i]);
    if(parity) {
      dataBuffer[i] = dataBuffer[i] | 0b10000000;
    } else {
      dataBuffer[i] = dataBuffer[i] & 0b01111111;
    }
  }
}

char calcParityBit (unsigned char v)
{
    return (0x6996u >> ((v ^ (v >> 4)) & 0xf)) & 1;
}

@jpmeijers
Congratulations.
If we ever make a SDI-12 module, might we use your patched SoftwareSerial library?

I’m using the standard SoftwareSerial library without any changed. All the required changes to do SERIAL_7E1 are done in the sketch posted above.

If you ever make an SDI-12 module, I would suggest you stick to HardwareSerial where one has native Serial Modes.