Measuring fast rate, LM1815 chip and RPM, ISR's from arduino, maxuino, HELP!

Gandalf's icon

Hello everyone,

I want to have my Toyota's engine RPM displayed in Max MSP. So, a rate which needs to be fairly instantaneous to be utilized for RPM-related operations such as servos which open/close variable intake runners etc. It also needs to be accurate and clean. I am using an LM1815 chip (zero crossing detector) which is receiving RPM information from my Toyota's ecu (NE wire). I have it going into one of my arduino digital inputs. For real-time and precision, the Ne signal from the distributor produces 24 pulses per cam revolution. It's a variable reluctor sensor, so the pulses are kinda ugly (among other things, the amplitude varies with RPM)... The LM1815 turns it into a nice square wave, and we can measure from edges (falling edge to falling edge). Time is equal to the time it just took the engine to travel 15 cam degrees or 30 crank degrees, or 12 pulses per revolution.

The problem is, it is meant to utilize ISR's on my arduino. As far as I know (please correct me if i am wrong), ISR's are not interpreted from maxuino into Max.

What I am getting in Max is a fast string of alternating zero's and ones, averaging about the same rate when compared (using the "route" object). I am using "counter" to give me a running tally of all events. At idle the tally comes in at about an event every 2.3 ms. At redline, this increases to an event every .23 ms. But according to the LM1815 application, at redline (7400 RPM) we should be getting about 1480 pulses per second, or a pulse every .676 ms. So obviously I am getting more "events" than just pulses, that are giving me a dirty signal.

My main questions are:
1) I am finding that the objects "timer" and "cpuclock" are not able to measure the time between events... it's too fast. I am using the method shown in "timer" help, the "Clever way to report time between events". I am using cpuclock in the same way. When I use the carry-count output of the counter to reduce the speed of the events (have it output a pulse every 50 or so events) I get some success but its very inconsistent. What is the best way in Max to measure the time between fast events? Is there a way?

2)How can I take a stream of numbers that fluctuates and changes constantly, discard the highest ones, discard the lowest ones, and just take the middle range? Using the "mean" object would include the highs and lows, which I don't want to do. For example, if I get a stream of numbers that average around 200, but I get some obviously out of range low numbers like in the teens, and then some obviously high out-of-range numbers like 600. Then as the RPM increases, the numbers now average around 2000, but i still get those occasional very low and high numbers that are just noise. What is a good way to clean up such data?

What I have tried is making a list and feeding it through "minimum" and "maximum" and mean, but this slows down the real-time response a lot. I have a feeling it is possible using the "route" object somehow, to keep it responsive, but have the route's arguments variable.

3) Some people have successfully been using the LM1815 chip and writing code to the arduino (not using Max/Maxuino at all), and getting the necessary timer information via ISR's. Is it possible to have Max running numerous activities through the arduino, and then having the arduino concurrently execute an additional code of instructions that has been loaded into it that has nothing to do with Max? Can this be done at the same time?

Any help would be much appreciated!

Simon's icon

I wonder if you are hitting timing problems on the serial port. What speed are your running at?

Gandalf's icon

How do I check this...? sorry if that is a dumb question...

brendan mccloskey's icon

Hi
as far as the Max domain goes, perhaps [speedlim] and [rampsmooth~] have some value here; and I think Simon is referring to the serial baud rate?

Brendan

Gandalf's icon

When I open up the maxuino patch, the serial baud rate argument in the serial object is at 57600... I can set it to 115200? There is also the qmetro object connected to the serial object, do i have to modify it as well?

There is also the serial object connected to the maxuino patch, it does not have an argument, so I assume it is at the default of 4800...

Gandalf's icon

Sorry, I should clarify, in the "select serial port" section, inside the patcher "p devices" there is a serial obect with no argument... that is the second one to which I refer.

Simon's icon

Yes sorry, I meant serial baud rate.
You could try upping to 115200. Be aware that you'll have to change the Arduino code & upload that to the board as well as changing Maxuino, which runs the port @57600.

Simon's icon

Just to add,
I also wonder what part Maxuino might play in your problem.
You might try Maxduino instead & see what you get. I would be interested to hear.
Maxduino uses Firmata, so no need to change anything on the Arduino,
it's here:-
https://github.com/firmata/maxduino

Gandalf's icon

Here is something to consider though. Just look at what the "cpuclock" and the "timer" objects do when are hooked up to metro, and you drop the metro rate below 30 ms. They start having serious issues reporting the elapsed stop/start time. They seem report a huge amount of noise/error/variation. Why? This really may not be a problem with the data coming in at all, but the way it is measured in Max. What I really need is a way to measure a fast rate... pulses every tenth of a ms...

Wetterberg's icon

