Go Down

Topic: 4pin DIN flow sensor using I2C communication with Arduino (Read 1 time) previous topic - next topic

efv_t

Hi,

I am trying to read the flow in a system using a flowmeter sensor and an Arduino Uno through I2C protocol. There are many things I am potentially doing wrong, and that is probably why I can't get a reading.

The sensor has a 0-5V analog output in a 4-pin DIN cable. I was told when I bought it that it uses an I2C protocol and I have a diagram of the functionality on each pin.
You can see how I wired the system in the picture attached. The Arduino is powered through the USB, while the sensor is powered through a 12V power supply regulated to 8V (which is its voltage specification).
Pull-up resistors are 3.3k+1.2k=4.5kOhms.

I tried several codes, but I am using the following now:
Code: [Select]

//libraries
#include <Wire.h>                   //include Wire library
int flowSens = 64;


void setup() {
  // Begin communication:
Serial.begin (9600);                //Start serial connection
Wire.begin();                       //initialise I2C bus
Serial.println("Flow in uL/min");   //print title for data acquisition
}

void getUdata(byte *msb, byte *lsb) {
  // Flow data aquisition:
  Wire.beginTransmission (flowSens);  //begin transmission to device#
  Wire.write((byte)0);                //ask for register zero
  Wire.endTransmission();             //complete transmisison

  Wire.beginTransmission (flowSens);
  Wire.requestFrom(flowSens,3);
  if (Wire.available()) {
    *msb=Wire.read();
    *lsb=Wire.read();
  Wire.endTransmission();
  }
}

void showUdata() {

  byte msb, lsb;
  getUdata(&msb,&lsb);
  Serial.print(lsb,DEC);
  Serial.print(".");
  Serial.println(msb,DEC);
}

void loop() {
    showUdata();
    delay (5000);                       //delay between readings
}



Well, the problem with this one is that I get constant values of 0.224
With variations of this code I got 0.216 or similar.
I really don't know if the problem is in the circuit or the code (or both :smiley-confuse: ), and what am I doing wrong.

Any suggestions are welcome. Thanks a lot!

Koepel

Suggestion number one : Stop

You have connected the pullup resistors to 8V ? That means you are damaging the Arduino and probably the sensor as well.

8V with 4k5 to Arduino pin = 0.67 mA pushed into the pin. You are in luck, the Arduino can have 1mA pushed into a pin. But it is not nice.

Can you get more information about the sensor. Which sensor is it ?
Perhaps it needs 8V for power, but what voltage is the I2C ? Is it a 5V I2C bus or a 3.3V I2C bus ?
If the sensor has internal pullup resistors, you could measure the voltage of SDA and SCL when nothing else is connected to the sensor (only the 8V power and GND of course).
Once you get the voltages right, run the i2c_scanner : http://playground.arduino.cc/Main/I2cScanner

Is that a LM317 for 8V ? I prefer capacitors at the input and output.

If the sensor has 4 pins, and also a 0-5V analog output in a 4-pin DIN cable and also I2C in the cable, that is not possible. You need better information about those pins.

The sketch is not okay.
The Wire.requestFrom() should not be encapsulated by beginTransmission() and endTransmission().

efv_t

It is a LM317. I will deal with noise using capacitors if I have to, when I figure things out (if I do)

It needs 8V 100mA input and output is 0-5V. That is what the spec sheet says. However, the sensor is not designed to work connected to an Arduino, but to a sensor reader. I would say its a 5V I2C then, but that is my interpretation.
I will attach all the information I have about the sensor (pinout), and you can find power specs in this link: http://www.elveflow.com/microfluidic-flow-control-products/microfluidic-flow-control-module/microfluidic-liquid-mass-flow-sensors/

Measuring the SDA and SCL is a great thought, I will.

I runed the I2C scanner already, but I will do it again when I change things.


I had 10kOhms as pull-up resistors connected initially, but then thought that might be too much. Is 10kOhms better then?
I runed the code with and withour encapsulating Wire.requestFrom() following different examples with the same result. But I will delete it now that I know it shouldn't be there.


