First AVR project using an Arduino Nano v3 w/atmega 328p.

Go To Last Post
41 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have a few newbie questions. This is my first project using an Avr, Atmel Studio, or an Arduino

platform.

 

?? Do i need a pin_definition.h file to use the Nano?, or do I only need to know the ports on

the atmega328p to define the pins I need?

 

My first project is a tachometer for my friends watercraft. There are tons of tachometer threads

on AVRFreaks, almost to many, and it has been difficult to find something that is close to what

I need. My basic program is simple. It requires 2 interrupts, 1st interrupt to count count rps (roughly

15 to 150 events per sec). The 2nd interrupt to create a timer overflow after 1 second, and shut

down all interrupts until the lcd has updated the present rpm (every couple seconds or more).

Then restart the interrupts and start again.

 

?? My questions are about sei(), cli() and any other flags that need to be shut down or reset.

 

The majority of my experience is with the Propeller, stamps, and registers are mostly a foreign

concept to me.

 

#include <avr/interrupt.h>

void main()
{
	while(1)
	{
		// endless do-nothing loop.
	}
}

ISR(INT1_vect)							// pin change on rising edge
{
	rps++;							// Counts ~15 to 150 rising edges/sec.
}

ISR(TIMER1_OVF_vect)						// Overflows once to create a 1 sec period
{
	cli();
	word rpm = rps * 60;
	if(rpm != oldrpm);
	{
		// separate digits into 1000's, 100's, 10's, 1's
		// call function to display data on lcd
		// clear any interrupt flags necessary
		oldrpm = rpm;				// create a check for new lcd input
		sei();						// enable all interrupts

	}

}

?? My last question is how C, C++ deals with converting a large # like 7236 rpm into individual

character digits and how they are sent to the lcd. Reading other character lcd code that has

been provided in the AVRFreaks Tutorial section, it appears there is just a keyword or built in

function? My code is below to show you how I would normally handle it.

 

void LCD_4_DIGITS
{
	char digits[3] = {0x00,0x00,0x00,0x00};

 // Init digits to all zeros
 // PUT digits, "0000"

 // Convert value to ascii digits
	while (value >= 1000)
	{
    digits(0)++;
    value = value - 1000;
	}
	while (value >= 100)
	{
    digits(1)++;
    value = value - 100;
	}
    while value >= 10
	{
    digits(2)++;
    value = value - 10;
	}
    while (value >= 0)
	{
	digits(3)++;
    value = value - 1;
	}
  // Send digits to LCD
FOR(idx=0,idx++, idx==3)			// idx = 0 TO 3
	{
    character = digits(idx);
    digitalwrite(RS, high);
    lcd_data =  character;
    pulseout(5);
    DELAY_US(40);
	}
void LCD_Put_String()
{
	DO;
	READ addr, character;
	addr = addr + 1;
	IF (character = 0) THEN EXIT;
	LCD_Write();
	LOOP;
	RETURN;
}

 

 

Eventually I need to reduce my error to +/- 1 rpm. But to do that I need to measure 1

revolution accurately in milliseconds and then use division to find the accurate rpm.

60/1 rev in milliseconds.

 

My problem is mostly with finding out how to first represent a time like .012 milli-seconds

in binary, and of course doing the math. Fortunately time is my friend. Displaying the rpm

too quickly will make the rpm difficult to read while you are bouncing around in the water.

Too slow, like every 5 to10 seconds would also be bad. Two to three second refresh should

be easier to see.

 

?? Is there any tutorials or reading sources you can point me towards.

 

Thank You

 

 

Bill M.

Last Edited: Wed. Aug 31, 2016 - 11:54 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

wmazz wrote:

Do i need a pin_definition.h file to use the Nano?, or do I only need to know the ports on

the atmega328p to define the pins I need?

 

Use the Port and Pin names as specified in the 328P datasheet.

 

This is the schematic symbol that I use to keep Nano pin to 328P pin names straight.

 

I am using Atmel Studio 6.2.  When I create a new project I see:

 

Select GCC Executable Project and give the project a name.  Then click OK. 

Be patient.  It takes about 5 seconds for the next window to appear.

 

Scroll down and select the ATmega328P.  Click OK.

After a delay, the project window will appear.

 

Note the line:  #include <avr/io.h>

This will include the device port and pin name definitions as shown in the 328P datasheet.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

wmazz wrote:

Eventually I need to reduce my error to +/- 1 rpm.

 

At 7000 rpm, +/- 1rpm = +/- 0.014%. 

There are two problems that will prevent you from achieving that.

 

First, the Arduino Nano uses a ceramic resonator that has an accuracy of +/- 0.5%, so your 2 second sampling period may be off as much as 0.5%.

This error can be reduced by calibrating each Nano, but you still have a frequency stability (temperature variation) of at least 0.1%.

 

Second, because the rps signal that generates the interrupt is asynchronous to the 1 second interrupt, the rps count will be off by +/- 1 count. 

At the minimum of 15 events per second  and a 2 second sampling period, you get an error of +/-1 in 30 = +/- 3%.

You can reduce this error by having a sensor that generates more than 1 event per revolution.

 

Given the above, your quest for +/- 1rpm accuracy is not realistic.

 

Last Edited: Thu. Sep 1, 2016 - 05:04 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

wmazz wrote:

My first project is a tachometer for my friends watercraft.

 

My basic program is simple. It requires 2 interrupts, 1st interrupt to count count rps (roughly

15 to 150 events per sec). The 2nd interrupt to create a timer overflow after 1 second, and shut

down all interrupts until the lcd has updated the present rpm (every couple seconds or more).

Then restart the interrupts and start again.

 

It would be better to do the calculations and LCD update outside the interrupts.

This keeps the interrupts short and allows counting the next value while concurrently calculating and displaying  the last value.

This way you don't need to disable and re-enable the interrupts.

 

 

ISR(INT1_vect)							// pin change on rising edge
{
	rps++;							// Counts ~15 to 150 rising edges/sec.
}

rps should be a global variable declared as volatile because it is being modified inside an ISR.

 

 

The Nano cpu clock is 16MHz.

TC1 is a 16-bit counter and with the correct prescaler can set to generate an interrupt every 2 or 3 seconds.

I think it would be better to use the output compare interrupt instead of the overflow interrupt.  You need to select the correct counter mode for that.

 

ISR(TIMER1_???_vect)						// Interrupt once every 2 or 3 seconds 
{
	rps_counts = rps;  // capture the current count
        rps = 0;           // reset for next value
	new_value = 1;     // indicate new value is ready	
}

rps_counts and new_value are global variables that are declared volatile.

 

 

void main()
{
        <initialize everything>

	while(1)
	{
	  while(new_value == 0); // wait for a new value 
          new_value = 0;

          my_rps_counts = rps_counts;  // copy to use for calculations - if larger than 1 byte, use atomic block

          <calculate the new rpm>
          <display the new rpm>

	}
}

 

I hope the above helps you get started.

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Chuck99, Thanks for the detailed response!

 

The following is just to clear up some of the details. But the details

are not all that important.

 

I could really use some help with the other questions if possible :)

