LabVIEW Interface for Arduino Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

LabVIEW interrupt handling to control YF-G1 water flow meter

Hello,


Right now i've been using LIFA for three months, and everything has worked as a charm. I didn't use LINX in the beginning because i felt it had fewer solutions available (for LIFA i found several videos that helped me); now i just think LINX could help me spread the reach of my current work. But, i want to troubleshoot this issue on LIFA first (I post it here because i think the programming logics between the two are very similar!).


I'm working with an Arduino UNO, and have succesfully connected and received readings from a DS18B20 temperature sensor, and have been able to change a X9C103P digital potentiometer value to the one i desire. My next quest is to be able to report the flow readings from a YF-G1 sensor.

To control each one of the sensors I've done the following:

—Each sensor has already a set of libraries and examples on the internet that I've found. I've copied the libraries to Arduino folder and after that I've identified the variables, the pinmodes and the functions on each one of the loops.

—In the Arduino file "LabviewInterface i've copied the variables and i have added cases to the "processCommand" method.

—Finally, i have manually set the "Send Receive" blocks so i could input the number of case i am in, and the input variables i need for each process.

As i told you i have succesfully donde that with two sensors. The third one is giving me trouble because it uses an "attachInterrupt()" method, that i've read gives some trouble. This is the code i've added to "LabVIEWInterface":


Variables:

CODE: SELECT ALL
//Flujometro
volatile int NbTopsFan; //measuring the rising edges of the signal
int Calc;                              
int hallsensor = 2;    //The pin location of the sensor
int contadorFlujo=0;



case:

CODE: SELECT ALL
   case 0x37:   // Flujometro
      Serial.print(ObtenerFlujo(command[2],command[3]));
      break;



Functions:

CODE: SELECT ALL
//Obtener flujo

float ObtenerFlujo(float tiempoEntreMedidas,float constanteFlujo)  

{

  if(contadorFlujo==0)

  {

    contadorFlujo++;

    attachInterrupt(0, rpm, RISING); //and the interrupt is attached

  }

  NbTopsFan = 0;   //Set NbTops to 0 ready for calculations

  sei();      //Enables interrupts

  delay (tiempoEntreMedidas);   //Wait "tiempoEntreMedidas" second

  cli();      //Disable interrupts

  Calc = NbTopsFan/constanteFlujo*60; //(Pulse frequency x 60) / Q, = flow rate in L/min

  return Calc; //Prints the number calculated above

}



void rpm ()     //This is the function that the interupt calls
{
  NbTopsFan++;  //This function measures the rising and falling edge of the hall effect sensors signal
}



This is the code i've added to "LIFA_Base"

On the setup:

CODE: SELECT ALL
  pinMode(2,INPUT);



And finally, this is the block diagram i've been trying to setup to read:

http://postimg.org/image/5glrb9k1l/