Thank you, thank you so much for the advice! I am really missing some knowledge.



chucktodd


It is a LM317. I will deal with noise using capacitors if I have to, when I figure things out (if I do)

It needs 8V 100mA input and output is 0-5V. That is what the spec sheet says. However, the sensor is not designed to work connected to an Arduino, but to a sensor reader. I would say its a 5V I2C then, but that is my interpretation.
I would try powering the sensor just using the Arduino,  
Connect pin 1 to VCC of the Arduino,
Connect pin 2 to SCL ( A5 of the Arduino)
Connect pin 3 to GND of the Arduino)
Connect pin 4 to SDA (A4 of the Arduino)


I had 10kOhms as pull-up resistors connected initially, but then thought that might be too much. Is 10kOhms better then?

Use 4.7k Ohm pull-up resistors,  The default Arduino Wire library runs at 100kbs.  If you use your 10k resistors, the signals may not go high fast enough.

The sketch is not okay.
The Wire.requestFrom() should not be encapsulated by beginTransmission() and endTransmission().

As Koepel said,  change your Sketch:
to receive data from the device use:

Code: [Select]


void getUdata(byte *msb, byte *lsb) {
  // Flow data aquisition:
  Wire.beginTransmission (flowSens);  //begin transmission to device#
  Wire.write((byte)0);                //ask for register zero
  Wire.endTransmission();             //complete transmisison

  Wire.requestFrom(flowSens,3); // why are you asking for three bytes and only using 2?
  if (Wire.available()) {
    *msb=Wire.read();
    *lsb=Wire.read();
  }
}



Chuck.
Currently built mega http server, Now converting it to ESP32.

efv_t

Voltage between SDA-GND and SCL-GND is 5V (both when powered using 5 or 8V supply), so it's a 5V bus. It is 5V constant regardless of flow.

I changed the sketch, tried powering through the Arduino, run the I2C scanner again... nothing seems to change.
I just get slightly different numbers in the monitor. Now 0.208.
Ia it possible that the sensor needs to be programmed differently than it is?

I don't know what else to do. Is it not possible?

Thank you all!

Koepel

Good, it's a 5V I2C bus.

Don't use a sketch to retrieve its data yet, make the i2c_scanner work first.

Could you add pullup resistors of 4k7 from SDA to 5V and from SCL to 5V ? For the 5V, use the Arduino 5V pin. Could make a photo of it, so that we can verify it ?

If you run the i2c_scanner, what is the output ? Does it say that nothing is found ? Perhaps you can make a screendump of the serial monitor, or copy-paste the complete output so we can see it. When you see that nothing seems to change, then I start pulling my hair :o because you have not told us what the output was in the first place.

If the i2c_scanner can find the sensor, and it is stable, then I have to take a better look at the sketch.
After that there is still a lot that can be done, for example changing the pullup resistors or lowering the SCL clock speed, and so on.

efv_t

Ok, so.

Monitor for the I2C scanner:
Code: [Select]
I2C Scanner
Scanning...
I2C device found at address 0x40  !
done

Scanning...
I2C device found at address 0x40  !
done

Scanning...
I2C device found at address 0x40  !
done

Scanning...
I2C device found at address 0x40  !
done


Sketch with the suggested modifications modifications:
Code: [Select]
/*read flow from flowSensor and print. Code from
://forum.arduino.cc/index.php?topic=160680.0
 */

//libraries
#include <Wire.h>                   //include Wire library
int flowSens = 64;


void setup() {
  // Begin communication:
Serial.begin (9600);                //Start serial connection
Wire.begin();                       //initialise I2C bus
Serial.println("Flow in uL/min");   //print title for data acquisition
}

