More Pic basic pro maths help.


Closed Thread
Results 1 to 6 of 6
  1. #1

    Default More Pic basic pro maths help.

    Ok i have a bit of code which reads a -100A - 0 - +100A current sensor.

    The sensor idles at 2.5v and swings rail to rail as current flows.

    I use a 10 bit adc to capture the value. No issues with all of this.

    Now I also capture a sensor offset value at program start up which is the 0A value. this doesnt change much perhaps by one number either way around 510 each day.

    So my formula looks like the below.

    Code:
    	if BatCurrent < Offset then		'If BatCurrent is < Offset means system is Discharging
    	BatCurrent = ((Offset - BatCurrent) * 2) / 10 	'Subtract offset to get a positive number (0-512 = 0-100A+) Max 99
    	AmpSign = 45				'Set ascii Character 45 (-) to be displayed if Discharging
    	goto ExitCurrent
    	endif
    The snippet checks which way the current is flowing and then calculates the value in amps. I cheated and just multiplied the value by 2 as i knew -100A would be an adc reading of 0 so in effect 512 became 1024 or -102.4A So it's a bit off, can anyone suggest some better maths. Vice versa applies and an adc reading of 1024 = +100A flowing

  2. #2
    timmers's Avatar
    timmers Guest


    Did you find this post helpful? Yes | No

    Default Re: More Pic basic pro maths help.

    So assuming :-

    Amps ADC value
    -100 0000
    0 0511
    +100 1023


    Equates to 201 amp values against 1024 a2d values gives us 1024/201 =5.094 a2d's per amp. By multiplying up we lose less in the division.
    If using LONG variables you can get even more accuracy.

    ADC_VALUE VAR WORD
    AMPS VAR BYTE
    AMPS_SIGN VAR BYTE
    AMPS_CHAR VAR BYTE

    ADCIN x,ADC_VALUE 'collect a2d
    ADC_VALUE = ADC_VALUE *64 'multiply up by 64 (assuming a WORD variable)
    AMPS = ADC_VALUE / 326 'divide down by 64 * 5.094
    IF AMPS <100 THEN 'negative amps
    AMPS_SIGN ="-"
    AMPS_CHAR =100 -AMPS
    ELSE 'positive amps
    AMPS_SIGN ="+"
    AMPS_CHAR =AMPS -100
    ENDIF
    LCDOUT $FE,128,AMPS_SIGN, DEC3 AMPS


    Ok.
    Timmers.

  3. #3


    Did you find this post helpful? Yes | No

    Default Re: More Pic basic pro maths help.

    Thanks Timmers that's a big improvement.

    I'm using a pic 16F886 so can't use long variables sadly.

    Anyone else any other ideas?

  4. #4
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: More Pic basic pro maths help.

    Hi,
    Not tested but how about:
    Code:
    ADC_VALUE VAR WORD
    AMPS VAR WORD
    i VAR BYTE
    
    AMPS = 0
    For i = 0 to 3              ' Sample 4 times
      ADCIN 0,ADC_VALUE         ' Get actual value
      AMPS = AMPS + ADC_VALUE   ' Accumulate
    NEXT
    
    AMPS = AMPS >> 1            ' Divide by 2, AMPS is now 0-2048
    AMPS = AMPS ** 64000        ' Multiply by ~0.97656, AMPS is now 0-2000
    AMPS = AMPS - 1000          ' AMPS is now +/-1000, change to AMPS=1000-AMPS to invert.
    
    LCDOUT $FE,$1, "Current: ", SDEC AMPS/10, ".", DEC ABS(AMPS // 10)
    /Henrik.

  5. #5


    Did you find this post helpful? Yes | No

    Default Re: More Pic basic pro maths help.

    Clever Henrik. I actually do capture ten samples and average them to get a reliable figure. But your maths after that is interesting. Wish i understood all the funny symbols >> etc

    Thanks i might try that.

  6. #6
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: More Pic basic pro maths help.

    Hi,
    The >> is the shift right operator, it shifts the word, in this case, one bit to the right which effectively is the same as dividing by 2. It's really not needed as you might as well change 64000 to 32000 to get the same end result (a value ranging from 0-2000)

    In your case, with ten accumulating samples you could remove the shift operation and do Amps = Amps ** 12800 to get value ranging from 0-2000.

    The ** operator multiplies by the value you specify and then returns the top 16bits of the intermediate 32bit result (you don't need LONGS for this). In effect this is the same as first multiplying by your value and then dividing by 65536. 12800/65536=0.1953 and 10240*0.1953=2000.

    Good luck!
    /Henrik.

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