2

I'm using a Arduino Uno to read pressure and I want to know if I have wired/coded the sensor correctly. I'm not sure I'm getting the correct readings (it could be the right readings - I just want to check I have done everything right). The sensor I am using is an OsiSense™ XMLP pressure sensor that reads between 0 and 100 bars and gives out a 0v (zero bars) to 10v (100 bars) charge. Due to the Arduino Uno only being capable of reading up to 5 volts, I've used a voltage divider to reduce the maximum voltage the Arduino receives to 5v.

I've attached a hand-written diagram. Let me know if you need any more information. I've attached the wiring and also the code.

enter image description here

/*
  ReadAnalogVoltage from a OsiSense XMLP presure sensor 

  Reads an analog input on pin 0, converts it to voltage and then bar pressure, and prints the result to the Serial Monitor and also MQTT. 
  Graphical representation is available using Serial Plotter (Tools > Serial Plotter menu).

  Todo 
  Static ip. set it to request IP from network 
  Work out best way to average readings

*/

#include <SPI.h>  //Serial Peripheral Interface (SPI)
#include <Ethernet.h>  //  These libraries are designed to work with the Arduino Ethernet Shield (Ethernet.h) 
#include <PubSubClient.h>  // This library provides a client for doing simple publish/subscribe messaging with a server that supports MQTT

// sets the MAC address and IP address for the network 
byte mac[]    = {  0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };
IPAddress ip(192,34,98,221);  // IP Address of the client 
IPAddress server(192,34,98,201); // The IP address of the MQTT server 

void callback(char* topic, byte* payload, unsigned int length) {
  // handle message arrived
}

EthernetClient ethClient;
PubSubClient client(server, 1883, callback, ethClient);

void setup() {
  Serial.println("Begin setup");
  Ethernet.begin(mac, ip);
  // Note - the default maximum packet size is 128 bytes. If the
  // combined length of clientId, username and password exceed this,
  // you will need to increase the value of MQTT_MAX_PACKET_SIZE in
  // PubSubClient.h

  // connects to MQTT and says hello world.  Probably change this later on to something more appropriate 
  if (client.connect("ArdRigTest")) {
    client.publish("outTopic","Ard Rig Test");
    client.subscribe("inTopic");
  }
  // start serial port
  Serial.begin(9600);
}

void loop() {
  // Note - the default maximum packet size is 128 bytes. If the
  // combined length of clientId, username and password exceed this,
  // you will need to increase the value of MQTT_MAX_PACKET_SIZE in
  // PubSubClient.h

  // read the input on analog pin 0:
  int sensorValue1 = analogRead(A0);
  delay(2); // read twice with small delay to get accurate reading.  
  int sensorValue2 = analogRead(A0);

  Serial.println(sensorValue2);
  //Test code. using map function 
  int MapBarPressure;
  MapBarPressure = map(sensorValue2, 0, 1023, 0, 100);
  if (client.connect("ArdRigTest" )) {
    client.publish("MapBarPressure",String(MapBarPressure).c_str());  //logs the pressure of the RigTest 
    client.subscribe("MapBarPressure");
  }
  delay(100); // Pauses the program for the amount of time (in miliseconds) specified as parameter. (There are 1000 milliseconds in a second.)
  client.loop();
}

Thanks in advance.

9
  • Assuming that you are using analogRead() with 0 for 0V and 1023 for 5V it is a question of mapping the range 0-1023 to the pressure range 0-100 bar (map(0, 1023, 0, 100)). See arduino.cc/en/Reference/Map. Or use float to keep the resolution. Sep 19, 2017 at 16:13
  • Which pressure sensor is it ? The output voltage is probably not 0.0 to 5.0V, but rather 0.5 to 4.5V. How good and stable is your Arduino 5V which is used to power the sensor ? That is important to know. Is the pressure sensor ratiometric ?
    – Jot
    Sep 19, 2017 at 18:26
  • Its a OsiSense™ XMLP. It kicks out a 10v output so I've built a circuit with a voltage divider so the output to the Arduino is a maximum of 5V. The power source to the sensor is 24v and is stable. Sep 19, 2017 at 18:41
  • I'm using analogread. I don't understand the maths behind map but I guess thats the beauty of the function. It simplifies the maths so I dont need to. Sep 19, 2017 at 18:43
  • 2
    The Arduino and the sensor need to share a common ground: connect the negative terminals of the power sources together. Sep 20, 2017 at 21:00

4 Answers 4

1

You can use map, ref. : https://www.arduino.cc/en/Reference/Map

Re-maps a number from one range to another. That is, a value of fromLow would get mapped to toLow, a value of fromHigh to toHigh, values in-between to values in-between, etc.