void getUdata(byte *msb, byte *lsb) {
  // Flow data aquisition:
  Wire.beginTransmission (flowSens);  //begin transmission to device#
  Wire.write((byte)0);                //ask for register zero
  Wire.endTransmission();             //complete transmisison

  Wire.requestFrom(flowSens,2);
  if (Wire.available()) {
    *msb=Wire.read();
    *lsb=Wire.read();
  }
}

void showUdata() {

  byte msb, lsb;
  getUdata(&msb,&lsb);
  Serial.print(lsb,DEC);
  Serial.print(".");
  Serial.println(msb,DEC);
}

void loop() {
    showUdata();
    delay (5000);                       //delay between readings
}


and the Monitor output for the code is:
Flow in uL/min
0.208
0.208
0.208
0.208
0.208
0.208
0.208
0.208
0.208

etc...



There are 4.5kOhm pull up resistors between 5V to SCL and SDA. I think I don't understand that suggestion. I will have a read about the SCL clock speed...

Thanks again!

efv_t

Something I just noticed.

The I2C scanner won't find any I2C device if the sensor is unplugged from the DIN cable (as it should be).

However, if I run my code when the device is unplugged it still gives the same outcome
:(

Using
while(Wire.available() ==0);
instead of
while(Wire.available());

i get a different more logic outcome:
Code: [Select]
Flow in uL/min
255.255
255.255
255.255
255.255
255.255
255.255

Koepel

You are always displaying the msb and lsb, regardless if they are read from the I2C bus or not.

The i2c_scanner is detecting the sensor. That is good, that was the hardest part.
How do you power the sensor ? with 5V ?
Maybe the sensor values will not be accurate at 5V, but it is safer for now.
If you connect the sensor to 8V, I would like to see a photo or schematic before you apply 8V to circuit.
(The 8V should only go into the red wire to the sensor, and the grounds should be connected).

Now I will take a look at the sketch ;)
0x40 = 64, that's okay.
Reading two bytes from register address 0 returns first byte = 208 (0xD0) and second byte = 0.
That might be a ID number for the sensor.

Where is the register description ?
I go here : http://www.elveflow.com/microfluidic-flow-control-products/microfluidic-flow-control-module/microfluidic-liquid-mass-flow-sensors/
And I open "Datasheet 2016", but that is not enough.
The brand is "elveflow", the flow sensor is called "Flow Sensor" or "MFS (Microfluidic Flow Sensor)" or "MFS (mass flow sensor)" or "FS1".
I think they forgot to give a good name or type number.

Then I selected "Software / Software & SDK" in the menu on the left ( http://www.elveflow.com/microfluidic-flow-control-products/flow-control-system/elveflow-software/ ) and I downloaded the newest version from the Download tab.
That seems to be only the interface, I can't find any description of the registers of the flow sensor.

Where is the register description ?
I think you might be the first person, trying to connect an Arduino to an Elveflow device.

efv_t

I am quite sure I am indeed the first person trying to connect one of those to an Arduino.
And, just like you, I can't find the regiters descrition. We are talking about the register that I am writing to (Wire.write(0)), isn't it?
I only looked into that about an hour ago, understood it, and thought that might be a problem.

Well, I will ask for more information and I hope I am lucky. I was given de DIN cable pinout when I requested so fingers crossed. I don't have any other specifiations other than what I attached previously.  :smiley-sad-blue:

Do you think that is the problem? any other suggestion while I try to figure that out??

Thank you so so much for your time!

Koepel

Reverse engineering ?
This sketch writes the register address and reads the data.
I assume that the chip has registers and that the registers are 8 bit, but there are I2C chips without registers.
Show me the complete output of the serial monitor.

Code: [Select]

// Test for : http://forum.arduino.cc/index.php?topic=385842.0

#include <Wire.h>                   // include Wire library
const int flowSens = 0x40;          // address found by i2c_scanner

void setup()
{
  // Begin communication:
  Serial.begin (9600);                // Start serial connection
  while( !Serial);                    // For Leonardo, wait for serial monitor
  Serial.println("Flow test sketch"); // print title
 
  Wire.begin();                       // initialize I2C bus

  for( int reg=0; reg<128; reg++)
  {
    int data = readRegister8( reg);   // read contents

    // The rest is text formatting for the serial monitor
    if( reg%16 == 0)
    {
      Serial.println();
      if( reg < 10)
        Serial.print( " ");
      if( reg < 100)
        Serial.print( " ");
      Serial.print( reg);
      Serial.print( ": ");
    }
    Serial.print( "0x");
    if( data < 0x10)
      Serial.print( "0");
    Serial.print( data, HEX);
    Serial.print( ", ");
  }
  Serial.println();
}

// The name 'register' is a reserved word, therefor I use the name 'reg8'.
// The 'reg8' is the register address inside the chip.
int readRegister8( int reg8)
{
  Wire.beginTransmission( flowSens);  // begin transmission to device
  Wire.write( reg8);                   // select register
  int error = Wire.endTransmission(); // complete transmisison
  if( error != 0)
    Serial.println( "Error at endTransmission");
   
  int n = Wire.requestFrom( flowSens, 1); // request 1 byte
  if( n != 1)                        // 1 byte received ?
    Serial.println( "Error at requestFrom");

  int dat = Wire.read();
  return( dat);
}

void loop()
{
}


Please note that I have changed the sketch above after I posted this message, it was wrong, but now it is okay ;)