I'd say switch to audiorate monitoring - if you're getting a very fast train of pulses, connecting your signal to an audio interface (what hardware are you on, btw? You didn't specify this), and then using something like fzero~ will give you the frequency quite readily, I suspect.

Gandalf's icon

I am using a Macbook Pro running 10.5.8.
-freeduino
-LM1815 chip (zero-crossing detector) which puts out square-wave pulses at about 2.3 volts
-source of the signal is the Ne wire, produces 24 pulses per cam revolution. It's a variable reluctor sensor, so the pulses are kinda ugly (among other things, the amplitude varies with RPM)... The LM1815 turns it into a nice square wave. This means 12 pulses per engine revolution.
What would be a simple/easy audio interface that will do the trick?

Gandalf's icon

Ohhh perhaps you were asking me if I was on Max 5 still (which I am)... I see fzero~ is one of the "new" objects in Max 6. So... not an option yet. I am afraid to upgrade my operating system due to incompatibilities between dozens of inter-dependent programs I have, most tied to Max somehow.

But that might be something to explore along those lines to get a reliable frequency in Max. When I think about it, it would be great to manipulate frequencies (for smoothing or filtering) just like high-pass or low-pass on an EQ... and pick the range I need etc. Just not sure what objects can do this for me...

Gandalf's icon

Well,
I have resolved one of the issues by focussing on the fact that metro was acting up badly at faster speeds.
In Max "Preferences" I looked under the scheduler tab, and tightened up "event interval", "scheduler interval", "scheduler slop", and turning on overdrive. All of a sudden, the huge variation between maximum and minimum values was gone... although it doesn't give me float increments of ms, just whole 1 ms increments.

However, hooked up to my source signal, I think its still coming in too fast. I think the baud rate is the next thing to look at. Not sure how to modify it in the arduino side (its been a while)... and I think maxDuino is not an option since I have a huge patch that is very maxuino-dependent at the moment.

Gandalf's icon

@Simon
As far as updating the baud rate to the arduino board, is that in the .pde file "arduinoserial"? It was set at 9600. Or, is that just a serial "tester" file... at the top it says:

// Arduino Serial Tester
// rld, cycling'74, 3.2008

Or, is it in the StandardFirmata .pde file required for maxuino, where it says "Firmata.begin(57600)" ?

Man, its been too long that I've been buried in Max and haven't had to mess with the arduino much.

Gandalf's icon

Well,
I think I solved the baud rate adjustment, to 115200, it seems to be properly synched up from Maxuino through to arduino. I won't know if this helps me until later this afternoon as far as the source signal speed yet.

Perhaps someone can help me with this: How can I get metro to output float amounts between 1ms and 2ms? In the scheduler, I decreased the scheduler interval to 1ms, but it won't go smaller than this. So, a dial hooked up to the timer from metro will snap to intervals of 1ms but no float inbetween...

Gandalf's icon

Wetterberg wrote:
"I'd say switch to audiorate monitoring - if you're getting a very fast train of pulses, connecting your signal to an audio interface (what hardware are you on, btw? You didn't specify this), and then using something like fzero~ will give you the frequency quite readily, I suspect."

I have a Firebox interface, I currently only use the firewire, and have input channels available on it... Do you mean to just run the source signal (square wave pulse, around 2-4 v) plus a ground into one of the input channels of the interface? Is it at acceptable power levels in this regard for the interface? Then just route the input channel into Max, and try and get a freq reading from it there?

Gandalf's icon

Well, I won't be home to try this for a few weeks, but I have done all the preparation in Max MSP (although I am just still on Max5). Once I run the signal into a Presonus Firebox input, I can grab it using the number~ object, I should be able to take the signal and convert it into a frequency value (it updates at a maximum of 20 ms, but this is still pretty darn fast), scale that to represent an RPM value, and run it to my digital tach (dial).

The irony of doing it this way is: with all of the people out there trying to remove that annoying whine out of their stereo system due to their electrical system, I might be the only person utilizing what is essentially the same thing and "listening" to it in Max MSP, and deriving engine RPM from it. Of course, I won't have any annoying whine... just cool oscilloscopes displaying the signal and a nice clean tach displayed on my Mac and iTouch "gauge" on my dash :).

I am still unclear if I need to do anything other than run the signal as positive, and then just run a ground from the car chassis to act as the signal "ground" going into the interface?

ćwiek's icon

maybe webcam + cv.jit.hough2lines, :p

Gandalf's icon

Wetterberg your idea put me onto the right track.
I ran the car's IGT signal (+a regular chassis ground) into one of my Presonus Firebox inputs, analyzed the signal as an audio frequency with [sigmund~] external object, and got perfect results.

See my project thread here, including lots of videos:
https://cycling74.com/forums/topic.php?id=38633