Thanks!

 

wmazz wrote:

My first project is a tachometer for my friends watercraft. There are tons of tachometer threads

on AVRFreaks, almost to many, and it has been difficult to find something that is close to what

I need. My basic program is simple. It requires 2 interrupts, 1st interrupt to count count rps (roughly

15 to 150 RPS. (during the 2nd interrupt)). The 2nd interrupt to create a timer overflow after 1 second,

and shut down all interrupts until the lcd has updated the present rpm (every couple seconds or more).

Then restart the interrupts and start again.

 

?? My questions are about sei(), cli() and any other flags that need to be shut down or reset.

 

Without getting technical with crystal issues and addition clock cycles caused by interrupt delays.

This tachometer should have a ~ +/- 30 rpm accuracy.

 

 

wmazz wrote:

Eventually I need to reduce my error to +/- 1 rpm. But to do that I need to measure 1

revolution accurately in milliseconds and then use division to find the accurate rpm.

60/1 rev in milliseconds.

 

My problem is mostly with finding out how to first represent a time like .012 milli-seconds

in binary, and of course doing the math. Fortunately time is my friend. Displaying the rpm

too quickly will make the rpm difficult to read while you are bouncing around in the water.

Too slow, like every 5 to10 seconds would also be bad. Two to three second refresh should

be easier to see.

 

?? Is there any tutorials or reading sources you can point me towards.

 

I am certain there will be rounding errors associated with my eventual goal of +/- 1 rpm.

 

What is important is not the accuracy, but the the binary math required to display rpm

based on 1 revolution.  

 

Thanks

 

 

Bill M.

 

Last Edited: Thu. Sep 1, 2016 - 06:18 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

wmazz wrote:

What is important is not the accuracy, but the the binary math required to display rpm

based on 1 revolution.  

 

First, the code you listed in post #1 showed counting events for a fixed period of time (2 to 3 seconds).

 

Counting the microseconds for 1 revolution is totally different.  Why do you want to do that?

 

Anyway, the amount of time (microseconds, etc) for 1 revolution depends on revolutions/sec.

At 7000rpm you have 116.7 rev/sec, 1 rev = 8571 microseconds or 137,143 16MHz clock cycles - the best resolution you can get with a Nano.

 

The accuracy is still dependent on the accuracy and stability of the Nano resonator (16MHz).

 

If accuracy is not critical, are you actually saying you want a resolution of 1 rpm?  That would be easy to do using integer math.

 

If 1 rev = x 16MHz clock cycles  ==>  t = x/16MHz   ==>  rpm = 60/t = (60 * 16,000,000)/x

 

In this approach you would use TC1 with a prescaler of 1 and also count the overflows for the higher significant bits.

The counter value & overflow counts forms the value of x.

 

 

 

Last Edited: Thu. Sep 1, 2016 - 06:57 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

It is better to use a timer in CTC mode for exact intervals.

And there is a function utoa() for converting a number to a string for Lcd display.

// atmega328  16 MHz

#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <avr/interrupt.h>

// global variables
volatile uint16_t rps;
volatile uint16_t pulse_count;
volatile uint8_t  ovf_flag;
uint16_t rpm;
char display_string[9];

int main()
{

// init Timer1 in CTC mode, prescale 256
   TCCR1B = (1<<WGM12)|(1<<CS12); 

// OCR1A = (time[microsec] * F_CPU[MHz] / prescaler)  - 1
   OCR1A = 62499;
   TIMSK1 = OCIE1A; //enable interrupt

   sei();

	while(1)
	{
	   if(ovf_flag)
           {
              ovf_flag = 0;
              rpm = pulse_count * 60;
              utoa(rpm,display_string,10); // converts integer to string
              LCD_Put_String(display_string);
           }
        }
}

ISR(INT1_vect)						// pin change on rising edge
{
	rps++;							// Counts ~15 to 150 rising edges/sec.
}

ISR(TIMER1_COMPA_vect)				// Overflows every sec
{
static uint16_t old_value, new_value;

   new_value   = rps;
   pulse_count = new_value - old_value;
   old_value   = new_value;
   ovf_flag    = 1;
}

 

 

Last Edited: Thu. Sep 1, 2016 - 07:10 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry I am lagging behind, I take a long time write my posts, while others are answering my

previous posts. TY people!

 

 

Chuck99 wrote:

wmazz wrote:

My first project is a tachometer for my friends watercraft.

 

My basic program is simple. It requires 2 interrupts, 1st interrupt to count count rps (roughly

15 to 150 events per sec). The 2nd interrupt to create a timer overflow after 1 second, and shut

down all interrupts until the lcd has updated the present rpm (every couple seconds or more).

Then restart the interrupts and start again.

 

It would be better to do the calculations and LCD update outside the interrupts.

This keeps the interrupts short and allows counting the next value while concurrently calculating and displaying  the last value.

This way you don't need to disable and re-enable the interrupts.

 

I have read that before, and I understand why. But I have no need for the program to continue

counting while the lcd is still processing information. It is really important for the tachometer to

be easily read while riding.

 

Tiny Tach's are an example of a cheap tachometer that is difficult to read, but for a different

reason. They update too slow, and there highest rpm capture figure is usually when the pump

catches air and is close to, or bouncing off the rev-limiter.

Chuck99 wrote:

ISR(INT1_vect)							// pin change on rising edge
{
	rps++;							// Counts ~15 to 150 rising edges/sec.
}

rps should be a global variable declared as volatile because it is being modified inside an ISR.

 

Agreed!

 

Chuck99 wrote:

The Nano cpu clock is 16MHz.

TC1 is a 16-bit counter and with the correct prescaler can set to generate an interrupt every 2 or 3 seconds.

I think it would be better to use the output compare interrupt instead of the overflow interrupt.  You need to select the correct counter mode for that.

 

 

I will look into " output compare interrupt." 

I was hoping that I could pick a prescaler, then write an (offset) to the timer before I start it, so the overflow

would occur as close to 1 second as possible.

 

 

 

Chuck99 wrote:
can set to generate an interrupt every 2 or 3 seconds

 

I don't understand why you are suggesting 2 to 3 seconds. It just seems to make things

more difficult??

 

 

Thanks

 

Bill M.

 

Last Edited: Thu. Sep 1, 2016 - 07:14 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I posted some code years ago that uses the input capture feature. Only one interrupt needed. The value is filtered to smooth out the changes. I recently used a similar technique on a bluetooth module and iPhone app.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

wmazz wrote:
I don't understand why you are suggesting 2 to 3 seconds. It just seems to make things more difficult??

I want to start over, about the overall aims.

 

wmazz wrote:
My first project is a tachometer for my friends watercraft.
wmazz wrote:
... eventual goal of +/- 1 rpm.

As discussed above, it certainly is practical to get instantaneous reading (using input capture) and updating the display each reading.

 

But to what end?  During any practical run, the lower two digits of the display will be dancing too fast as to be unusable.  So your user will end up putting a piece of tape over them.

 

Thus the typical way to make a usable display is to update it several times per second.  10x is too fast; 1x is too slow.  IME, and general guidelines.

 

Now, you can get an "exact" display by, say, counting the pulses every 100ms and then total 10 readings for the display--for the past second.  But again:  in any practical run, is  that number so useful as to make +/-1rpm of any use?  Yes, it is as close to exact as you can get for that past second.  But one could be accelerating or decelerating  during that time.

 

A very similar discussion in 2008:

http://www.avrfreaks.net/forum/o...

 

With a faster max rate:  http://www.avrfreaks.net/forum/c...

 

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Thu. Sep 1, 2016 - 04:58 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sometimes having an analog representation makes the data more clearly understood. I prefer an analog tach. (YMMV)

David (aka frog_jr)

Last Edited: Thu. Sep 1, 2016 - 04:58 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The TC has the ability to count external pulses, so it can be configured to count RPS directly without requiring an interrupt.  Once every second in an ISR you grab the current count, reset it, and set a "new data" flag.  In your main loop you test the flag and, when it is set, you clear it, do any required calculations, and send it to the LCD.

Greg Muth

Portland, OR, US

Atmel Studio 7.0 on Windows 10

Xplained/Pro/Mini Boards mostly

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Now y'all have gotten me thinking.  Chuck99 mentioned 16MHz Nano (typical? always?) with a ceramic resonator (typical? always?).  IME ceramic resonators are pretty close to nominal, but in OP's quest for absolute precision (and the app implies varying conditions) obviously the results are only going to be as good as the clock.  Now, if it is pretty stable over temperature and time a one-time cal could be used.

 

I'f I'm doing the arithmetic (I don't want to say "math" or "maths") correctly that is 50rps at the maximum 3000rpm.  Chuck99 pointed that out as well.  (will it really be +/-1 or only off in one direction?  Can't get to 0.1% 1/1000, or better, in either case.

 

However, given an AVR clock "close enough" to nominal, then input capture can time each revolution to less than a microsecond; down to +/-1 AVR clock.  And with 20ms or more between "hits" that part is no problem.

 

One must also postulate that the input signal is "clean enough".  perhaps it may need to be filtered but in steady-state any time lag from the filter should cancel out, right?

 

=============

Part 1:  Exploring Maximum Precision

 

Maximum precision can be had with an AVR8 with the signal to the ICP1 pin and a /1 prescaler on timer 1.

 

Let's see how that comes out at 3000rpm 50rps 20.0000000ms.  [I see now that there was a mention of 7000rpm but not by the OP.  I'll continue right now with 3000rpm to get nicely dividable numbers and we can adjust later for maximum rpm.]

 

