Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Is this formula too tricky in assembly?

Status
Not open for further replies.
Hi,

I'm sampling the output from a Honeywell HIH 5030 humidity sensor using 10 bit A/D and the PIC's (18F2420) internal (5V) ref. The A/D conversion result has to be scaled and converted to BCD before being written to an LCD.

I obtained the scaling formula from a trend line in an XL chart and it is this: %RH = 0.1163(ADRES) - 23.821

Is this formula easily 'do-able' in ASM. I'm hopeless at maths stuff so don't want to even try this until I know it's manageable. Not done any 'C' programming but I think in 'C' you could just enter the formula and get the result?

Thanks in advance for any help.
 

Attachments

  • Honeywell Humidity sensor.pdf
    184.4 KB · Views: 272
  • humidity(XL Workbook).txt
    68.5 KB · Views: 168
Last edited:
It's not really a problem to do in assembler, just download some maths routines - you don't even need floating point, just scale the numbers to be integer, and insert the decimal point in the correct place at the end.

There are 32 bit integer maths routines on the EPE website.
 
To give you an idea of what the integer math routines would give you, the equivalent to your formula is %RH = (119*ADRES - 24393)/1024. To put that into excel you would enter =INT((ADRES*119-24393)/1024). If you wanted to round to the nearest whole number you would use =INT((ADRES*119-24393+512)/1024). If you wanted to keep some of the decimal part that can also be done.

Mike.
 
Well I've written a couple of routines in assembly that fit cubic curves to 4 points. The maths that you need is perfectly possible in assembly.

I suggest you used fixed point arithmetic with the least significant bit equal to the resolution that you want displayed. For instance, if you want one digit after the decimal point, (00.0 to 99.9% humidity) then you should calculate with 0 - 999 representing 00.0 to 99.9 %.

Conversion to BCD is best done by testing to see if you can subtract each bit of the BCD number in turn. So for 0 - 999 you test to see if you can subtract 800, then 400, then 200, then 100 then 80 then 40 etc all the way down to 10. After that, what is left is the last digit.
 
This method uses 16 bit multiplication:

Take ADRES times 30. Store the result as a two byte number. Take the upper byte, which is the same as dividing by 256. Subtract 24 from that number for your humidity.

30/256=0.11719, which is 0.7% error from your 0.1163 term. the 23.821 can be rounded to 24, assuming you don't really want to try reading humidity to a tenth of a percent.

This technique can be widely used when a floating point multiplicative factor is needed.

This method uses repeated addition:

Take ADRES and add it together 30 times into a 16 bit sum. Continue as above.
 
Last edited:
Hi,

I've made progress but now stuck again. I have a 16 x 16 multiplication routine (from EPA) and a 32 bit subtraction routine (PIClist). The calculations go ok that far, but the EPA division routine won't work for me. Wondered if you could have a quick look.....

Code:
;Divide 16bit dividend (dividL,H) by 16bit divisor (divisL,H)
;Result (quotient) in dividL,H and remdrL,H
;processor 16f84 (I'm using 18f2420)
;instructions in [] have been changed by me becaue of build error
    
Divide    
    movf    divisL,w
    iorwf   divisH,w
    btfsc   STATUS,Z      ;[skpnz]
    goto    div0          ;Division by zero !

    movlw   .16           ;16 bit    division
    movwf   bitcnt  
    clrf    remdrH        ;Clear remainder
    clrf    remdrL

dvloop    
    bcf     STATUS,C      ;[clrc]    ;Set quotient bit to 0
    rlcf    dividL        ;Shift left dividend and quotient
    rlcf    dividH        ;Msb into carry
    rlcf    remdrL        ;and then into partial remainder
    rlcf    remdrH

    movf    divisH,w      ;Compare partial remainder and divisor
    subwf   remdrH,w
    btfsc   STATUS,Z
    goto    testgt        ;Not equal so test if remdrH is greater
    movf    divisL,w      ;High bytes are equal,compare low bytes
    subwf   remdrL,w
    
testgt
    btfsc   STATUS,C      ;[skpc];Carry set if remdr >= divis
    goto    remrlt

    movf    divisL,w      ;Subtract divisor from partial remainder
    subwf   remdrL
    btfsc   STATUS,C     ;[skpc];Test for borrow
    decf    remdrH        ;Subtract borrow
    movf    divisH,w
    subwf   remdrH
    bsf     dividL,0      ;Set quotient bit to 1
                          ;Quotient replaces dividend which is lost
remrlt
    decfsz  bitcnt
    goto    dvloop
    bcf     STATUS,Z     ;[clrz];Clear error flag (z)
    
div0
    return                ;Return with z set if error
Thanks very much for help so far....
 
If you use the function I posted earlier, namely %RH = (119*ADRES - 24393)/1024, then to divide by 1024 you simply shift right 10 times.

Mike.
 
To give you an idea of what the integer math routines would give you, the equivalent to your formula is %RH = (119*ADRES - 24393)/1024. To put that into excel you would enter =INT((ADRES*119-24393)/1024). If you wanted to round to the nearest whole number you would use =INT((ADRES*119-24393+512)/1024). If you wanted to keep some of the decimal part that can also be done.

Mike.

Hi,

How did you get that first formula?

Thanks.
 
Hi,

How did you get that first formula?

Thanks.

I just multiplied all your constants by 1024, placed it all in brackets and then divided it all by 1024. Simple really.

If you don't need that kind of accuracy you could just multiply/divide by 256 and then it will still fit in a 16 bit variable.

Mike.
 
I would recommend double checking your conversion factors. Honeywell's data sheet for this device gives the output (which is ratiometric to Vdd) as: Vout = Vdd*(0.00636*RH + 0.1515) and they include a temperature compensation formula as well but if you're operating near 25 degrees C and aren't too concerned about accuracy, then you can ignore this (compensation only seems to adjust 1-2%).

The others have given you good tips on using fixed point math to do the fractional factors (hint: Think of the 'binary' point as an arbitrary concept that can be adjusted to suit your equations and, for the most part, permit you to work entirely with multiplications, rather than divisions, ie a 'division' is nothing more than multiplying by a reciprocal value).

By the way, I've been bitten by Honeywell's datasheet where they claim a resistor load as a "Minimum load" - don't believe it - it's a Maximum LOAD.

Tom
 
Last edited:
Thanks Tom,

Still getting to grips with the maths...... Aha! I was a bit puzzled by the 65K 'minimum' load. Found that reducing it gave a humidity reading closer to another proffesional humidity measuring instrument, so thanks for that.
 
Status
Not open for further replies.

Latest threads

Back
Top