PinChangeInt : Monitoring Marine engine

Dear All …

I’m planning on using arduino and a PC as data logger of Marine Engine (tug boat with 2 diesel engine).
The arduino will only function as ‘pulse to ascii converter’.
The pulse will come from :

  • 4 x Fuel Flow meter
  • 2 x RPM (Magnetic Pickup)

Currently all I know is that the max fuel flow is 4L/minute , while the Flow sensor is about 1000 pulse per L.
So for single FlowMeter there will be max of 4000 pulse per minute, about 67 pulse per second.

About the magnetic pickup for RPM :

  1. The flywheel is +/- : 200 Tooth
  2. Max RPM : 1800 RPM
    So the max pulse for the RPM will be around : 360000 pulse per minute , 6000 pulse per second.

So the summary, Arduino will receive (at max) :

  1. 4x Interupt , each at 67 Interupt per second
  2. 2x Interupt , each at 6000 interupt per second

I’m planing to use PinChangeInt library to receive pulse, something like this :

/*
Adopted from :
http://arduino.cc/playground/Main/PinChangeIntExample?action=sourceblock&num=1
*/
#include <PinChangeInt.h>
#include <PinChangeIntConfig.h>

#define FL_A1 14  // Will be flowmeter A1
#define FL_A2 15  // Will be flowmeter A2
#define RPM_A 16  // Will be RPM A

#define FL_B1 14  // Will be flowmeter B1
#define FL_B2 15  // Will be flowmeter B2
#define RPM_B 16  // Will be RPM B

void setup() {
  Serial.begin(9600);
  Serial.print("PinChangeInt test on pin 14-19");

  pinMode(FL_A1, INPUT);     //set the pin to input
  digitalWrite(FL_A1, HIGH); //use the internal pullup resistor
  PCintPort::attachInterrupt(FL_A1, cb_fla1,RISING); // attach a PinChange Interrupt

  pinMode(FL_A2, INPUT);     //set the pin to input
  digitalWrite(FL_A2, HIGH); //use the internal pullup resistor
  PCintPort::attachInterrupt(FL_A2, cb_fla2,RISING); // attach a PinChange Interrupt

  pinMode(RPM_A, INPUT);     //set the pin to input
  digitalWrite(RPM_A, HIGH); //use the internal pullup resistor
  PCintPort::attachInterrupt(RPM_A, cb_rpma,RISING); // attach a PinChange Interrupt

  pinMode(FL_B1, INPUT);     //set the pin to input
  digitalWrite(FL_B1, HIGH); //use the internal pullup resistor
  PCintPort::attachInterrupt(FL_B1, cb_fla1,RISING); // attach a PinChange Interrupt

  pinMode(FL_B2, INPUT);     //set the pin to input
  digitalWrite(FL_B2, HIGH); //use the internal pullup resistor
  PCintPort::attachInterrupt(FL_B2, cb_fla2,RISING); // attach a PinChange Interrupt

  pinMode(RPM_B, INPUT);     //set the pin to input
  digitalWrite(RPM_B, HIGH); //use the internal pullup resistor
  PCintPort::attachInterrupt(RPM_B, cb_rpmb,RISING); // attach a PinChange Interrupt

  }

void loop() {
}

void cb_fla1()
{
  Serial.println("A,FL,1");
}
void cb_fla2()
{
  Serial.println("A,FL,2");
}
void cb_rpma()
{
  Serial.println("A,RPM,0");
}

void cb_flb1()
{
  Serial.println("B,FL,1");
}
void cb_flb2()
{
  Serial.println("B,FL,2");
}
void cb_rpmb()
{
  Serial.println("B,RPM,0");
}

My question :

  1. Is there any processing time enough for that interupts ?
  2. Will the interupts process hit/break/intervere each other ?

Note : Currently I don’t have any pulse generators on my desk to simulate the task.

Sincerely
-bino-

  1. Is there any processing time enough for that interupts ?

6000 interrupts a second is one every 166 uS. Since an interrupt takes around 5 uS to process that should be OK.

  1. Will the interupts process hit/break/intervere each other ?