Period of exactly 20ms, with 16000 timer counts per millisecond, gives 320000 timer counts.  16000000 cycles/second * 60 seconds/minute / 320000 cycles/period gives 3000 periods per second.

 

Now, let's say we have one more and one less timer count...

 

320001 counts gives 2999.99rpm

319999 counts gives 3000.009rpm

 

Note that the above is done with 32 bit integer arithmetic, except for showing the fractional leftover amounts.  It shows that with the ICP method a resolution roughly 100x OP's desired resolution can be obtained.

 

But I'd never do it that way, unless I had to.  To get to 320000 there will be several timer overflows that would need to be handled. As the resolution is way beyond desires or practical needs, KISS, and use a timer prescaler.

 

=============

Part 2:  Exploring Practical Precision

 

So if we want to use a prescaler, which one to use?  All the way to /64 gives us the desired resolution of 1 part out of 3000.

 

But that is at max rate.  Of concern is how slow can we go, get good readings, and not have to fuss too much with overflows?

 

A bit of work with KAVRCALC indicates that 16MHz and /64 the timer has a reach of 262ms, or ~4Hz, or about 240rpm.  That sounds pretty good to me for most work--below that the engine probably isn't running.  So if a reading gets more than one overflow it is discarded.  And at the very slow end like this, handling a few overflows isn't a big deal once you do it cleanly.  If you want to go about 1000rpm minimum then use /16.

 

=============

Summary:  Above shows that using ICP (Input CaPture) on AVR8 timer1 when running at 16MHz, a practical /64 prescaler lets one have a range of about 250rpm to many 10's of thousands of rpm without worrying about any overflows other than to detect "loss of signal".

 

It might need to be adjusted a bit for a 10000rpm engine to still reach 1rpm resolution.  No real problem; use /16 or lower prescaler and handle 2+ overflows for the low end.

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Thu. Sep 1, 2016 - 08:07 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Greg_Muth wrote:
The TC has the ability to count external pulses, so it can be configured to count RPS directly without requiring an interrupt. Once every second in an ISR you grab the current count, reset it, and set a "new data" flag. In your main loop you test the flag and, when it is set, you clear it, do any required calculations, and send it to the LCD.

Indeed very straightforward and practical.  Except, as Chuck99 went into, rps is so coarse that it would be impossible/very difficult to hit OP's 1rpm resolution goal.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Except, as Chuck99 went into, rps is so coarse that it would be impossible/very difficult to hit OP's 1rpm resolution goal.

I didn't address that issue as I felt it had already been beaten to death.  It's clear from the discussion above that +/- 1 RPM is an unrealistic goal.

Greg Muth

Portland, OR, US

Atmel Studio 7.0 on Windows 10

Xplained/Pro/Mini Boards mostly

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Using a tachometer on a watercraft or jetski is a little different then a tachometer

on many other vehicles. For example:

 

(1) Unlike vehicles with a transmission or direct drive like many karts, the engine

will have little or no over-rev beyond peak HP.

 

(2) A good test run is only 50 yards (~50meters) long, with a top speed near 50

mph (80kph).

 

(3) On stand-up style watercraft, it is difficult to watch a tachometer.  Generally,

there is little time to catch a glimpse of the tach. That is one reason why I need an

rpm update about every 2 to 3 seconds.

 

(4) On modified watercraft (jetski's) the engine will blow-up (normally by detonation,

followed by preignition) if the engine is unable to make peak HP rpm while running

at wide open throttle.

 

That is why it is so important to use a tach while tuning an engine for the first time,

and to test the ski with at least an idea where peak HP will occur. Of course, using a

tach while "tuning" is always important. It is important to always have expected results.

 

(5) The jet pump that watercraft or jet ski's use acts as a rpm governor at wide

open throttle.

 

The purpose of the tachometer is to be able display peak rpm within 50 yards. First

The rider needs to catch a glimpse of the tach within that distance to determine if his

impeller allows the engine to closely approach peak HP, or achieve peak HP rpm.

Second, the rider needs to determine if adjustments to his carburetor jetting, or

other fine tuning allows the engine to achieve peak HP rpm, or a few hundred rpm 

past peak HP.

 

Kartman wrote:

I posted some code years ago that uses the input capture feature. Only one interrupt needed. The value is filtered to smooth out the changes.

I recently used a similar technique on a bluetooth module and iPhone app.

 

I have already reviewed your code, but unfortunately I have collected so many 

examples, I don't know which one is yours :(

 

I will revisit it.

 

In the future I would like to add a bluetooth play-back feature. But I need to

complete this before I think any further ahead.

 

 

 

Greg_Muth wrote:

The TC has the ability to count external pulses, so it can be configured to count RPS directly without requiring an interrupt. 

Once every second in an ISR you grab the current count, reset it, and set a "new data" flag.  In your main loop you test the

flag and, when it is set, you clear it, do any required calculations, and send it to the LCD.

"TC" Timer/Counter?

That is basically what I was trying to do with my first tach, and I am sure that

other tachometer examples may have done the same. But I was unable to properly

read the code.

 

There were some examples that I read, that did a poor job, imo. Some programs appeared

to stop the counting after 1 second.

 

