Go Down

Topic: Processing multiple digital inputs (Read 4559 times) previous topic - next topic

Oldbeaver


Oldbeaver

Dear AWOL and Mem,

Here is my sketch for a single pulse duration counting:

/* =======Millis per Pulse counter ================*/

#include <DateTime.h>
#include <LiquidCrystal.h>

/* ------------- reset pins, define pins, variables ---------------- */
int resetPin = 3;              // pin 3 resets the time
int pin = 2;
unsigned long duration;

/* ------- create object to control an LCD GMD1602K -------*/
LiquidCrystal lcd(12, 11, 6, 7, 8, 9, 10); // mem changed pin 2 to 6 (why?)

/* ============== SETUP ==================== */
void setup(){

pinMode(pin, INPUT);               // a button on this pin resets the time
digitalWrite(resetPin,HIGH);   // this line enables pull-up
DateTime.sync( 0 );              // set time to zero

}

void loop(){
/* =======Execute program over and over =============*/
 float x;
 lcd.clear();                                    //cleans display
 
 duration = pulseIn(pin, HIGH);        //counts pulses in one second

 lcd.setCursor(0,0);
 lcd.print("Millis");
 lcd.print(" ");
 x=duration;                                   //counts millis per pulse
 lcdPrintFloat(x,0);

 x = 60000/duration;                       //converts pulses to rpm
 
 lcd.setCursor(0,1);
 lcd.print("rpm");
 lcd.print(" ");
 lcdPrintFloat(x,1);
 delay(1000);
}

/* -------------- Function LcdPrintFloat ---------------- */  
void lcdPrintFloat( float x, byte precision){
 // prints val on a ver 0012 text lcd with number of decimal places determine by precision
 // precision is a number from 0 to 6 indicating the desired decimal places

 if(x < 0.0){
   lcd.print('-');
   x = -x;
 }

 lcd.print ((long)x);              //prints the integer part
 if( precision > 0) {
   lcd.print(".");                 //prints decimal point
   unsigned long frac;
   unsigned long mult = 1;
   byte padding = precision -1;
   while(precision--)
     mult *=10;                  //"amplifies" decimal values

   if(x >= 0)
     frac = (x - int(x)) * mult;
   else
     frac = (int(x)- x) * mult;
   unsigned long frac1 = frac;
   while( frac1 /= 10 )
     padding--;                  
   while(  padding--)
     lcd.print("0");
   lcd.print(frac,DEC) ;
 }
}


The results are instable, varies from 14 to 18 millis / pulse, but this may be due to signal generator armonics and noise.

Besides, suddendly the screen is full with zeros. ??
Seems to be a overrun.

Any improvement suggestions?

OldBeaver

mem

Try printing the output from pulseIn so you can see what the actual period is. It may  help to also print the period of the low pulse:
  duration = pulseIn(pin, LOW);      

Oldbeaver

Dear Mem,

LOW count seems to be a lot more stable.

The sketch is as follows:

/* =============== Millis per Pulse counter ====================*/

#include <DateTime.h>
#include <LiquidCrystal.h>

/* ------------- reset pins, define pins, variables ---------------- */
int resetPin = 3;              // pin 3 resets the time
unsigned long rpmduration;

/* ------- create object to control an LCD GMD1602K -------*/
LiquidCrystal lcd(12, 11, 6, 7, 8, 9, 10); // mem changed pin 2 to 6 (why?)

/* ==================== SETUP ================================== */
void setup(){
pinMode(2, INPUT);               // a button on this pin resets the time
digitalWrite(resetPin, HIGH);   // this line enables pull-up
DateTime.sync( 0 );             // set time to zero
lcd.clear();                          //cleans display
}

