Searching \ for 'linearization of table' in subject line. () Help us get a faster server
FAQ page: www.piclist.com/techref/mems.htm?key=table
Search entire site for: 'linearization of table'.

Truncated match.
'linearization of table'
1998\10\08@161319 by  Would anybody have how to help me to solve a problem, although simple,
but not for a less experienced user?

I am using a sensor of pressure and an operational one that supplies me
the following values:

PSI      Volts

0          1,183
5          1,440
10        1,773
15        2,092
20        2,471
25        2,823
30        3,150
35        3,460
40        3,750

When using a test routine multiplying the value of ADRES (PIC16C74A) for
16 and the routine bin_bcd I get to obtain a reading in display of 40,80
when in full scale (255).

But as there is not linear of the circuit in subject, I don't get to
maintain a proportional value in the display to input of  PIC.

How make a table that maintains the proportion?

Does a formula exist for this problem?

If somebody possesses an answer, I would thank if  could send me.

Thank you

Joco Batista - Jq96 claret.com.br / jq96 netsite.com.br  Joao,

Steve's Workbench, from Radio Shack, has an article discussing the use of a
thermistor with a Basic Stamp II.  The article has a clear explanation of
linearization and even has a simple Gauss fit program in basic.  You can
find the article at

Hope it helps,

Larry
snip
{Quote hidden}

snip   Hi Joco,

You can use the table that you just showed here, and then use linear
interpolation between the points.

(NOTE: I will use the english "." convention for the decimal point, instead
of the ",")

For example, between 10 and 15 psi, you get about 0,0638 volts per psi. So,
if the measured input voltage falls between 1.773 and 2.092, like, for
example, 2.000 volts, you do the following:

2.000 - 1.773 = 0.277

0.277 / 0.0638 = 3.56 psi

final reading: 13.56 psi,  which I think you will find to be very close to
the real value.

You do this for every point in your table (i.e. you calculate this "slope"
factor between 0 and 5, between 5 and 10, etc) and then put them in a
lookup table. You also put the base values in another table. So, in your case:

Vb                          S
1.183                        .0514
1.440                        .0666
1.773                        .0638
2.092                        .0758
2.471                     .0704
2.823                        .0654
3.150                     .0620
3.460                         .0580
3.750                         .0580 (Just make it the same as the last one)

So, your pic does the following:

2) Look up ADC value and see between which two Vb values it falls, and pick
the lower of the
two.
3) Look up the corresponding S value and compute the PSI: psi = (Vadc - Vb)/S

Now, of course, this would require floating point division and floating
point comparison, and there are ways to make this better for the PIC:

1) Don't put floating point values of Vb into the table. Instead, store the
actual code that you will get from the ADC.

2) Instead of picking the values of the table to be evenly spaced as far as
PSI goes, pick them to be evenly spaced as far as Vb goes, and pick them so
that the number which you get from the ADC has zeros in as many of its
lower bits as possible (so if the interval between table ADC values is,
say, 4, and you start at a multiple of four, then the lowest two bits of
each table ADC value will be zero) This allows you to eliminate the
floating point compare from the table lookup process. You can just see if
the upper 6 bits of the value you read from the ADC are the same as the
upper 6 bits of a value in the table, and select that one.

3) If you use more points than you have given here, your answer will be
more accurate. Not only that, but the slope values will not matter as much,
and you can round them off to be powers of two, so that the floating point
division just becomes an integer binary right shift (pic instruction RRF)

I know that this is not very clear. Please feel free to email me privately
and I will explain it further.

Good luck,

Sean

At 05:04 PM 10/8/98 -0300, you wrote:
{Quote hidden}

+--------------------------------+
| Sean Breheny                   |
| Amateur Radio Callsign: KA3YXM |
| Electrical Engineering Student |
+--------------------------------+
Save lives, please look at http://www.all.org
Personal page: http://www.people.cornell.edu/pages/shb7
shb7 cornell.edu  Phone(USA): (607) 253-0315 ICQ #: 3329174  Hi,

I have checked the data using the regression analysis technique, and the
connection is LINEAR. The estimated formula is:

PSI = -17.20598 + Volts * 15.12302

Any better pocket calculator would do also this fit. However, to check
whether the connection is really linear, is a bit (not very) harder.

I hope this helps you.

Regards,
Imre

On Thu, 8 Oct 1998, Joao Batista wrote:

{Quote hidden}  Dear Sean,

I received its solution proposal for my problem, only that I didn't understand
very well, as to use a routine of floating point.
It is probable that due to my lack of experience in division with floating point
is hindering my understanding.
I please request its help in this point, if it is possible..

Respectfully,

Joco Batista

Sean Breheny wrote:

{Quote hidden}  > From: Joao Batista <jq96 CLARET.COM.BR>
> Subject: linearization of table

Although not an exact solution to the PSI-to-Volts problem posed, the
following code is probably directly usable with little modification.

It's an example of piece-wise linearization.  Ie., a sensor that's
very non-linear over its full-range is often "linear enough" across
segments of its range.