theusch wrote:

One must also postulate that the input signal is "clean enough".  perhaps it may need to be filtered but in steady-state any

time lag from the filter should cancel out, right?

 

I have read a post in AVRFreak's, where the input signal was ringing. My circuit

is from a timing light, and uses a few filters and a 555 timer to send the signal

to the u-controller. Here it is at Sport Devices

 

 

Accuracy

Because I started with Basic Stamps, I noticed most BS code created rather large

errors. Before the Propeller, I used the SX, and the best code we developed

used the time of one 1 revolution based on 6 million micro seconds.

 

 

Bill M.

 

Thank you, Chuck99, Visiovian, Greg_Muth, frog_jr, theusch!

 

 

Last Edited: Fri. Sep 2, 2016 - 01:24 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I just use a bit of wire cable tied to the ignition lead, a transistor, two diodes, four resistors and a capacitor to filter the ringing.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Greg_Muth wrote:
It's clear from the discussion above that +/- 1 RPM is an unrealistic goal.

...by counting pulses.  I think I demonstrated that it can be done with ICP.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

wmazz wrote:
That is why it is so important to use a tach while tuning an engine for the first time, and to test the ski with at least an idea where peak HP will occur. Of course, using a tach while "tuning" is always important.
sounds to me that you need something more like an engine management system than a tachometer and putting a hugely unreliable shaved ape in the middle of the control loop! Have something like an "electronic throttle" and simply don't relay its commands to the engine if to do so would cause it to blow up. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

wmazz wrote:

That is why it is so important to use a tach while tuning an engine for the first time, and to test the ski with at

least an idea where peak HP will occur. Of course, using a tach while "tuning" is always important.

 

sounds to me that you need something more like an engine management system than a tachometer and putting a hugely unreliable shaved ape in the

middle of the control loop! Have something like an "electronic throttle" and simply don't relay its commands to the engine if to do so would cause it to blow

up. 

 

I participate on a watercraft forum, where most members try to tune their ski's

without a tach. It is a common mistake to use an impeller that is too large for

their application. Many vendors sell impellers on the idea that the more HP your

engine makes, the larger the impeller should be. Other so called experts think

that when you want more speed, you just add a larger impeller as if they were

sprockets. Some of that works for easy modifications on a stock or lightly ported

engine, but after that point, impeller choice is critical.

 

The above doesn't even cover the myths and common mistakes surrounding tuning,

or all the junk that people find in classifieds and ebay.

 

My intention is to share this "simple" tach with others.

 

 

Kartman wrote:

I just use a bit of wire cable tied to the ignition lead, a transistor, two diodes, four resistors and a capacitor to filter the ringing.

 

Kartman, do you use something similar to this attachment??

 

 

Bill M.

 

 

Attachment(s): 

Last Edited: Fri. Sep 2, 2016 - 10:30 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No. I don't use an inductive sensor. I use a capacitive sensor ie: a piece of wire.

I just noticed the transistor should be a pnp one - BC557

Last Edited: Sun. Sep 4, 2016 - 04:47 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you Kartman, I was just about ask you about two other circuits I have

collected.

 

Kartman, why do capacitive pick-ups not require a ground connected to the

coiled copper wire?

 

In the U.S., they sell a horrible little tach/hour meter called: "Tiny Tach" and it

uses a similar circuit, except it uses shielded copper wire with a ground lug

near the spark plug, and from what I tell, it uses copper fills on the circuit

board to contribute to the circuit.

 

Thanks

 

Bill M.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The wire is not coiled. You just cable tie it on for a couple of inches. As for ground, stray capacitance completes the circuit.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How close to the nano, can I route the capacitive wire lead from the spark plug

wire.

 

Or, if I ran the capacitive wire lead in the opposite direction of the Nano, how

close to the Nano can I put your circuit (or a similar circuit)? Is there a potential

problem with RFi if the circuit is too close to the Nano?

 

Kartman wrote:

I just noticed the transistor should be a pnp one - BC557

 

Thank you for the update!

 

Bill M.

Last Edited: Thu. Sep 8, 2016 - 05:55 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It is all down to layout. I have no trouble with my setup which uses a bluetooth module. I have the sensor wire away from other wiring and it goes through the 100k resistor. The energy in the wire is quite small. My setup is on my gokart with a rotax fr125 engine in the usual place and my electronics sit in the front of the kart between my feet. Just about every digital dadh on a kart works the same way.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:

My setup is on my gokart with a rotax fr125 engine in the usual place and my electronics sit in the front of the kart between my feet.

Just about every digital dadh on a kart works the same way.

 

At least now I know where "Kartman" comes from.

 

What does dadh mean?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My guess is a mistyped "dash"...

 

Ross McKenzie ValuSoft Melbourne Australia

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am fairly familiar with karting, my local track is just a mile from my house. Adam's Kart Track

There is still few other tracks close by. There used to be a really long track, that was owned

by a father-son Indy car drivers.

 

Do you run that Rotax in a spec class?

 

 

Bill M.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Chuck99 wrote:
At least now I know where "Kartman" comes from.

 

Aw. You mean it has nothing to do with South Park?! wink

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

valusoft wrote:

My guess is a mistyped "dash"...

 

Palm to forehead ... Doh!

I wasted at least 5 minutes searching for "dadh".

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Did you find the affectionate form of "Dad"?

 

Ross McKenzie ValuSoft Melbourne Australia

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Interesting Thread.

 

Lots of ways to skin a cat, obviously.

 

I'm glad that the accuracy issue was already handled.  With a 16 MHz uC one can make the Tacho as accurate as you wish, (within the accuracy and drift of the uC's clock).

 

Displaying the least significant digit of the result is always a designer's choice on how it should be done.  Adding the "extra" digit just gives one a bouncing, poorly readable, display.  Rounding the result to X digits is usually reasonable.

 

I am fascinated by the OP's desire to only update the display once every 2 - 3 seconds.  I don't have any experience with high performance / racing jetskis, but that seems like a less-than-optimal approach to me.

 

When I am looking at an instrument cluster, I generally want the most current data available.  Not data that is 3 seconds old.

 

It seems to me that one's algorithm for how one filters the data, and captures peak rpm data, etc., ought to be a separate design question to how one displays the data.  In fact one might envision the end device having several different modes of operation, user selectable, that essentially just change the data filtering algorithm, (response time, etc.), while the core hardware and display routines remain unchanged.

 

I would think that if the user only glances at the display very briefly, every now and then, then having a larger, brighter, sunlight readable display would improve the user interface, (ability to read the data), more than slowing the display update to such a slow rate.

 

Perhaps a better user interface, eventually, is a heads up display, such as is commonly found on jet fighters, high performance cars, sky divers, etc.  Think Google Glasses type display where the data is shown in the corner of one's visual field, and one doesn't have to turn their head & neck to locate and then focus on the display. 

 

I guess an underlying question is just how fast does an engine "blow up", once it is operated out of the allowable parameters?  When the jetski catches air, unloads the impeller, loses the governor function of the impeller, how quickly does the engine over speed, and is that what precipitates the engine "blowing up"?

 

If so, then relying on the human in the control loop, as Cliff mentioned, seems like a bad idea.  Relying on the human to occasionally glance down at the tach and process the data and throttle down, (and use 3 second old data at that), doesn't seem like a great plan.

 

Time to change gears, (albeit your jetski doesn't have any...)

 

If your background includes using a Basic Stamp then your initial global concept on how to proceed is reasonable.  The BS doesn't have user useable interrupts, and can't "multi-task" well.  It is/was common when using a BS to segmentalize one's program's tasks, and perform them sequentially.  Hence your plan to capture the data, then shut down the data capture process and switch to the data calculate and display routines, then loop.

 

I wrote many BS programs using that paradigm.  But now that you have switched to an AVR you have the ability to approach the problem in another manner.  The "classic" approach with a current, relatively high speed (16 MHz) uC, with interrupts available, would be to have your data collection process running continuously, (typically in the background, i.e. interrupt driven, and invisible to the rest of the application).  In the foreground, Main Loop, you would run your data crunch and display update routine, as well as read any user push button switches to reset the Max RPM value, cycle the display through other data, (Max Cylinder Head Temp, Max rate of RPM change, Number (or rate) of cylinder mis-fires, etc.) .

 

If you wanted to update the display "slowly", say 4 times / second or slower, down to your original once every 3 seconds, the process in the main loop is to grab the current data value from the data capture routines running in the background, process that data, and display it, ... then wait ... and then repeat the process.  Know that with the uC running at 16 MHz, even doing the calculations with floating point math instead of (faster) scaled integer math is still very fast from a user perspective, perhaps 10's of milliseconds.  That, from a practical perspective, when one is only updating at 0.333 to 4 Hz, is totally irrelevant.

 

I don't think you mentioned whether your display will be an LCD or an OLED graphic display, or a 7-Segment LED display.  The 7-Seg LED display would run, continuously, as another interrupt driven task in the background, taking whatever the current display data value ( s ) are and displaying them.  The LCD and OLED displays might be updated in the foreground task, when slow updates are performed.

 

Hardware wise I think I would put Kartman's "analog front end" signal processing circuit next to the engine, perhaps attached to the engine or to a semi-rigid structure in the close vicinity of the cylinder being monitored.  I would run a shielded cable carrying the clean, output pulse, (and power and ground), back to the main box with the uC and the display, and perhaps any user interface buttons or LEDs. 

 

Your project is obviously operating in a tough environment, so you will have to pay very careful attention to waterproofing your project. 

 

You didn't mention if your project will run off of the jetski's power bus, (does it have an alternator?), or from its own battery.  If it runs off of the jetski's power bus then you will need to pay close attention to your power supply design, as well.  You don't want to fry your electronics from power bus spikes, and you don't want spikes to trash your data.

 

An analog display was mentioned above, also.  Know that with a graphics LCD you can, of course, do both.  One could have a large display font on the top of the display and a wide, easily seen, "bar graph" running vertically on the side, or horizontally, across the display. 

 

It would be interesting to hear feedback from the users as to which part of the display they used the most.

The display could also easily show the various data parameters in a normal sized font after the test run.

 

For commercial items cost is obviously an issue, although if the device saves one's rather expensive engine, then I guess shaving a few pennies or dollars off the price isn't that important.  Likewise, if you are only building one or several to begin with, cost shouldn't be an issue.  Point being, you might consider a rather decent sized, color, GLCD for the project's display.

 

Finally, know that with an AVR as compared to a Basic Stamp adding "features" like the CHT is trivial.  Likewise, other parameters like the rate of change of the RPM is just a matter of software, and with a 16 MHz processor, an interrupt driven (and hence low overhead) input signal system, you have plenty of computing power to do such things.

 

Good luck with your project.

 

We like to see photos, both of the project itself, and of course of a high performance jetski in action!

 

JC

 

Edit: Typos

 

Last Edited: Thu. Sep 8, 2016 - 05:10 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Doc, no need to separate the 'front end' as the ignition signal is capacitively coupled by i'd guess a few 10's of pF. The circuit is basically a one shot, so one could use a 555 for the same effect. The commercial kart dash units use this technique.

Wmazz - the kart is a 'spec' one although i don't competively race anymore.

Eventually i might get around to publishing my little bluetooth unit that reads rpm and a couple of analog signals ( in my case throttle pos and steering). As an aside, i can report that mounting a iphone on a gokart is not a good idea for video. The engine vibration gives a wave effect on the video.

Last Edited: Thu. Sep 8, 2016 - 10:26 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

DocJC wrote:
 

 I'm glad that the accuracy issue was already handled.  With a 16 MHz uC one can make the Tacho as accurate as you wish, (within the accuracy and drift of the uC's clock).

 

