Lookup tables for Altitude determination


Closed Thread
Results 1 to 6 of 6
  1. #1
    Join Date
    Jan 2010
    Posts
    19

    Default Lookup tables for Altitude determination

    I am trying to understand from examples using Lookup2 on this forum how to construct a lookup table to determine altitude from my MPX6115 pressure sensor.
    Here iwhat I have so far:

    1. I am reading the sensor with an 18F2423 which has a 12bit A/D. Not using oversampling.
    2. The pressure where I live is roughly 14.46 PSI, elevation 440 ft.
    3. I am reading an ADValue of about 3344 at present elevation.
    4. I am aware of the MPX4115A calculator.
    5. I have used an online calculator to convert elevation to PSI in order to get some numbers.

    Now with all of this, where do I go from here to develop this table, or is there a better way to determine altitude?

  2. #2
    Join Date
    Sep 2005
    Location
    Campbell, CA
    Posts
    1,107


    Did you find this post helpful? Yes | No

    Default Re: Lookup tables for Altitude determination

    I'm sure there are equations out there, but I imagine most are a bit hard for integer math.

    An approach I would use:

    Assuming that your A/D readings decrease with altitude:
    Build an array (array 1) with ArrayWrite that has as many points as you can easily create that contains the A/D readings of increasing altitude.

    If the elements of your array are at even altitudes (100, 200, 300, 400 feet, for example), create a simple equation of altitude vs. array element.
    example - element 1 = 100 feet, element 2 = 200 feet. Then the translation is element X 100 = altitude.

    If the elements of your array are not at evenly spaced altutudes, they you will have to create another array (array 2) with the translation.
    example - element 1 = 132 feet, element 2 = 619 feet,

    Take your A/D reading and check against every element of array 1 in a for-next loop.
    When the A/D is larger than the reading, note the element (n). Also note the value in element n-1.

    Subtract the value of element n from the value in n-1. Call this value "DELTA". If you are using array2, do the subtraction on those elements.

    Subtract the value of your A/D from the value in n. Call this value DELTA2
    divide DELTA by DELTA2 (you may have to multiply and use LONGs to get adequate resolution).
    Multiply the altitude difference of n and n-1 by the previous result.
    Charles Linquist

  3. #3


    Did you find this post helpful? Yes | No

    Default Re: Lookup tables for Altitude determination


  4. #4
    Join Date
    Jan 2010
    Posts
    19


    Did you find this post helpful? Yes | No

    Default Re: Lookup tables for Altitude determination

    Thanks Charles that will certainly help me to get started.
    As far as A/D readings are concerned, to get a relationship to altitude should I work backwards from the formula:

    P = 0.0039 * ADval + 1.53

    to get Pressure. Then I would take the pressure value and use a standard barometric chart such as the one Aerostar has linked to in this thread
    to get altitude data. This data would go into one table and the A/D values into the other table?

    And what if my sensor is off by some error factor. If I can determine the amount of error, should I offset all the A/D reading by a set amount
    to offset the error?


    Quote Originally Posted by Charles Linquis View Post
    I'm sure there are equations out there, but I imagine most are a bit hard for integer math.

    An approach I would use:

    Assuming that your A/D readings decrease with altitude:
    Build an array (array 1) with ArrayWrite that has as many points as you can easily create that contains the A/D readings of increasing altitude.

    If the elements of your array are at even altitudes (100, 200, 300, 400 feet, for example), create a simple equation of altitude vs. array element.
    example - element 1 = 100 feet, element 2 = 200 feet. Then the translation is element X 100 = altitude.

    If the elements of your array are not at evenly spaced altutudes, they you will have to create another array (array 2) with the translation.
    example - element 1 = 132 feet, element 2 = 619 feet,

    Take your A/D reading and check against every element of array 1 in a for-next loop.
    When the A/D is larger than the reading, note the element (n). Also note the value in element n-1.

    Subtract the value of element n from the value in n-1. Call this value "DELTA". If you are using array2, do the subtraction on those elements.

    Subtract the value of your A/D from the value in n. Call this value DELTA2
    divide DELTA by DELTA2 (you may have to multiply and use LONGs to get adequate resolution).
    Multiply the altitude difference of n and n-1 by the previous result.

  5. #5
    Join Date
    Sep 2005
    Location
    Campbell, CA
    Posts
    1,107


    Did you find this post helpful? Yes | No

    Default Re: Lookup tables for Altitude determination

    A lot depends on the accuracy you need. If the values in the table that aerostar 'pointed to' are good enough, then

    Create an array that has an element for every listed altitude in the table.
    Using the formula that you mention, calculate the A/D value for each of the cells of the array. And fill the array with those A/D values.

    Filling the array with A/D values rather than pressures will save your PIC a lot of processing time (EXCEL can help you save a lot of work by doing the calcs).

    Create a second array with the altitudes represented by the cells in the first array. Cell #0 = 0 (feet), cell #1 = 50 (feet), cell #2 = 100 etc.

    In your program, get an A/D count and compare it against every cell in array #1 starting with the first. Just as an example, assume that array element #19 has a value of 493 and element number #20 has a value of 470. If your A/D has a result of 482, and you worked through the array, you would find that the first cell where your A/D count was larger was cell #19. Now you can check the value of element #19 in Array 2. There is your altitude.

    If you need more accuracy, you will have to interpolate. That is what I was referring to in the earlier post. But if you don't need that kind of accuracy, there is no need to explain further. If you do, I'll explain that later.
    Charles Linquist

  6. #6


    Did you find this post helpful? Yes | No

    Default Re: Lookup tables for Altitude determination

    Here is a snip that uses a lookdown table with linear interpolation between key values. It has had a lot of junk snipped out but it comes from a running program using a PIC16F88.

    HTH
    Brian

    /code
    data @0, "Delivery ver Ce 14 Nov 11 " '40 characters
    '***** Configuration fuses set via melabs U2 USB Pgmr ***************
    ' Device = PIC16F88 @ 20 MHz.
    ' Osc = HS, WDT = Disabled, PwrUpTmr = En, MCLR = Reset, BrnOutRst = En
    ' LVP = Dis, FlashPgmWrite = En, CCP mux with RB3, Code = Not Prot,
    ' Data EEPROM = Not Prot, FSCM = En, IntExtSwitch = En
    '************************************************* ******************
    ' OnTime is a BYTE array in this version

    '************************* Strategy *****************************
    'Delivery.pbp aims to deliver short gas 'burps' at a steady rate
    'regardless of tank pressure.
    'One litre of gas should be delivered in 200 pulses each of 5 mls @ STP,
    'each causing a 20 mBar drop in tank pressure. The start pressure is
    '6000 mBar and the end pressure after 200 'burps' is 2000 mB. The
    'pressure drop is 6000 - 2000 or 4000 mBar in 200 'burps' = 20 mB/burp.
    'The pulse rate is nominally once per second for a delivery time of
    '200 seconds or a little over three minutes.

    'MaxTank = 6000, MinTank = 2000, Delta P is 4000 mBar, Tank
    'volume is 250 mls @ STP.

    'Delivery.bpb gets tank pressure messages from the GasMixer on an
    'intermittent basis. In between times, it estimates the pressure drop
    'from each firing and corrects its estimate whenever a true pressure
    'reading comes in.

    'The OnTimes are stored as BYTE variables in the two LookDown tables.
    'Below are ARBITRARY STARTING VALUES which get overridden during
    'Calibration.

    ''Tank0 Dlvry0 LookDown values
    'data @100, 250 'OnTime @ 1500 mB for 20 mB drop
    'data @101, 208 '2000 mB
    'data @102, 170 '2500
    'data @103, 136 '3000
    'data @104, 106 '3500
    'data @105, 80 '4000
    'data @106, 58 '4500
    'data @107, 40 '5000
    'data @108, 26 '5500
    'data @109, 16 '6000
    'data @110, 10 '6500
    '
    'data @115, 0 'SolCal value. 0 = not calibrated, 1 = calibrated
    '
    ''At GasMix startup there is a brief pause during which the operator
    ''can hit "D" or "d" and start diagnostics. Selecting Solenoid Cal
    ''will send the DELIVERY 16F88 into the calibration routines.
    ''At end, SolCal will be set to 1 and the two tables will be updated.

    ''Tank1 Dlvry1 LookDown values
    'data @120, 250 'OnTime @ 1500 mB for 20 mB drop
    'data @121, 208 '2000 mB
    'data @122, 170 '2500
    'data @123, 136 '3000
    'data @124, 106 '3500
    'data @125, 80 '4000
    'data @126, 58 '4500
    'data @127, 40 '5000
    'data @128, 26 '5500
    'data @129, 16 '6000
    'data @130, 10 '6500

    DEFINE LOADER_USED 1
    DEFINE OSC 20
    DEFINE SHIFT_PAUSEUS 50
    define char_pacing 100
    DEFINE DEBUG_REG PORTB 'Debug pin port
    DEFINE DEBUG_BIT 5 'Debug output pin bit
    DEFINE DEBUG_BAUD 9600 'Debug baud rate
    DEFINE DEBUG_MODE 0 'Debug mode: 0 = True, 1 = Inverted
    DEFINE DEBUG_PACING 500 'Debug character pacing in us
    DEFINE DEBUGIN_REG PORTB 'Debugin pin port
    DEFINE DEBUGIN_BIT 2 'Debugin pin bit
    DEFINE DEBUGIN_MODE 0 'Debugin mode: 0 = True, 1 = Inverted

    '''''''''''''''''''''''Hardware assignment '''''''''''''''''
    Dlvry0 var PortA.0 'Solenoid driver Tank0 delivery
    Dlvry1 var PortA.1 'Solenoid driver Tank1 delivery
    SpareA2 var PortA.2
    SpareA3 var PortA.3
    SpareA4 var PortA.4
    TRISA = %00000000 'all outputs.
    PortA = %00000000
    ANSEL = %00000000 'all ports digital
    CMCON = %00000111 'comparators OFF

    'PortB 'MUST have Weak PullUps ACTIVE for comms to/from '4620.
    'WPU pulls Alert, Reply and DataIO high. These go low when active.
    Reply var PortB.0 'p6 Idle INPUT. LOW to Acknowledge a poll.
    DataIO var PortB.1 'p7 Idle INPUT. Bidirectional data exchange.
    RxD var PortB.2 'p8 Boot or RS232 data IN. Idles HIGH
    LED var PortB.3 'p9 activity LED
    Alert var PortB.4 'p10 Idle INPUT. Pulled LOW by calling party.
    TxD var PortB.5 'p11 Boot data or RS232 OUT
    SpareB6 var PortB.6 'p12 unused - set as OUT
    SpareB7 var PortB.7 'p13 unused - set as OUT
    TRISB = %00011111
    PortB = %00100000 'idle TxD high
    OPTION_REG.7 = 0 'Enable WeakPullUps

    '*********************** Variables *****************************
    A var byte
    B var byte
    C var byte
    D var byte
    Delta var byte 'interpolation in LookDown table
    ChkSum var byte 'The appemded CheckSum calculated by Mixer
    LclChk var byte 'the locally calculated CheckSum
    OT0 var byte[11] 'LookDown OnTime array entry for Tank 0
    OT1 var byte[11] 'LookDown OnTime array entry for Tank 1
    SolCalDone var bit '0 until calibration routine is run.
    OnTime var word 'actual solenoid open time.
    'Calculated as word then truncated to byte.
    Pace var word 'time between each firing in mSecs
    SoakFlag var bit '0 when in normal delivery, 1 in Soak
    SoakCtr var word '10 mSec increments from 0 to 10 minutes
    SoakTime var byte 'in minutes
    Tank var byte '0 or 1
    TankPress var word 'Measured value supplied by Mixer
    EstPress var word 'Estimated pressure in the active tank.
    PressDec con 30 'target pressure decrement per pulse = 30 mB
    TestP var word '500, 1000,2000,3500 mB etc targets
    LastP var word
    Ident var byte 'Identifier shows what MsgType is coming in.
    TimeOut var word
    Burps var word ' the number of times gas has been released
    W var word
    X var word
    Y var word
    Z var word
    AA var byte
    '********************** Subroutines ****************************
    goto endsubs

    'any subroutines go here

    EndSubs: '******************* End Subs **********************


    Initialise: '****************** Initialise *********************
    TRISA = %00000000 'all outputs.
    PortA = %00100000 'MCLR an input
    ANSEL = %00000000 'all ports digital
    CMCON = %00000111 'comparators OFF
    TRISB = %00010111 '
    PortB = %00110111 'idle TxD high
    OPTION_REG.7 = 0 'Enable WeakPullUps

    low dlvry0 : low dlvry1 : input reply : input alert : input dataio
    low led : timeout = 0 : ident = 8 : ontime = 0 : burps = 0
    testp = 0 : lastp = 0 : estpress = 6250 : soakflaG = 0
    '
    Main: '********************** MAIN *******************************

    TRISA = %00000000 'all outputs.
    PortA = %00100000 'MCLR an input
    ANSEL = %00000000 'all ports digital
    CMCON = %00000111 'comparators OFF
    TRISB = %00010111 '
    PortB = %00110111 'idle TxD high
    OPTION_REG.7 = 0 'Enable WeakPullUps
    low dlvry0 : low dlvry1
    input reply : input alert : input dataio
    pace = 1000 'the time between each burp

    '************************** FlowToChamber **************************
    FlowToChamber:
    '
    ' The working pressure range is from 1500 mBar to 6500 mBar. This is
    ' broken into 500 mBar bands and the solenoid OnTime necessary to
    ' get a 20 mBar pressure drop for each end of these bands is stored.
    ' Linear interpolation is used within each pressure band. The table
    ' MUST be monotonic with the time taken to deliver the gas pulse
    ' increasing as the pressure falls.

    if (ident = 2) and (alert = 1) then
    high led
    if estpress > 6499 then estpress = 6499
    if estpress < 1520 then estpress = 1520 'keep index always > 0
    'Explanation of the LookDown Table logic
    'Returns 'A' between 0 and 10 for TankPress between 1501 and
    '6499 mBar.
    'A table, starting at EEROM 100 for OT0, has byte entries in mSec.
    'OnTimes range from 8 to 255 mS and are unique to the delivery
    'valves and tank restrictors. Values below 10 pushed up to 10.
    'A is the index to find the solenoid opening time for that
    'pressure band. A is zero if T0Pressure < 1500.
    ' For example A = 6 if T0Pressure >= 4000 but < 4500
    'To compute Dlvry0 OnTime we need the times from A and A-1
    'Worked example
    ' suppose T0Pressure = 3345 mBar.
    ' A will be 4 because T0Pressure is < 3500.
    ' The OnTime at location 400 + A (i.e. C) is for 3500 mBar,
    ' say 55.
    ' The OnTime at location 400 + (A-1) (i.e. B) relates to 3000,
    ' say 75
    'Delta =(OnTime at lower pressure)-(OnTime at higher pressure)
    'Delta = 75 - 55 = 20 in this example
    '
    'Find the lower pressure OnTime.
    'Assume W = T0Pressure = 3450 mB
    'lookdown2 tankpress, <[1500, 2000, 2500, 3000, 3500, 4000, _
    ' 4500, 5000, 5500, 6000, 6500], a
    if tank = 0 then
    lookdown2 estpress, <[1500, 2000, 2500, 3000, 3500, 4000, _
    4500, 5000, 5500, 6000, 6500], A
    read (100 + A) ,b 'this is the higher pressure = shorter
    read (100 + a - 1), c 'lower pressure = longer open time
    delta = (c - b)
    'OnTime = time at higher pressure plus a proportion
    'of the delta.
    x = estpress//500 '= 450 if T0Pressure was 3450 0<X<500
    ontime = b + ((delta * (500 - x) + 250)/500)
    if ontime > 255 then ontime = 255
    endif 'Tank = 0 case

    if tank = 1 then
    lookdown2 estpress, <[1500, 2000, 2500, 3000, 3500, 4000, _
    4500, 5000, 5500, 6000, 6500], a
    read (120 + A), b 'the ontime at the upper pressure point
    read (120 + a - 1), c 'ontime at the lower pressure
    delta = (c - b)
    x = estpress//500 'eg = 450 if T0Pressure was 3450 0<X<13
    ontime = b + (((delta * (500 - x))+250)/500)
    if ontime > 255 then ontime = 255 'OnTime here is a WORD
    endif 'Tank = 1 case
    endif 'Ident = 2 AND Alert = 1 case

    DriveValve:
    if (ident = 2) and (alert = 1) then
    timeout = timeout + 1 : pause 1
    if timeout > (pace - ontime) then 'fire solenoid
    if tank = 0 then
    high dlvry0 : pause ontime : low dlvry0
    endif
    if tank = 1 then
    high dlvry1 : pause ontime : low dlvry1
    endif
    'Keep a local estimate of the declining TankPress
    'correct this when new data from the GasMix module arrives.
    estpress = estpress - pressdec
    'PressDec is the target Pdrop per pulse = 20 mBar.
    if estpress < 1540 then estpress = 1540
    'EstPress gets updated whenever new pressure info comes in
    debug "Burps ", # burps, ", T ", # tank, ", ActP ",_
    # tankpress, ", EstP ", # estpress, ", On ", # ontime, _
    ", SkFlg ", # soakflag, ", SkTm ", # soaktime, 13, 10
    timeout = 0 : burps = burps + 1
    endif ' Timeout passed
    endif 'Ident = 2 AND Alert = 1 case
    low led
    goto main
    end

    /endcode

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts