|
|
| Author |
Message |
kurakaira
Joined: 21 Mar 2007
Posts: 32
Location: Finland
|
|
Posted: 31 May 2009, 19:30 PM Post subject: ZX-24a reading RPM information . . . |
|
|
I have a project that uses the ZX-24a processor .
It displays many temperature and pressure values on a serial color tft display .
It also reads a 4 Hz GPS ( only the RMC sentence ) at 4800bps , and outputs all data to a SD logger with the com3 4800 outpin .
I have a problem reading the cars RPM , i currently use CountTransitions with a 50ms window , but i feel that i lose GPS data when allowing the CountTransitions read as long as 50ms .
The car rev's between 0 - 10000rpm , and i can change the RPM signal from the engine managment box ( Haltech ) from 1 to 10 signals per revolution .
What would be a faster way to determine the rpm value ??
Haltech outputs a 50/50 duty squarewave .
Tomorrow i will add a turbocharger speed sensor to my project , but i think this will be much easier since i don't need more resolution than 1000 rpm and the charger will go up to 140 000 rpm .
Should i use the PulseIn function to determine the engine rpm ?
Or should i just simply convert the RPM to a 0-5 V voltage and read it with the ADC ?
And by the way , the display is a Reach Technology 4" serial color display .
A very easy to use and a great display !
I recommend everyone to check out , www.reachtech.com |
|
| Back to top |
|
 |
dlh
Joined: 15 Dec 2006
Posts: 266
Location: ~Cincinnati
|
|
Posted: 31 May 2009, 20:15 PM Post subject: |
|
|
One way would be to use one of the native mode chips and write an ISR for the RPM readings. ZBasic and native mode makes this super simple.
I used this PinChangeInterrupt ISR | Code: | ISR PCINT0()
If (GetPin(14)=1) Then 'rising edge
Call GetMicroTime(micro)
rfSTX=0
Else 'falling edge
rfSTX=GetElapsedMicroTime(micro) '* 4.34=µS
End If
End ISR | to capture the time between rising and falling edges (i.e. PulseIn without tying up the processor between edges - the ISR executes only at each rising or falling edge). Then I process it in my main loop. | Code: | If ((rfSTX>1750) And (rfSTX<2300)) Then
'process here
End If |
|
|
| Back to top |
|
 |
dkinzer Site Admin
Joined: 03 Sep 2005
Posts: 2499
Location: Portland, OR
|
|
Posted: 31 May 2009, 20:28 PM Post subject: Re: ZX-24a reading RPM information . . . |
|
|
| kurakaira wrote: | | i feel that i lose GPS data when allowing the CountTransitions read as long as 50ms. | If you're using a software UART (channel 3-6) for receiving this data stream then you can't have interrupts disabled for more than about 1/4 of the bit time. At 4800 baud, each bit time is 208uS meaning that the duration of interrupts being disabled should be no more than 50uS (and less would be better). If you read the description of CountTransitions(), you'll see it clearly stated that interrupts are disabled during the counting period. Due to this fact, CountTransitions() isn't suitable for your application. PulseIn() has the same limitation.
An alternate strategy is to use pin change interrupts on a native mode device as Dave suggested. Another idea is to use InputCapture() or InputCaptureEx(). |
|
| Back to top |
|
 |
kurakaira
Joined: 21 Mar 2007
Posts: 32
Location: Finland
|
|
Posted: 31 May 2009, 20:38 PM Post subject: Native mode |
|
|
The problem is that i don't have any experience with the native mode devices .
And the control box for this car is allready built , i would hate to have to dismantle it ...
I have 8 ZX-24a 's left .. I will build a few more projects with them , and then order a few native mode devices to study , and probably buy a bunch of ZX-24p 's .
I understand that my requirements are much from a ZX-24a , but as building these engine monitors is my hobby , i have too little time to learn something totally new .
So i will stick with the ZX-24a with this project . ( Or i will add another ZX-24a to listen the GPS and output only the speed reading for the original ZX ... ) |
|
| Back to top |
|
 |
dlh
Joined: 15 Dec 2006
Posts: 266
Location: ~Cincinnati
|
|
Posted: 31 May 2009, 20:54 PM Post subject: |
|
|
| Then Don's suggestion for InputCapture() or InputCaptureEx() is the way to go. |
|
| Back to top |
|
 |
GTBecker
Joined: 18 Jan 2006
Posts: 457
Location: Cape Coral
|
|
Posted: 31 May 2009, 22:09 PM Post subject: ZX-24a reading RPM information . . . |
|
|
kurakaira's ADC idea is worth pursuing, too. If the source RPM signal
is a 50/50 squarewave, making it a fixed-width pulse, then
integrating/averaging the resultant pulse stream into a voltage to an
ADC pin should work. For best resolution, the fixed pulse width should
produce 100% PWM at the fullscale RPM.
Tom |
|
| Back to top |
|
 |
dlh
Joined: 15 Dec 2006
Posts: 266
Location: ~Cincinnati
|
|
Posted: 31 May 2009, 22:27 PM Post subject: |
|
|
| GetADC() takes 220µS but it's not clear whether Interrupts are disabled for the duration. |
|
| Back to top |
|
 |