7
  • With the caveat that "The map() function uses integer math so will not generate fractions, when the math might indicate that it should do so. Fractional remainders are truncated, and are not rounded or averaged." Sep 19, 2017 at 16:12
  • 1
    so sometimes it's worth thinking in decibars internally and only convert to bars when you need to show it to the user. Sep 19, 2017 at 16:17
  • @josecanuc did the OP ask to get decimals?
    – MatsK
    Sep 19, 2017 at 17:24
  • Indeed the OP did not specify any requirements in that regard, but if he or she uses map(), I only wished to clarify the limitation. Sep 19, 2017 at 17:38
  • Please use a more constructive way to explain it then!
    – MatsK
    Sep 19, 2017 at 18:08
1

If you need to use fractional pressure values, then the formula is

float MapBarPressure;
MapBarPressure = sensorValue2 / 10.24;

This was obtained by seeing that the maximum reading from AnalogRead(A0) is 1024, which corresponds to 5V on A0 (and which also means 10V output from the sensor.) If you read 1024 from A0, it means you are measuring 100bar, so

bar = (A0 / 1024) * 100

Alternatively, you could maintain 1 decimal place of accuracy in bar if you keep with int values:

int MapDeciBarPressure;
MapDeciBarPressure = map(sensorValue2, 0, 1023, 0, 1000);

Then your variable is holding "tenths of bar" (deciBar) and you only convert it to bar by dividing by 10.0 (not 10, which is an int, but 10.0, which is a float and does floating point math and returns a float response.)

One other note: you write:

// read the input on analog pin 0:
int sensorValue1 = analogRead(A0);
delay(2); // read twice with small delay to get accurate reading.  
int sensorValue2 = analogRead(A0);

Just reading twice doesn't gain accuracy -- you have to average the values:

int sensorValAvg = (sensorValue1 + sensorValue2) / 2;

Then, use sensorValAvg for your less noisy value.

Edit: Also, make sure you connect all ground lines together, both from the sensor and the Arduino!

2
  • The conversion factor is 1024, not 1023. Sep 20, 2017 at 20:59
  • Caught me again! Edited. Sep 20, 2017 at 21:11
0

About accuracy.

I assume you have read @edgar-bonet about connecting the GND's.
I assume you understand the other answer to calculate the pressure. I would write it like this:

// This is for the DEFAULT 5V analog reference.
// v = the voltage at the pin in Volts.
// p = the pressure in bar.
// Note that 'bar' is the pressure relative to the
// normal atmospheric pressure at that moment.
float v = (float) analogRead(A0) / 1024.0 * 5.0;
float p = v / 5.0 * 100.0;

The analogRead uses default the 5V as reference.

That means that if the project is powered by a USB cable, the 5V could vary between 4.5 and 5.0 V. That 10% difference will be seen in the resulting calculated pressure. In that case you can not measure more accurate than 10%.

If the project is powered with a power supply to the power barrel jack, then the resulting accuracy depends on the accuracy of the voltage regulator on the Arduino board.

The analog reference can be set with analogReference.
The internal voltage reference of the Arduino Uno is 1.1V. That is reasonably stable, but it depends a little on the voltage of VCC and the temperature. The main problem is that it is different for each Arduino Uno, and it can be between 1.0 and 1.2 V. Therefor you have to measure it, and use the measured value in the calculation in the sketch.

The input range is between 0V and the analog reference. Therefor you have to adjust the voltage divider to get 0..10V down to 0..1.1V. You could try: R1 = 100k and R2 = 10k.

const int pressureSignalPin = A0;

void setup()
{
  analogReference( INTERNAL);
}

void loop()
{
  // v = the voltage at the pin in Volts.
  // p = the pressure in bar.
  // Note that 'bar' is the pressure relative to the
  // normal atmospheric pressure at that moment.
  // The "(100.0 + 10.0) / 10.0" is the factor by the voltage divider
  // with 100k and 10k.
  // Measure the AREF pin, and fill the value in for "1.10".
  float v = (float) analogRead(A0) / 1024.0 * 1.10;
  float p = v * ((100.0 + 10.0) / 10.0);
}
1
  • Thanks. I've connect the grounds between the arduino and the sensor so they are all common. I've not tried the internal reference yet.. The power in is from a POE converter to the usb cable. I've attached a USB current/voltage reader and you can see the video hear : youtube.com/watch?v=Tb7qJXcJl9M&feature=youtu.be Sep 22, 2017 at 15:08
0

Everything is just fine.

All you have to do is to provide the common ground (0 potential) to your Arduino and your Sensor.

The problem here is that they might be on a different potential.

So just connect the ground of your 5 volts and 24 volts together and everything will work perfectly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.