This is 1st-pass, *but* functional code; a fragment of a 12c672 based
temperature sensor project.  Optimization is clearly possible, especially
for register use.  But, the simple "block" code is more straight-forward.

To build the piece-wise linearization tables, calculate the x_data
points (0-255 atod values) for convenient y_data points (deg_F with
perfect deg_C equivalents in this case).

+---[ thermistor ]---< Vdd
12c672 GP0/AN0: o----+        10k
+-------\/\/\/-------> Vss

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

cblock _ram_              ; registers
idx                             ;coordinate look-up index, bit count
x1,x2                           ;x1,x2 coordinates
y1,y2                           ;y1,y2 coordinates
rpt,xpt,ypt,zpt                 ;linearization multiply,division regs
endc

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; use example:

call    set_xy              ;set x1,x2 y1,y2 coordinates
call    lin_xy              ;linearize

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; entered with w=X, returns x1,x2 and y1,y2 coordinates from x_tbl,y_tbl
; such that X is between x1,x2 (x1<=X<x2)

set_xy: movwf   x_dat                   ;save X data
movlw   (y_tbl-x_tbl)-1         ;length of x_tbl -1
movwf   idx                     ;init index
s1_xy:  decf    idx,f                   ;next location's index
movlw   x_tbl                   ;start of x_tbl
call    nxtbl                   ;get data at tbl+idx
subwf   x_dat,w                 ;w= x_dat-w
btfss   status,c                ;skips next if carry_set
goto    s1_xy                   ;c_clr -- x_dat < tbl_dat

movlw   x_tbl                   ;else -- x_dat >= tbl_dat
call    nxtbl                   ;get data at tbl+idx
movwf   x1                      ;save
movlw   x_tbl+1
call    nxtbl                   ;get data at tbl+idx
movwf   x2                      ;save
movlw   y_tbl
call    nxtbl                   ;get data at tbl+idx
movwf   y1                      ;save
movlw   y_tbl+1
call    nxtbl                   ;get data at tbl+idx
movwf   y2                      ;save
return

nxtbl:  addwf   idx,w                   ;index table location
movwf   pcl                     ;returns data at pcl in w

; x,y coordinate pair lookup tables for -22F (-30C) to 122F (+50C)
; equal length, in ascending order, 1st & last xy_pairs for range guard

; x= (ysi44006 thermistor to vdd with 10k to vss), y= (deg_f)

x_tbl: dt   0, 18, 23,29,36,44,54,65,76,89,101,115,128,140,152,164,174,184,255
y_tbl: dt -40,-22,-13,-4, 5,14,23,32,41,50, 59, 68, 77, 86, 95,104,113,122,212

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; coordinate linearization: x1,x2 -- y1,y2
; return w= ((y2-y1)/(x2-x1)) * (X-x1) + y1

lin_xy: movf    x1,w
subwf   x_dat,w                 ;w= x_dat-x1
movwf   xpt                     ;set x_part= x_dat-x1
movf    y1,w
subwf   y2,w                    ;w= y2-y1
movwf   zpt                     ;set z_part= y2-y1
movf    x1,w
subwf   x2,w                    ;w= x2-x1
movwf   ypt                     ;set y_part= x2-x1
call    scale                   ;xpt= xpt*zpt/ypt
movf    xpt,w
return

scale:  ;   x= x*z/y    y & z are unchanged
;               x,y,z are 8-bit, (x*z) <= 15-bits

#define bcnt    idx

mult:                               ; r:x <- x*z
movlw   8
movwf   bcnt                    ;set bit count
clrf    rpt                     ;clear ms8 of product
bcf     status,c                ;clear carry
rrf     xpt,f                   ;lsb of multiplier into carry
mul1:   btfss   status,c
goto    mul2                    ;carry was clear
movf    zpt,w
mul2:   rrf     rpt,f                   ;align 16-bit product, r:x
rrf     xpt,f                   ;(prod_ls8 replaces multiplier)
decfsz  bcnt,f                  ;loop thru bits
goto    mul1

divi:                               ; x <- r:x/y (remainder in r)
movlw   8
movwf   bcnt                    ;set bit count
div1:   bcf     status,c                ;dividend *2
rlf     xpt,f
rlf     rpt,f
movf    ypt,w                   ;subtract divisor from dividend ms_8
subwf   rpt,f
btfss   rpt,7                   ;check if msb set
goto    div2                    ;ok -- bit clear
movf    ypt,w                   ;else set -- undo previous sutraction
goto    div3
div2:   incf    xpt,f                   ;count previous subtraction
div3:   decfsz  bcnt,f                  ;loop thru bits
goto    div1

#define round_up

ifdef   round_up            ; round-up result -- destroys remainder
bcf     status,c                ;remainder *2 for rounding
rlf     rpt,f
movf    ypt,w                   ;subtract divisor from rmdr*2
subwf   rpt,f
btfss   status,c                ;skip next on carry set
goto    divx                    ;else carry clear -- 2*r < divisor
incf    xpt,f                   ;round x up
divx:
endif
return

--
evd gwis.com
.

More... (looser matching)
- Last day of these posts
- In 1998 , 1999 only
- Today
- New search...