Shop OBEX P1 Docs P2 Docs Learn Events
Accurately read 0 - 15000 + RPM with the SX using ignition 5v square wave — Parallax Forums

Accurately read 0 - 15000 + RPM with the SX using ignition 5v square wave

eagletalontimeagletalontim Posts: 1,399
edited 2009-03-18 00:46 in General Discussion
Here I am again tongue.gif 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 :
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

  • JonnyMacJonnyMac Posts: 9,214
    edited 2009-03-14 17:41
    Patient: Doc, it hurts when I do this.
    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.
  • eagletalontimeagletalontim Posts: 1,399
    edited 2009-03-14 18:05
    The reason it is not running at 50mhz is because the 7805 is already getting hot to the touch with just 5mhz. I read somewhere on the forum that the faster it runs, the more room for errors, RF problems and heat. I tried the interrupt routine you posted in another forum and could not get it to read right for some reason. I know it was supposed to be run at 50mhz, but I already purchased 10 5mhz crystals and was hoping to use that. I am going to go ahead and order some 50mhz crystals and see if I can keep the heat down. Last time, I tried the 50mhz resonator but after 5 minutes both SX's got hot as hell and eventually the 7805 gave out and fried everything. Everything was wired correctly to specs of several different schematics posted on this forum.
    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 tongue.gif
  • eagletalontimeagletalontim Posts: 1,399
    edited 2009-03-14 18:40
    ok, i just tried your code again JonnyMac with the interrupt and something is acting strange with it. Maybe you can help me understand it. What is happening is as soon as the chips are syncing together, it automatically jumps into menu 1 and nothing from the EEprom is retrieved and the SX locks up completely. This only happens if I add the interrupt. If I remove the interrupt, everything works 100% as for the boot process.

    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:

    RPM_signal      PIN     RB.4 INPUT SCHMITT
    
    tmpW1        VAR    Word
    'tmpW2        VAR    Word
    temp1        VAR    Byte
    temp2        VAR    Byte
    temp3        VAR    Byte
    temp4        VAR    Byte
    s3        VAR    Byte
    s4        VAR    Byte
    menuis        VAR    Byte
    idx        VAR    Byte
    values1        VAR    Byte(16)
    values2        VAR    Byte(16)
    
    rpm        VAR    Byte
    tachWork    VAR    Byte (5)
     tachCheck    VAR    tachWork(0)
     rpmTemp    VAR    tachWork(1)
     tachTmr_LSB    VAR    tachWork(2)
     tachTmr_MID    VAR    tachWork(3)
     tachTmr_MSB    VAR    tachWork(4)
    
    INTERRUPT NOCODE 300_000            ' (3)   3.333us
    
    Tach:
      ASM
        MOV   FSR, #tachWork            ' (2)
        MOVB  C, RPM_signal                ' (4)   capture tach input
        RL    tachCheck                ' (1)   move into tachCheck
        AND   tachCheck, #%0000_0011        ' (2)   mask off old bits
        CSNE  tachCheck, #%0000_0001         ' (3/4) skip if not 0->1
        INC   rpmTemp                ' (1)   update on new edge
    
    Tach_Timer:
        INC   tachTmr_LSB                ' (1)   increment timer
        ADDB  tachTmr_MID, Z            ' (2)
        ADDB  tachTmr_MSB, Z            ' (2)
        CJNE  tachTmr_LSB, #$20, Tach_Exit        ' (4/6) exit if not $02_BF20
        CJNE  tachTmr_MID, #$BF, Tach_Exit        ' (4/6)
        CJNE  tachTmr_MSB, #$02, Tach_Exit         ' (4/6)
    
    Update_RPM:
        MOV   rpm, rpmTemp            ' (2)   update user rpm            
        CLR   rpmTemp                ' (1)   reset tach input
        CLR   tachTmr_LSB                ' (1)
        CLR   tachTmr_MID                ' (1)
        CLR   tachTmr_MSB                ' (1)
    
    Tach_Exit:
      ENDASM
    RETURNINT
    
    wait        SUB    1, 2            ' delay in milliseconds
    SEND_BYTE    SUB    4
    button_hold    SUB    0
    Set_level    SUB    2
    Limp_Mode    SUB    0
    RX_BYTE        FUNC    1, 0
    getrpm        FUNC    1, 0     'No longer used.
    
    PROGRAM Start
    Start:
      PLP_A = %0011                    ' pull up unused pins
      PLP_B = %00011111
      TRIS_C = %11110000
      s3 = 0
      s4 = 0
      ltimer = 0
      menuis = 1
      wait 100        'ensure both chips are running
      FOR idx = 0 to 20
        wait 10
        SEND_BYTE LoadData, idx, s3, s4
        wait 10
    Grab:
        temp2 = RX_BYTE
        IF temp2 = SYNC THEN Grab
        IF idx < 16 THEN
          values1(idx) = temp2  'Store eprom into array1
        ELSE
          temp1 = idx - 16
          values2(temp1) = temp2  'Store eprom into array2 if array1 filled
        ENDIF
      NEXT
      wait 50
      IF values1(13) = $00 THEN
        values1(13) = 90
        values1(14) = 255
      ENDIF
    
    Main:
      IF MenuBt = 1 THEN GOTO ChangeMenu
      IF UpBt = 1 THEN GOTO Update
      IF DownBt = 1 THEN GOTO Update
      IF EnterBt = 1 THEN GOTO Save
      IF menuis = 1 THEN
         'rpm = getrpm
         '........USE RPM DATA HERE.......
      ENDIF
      GOTO Main
    
    ChangeMenu:
      INC menuis
      IF menuis = 21 THEN
        menuis = 1
      ENDIF
      READ Multiplier + menuis, s4
      IF menuis < 16 THEN
        s3 = values1(menuis)
      ELSE
        temp1 = menuis - 16
        s3 = values2(temp1)
      ENDIF
      SEND_BYTE ShowMenu, menuis, s3, s4
      wait 50
      button_hold
      GOTO Main
    
    
  • JonnyMacJonnyMac Posts: 9,214
    edited 2009-03-14 18:54
    I'm going to assume (we know what that does, don't we?) that SEND_BYTE is a shell for SEROUT of some sort -- this is getting hosed up by the interrupt. You see, you can't just drop the ISR code in willy-nilly; anything timing oriented (SEROUT, SERIN, PAUSE) will be affected by it.

    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!"
  • eagletalontimeagletalontim Posts: 1,399
    edited 2009-03-14 19:15
    I am guessing the usage of TX_BYTE would be something like :

    TX_BYTE temp1

    instead of :

    SEROUT RX, Baud, temp1

    Sorry for all the questions. I am new to the ASM stuff [noparse]:)[/noparse]
  • eagletalontimeagletalontim Posts: 1,399
    edited 2009-03-14 19:34
    and one more thing.....My current set up is a 1 wire serial between the 2 chips. The new code looks to be a 2 wire. Is this correct? It was transmitting at T9600.
  • eagletalontimeagletalontim Posts: 1,399
    edited 2009-03-14 19:43
    I tried to compile it and got this error :

    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
  • eagletalontimeagletalontim Posts: 1,399
    edited 2009-03-14 20:36
    Well, I downloaded the 2.0 compiler and installed it into my 3.2.92 version and changed both chips to work with the interrupt JonnyMac had given me. Now, the screen just shows a _ at first boot and nothing happens. I have gotten to the point I feel like there is a major communication problem since I did not want to post my entire code so I will finally post my entire project. I don't have the knowledge to get this working and I know there are several members on here that really know what to do. If someone has the time to help me, I really appreciate it. This has been an ongoing project for several months now with no success and I really need some good expert advice on how to get it working properly.

    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
  • JonnyMacJonnyMac Posts: 9,214
    edited 2009-03-14 21:44
    In your operational program which pins are you you using for 1-wire serial and the LCD?
  • eagletalontimeagletalontim Posts: 1,399
    edited 2009-03-14 21:54
    on chip 1 (Serial-LCD) the pins are RA.2 and RA.3 It was just RA.2 with the 1 wire serial. RA.3 was the LCD pin. On chip 2 (Serial-LCD-chip2) it is RA.0 and RA.1. It was RA.0 for the 1 wire serial.
  • JonnyMacJonnyMac Posts: 9,214
    edited 2009-03-14 22:18
    As ever, I'm confused. You main program needs to talk to a serial LCD (output only) and another chip (input and output), right? If yes, what pins do you want to use? Adjusting for 1-wire serial takes a little more information than just the pin #, so I will do that for you.
  • eagletalontimeagletalontim Posts: 1,399
    edited 2009-03-15 01:49
    sorry about the wait. Yes, I had to use 2 chips because 1 did not have enough code space or variable space to run the entire program. I split the functions between 2 chips to make things easier. Chip 1 controls user interface options and eeprom data. Chip 2 controls the transmission. The data sent between the 2 chips is only Byte variables which are sent in a specific order from Chip 1 to Chip 2 and data sent back to chip 1 from chip 2 is labeled with a menu number which is also the eeprom address to save to.

    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
  • Bill ChennaultBill Chennault Posts: 1,198
    edited 2009-03-15 02:51
    eagletalontim--

    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.
  • eagletalontimeagletalontim Posts: 1,399
    edited 2009-03-15 02:54
    I could probably go with the SX48, but I don't have the money to drop into a new programmer board or to purchase chips at the moment. I currently sell another product that uses the sx28 so I have plenty on hand to test with. If I could afford it, I would definitely switch!
  • eagletalontimeagletalontim Posts: 1,399
    edited 2009-03-15 23:50
    I have tried making some changes to get the screen to show something, but it is still not working. any ideas on this?
  • eagletalontimeagletalontim Posts: 1,399
    edited 2009-03-17 02:06
    hey jonnymac, I was just wondering if you were able to figure why the program stopped working after I compiled with 2.0?
  • JonnyMacJonnyMac Posts: 9,214
    edited 2009-03-17 03:43
    At the moment I'm really hammered preparing for a trade show and working with my partner to get our own SX-based devices into the production -- like this:

    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.
  • eagletalontimeagletalontim Posts: 1,399
    edited 2009-03-18 00:07
    ok, I have seriously thought about switching to a SX48 since it has more pins and more room. The biggest problem I am running into is that I want to be able to move the chip back and forth from my car to the house to program it when needed. I have no idea how the programmer holds the chip to the board since the chips are surface mount. I don't want to solder anything to the Protoboard since it appears to be the programmer for the SX48 and it is a pain to have to keep hooking and unhooking wires on my car, but if it has to be done, I guess I will have to do it that way. Is there a DIP socket that can hold the SX48? It would make things a bit easier on my end for R&D. If someone could explain how the surface mount programming board holds the SX and if it allows for multiple chip programming or if I would have to build the programming circuit into my PCB, I would greatly appreciate it!
  • PJMontyPJMonty Posts: 983
    edited 2009-03-18 00:21
    Eagletalontim,

    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
  • eagletalontimeagletalontim Posts: 1,399
    edited 2009-03-18 00:25
    Well, the reason I wanted to keep with just moving the chip is because I have to crawl up under my dash to connect the circuit to the car. Having to do this over and over becomes a pain. If I could just move the chip, it makes things a hell of alot easier [noparse]:)[/noparse] I guess it is something I will have to deal with. I do have a header plug, but I am worried the plug pins will not fit in the protoboard.
  • JonnyMacJonnyMac Posts: 9,214
    edited 2009-03-18 00:46
    As Bill pointed out, Robert Doerr has a nice SX48 module that will plug into a DIP socket.
Sign In or Register to comment.