That is a possibility. One interrupt can't interrupt another one, however the second one would be remembered, up to a point. Why not use the external interrupts, rather than the pin change interrupts?

What is the objective here? To work out the engine speed?

You can use timers to count events like that, which will be very efficient and accurate. I have some examples here:

Dear Nick Gammon
I really really appreciate your enlightment

Since there is only 2 external interupts on arduino, while I need to handle 6 pulse source

Really good examples, but I try to off-load the Math/Counting from arduino to a PC. Thats why I just use the arduino as 'pulse to ASCII' translator

Sincerely
-bino-

Thats why I just use the arduino as ‘pulse to ASCII’ translator

That is a bad idea, especially when you are sending serial data from within an interrupt routine.
You are sending 8 characters (including the linefeed and carriage return) on each interrupt. At 9600 baud it will take over 8 milliseconds to send just one message during which time you will have received at least 48 more interrupts just from one RPM input.
You would be a lot better off counting the pulses in the interrupt routines and then periodically sending a summary to the PC.

Pete

How are you going to offload this counting to a PC? Through the serial port?

Anyway, for the 2 x 6000 counts you could use external interrupts, and pin changes on the slower ones. The trouble with pin change interrupts is you only get one interrupt per port, so you have to spend time working out which pin changed (out of the 8 possible).

However I would still be tempted to use the internal timers for at least the high-speed events. You could then count how many happen in (say) a second, and upload the counts, plus the counts from the other interrupts, to the PC once a second.

(edit) Ninja'd by el_supremo ... yeah, what he said.

Dear Nick Gamon and El_supremo.

I realy appreciate your enlightment.

Hmmm … second thought …
What About this :

  1. Use PinChange For that 4 Flow meter (Low pulse per minute), and
  2. Use Frequency-to-voltage IC and feed the output to Analog pin to read the current engine RPM

Something that noted at http://www.jaycar.com.au/images_uploaded/LM2907.PDF page 7 (Minimum Component Tachometer) , Plus a voltage devider .

About periodic Serial.println … could be done.
Maybe once per second ?

Sincerely
-bino-

binooetomo:
2. Use Frequency-to-voltage IC and feed the output to Analog pin to read the current engine RPM

You are chucking resolution out the window doing that. The max the analog pin can read is 1023, so for 6000 revs a second you would not be able to tell the difference between 5999 and 6002. Just hook it up to the timer input. Simple and elegant. Have an overflow interrupt to handle when the timer overflows.

Dear Nick Gammon.

My apologize, my brain is not good enough to understand your code.
Thats why I look for a dumb work around.

I got additional info about target engine
The engine have 132 tooth flywheel, and max RPM is 2500

and I will use this to convert from Frequency to Voltage

with Magnetic Pickup like above, I thing I can use (cmiiw) the math of :

Freq = Gear x Rpm

means that the max Freq will be : 132 x 2500 = 330,000 Hz

and the max Voltage will be 4925.373134328 V.
Using Voltage devider of factor 0.001 at the Vout point, I'll got max volt of 4.925373 V where the arduino analog pin can handle.
And I thing the max analogread value returnd will be (4.925373/5)*1023 => 1007.7313
That is the max value that will be reported to PC.

Thats what I can thing it so far.

Sincerely
-bino-

binooetomo:
and the max Voltage will be 4925.373134328 V.

So you would prefer to work with 4925 volts than just have a timer count pulses?

Dear Nick Gammon.

I knew that arduino analog will unable to handle that level of voltage

Well ... actualy after some correction on that ''
with 132 tooth wheel, it can reach 154.985074626866 V at 4720 RPM

Using Voltage devider before entering Analog Pin

