RS 485 communication two Geokon VW sensors

Hi all,

My programming level is very basic and I want some help.

Below a code to interrogate a VW sensor using Arduino Mega. The code works well for one sensor.

Can someone help me modify the code so it can read and display TWO sensors?

Thanks a lot.


#include  <ModbusMaster.h>    // For Modbus communication
ModbusMaster node;          // Initialise a modbusmaster node object

// == 1 GLOBAL VARS ==

const int enablePin = 7;    // pin is held high for transmit, low for recieve
byte sensorAddress = 0x01;  // the address of the sensor, default = 1

bool smallSensor = true;   // set this to true if using geokon 4202 (small vw sensor), otherwise false for 4200 (large sensor)
int readDelay = 1000;       // milliseconds between strain readings. Ensure this is not lower than 370 ms.

// == 1 END GLOBAL VARS ==


// == 2 SUPPORT FUNCTIONS ==

// function 1 required to make MAX485 work
void  preTransmission() {
  digitalWrite(enablePin, HIGH); // transmit
  delay(10);
}

// function 2 required to make MAX485 work
void  postTransmission() {
  delay(1); // must set delay(1). delay(2) = E0 error, delay(1) = 0 (no error).
  digitalWrite(enablePin, LOW); // recieve
}

// function to convert two 16-bit hex values into a float (as per geokon manual)
// and https://gregstoll.com/~gregstoll/floattohex/
float hexToFloat(uint16_t A, uint16_t B) {
  // This will work for IEEE-754 floating point responses in two parts
  unsigned int data[2] = {A, B};
  float floatingNumber;
  memcpy(&floatingNumber, data, 4);
  return floatingNumber;
}

// function to read temperature of geokon sensor
float getTemperature() {
  uint16_t resultMain;

  // read the onboard thermistor resistance (2 registers at 0x0102)
  resultMain = node.readHoldingRegisters(0x0102, 2);

  if (resultMain == node.ku8MBSuccess) {    // if error code returned = 0 (no error)

    // convert the data (hex) into float
    float TempC = hexToFloat(node.getResponseBuffer(0x00), node.getResponseBuffer(0x01));

    // This function is the fit between resistance and temperature between 0 and 30 degC (see excel sheet)
    float T = 197.14 - 21.5 * log(TempC);     // to do: calibrate, can't rely on factory data.
    return T;

  } else {
    return -1000;  // function returns an unphysical value if read fails
  }

}


// function to ping and read frequency of geokon sensor's vibrating wire
float getFrequency() {

  uint16_t resultMain;

  //ping the VW strain gauge by writing 1 to 0x0118
  resultMain = node.writeSingleRegister(0x0118, 1);

  // wait at least 370 ms
  delay(readDelay);

  //read two holding registers at 0x0100 to retrieve frequency
  resultMain = node.readHoldingRegisters(0x0100, 2);

  if (resultMain == node.ku8MBSuccess) {    // if error code returned = 0 (no error)

    // convert the data (hex) into float
    float Frq = hexToFloat(node.getResponseBuffer(0x00), node.getResponseBuffer(0x01));
    return Frq;

  } else {
    return -1;  // function returns an unphysical value if read fails
  }

}


// function to convert VW frequency to strain according to geokon manual
// https://www.geokon.com/content/manuals/4200-4202-4204-4210_Strain_Gages.pdf
float freqToStrain(float Frequency, bool smallSensor) {

  float gaugeFactor;
  float datumFreq;

  if (smallSensor == false) {   // if we're using the larger form factor (4200 gauge)
    gaugeFactor = 3.304;        // gauge factor is 3.304
    datumFreq = 842.32;         // Frequency at 0 strain is about 842.32 Hz
  } else {                      // otherwise we're using the 4204 strain gauge (the small one)
    gaugeFactor = 0.3910;       // gauge factor is 0.3910
    datumFreq = 2310;           // Freq at 0 strain is about 2310 Hz, but this freq is tunable using the nut on the sensor
  }

  // Apply following equation to convert freq to strain (taken from manual)
  float strain = gaugeFactor * (pow(Frequency, 2) - pow(datumFreq, 2)) * 0.001; // to do: this is not temperature corrected
  return strain;
}

// == 2 END SUPPORT FUNCTIONS ==

// == 3 MAIN SETUP, LOOP ==

void setup() {

  pinMode(enablePin, OUTPUT);   // switch on enablePin
  digitalWrite(enablePin, LOW); // initialise in receive mode

  // Default serial port must be used for serial monitor - this connected internally to usb
  Serial.begin(115200);   // ensure baud rate on your serial monitor is set to 115200
  while (!Serial) {};     // wait for serial monitor to be opened by user


  // Arduino mega has more serial ports. The first of these is "Serial1" on pins 19 (RX) and 18 (TX)
  Serial1.begin(115200);               // Modbus communication for VW gauge runs at 115200 baud
  node.begin(sensorAddress, Serial1);  // Initialise modbus sensor to communicate over serial port 1

  // callbacks allow us to configure RS485 correctly
  node.preTransmission(preTransmission);
  node.postTransmission(postTransmission);

  Serial.println("Setup complete");

}


void loop () {

  // get freq and temperature readings
  float Freq = getFrequency();
  float Temperature = getTemperature();

  // convert frequency to strain
  float strain = freqToStrain(Freq, smallSensor);

  // print to Serial monitor
  Serial.print("Frequency: ");
  Serial.print(Freq);
  Serial.print(" Hz        ");

  Serial.print("Strain: ");
  Serial.print(strain);
  Serial.print(" microstrain        ");

  Serial.print("Temperature = ");
  Serial.print(Temperature);
  Serial.println(" degC");

}

// == 3 END MAIN SETUP, LOOP ==

Please edit your post to add code tags, as described in the "How to get the best out of the forum" post.

1 Like

Thanks, is that okay now?

Hi, @tresor
Welcome to the forum.

What is a VW sensor?
Can you please post link to spec/data?

Thanks.. Tom... :smiley: :+1: :coffee: :australia:

1 Like

Hi George and thanks for the welcome message. A VW sensor is a Vibrating Wire sensor used in construction to measure material (concrete in my case) strains.

Here is the manual of the VW:

Here is the manual for the Modbus addressable VW interface:
VW Modbus Interface Manual

I hope this help and let me know if you need more info
All the best

Hi @TomGeorge Just to check with you if you had some time to check my code. Thanks in advance

Hi @jremington. I hope you have a few minutes to check the codes and manuals I posted about this topic.

How looks your circuit?