It certainly opened my eyes! Originally my first tachs used a 50mhz SX processor, written in basic, and

compiled into assembly. I used a hall sensor to measure the crankshaft revolutions. We thought the

code was accurate to +/-1 rpm without any thought of how accurate we captured 1 rpm, or the inaccuracies

with the resonator.

 

This was about 10 years ago, and the tach was for giant scale r/c pylon racers with 80cc, 160cc, and

290cc  nitro-methane engines.  

 

 

DocJC wrote:
 

Displaying the least significant digit of the result is always a designer's choice on how it should be done.  Adding the "extra" digit just gives one a bouncing, poorly readable, display. 

Rounding the result to X digits is usually reasonable.

 

I really like that idea, I know it has been brought up several times. TY

 

DocJC wrote:
 

I am fascinated by the OP's desire to only update the display once every 2 - 3 seconds.  I don't have any experience with high performance / racing jetskis, but that seems like a

less-than-optimal approach to me. When I am looking at an instrument cluster, I generally want the most current data available.  Not data that is 3 seconds old.

DocJC wrote:
 

It seems to me that one's algorithm for how one filters the data, and captures peak rpm data, etc., ought to be a separate design question to how one displays the data.  In fact

one might envision the end device having several different modes of operation, user selectable, that essentially just change the data filtering algorithm, (response time, etc.), while

the core hardware and display routines remain unchanged. 

 

I was originally planning on shutting down the ISR, pause, and display. But through our discussions,

I have decide to process 2 or more readings and the average the results and display the rpm.

 

DocJC wrote:

I would think that if the user only glances at the display very briefly, every now and then, then having a larger, brighter, sunlight readable display would improve the user interface,

(ability to read the data), more than slowing the display update to such a slow rate.

DocJC wrote:
 

I guess an underlying question is just how fast does an engine "blow up", once it is operated out of the allowable parameters?  When the jetski catches air, unloads the impeller, loses

the governor function of the impeller, how quickly does the engine over speed, and is that what precipitates the engine "blowing up"?

clawson wrote:

sounds to me that you need something more like an engine management system than a tachometer and putting a hugely unreliable shaved ape in the middle of the control loop! Have

something like an "electronic throttle" and simply don't relay its commands to the engine if to do so would cause it to blow up. 

DocJC wrote:
 

If so, then relying on the human in the control loop, as Cliff mentioned, seems like a bad idea.  Relying on the human to occasionally glance down at the tach and process the data and

throttle down, (and use 3 second old data at that), doesn't seem like a great plan.

 