dkinzer Site Admin
Joined: 03 Sep 2005
Posts: 2499
Location: Portland, OR
|
|
Posted: 31 May 2009, 23:22 PM Post subject: |
|
|
| dlh wrote: | | [...] it's not clear whether Interrupts are disabled for the duration. | They are not.
In the descriptions of the ZBasic System Library routines I believe that we've explicitly indicated in every case that interrupts are disabled for long periods of time. If no such caveat is present in the description of a particular routine, you can (reasonably safely) assume that interrupts are not disabled for any significant period of time. |
|
| Back to top |
|
 |
kurakaira
Joined: 21 Mar 2007
Posts: 32
Location: Finland
|
|
Posted: 02 June 2009, 11:12 AM Post subject: Work in progress ... |
|
|
I didn't have time yesterday to modify the control box , i will do it tonight .
The enclosure i built is a bit tight with all the connectors in the way ...
I need to move a MAX6675 serial output pin from pin 12 to pin 27 .
And i will connect pin 12 to pin 13 . ( i have pin 13 connected to a 16 ch mux , that reads both analog and digital values )
RPM values i'm going to measure come trough the mux .
Any suggestions why this would be a bad idea ? ( since both pins are inputs )
I'm also using Pulseout to drive a 74595 , but it only writes 8 bits , can't take long , can it .
And i use Pulseout to drive a MCP4921 DAC , 16 bits of data .
Would it be better if i use them with "Bit Banging" ?
Sorry , i'm posting code that i haven't tried yet .
But i should have this RPM counting working tonight ...
So does this look right to You ?
| Code: | Dim pdUI(1 to 5) as UnsignedInteger
Call PutPin(12, zxInputTriState)
Call InputCapture(pdUI, UBound(pdUI), 0, 44) ' timeout in 200ms
RpmS = 0.0
For KertaaB = 1 to Cbyte(UBound(pdUI))
RpmS = RpmS + (Csng(pdUI(KertaaB)) * 0.000000678 ) ' times the clock tick
Next
RpmS = RpmS / Csng(UBound(pdUI))
RpmS = 60.0 / RpmS ' Rounds per minute
RpmS = RpmS * 1.0 ' Pulses per revolution |
|
|
| Back to top |
|
 |
dlh
Joined: 15 Dec 2006
Posts: 266
Location: ~Cincinnati
|
|
Posted: 02 June 2009, 11:23 AM Post subject: |
|
|
| I think it's simpler than that. You only need two elements to capture 1 full cycle (1 pulse, 1 space). The total duration of these two elements gives you the period (in timer ticks) and 60.0/(CSng(period)*0.000000678)=RPM. |
|
| Back to top |
|
 |
dkinzer Site Admin
Joined: 03 Sep 2005
Posts: 2499
Location: Portland, OR
|
|
Posted: 02 June 2009, 15:58 PM Post subject: Re: Work in progress ... |
|
|
| kurakaira wrote: | | I'm also using Pulseout to drive a 74595 , but it only writes 8 bits , can't take long , can it . | That depends on the length of the pulse. You might consider using PutPin() with the second parameter zxOutputPulse. This will generate a short pulse (about 500nS); long enough for many hardware devices. Interrupts are not disabled for any significant duration.
| kurakaira wrote: | | And i use Pulseout to drive a MCP4921 DAC , 16 bits of data. Would it be better if i use them with "Bit Banging" ? | This device has an SPI interface so you could use SPICmd(). Alternately, you can bit-bang the SPI interface relatively easily. However, instead of using PulseOut() I would recommend using PutPin() with the second parameter of zxOutputToggle or zxOutputPulse to implement the SCK signal. |
|
| Back to top |
|
 |
kurakaira
Joined: 21 Mar 2007
Posts: 32
Location: Finland
|
|
Posted: 02 June 2009, 18:15 PM Post subject: Shiftout . . . |
|
|
Sorry , what i meant was ShifOut not PulseOut .
I'm too tired to think ... I have worked on this car every evening after work for 3 weeks now .
Anyhow I got the RPM reading to work , i modified the control box ( connected pin12 to pin13 , and added Opto isolators to read the turbo RPM and the state of a water pump fuse )
I'll get back to You with a success report when i finish wiring the Turbo RPM sensor .
The code i'm using now is :
| Code: | Dim pdUI(1 to 2) as UnsignedInteger
Call InputCapture(pdUI, 1, 0, 22) ' timeout in 100ms
Call InputCapture(pdUI, 2, 1, 22) ' timeout in 100ms
RpmS = 0.0
RpmS = RpmS + (Csng(pdUI(1)) + Csng(pdUI(2)))
RpmS = 60.0 / (RpmS * 0.000000678) ' Rounds per minute
RpmS = RpmS * 2.0 ' Pulses per revolution ' don't know why but it show only half of the actual rpm
if pdUI(1) = 65534 or pdUI(2) = 65534 then ' if engine is not running
RpmS = 0.0
End if
RpmS = RpmS / 50.0 ' rounding to 50
RpmS = fix(RpmS)
RpmS = RpmS * 50.0 |
|
|
| Back to top |
|
 |