void loop(){
/* ============= Execute program over and over ===============*/
 lcd.clear();                          //cleans display
 /* -------- input variables ----------------*/  
 lcd.setCursor(0,0);
 lcd.print("MillH");
 lcd.print(pulseIn(2, HIGH));        //millis between two HIGH pulses
 lcd.print(" ");
 lcd.print("MillL");
 lcd.print(" ");
 lcd.print(pulseIn(2, LOW));         //millis between two LOW pulses
 lcd.setCursor(0,1);
 lcd.print("rpm");
 lcd.print(" ");
 lcd.print(60000/(pulseIn(2,LOW)));  //converts pulses to rpm & prints  
 
  delay(500);
}

Oldbeaver

Dear Mem,

I followed your advice and now the sketch is a lot more compact:

/* ================== Diesel fuel performance ====================*/

#include <DateTime.h>
#include <LiquidCrystal.h>

/* ------------- reset pins, define pins, variables ---------------- */
int resetPin = 3;             // pin 3 resets the time

/* ------- create object to control an LCD GMD1602K -------*/
LiquidCrystal lcd(12, 11, 6, 7, 8, 9, 10); // mem changed pin 2 to 6 (why?)

/* ==================== SETUP ================================== */
void setup(){
pinMode(2, INPUT);               // a button on this pin resets the time
digitalWrite(resetPin, HIGH);   // this line enables pull-up
DateTime.sync( 0 );             // set time to zero
lcd.clear();                    //cleans display
}

void loop(){
/* ============= Execute program over and over ===============*/
 lcd.clear();                          //cleans display
 /* -------- Process of RPM sensor ----------------*/  
 lcd.setCursor(0,0);
 lcd.print("Rpm");
 lcd.print(" ");
 lcd.print(60000/(pulseIn(2,LOW)));  //converts pulses to RPM & prints
 
 /* -------- Process of Vel sensor ----------------*/  
 lcd.setCursor(8,0);
 lcd.print("Vel");
 lcd.print(" ");
 lcd.print(1800/(pulseIn(4, LOW)));  //converts pulses to Vel & prints

 /* -------- Process of Fuel consumption ----------------*/  
 lcd.setCursor(0,1);
 lcd.print("Fuel");
 lcd.print(" ");
 lcd.print((pulseIn(1, LOW))-(pulseIn(3,LOW))); // what is this? Milliseconds...
 
 /* -------- Process of Performance --------------------*/
 // Performance is defined as Vel (km/h) divided by fuel spend (lt/h)
 lcd.setCursor(8,1);
 lcd.print("Perf");
 lcd.print(" ");
 lcd.print(((pulseIn(1, LOW))-(pulseIn(3,LOW)))/(1800/(pulseIn(4, LOW))));
 //lcdPrintFloat(x,1);  // this may be used for decimal results later
 
}

But there is a conceptual mistake in the perf calculus, I think. I am dividing speed by milliseconds, and that donĀ“t make sense to me.

Because, what we have precisely is a volume per pulse of each of the fuel flow sensors. What we need is the difference between them to calculate net consumption.

Fuel consumption is final, no need of relate it to km, to speed or to rpm. It is the true consumption measured.

So what I need is to use the old routine that counted pulses together with this new routine that counts millis. Use two interrupts, and count the pulses of two independent sensors, not the milliseconds. I cannot find any way of converting millis to liters in this case. Am I wrong?

Maybe there is a way. I am not clever today.

Any ideas?

Tks,

OldBeaver

mem

If the fuel flow can change quickly over short periods of time then you may need to count these pulses using interrupts instead of using pulse width. You have two interrupts free so go ahead and try using attach interrupt to do the count. I suggest that you start off with a test sketch that just displays the fuel count and calculated fuel consumption. When you have that working you can add in the other measurements and the performance calculations.

Oldbeaver

I think that is the case: flows will change quickly over time. What you suggest makes sense to me.  I will do just that.

Last night I was reading some Arduino learning material that I downloaded. Very extense and very good. A lot more complete than the manual I got. This should help too.

Thank you very much for the suggestions. I hope I can make the sketch for the two interrupts myself. Will try to work more systematically.

Best,

OldBeaver  :)

mem

Why not post a link, others reading this thread may find that information useful also.

Oldbeaver

Ok. What thread name would you use and in what forum? This project embraces several aspects of Arduino application.

By the way, in the interrupt routine there is the following statement I do not see mentioned but once at the beginning:

long intTachoInHz_Millis = 0;

What is this for?

Oldbeaver

Sorry, you mean a link. A link to where?

OldBeaver

mem

#25
Jun 03, 2009, 10:30 pm Last Edit: Jun 03, 2009, 11:01 pm by mem Reason: 1
A link to this place: "Last night I was reading some Arduino learning material that I downloaded..."

Oldbeaver

The Arduino documents I downloaded can be find in this link:

http://arduino.cc/en/Main/Software

I downloaded the version 012. Now I see there are newer versions.
I have Arduino Diecimila and probably that was the appropriate version in that moment (November 2008).


Oldbeaver

Dear Mem and all,

Follows my pulsecount sketch for two variables.

It compiles well, however, result is always zero for both counters.

Please take a look at it:

// ===================== Cuenta Pulsos New ===================
#include <DateTime.h>
#include <LiquidCrystal.h>

/* -------- reset pins, define pins, variables ------------ */

volatile byte InCount1 = 0;       // declare this as a byte if the count is always less than 255
volatile byte InCount2 = 0;       // declare this as a byte if the count is always less than 255                            
                                 // so you don't have to disable interrupts when using in loop

/* ------- create object to control an LCD GMD1602K -------*/
LiquidCrystal lcd(12, 11, 6, 7, 8, 9, 10);

void setup(){

DateTime.sync( 0 );                 // set time to zero
lcd.clear();                        // clear screen

/* ------------------ Configure pin modes -------------------*/
pinMode(2, INPUT);
digitalWrite(2, HIGH);              // Turn on pullup resistor
attachInterrupt(0, count1, FALLING);   // call count1 when pin falls

pinMode(3, INPUT);
digitalWrite(3, HIGH);              // Turn on pullup resistor
attachInterrupt(1, count2, FALLING);   // call count2 when pin falls
}

void loop(){
// ============= Execute program over and over ===============
/* ------------- declares and reset input count variables ------*/
int InCount1;
int InCount2;
float x;

if(digitalRead(2) == LOW)
    {DateTime.sync( 0 );       // reset time to zero if button pressed
InCount1= 0;                    // reset count1 to zero
    }
if(digitalRead(3) == LOW)
    {DateTime.sync( 0 );       // reset time to zero if button pressed
InCount2= 0;                    // reset count2 to zero
    }
/* --------------- print pulses count1 on LCD ---------------*/
 lcd.setCursor(0,0);
 lcd.print("CountHz1");
 lcd.print(" ");
 x = InCount1;
 lcd.print(int(x));

/* --------------- print pulses count1 on LCD ---------------*/
 lcd.setCursor(0,1);
 lcd.print("CountHz2");
 lcd.print(" ");
 x = InCount2;
 lcd.print(int(x));
   
}

In both interrupts I used HIGH, RISING and FALLING, with no results.

Looking forward to your comments,

OldBeaver

/* --------------- Function count1 ----------------------- */
void count1(){
 InCount1++;
}
/* --------------- Function count2 ----------------------- */
void count2(){
 InCount2++;
}


mem

#28
Jun 04, 2009, 01:03 am Last Edit: Jun 04, 2009, 01:12 am by mem Reason: 1
You have adeclared local version of the variables, remove these from loop:
int InCount1;
int InCount2;

you are also reseting the variables back to 0 in loop when the pin is low

Oldbeaver

Ok, thank you. Worked immediately. ;D

I added a delay of 500 miliseconds at the end of loop, cause counters displayed too fast to see them.

Now I will test a little in the car so to adjust scales, volts, and so on.  8-)

After that, I will test the pulseIn input lines of the other sketch with the car. Once both are ok, will work with them all together. In this routine I have the problem that have to button reset it to make it work. It runs for a while and stops. Maybe for the lack of inputs?

Thank you once more for your kind help.

OldBeaver


Will keep the Forum updated.

Go Up