I published this question on LINX forums, but i wanted to reach more people (I hope that doesn't bother you guys). I really appreciate your help, thanks in advance!!!!

0 Kudos
Message 1 of 10
(8,161 Views)

If you could post a reliable datasheet for the sensor, it would make it easier to determine what is needed.  Links to the library would also help.

Based on a quick search, it seems like the output is frequency of a 50% duty cycle waveform.  One method to measure such a sensor, is to use pulseIn().  It measures the time of a single pulse (which you can get the frequency from).

0 Kudos
Message 2 of 10
(5,083 Views)

Thanks for answering!

This is the sensor I'm using, the library they use is in the same website: http://www.seeedstudio.com/wiki/G1%22_Water_Flow_Sensor

I've succesfully read from Arduino IDE using the code that is already written there.

Yes, if I'm not wrong it wil give a high and low value ach time it turns around.

About the pulses, I've tried that already (thanks to one of your previous posts) changing the code i wrote in the "LabVIEWInterface" file to:

"

case 0x37:   // Flujometro

      Serial.print(ObtenerFlujo(command[2]);

      break;

(....some code in between...)

float ObtenerFlujo(float tiempoEntreMedidas) 

{

     unsigned long puls=pulseIn(2,HIGH,tiempoEntreMedidas*1000) //Time in microseconds;

    return puls;

}

"

But I'm always getting 5003 error, and it is always on the Send Receive block. Could it had something to do with timing? I was wondering: In LabVIEW i am inside a loop that runs again and again each 200 ms as i have it right now, and maybe there are pulses coming each 30-75 miliseconds (more or less, it just depens on the flow rate I'm working with) that can be in conflict with that loop. Could it be timing related?

0 Kudos
Message 3 of 10
(5,083 Views)

Could you please attach your VIs (the primary VI and the subVI for this function)?  If you are using 2014, could you please save it for 2013?

Regarding the Seeeduino solution, you can't add delays into the Arduino code unless you account for it in LIFA (the timeout) and remember that your loop will not execute as fast as you are trying to have it run (depending on the delay you give it).

0 Kudos
Message 4 of 10
(5,083 Views)

Hello Nathan,

In the attached folder I sent four main files:

1. The first one is a folder where the Arduino code is written. You have to open '_12_01_Flujometro.ino' and all the rest of files will open automatically. The modifications of the cases and the variables are in the file 'LabVIEWInterface.ino'.

2. The second one is the VI i ran with that code in the Arduino. It is made for AttachInterrupt.

3. It is the VI i modified so i could work with the PulseIn function. Doesn't work either...

4. This is the VI that It's already working with my other sensors is '10_07 Final Code.vi' that depends on 'PotenciometroCorregido.vi' and '10_07 ObtenerTemperatura.vi'. My idea is to copy the working flowmeter VI to this VI so i integrate my temperature readings, my potentiometer change and the flow reading. What I want to do next is according to the temperature, the digital potentiometer value is changed. That change will change the speed of a centrifugal pump (which has a Siemens Micromaster frequency inverter in manual mode—with potentiometer—), and that change will change the temperature reading.

The flow sensor is used for the feedback of the pump: with the initial temperature reading i calculate how much flow i need (according to the enthalpy difference), and i compare that value with the real flow I'm having. I also attached the picture of the system I want to have at the end (Termómetro is the temp. reading, Controlador k is the function to calculate desired flow, flujómetro is the flow meter reading and Bomba is the change in pot. value and corresponding output with the centrifugal pump.

For now my current functions do not have delays, if i'm not wrong. They just make the respective measurements for every loop iteration.

Thank you very much again!!

0 Kudos
Message 5 of 10
(5,083 Views)

The first thing that must be fixed is the branching of the resource wire.  You can't do that.  You should have only one Close.vi for each Init.vi (aka a physical Arduino).  See this explanation (it's in the context of LINX but it's the same thing).

I'll try to look at it more here in a lilttle while.

0 Kudos
Message 6 of 10
(5,083 Views)

A few other things that I noticed while looking your LabVIEW code.  In your flow meter subVI (not the PulseIn one) you have a few things that just won't work.  Since you have a delay in your Arduino code, you need to make sure that the timeout on the LIFA subVI for reading bytes from Arduino is sufficiently long enough to account for the delay in the firmware code.  The wait VI will not prevent that VI from timing out and erroring.

Also, you are currently telling the 'Send Receive' VI to read zero (0) bytes back from the Arduino.  You have to know the exact number of bytes that your function is going to send bad.

Related to that is that you can't simply send back any random floating point number (because the number of bytes that will be coming back is unknown).  This means that you shouldn't ever use Serial.print() because it sends back a string with ASCII numbers in it of unknown length.  You will need to send it back in raw bytes (you can do this with floating point numbers but you could also do it as a single integer which would probably be easier).

If you don't need to change the mode of a digital pin (input or output) then you should set the pin mode before the loop starts.  The digital write VI only needs a 0 or a 1.  I'm not sure what it would do if you send something that is not a 0 or a 1.

One thing that you should get used to is using the error wires.  At the very least, wire the error write through all of the LIFA VI's.

Message 7 of 10
(5,083 Views)

Hello Nathan!

First of all thanks for your answer, I had a trip so I could answer only until today.

Well, today I managed to read from the sensor thanks to you and some investigations I made. My insights were:

-You were right about the connection of a single Arduino cable and the wiring of error helped me troubleshoot easier.

-In the code I used a delay that was messing up the readings. What I did was that I let the timer on LabVIEW determine the delay on the interrupts. When Labview calls the sensor, it stops interrupts, saves the number of pulses in a new variable, begins again interrupts and returns the desired value.

What I did was:

On the code, I added one case for reading from the sensor and one for setup and Interrupt attach:

case 0x37:   // Flujometro

      ObtenerFlujo();

      break;

case 0x38:  // Inicializa Flujometro


      pinMode(2,INPUT);

      attachInterrupt(0, rpm, RISING); //and the interrupt is attached

      break;

And the function goes

float ObtenerFlujo()  

{

    noInterrupts();

    float pulsos=NbTopsFan;

    NbTopsFan=10;

    interrupts();

    Serial.print(pulsos);

}

void rpm ()     //This is the function that the interupt calls

{

  NbTopsFan++;  //This function measures the rising and falling edge of the hall effect sensors signal

}

I put the value of 10 when I redefine NbTopsFan because i had a problem: When I began in zero (0.00), i had to indicate that the Arduino would send 4 bytes, but if the value had more digits it started to jump (for example if it read '12' and then '15', the indicator showed first '12.0', then '015.', '00.0' and so on). With 10 I could define 5 bytes from the beginning, because my data will never use more than 2 figures.

The integrated VI's are attached for the whole system. Thanks again!

0 Kudos
Message 8 of 10
(5,083 Views)

About the problem I had with the NbTopsFan, I haven't been able to solve it

As you said, I need to know the exact length of the information being sent. The trick I used with NbTopsFan works because I will always have that number of figures (10.00, 25.39, etc). But right now I'm implementing a rotary encoder that varies from 0 to more than 1000. I've tried to send it as a byte, and also as a HEX but i haven't been able to accomplish it. Do you know what is the best option for sending and integer value to LabVIEW?

0 Kudos
Message 9 of 10
(5,083 Views)

The problem with sending back a text string of a number is that you will not be consistent length.  Your examples are 10.00 and 25.38 . . . what happens when you have a value of 9.34 or 100.01?

All data sent back from an Arduino is sent as bytes (if you data requires more than one byte, you have to break it up into individual bytes and then reassemble them in LabVIEW.  A single byte (8 bits) can represent only up to a value of 255 (if it's unsigned).  If you need something larger, you need to have another byte.  Take a look at some of the other functions, there should be several that show how to break up two bytes for sending it back to LabVIEW (it involves using bitwise AND with 0xFF then shifting the value by 8 bits then doing the AND again.

"Hex" is just a method of representing numbers in text and doesn't change the values sent from the Arduino (basically "hex" is just for making it simple for humans to read).

So, try and figure it out based on some of the other functions in the firmware.  If you are still having trouble, post the Arduino code snippet that you tried and I will take a little more time either looking for a specific example in the firmware or trying to explain it in a more techincal manner.

0 Kudos
Message 10 of 10
(5,083 Views)