dlh
Joined: 15 Dec 2006
Posts: 266
Location: ~Cincinnati
|
|
Posted: 02 June 2009, 18:32 PM Post subject: |
|
|
You only need one call to InputCapture. | Code: | | Call InputCapture(pdUI, 2, 1, 22) ' timeout in 100ms | This will start with the next rising edge and the first element will hold the count from rising edge to the next falling edge. The second element will hold the count from falling edge to the next rising edge. Their sum is the count between consecutive rising edges.
You can also save excessive writes to the LCD by saving the value and only updating when it changes. |
|
| Back to top |
|
 |
spamiam
Joined: 13 Nov 2005
Posts: 666
|
|
Posted: 02 June 2009, 19:07 PM Post subject: |
|
|
| dlh wrote: | | You can also save excessive writes to the LCD by saving the value and only updating when it changes. |
I would make tht statement read "... when it changes enough". I doubt that changes of less than 100 RPM are meaningful or useful. Maybe 250 RPM changes are a good limit, though seeing the RPM displayed down to the exact single digit is cool. Remember, you will almost certainly need filtering of the readings. Maybe using a moving average over a half second or a full second.
Another thing.: It is easy to update the display much more often than necessary. Most displays have a liquid crystal persistence of about 100mS, so updating more often than 10Hz is just creating a blur.
Since the GPS updates at 4Hz, it might be useful to use the GPS receive cycle for the LCD updates.
-Tony |
|
| Back to top |
|
 |
kurakaira
Joined: 21 Mar 2007
Posts: 32
Location: Finland
|
|
Posted: 04 June 2009, 8:03 AM Post subject: Update |
|
|
Problems ... again , but i think i guess why ...
Here is a more detailed description of my wiring ,
Pin 1 & 2 : 19200bps serial to and from a 4" serial color tft
Pin 5 : 4Hz gps serial input ( 4800bps , only the RMC sentence )
Pin 6 : Serial output to a SD logger ( Sparkfun Logomatic v2 , 4800bps )
Pin 7 : Chip Select to 74595 ( Driving 4 shift leds , 1 alarm led , 1 oil valve )
Pin 8 : CS to MCP4921 ( DAC , Exhaust temp 0-1024'c )
Pin 9 : CS to MAX6675 ( Exhaust temp , K-type to SPI , bit banged )
Pin 10 : Serial output to 74595 & MCP4921
Pin 11 : Serial input from MAX6675
Pin 12 & 13 : InputCapture and ADC connected to 16ch CD74HC4067 MUX
Pin 14 - 17 : MUX S0 - S3 Select inputs
Pin 27 : Serial Clock for 74595 & MCP4921 & MAX6675
The problem could be now that i connected 2 pushbuttons ( Mem & Clear ) to the MUX inputs , and i have a separate task to only read the buttons and check if GPS data is available , the task works also as a delay ( Loop until Timer - TimeBeforeS > 0.200 ' 200ms minimum delay )
But as my task calling is like this ,
Do
Call GetMux ' Gets all 16 values including 2 RPM values
Call UpdateLCD ' Writes new data to LCD
Call Idle ' Here it reads the 2 pushbuttons and delays 200ms
Loop
Am i right that these tasks can run simultaniously ?
At GetMux , InputCapture tries to read the PulseDuration with the MUX in position 1 or 2 ( Rpm or TurboRpm )
But at the same time the Idle , switches the MUX to read the 2 switches , that will mess up the InputCapture . ( channels 3 and 4 )
This is just an idea i had last night in my sleep .
I have to drive 50km after work to get to the car and try to disable reading of the switches or locking the GetMux task .
Can You think of a better way to monitor the switches ??
Also i am planning to use the touch screen function of the display , but not before i get the RPM readings to display correctly )
This is the code i am currently using to read the RPM ( still it acts funny , at idle it displays nice 1400rpm , but at about 5000 it shows too much , like 7000 ... )
| Code: |
Call InputCapture(pdUI, 2, 1, 22) ' timeout in 100ms
if pdUI(1) = 65534 or pdUI(2) = 65534 then ' if engine not running , skip
RpmS = 0.0
else
Call InputCapture(pdUI, 6, 1, 22) ' timeout in 100ms
RpmS = 0.0
RpmS = RpmS + Csng(pdUI(1)) + Csng(pdUI(2)) + Csng(pdUI(3)) + Csng(pdUI(4)) + Csng(pdUI(5)) + Csng(pdUI(6))
RpmS = RpmS / 3.0 ' AVG of three pulses
RpmS = 60.0 / (RpmS * 0.0000000678) ' Rounds per minute
RpmS = RpmS / 5.0 ' This show correct idle rpm
RpmS = RpmS / 100.0 ' Rounding to 100
RpmS = fix(RpmS)
RpmS = RpmS * 100.0
End if | [/code] |
|
| Back to top |
|
 |
|