efv_t

Wow, I have no idea what that does!
This is the complete monitor output for your sketch:

Code: [Select]
Flow test sketch
Error at endTransmission
Error at requestFrom

  0: 0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom

 16: 0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at requestFrom
0x0FFFFFFFF, Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom

 32: 0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom

 48: 0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at requestFrom
0x0FFFFFFFF, Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom

 64: 0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom

 80: 0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at requestFrom
0x0FFFFFFFF, Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom

 96: 0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom

112: 0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at requestFrom
0x0FFFFFFFF, Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF, Error at endTransmission
Error at requestFrom
0x0FFFFFFFF,


I hope you will help me understand that.... :S
Thanks!

Koepel

That means that the sensor is not responding at all.
Perhaps something has changed, the i2c_scanner will probably not work either.
Perhaps writing the register address has changed the I2C address and it is no longer 0x40.

Could you try the i2c_scanner again ?

It is normal to have a few test sketches when developing a project.


Koepel

I don't understand it. The i2c_scanner 'sees' the sensor at 0x40 because the Wire.endTransmission() has no error (the Slave gave an ACK signal). The test sketch does the same thing but then Wire.endTransmission() does give an error. The only difference is that the register address 'reg8' is written.
Perhaps the sensor doesn't like to be written to.

Let's do only reads:
Code: [Select]


// Test for : http://forum.arduino.cc/index.php?topic=385842.0
// Only reading

#include <Wire.h>                   // include Wire library
const int flowSens = 0x40;          // address found by i2c_scanner

void setup()
{
  // Begin communication:
  Serial.begin( 9600);                // Start serial connection
  while( !Serial);                    // For Leonardo, wait for serial monitor
  Serial.println( "Flow read test sketch"); // print title
 
  Wire.begin();                       // initialize I2C bus
  delay( 100);                        // give sensor some time to know that the I2C bus is idle.
}

void loop()
{
  // Read 16 bytes, all from the same I2C address
  int n = Wire.requestFrom( flowSens, 16); // request 16 bytes

  Serial.print( "16 bytes requested, ");
  Serial.print( n);
  Serial.print( " bytes received : ");

  int data = Wire.read();
  for( int i=0; i<n; i++)
  {
    Serial.print( "0x");
    if( data < 0x10)
      Serial.print( "0");
    Serial.print( data, HEX);
    Serial.print( ", ");
  }
  Serial.println();

  delay(1000);
}


After a number of lines, the data should start repeating itself if it was a normal sensor. This sensor might not have an internal register, so perhaps only the first bytes of every line are valid. Perhaps they are the 0xD0 and 0x00 again, but I'm hoping that more data follows after those.

Go Up