Time to change gears, (albeit your jetski doesn't have any...)

 

 

Here is an example of someone that needed a tachometer. Mr. Noisy (Sam) from the UK, blew up his engine

because he had a bad set-up.

 

In this thread, Miguelxj (Portugal) is just trying to properly rejet his carbs. He is not at a risk of

blowing up his engine, but he does need to an rpm goal (expected results) for his pipe, impeller and jetting.

 

DocJC wrote:
 

I wrote many BS programs using that paradigm.  But now that you have switched to an AVR you have the ability to approach the problem in another manner.  The "classic" approach

with a current, relatively high speed (16 MHz) uC, with interrupts available, would be to have your data collection process running continuously, (typically in the background, i.e.

interrupt driven, and invisible to the rest of the application).  In the foreground, Main Loop, you would run your data crunch and display update routine, as well as read any user push

button switches to reset the Max RPM value, cycle the display through other data, (Max Cylinder Head Temp, Max rate of RPM change, Number (or rate) of cylinder mis-fires, etc.) .

 

Finally, know that with an AVR as compared to a Basic Stamp adding "features" like the CHT is trivial.  Likewise, other parameters like the rate of change of the RPM is just a matter of

software, and with a 16 MHz processor, an interrupt driven (and hence low overhead) input signal system, you have plenty of computing power to do such things.

 

I have two tachometer projects: the first one is the one we have been discussing, and my primary goals

are to use parts that are inexpensive and easy to find within their country, or easily accessible through

other international sources. It must be waterproof, a reasonable size that can be mounted on a dash,

hand-pole, or handlebars.

 

 I will also need to decide if it will be open source or not. I am not sure about what legal responsibilities I

would have (if any). This is something I need to ask about in the future.

 

The second tachometer will have many data acquisition capabilities. Will be just for me to use on the race

skis that I work on. I am planning on mounting the guts inside a waterproof aluminum box inside the engine

compartment with a display and a few buttons mounted on the dash, or handlebars. But that tachometer &

daq is being built with a Propeller.   

 

DocJC wrote:
 

I don't think you mentioned whether your display will be an LCD or an OLED graphic display, or a 7-Segment LED display.  The 7-Seg LED display would run, continuously, as another interrupt

driven task in the background, taking whatever the current display data value ( s ) are and displaying them.  The LCD and OLED displays might be updated in the foreground task, when slow

updates are performed.

 

My first tachometer is already fitted with a 4x20 character lcd. But I am concerned the character size is too

small. It will display rpm, acceleration, and 2 cylinder head temps. My second tachometer is the one we have

been discussing, and it will use a large 4 digit, 7 segment lcd.

 

DocJC wrote:
 

Hardware wise I think I would put Kartman's "analog front end" signal processing circuit next to the engine, perhaps attached to the engine or to a semi-rigid structure in the close vicinity of

the cylinder being monitored.  I would run a shielded cable carrying the clean, output pulse, (and power and ground), back to the main box with the uC and the display, and perhaps any user

interface buttons or LEDs. 

 

Your project is obviously operating in a tough environment, so you will have to pay very careful attention to waterproofing your project. 

 

I am worried about both displays getting wet, and their visibility in the sun light. This is something I want

to discuss in the future, but for now they will be inside a "zip-loc" plastic bag.

 

DocJC wrote:
 

You didn't mention if your project will run off of the jetski's power bus, (does it have an alternator?), or from its own battery.  If it runs off of the jetski's power bus then you will need to pay close

attention to your power supply design, as well.  You don't want to fry your electronics from power bus spikes, and you don't want spikes to trash your data.

 

I was planning on both tachometers to use the watercraft battery, and I was planning to use a diode on

the positive wire. Most old 2-stroke watercraft have battery charging systems that are similar to a trickle

charger. One of the reasons for the Nano (besides it size & cost) was the ability to supply it with 12 volts.

 

Is that a bad idea?  

 

DocJC wrote:
 

We like to see photos, both of the project itself, and of course of a high performance jetski in action!

 

This is one of the ski's I will test the tachometers on. It has my old PJS super cylinder on it, a pair of

modified dual 46mm mikuni's, MSD ignition, and a custom pipe I built.

 

 

 

Bill M.

Attachment(s): 

Last Edited: Sun. Sep 11, 2016 - 07:00 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

wmazz wrote:

Originally my first tachs used a 50mhz SX processor ... We thought the

code was accurate to +/-1 rpm without any thought of how accurate we captured 1 rpm, or the inaccuracies

with the resonator.

 

I don't mean to belabor this point, but ...

 

The 50MHz source for the SX processor was most likely a crystal, not a ceramic resonator that the Nano uses.

 

The ceramic resonator is accurate to +/- 0.5% while a crystal is usually  +/- 100 ppm( = 0.01%) or less.

 

If you want the +/- 1 rpm, you can add an external 6MHz crystal oscillator that clocks Timer/Counter 1 in the Nano.

Why 6MHz?  Because the external clock for the timer must be less than the cpu clock divided by 2.5 or 16MHz/2.5 = 6.4MHz.

 

External oscillators can cost as little as $2 and provide +/-50ppm (0.005%) accuracy.

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The engine speed at a given instant changes by a few RPM. Whilst it's easy to get sub -1RPM resolution, I'd argue that 1RPM accuracy is useful for human readout,  100rpm increments is probably the easiest to read. Anything less jumps around and if you filter it enough, your response suffers. For my video logger app, I store the raw data and post process to remove the noise with the live filtered data being used for the display widgets. Since engine performance is related to the environment, I doubt if high resolution RPM measurement is going to assist your endeavours.

If you're dealing with hand-grenade two strokes, I'd be measuring EGT and listening for pre-ignition and detonation with an accelerometer and some DSP. We all know that a two stroke runs best just before it blows up!

 

As the Doc mentions, running stuff off automotive electrics presents some challenges - the worst being load dumps from the alternator. With the ready availability of LiPo battery packs, that is what I use in my gadget.A little LiPo pack runs the electronics for weeks! Then charge off USB.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman,

 

You said the lead that lays parallel to the spark plug wire was a small gauge wire. About 16 to 18ga?

 

Does it need to be solid or will braided wire work ok?

 

How long can the pick-up wire be? possibly (60cm to 1m) 2 to 3 ft.

 

Kartman wrote:

As the Doc mentions, running stuff off automotive electrics presents some challenges - the worst being load dumps from the alternator.

 

With the ready availability of LiPo battery packs, that is what I use in my gadget.A little LiPo pack runs the electronics for weeks! Then charge off USB.

 

I like the idea of using a lipo :)

 

 

Bill M.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

One other question (for the moment) Does the circuit trigger the micro with a falling edge or a rising edge?

 

It idles high @ 3.3v, right?

 

 

Bill M.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The wire is not critical. A few metres is ok. The signal from a cdi is rather healthy, so it doesn’t take much to read it. I was testing my garden blower last week. Only needed to put the wire close! I also need to put around 150us of blanking time to get a stable reading. When i detect a pulse, the capture gets the time stamp, disable the capture then set a timer for 150us. When the timer elapses, i re-enable the input capture.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks, That was very helpful.

 

Do you know why some manufactures like MSD, possibly Digitron install the 100K resistor at the end of the pick-up wire,

and possibly why some manufactures recommend mounting the pick-up wire at least 2 inches (~50mm) from the spark plug

boot?

 

Thanks

 

 

Bill M.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I’d suggest the answer is so that you avoid the possibility of getting a direct flashover into your sense wire! The 100k is probably to limit the amount of energy you pick up.