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 ==