Accurately read 0 - 15000 + RPM with the SX using ignition 5v square wave
Here I am again
I have searched the entire Parallax forum for any good information on how to read high RPM fast and accurate, but I have not found anything yet [noparse]:([/noparse]
The code I am using now is :
The code works and is accurate, but not accurate enough. The problem with the code above is that around 1400 RPM, it acts up and outputs a strange number which throws off the rest of the calculations. I have tried using COUNT 300 but if the engine revs fast, the count cannot accurately read the RPM's because it takes too long. As you can see, the COUNT is nulled out since it is not accurate enough. I hope to use this commercially soon so I need it to be as accurate as possible.
Here is what I am working with....
I am using an SX28 running at 5mhz.
I only have enough room for 2 word variables.
There are 4 open TEMP variables if needed.
I am using the stock RPM signal from the ignition coils.
The signal wire is the stock signal wire which was originally connected to the circuit I am replacing. It is a 5v Square Wave.
Here is what I am wanting to accomplish :
Accurately read RPM's ranging from 0 to 15,000 + RPM's (Tolerance can be +/- 100 RPM)
RPM variable is a BYTE so 100 RPM would be 1 and 15,000 RPM would be 150
I do not want to use an interrupt since the RPM only needs to be read when called for.
Since this will eventually be used commercially and each vehicle may be modified different, the function has to be able to return the accurate RPM as fast as possible.
Here is Bean's RPM Code that works:
The way I have the SX connected to the signal wire is like this :
10K
RPM Signal
\/\/\/\/
RB.4
| 100K
\/\/\/\/
Ground
I do not have access to an O-Scope so I am not able to see the exact cycles and how clean they are. As said before, I hope to use this commercially so each car would also be different. One may have a clean signal, and another may not. I am not sure how to hook up the SX to the RPM signal wire and filter out any unclean signals.
So to basically sum up all my questions into one area, here they are...
Can someone help me convert my RPM function to read accurate results in a BYTE variable without using too much Variable space?
If there is a better way to connect the SX to the RPM signal and get clean results, could someone better explain it to me?
I greatly appreciate all the help I have received so far in the past threads and hope I can soon get this working!
![tongue.gif](http://forums.parallax.com/images/smilies/tongue.gif)
The code I am using now is :
FUNC getrpm 'tmpW1 = 300 + values1(15) 'COUNT RPM_signal, tmpW1, tmpW1 PULSIN RPM_signal, 0, tmpW1 PULSIN RPM_signal, 1, tmpW2 tmpW1 = tmpW1 + tmpW2 tmpW1 = 30000 / tmpW1 IF C = 0 THEN RETURN rpm ELSE RETURN tmpW1_LSB ENDIF ENDFUNC
The code works and is accurate, but not accurate enough. The problem with the code above is that around 1400 RPM, it acts up and outputs a strange number which throws off the rest of the calculations. I have tried using COUNT 300 but if the engine revs fast, the count cannot accurately read the RPM's because it takes too long. As you can see, the COUNT is nulled out since it is not accurate enough. I hope to use this commercially soon so I need it to be as accurate as possible.
Here is what I am working with....
I am using an SX28 running at 5mhz.
I only have enough room for 2 word variables.
There are 4 open TEMP variables if needed.
I am using the stock RPM signal from the ignition coils.
The signal wire is the stock signal wire which was originally connected to the circuit I am replacing. It is a 5v Square Wave.
Here is what I am wanting to accomplish :
Accurately read RPM's ranging from 0 to 15,000 + RPM's (Tolerance can be +/- 100 RPM)
RPM variable is a BYTE so 100 RPM would be 1 and 15,000 RPM would be 150
I do not want to use an interrupt since the RPM only needs to be read when called for.
Since this will eventually be used commercially and each vehicle may be modified different, the function has to be able to return the accurate RPM as fast as possible.
Here is Bean's RPM Code that works:
rpm VAR WORD 'too much space used here pWidth0 VAR WORD pWidth1 VAR WORD dividendMSW VAR WORD 'too much space used here dividendLSW VAR WORD 'too much space used here overflow VAR BIT doneBit VAR BIT PULSIN RPM_signal, 0, pWidth0 PULSIN RPM_signal, 1, pWidth1 watch pWidth0 pWidth0 = pWidth0 + pWidth1 pWidth0 = pWidth0 * 2 dividendMSW = $005B dividendLSW = $8D80 rpm = 1 overflow = 0 DO doneBit = rpm.15 rpm = rpm << 1 IF overflow = 1 THEN rpm.0 = 1 dividendMSW = dividendMSW - pWidth0 ELSE IF dividendMSW >= pWidth0 THEN rpm.0 = 1 dividendMSW = dividendMSW - pWidth0 ENDIF ENDIF overflow = dividendMSW.15 dividendMSW = dividendMSW << 1 dividendMSW.0 = dividendLSW.15 dividendLSW = dividendLSW << 1 LOOP UNTIL doneBit = 1 rpm = rpm << 1 rpm.0 = overflow IF dividendMSW >= pWidth0 THEN rpm.0 = 1 ENDIF
The way I have the SX connected to the signal wire is like this :
10K
RPM Signal
\/\/\/\/
RB.4
| 100K
\/\/\/\/
Ground
I do not have access to an O-Scope so I am not able to see the exact cycles and how clean they are. As said before, I hope to use this commercially so each car would also be different. One may have a clean signal, and another may not. I am not sure how to hook up the SX to the RPM signal wire and filter out any unclean signals.
So to basically sum up all my questions into one area, here they are...
Can someone help me convert my RPM function to read accurate results in a BYTE variable without using too much Variable space?
If there is a better way to connect the SX to the RPM signal and get clean results, could someone better explain it to me?
I greatly appreciate all the help I have received so far in the past threads and hope I can soon get this working!
Comments
Doctor: Don't do that.
This (commercial?) project has been running in circles for what seems months and despite a lot of good feedback from very experienced SX users you continue to beat your head into a wall saying, "No, I refuse to do it that way!" Why?
You can't stuff 50 pounds of sausage into a 5 pound bag and, in a way, that's what you're trying to do. You demand accuracy and yet you run the SX at the creep-along speed of 5MHz. Again, why? One assumes that as an automotive device you're getting power from the car so the additional 75mA or so by cranking up to 50MHz is not going to be a problem. What this does is give functions like PULSIN much better accuracy.
And your absolute refusal to use an interrupt is also mind boggling -- especially since I and others have given you working code (I wrote a program for you that gave you RPMs in 100 RPM units -- exactly what you want). Using an interrupt would allow you to have an on-demand RPM reading (you can't get faster than that) without the use of a complicated 32-bit division routine; this would save program space and make the program far less complicated.
As for the interrupts....I have tinkered with them for quite a few months and can never seem to figure them out....especially the timing [noparse]:([/noparse] This is the biggest reason I wanted to try and stay away from them. It seems they must be the best way to go, but I don't want to ask a million more questions to try and figure them out. Math was never my best subject, but I try my best to learn now
Here is how I have it implemented into my program. Some parts have been removed to shorten code but they are not needed with this problem:
I've attached an update of the program I wrote for you. Where you once used SEROUT, use TX_BYTE; replace SERIN with RX_BYTE, and PAUSE with DELAY_MS. This should help. When you need the last RPM update (which happens every 0.6 seconds) you do this:
someVariable = GET_RPM
The SX/B 2.00.16 allows us to update the EEPROM routines so they're as easy to use with a byte address as with a word (the program now works with both).
At some point you will look back and say, "Wow, that's pretty cool and wasn't too hard -- once everything made sense!"
TX_BYTE temp1
instead of :
SEROUT RX, Baud, temp1
Sorry for all the questions. I am new to the ASM stuff [noparse]:)[/noparse]
BANK __DEFAULT
"Symbol __DEFAULT is not defined."
I am using the 1.5 compiler since when using the 2.0 compiler nothing worked and the chip instantly locked up on power up with working code for the 1.5 version
To explain what this project is, it is basically a User programmable transmission control unit (TCU) for electronically controlled automatic transmissions. The throttle position sensor and RPM are used to determine shift points based on what the user saves for each gear. This part works pretty good so far except now since I added the interrupt. I have been driving with it for about 2 months now with no problems except the RPM readings not being accurate enough. Racing season is coming up soon and I need to try and get this working if possible.
File 1 : Serial-LCD.sxb - This file runs the EEPROM, the LCD display, the 7 segment LED display, stores all menu items, and converts all serial data from chip2 to display on the screen.
File 2 : Serial-LCD-chip2.sxb - This reads all the sensors used to control the transmission, does the major math to calculate shift points, processes button presses for the menu system and controls the solenoids to shift the vehicle.
Thanks for all the help in advance!
Post Edited (eagletalontim) : 3/22/2009 1:50:40 AM GMT
The LCD driver chip (Chip 1) pin connection is :
RA.0 -> SDA
RA.1 -> SCL
RA.2 -> RX (to other chip) Baud T9600
RA.3 -> LCD Serial Baud T19200
The Main chip (Chip 2) pin connection is :
RA.0 -> RX
RA.1 -> Drive lever switch. (Used to hold current gear if driver switches to neutral while driving.)
RA.2 -> open
RA.3 -> open
Couldn't you·almost double your RAM and double your EE by going to the SX48? Robert Doerr (RobotWorkshop) sells a very professional kit or assembled module that is a drop-in replacement for a BS2p40. I have a few running with 20mhz ceramic resonators.
--Bill
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
You are what you write.
www.efx-tek.com/php/smf/index.php?topic=994.0
This uses a lot of the code I've been trying to share with you.
Do you have a spare $15? buy this:
SX48 Proto Board
It has the SX48, a working power supply, the SX-Key interface (for programming and debugging), areas to plug in either resonators or TTL oscillators, and a prototyping area to add your own circuitry. Best of all is that it's already built, soldered together, and working when it arrives at your house.
Buy the proto board plus either a resonator or oscillator, add any custom circuitry you need to the prototyping area, and start working on your project. You can program and debug the proto board using the SX-Key, as well as plug in a resonator or oscillator and run the project in standalone mode without the SX-Key. You won't be moving the chip back and forth between projects, you'll just move the whole project.
Regarding a much earlier post you had, 7805 chips get hot when powering devices that draw any appreciable amount of current. That's why they need heatsinking. I have a lot of SX28 projects running at 50 MHz using a 7805 regulator and they work just fine. This proto board is the same, and it has the heatsinking built in already.
Once you have your circuit working, if you want to lay out a custom PCB or hand build a board, you'll have a working prototype to use as your guide.
Thanks,
PeterM