using R1=300 Ohm , and R2=10 Ohm
and
Vout = (R1/(R1+R2)Vin*

The Vout at 4720 RPM will be 4.99951853635051 Volt ... It is compatible with Analog PIN

The problem will : How much is the real max RPM of the engine

Sincerely
-bino-

guys why wouldn’t you use a counter ic as a prescaler on the 6000 pulses per second ?

Duane B

rcarduino.blogspot.com

Just a few thoughts / comments.

Variable reluctance sensors' voltage changes with speed, low V at low speed, high V at high speed. The voltage can vary by a factor of 100 over a normal RPM range. Also, the voltage swings positive and negative. You can't connect a VR sensor to a micro with a simple resistor divider.

I question the tachometer circuit. It's output will be a signal between 0 and 15V, either a pulse width modulated signal or an analog voltage (depending on filtering). I think the VR signal conditioner on the front end needs some protection and it may not work at slow speeds. I don't understand what the block labeled "charge pump" does unless it is a switched cap amplifier to isolate the output from the input.

You really need to put an oscilloscope on the signal and see what you have to work with. What is the signal going to the tachometer in the cabin? Does it get the raw VR signal? or is it processed somehow? Can you capture that signal?. In the end it may be easier to add another sensor to the engine. Most Hall effect sensors or optical sensors put out simple digital signals that can be connected directly to a micro. You may be able to select the number of pulses per revolution to something that suits your system better.

Speed and throttle don't usually change very fast in a boat; if you are logging hours at each speed / load you probably don't need millisecond data. Why not measure one input at a time (particularly the fast engine speed signals) and then send the serial data all at once. Measure engine 1 for 100mS (or whatever makes sense) then measure engine 2, then measure the flow sensors. Then send one message with all the data. Alternatively send the engine 1 message while you are measuring engine 2. By the time you are done measuring engine 2 the first serial message will be complete.

You should be able to capture a set of data every second or two which is probably good enough for an application like this (if I understand it correctly)

DuaneB:
guys why wouldn't you use a counter ic as a prescaler on the 6000 pulses per second ?

Bingo. Bring that max 6000 pulses-per-second down to a more reasonable number by dividing by (e.g.) 2, 3, or 6. That relaxes the demand on the AVR handling interrupt requests considerably. High dividers trade reduced resolution for less processing time. Assuming you're just looking for a heads-up display for RPM, you don't need single-revolution precision anyway.

(Although, in retrospect, it looks like this is basically what Nick was suggesting by using the timer input to fire once every however-many pulses.)

Dear DuaneB

DuaneB:
guys why wouldn't you use a counter ic as a prescaler on the 6000 pulses per second ?

Could you please give me the part name ?

Sincerely
-bino-

SirNickity:
Bingo. Bring that max 6000 pulses-per-second down to a more reasonable number by dividing by (e.g.) 2, 3, or 6. That relaxes the demand on the AVR handling interrupt requests considerably. High dividers trade reduced resolution for less processing time. Assuming you're just looking for a heads-up display for RPM, you don't need single-revolution precision anyway.

Actualy it is for data loging.
The log will be used to judge the sailor behavior.

SirNickity:
(Although, in retrospect, it looks like this is basically what Nick was suggesting by using the timer input to fire once every however-many pulses.)

Agree.
But as I state above, i'm not good enough to understand His code.
I never play with timer before.

I only have 2 weeks to finish the project, including all server side programming.

Sincerely
-bino-

sdturner:
I question the tachometer circuit. It's output will be a signal between 0 and 15V, either a pulse width modulated signal or an analog voltage (depending on filtering). I think the VR signal conditioner on the front end needs some protection and it may not work at slow speeds. I don't understand what the block labeled "charge pump" does unless it is a switched cap amplifier to isolate the output from the input.

That "Charge pump" is internal of LM2917

Ok Here my try

I'm adopting http://www.ti.com/lit/ds/symlink/lm2907-n.pdf Page 10.
It say 66 Hz / Volt ... thats how my max Volt will be very High at first.
Then I try to put Voltage devider to the output ... and feed the devided voltage to arduino


OOpppsss ... My apologize ... I don't know the code to shrink down the image for display

R3 and R4 are the voltage devider.

MPU is : Magnetic PickUp
TACH Pin is the one that connected to Arduino Analog Pin.
Whith 132 tooth wheel the freq/RPM is : 2.2 Hz/RPM
And with that Volt devider, Hopefully the Volt/RPM is arround : 0.00105922002889 Volt

Sincerely
-bino-