Shop OBEX P1 Docs P2 Docs Learn Events
measuring voltage with RC slope — Parallax Forums

measuring voltage with RC slope

ManAtWorkManAtWork Posts: 2,176
edited 2014-05-19 00:35 in Propeller 1
I need a simple way to measure a voltage over an isolation barrier. An ADC would be much to complicated and expensive and I don't need high precision so I thought I could do it by comparing the voltage against the slope of an RC oscillator and sending the result to the propeller with an optoisolator.

The C of the RC oscillator is charged with a resistor from a 5V supply. It is discharged when the voltage reaches aprox. 4V (exact value doesn't matter). The voltage to be measured is divided down to a range from 0 to 2.5V. At the trigger point of the comperator the input voltage is equal to the slope voltage

V(t) = 5V * (1 - exp(-t/RC))

where t is the time from the end of the discharge pulse to the trigger point of the comperator. Unfortunatelly, the relation is non-linear opposed to the RC decay example in the propeller education kit example where R is measured. To avoid floating point math, we could use the antilog table in the propeller.

As the input is limited to half the supply voltage t/RC stays between 0 and 1 which means the argument to the e-function is between 0 and -1. How can this be shifted to the correct range for the antilog table? I know it must be simple but I just can't get rid of the board before my head, at the moment, and math at school was too long time ago...:confused:

Comments

  • RickBRickB Posts: 395
    edited 2014-05-16 12:08
    The cd4046 pll chip contains a linear vco that would work for less than $1.
    TI makes a newer version (CD74HCT4046A) that works up to about 15 MHz.

    Google vco ic for others.
  • Tracy AllenTracy Allen Posts: 6,664
    edited 2014-05-16 12:57
    If you can turn it into an voltage controlled RC oscillator, then the period could be directly proportional to the input voltage. Easy to isolate and may be easier than RCTIME measurements. (+1 what RickB said.)

    For RCTIME though, for low accuracy, you may get away with a simple inverse relationship,
    [FONT=courier new]P[SIZE=1]RI GetVolts
      result := multiplier / GetRCtime  ' empirical constant divided by time[/SIZE]
    [/FONT]
    
    It works best when the voltage to be determined is more than twice the threshold trigger voltage. A second constant result = k/t+c can improve it a bit.


    To do what you ask, the equation needs to be adjusted to fit the power of two hub table. It is a process--Deep breath!
    Vtrig = Vtbd * (1 - exp(-t/RC))
    Vtrig= Vtbd * (1 - 0.693 * 2^(-t/(R*C*0.693))) base 2 exp
    You know RC in advance, and the Prop measures t. Keep them in commensurate units. Both in microseconds say. Then when doing the division on t/RC, have it come out normalized to a denominator of 2048, that is Z + F/2048, where Z is the integer part of the division and F/2048 is the fractional part. Use 2048 because that is the number of words in the exp hub table. Since the exponent is negative, adjust both integer and fractional parts to make the fractional part positive... -Z - F/2048 = -Z-1 + (2048 - F)/2048.
    Now, (2048 - F)*2 is the index into the EXP hub table based at $D000 (*2 for word address). The value returned is a 16 bit integer X, which represents a fraction X/65536, and you have to supply and implied integer part. 1+X/65536. (The answer is a number between 1 and 2, because the exponent of 2 is between 0 and 1). In binary, you have a 17 bit number with a 1 in bit 16 and the fractional part in bits 0 to 15. Now adjust that answer by the integer part from above, -Z-1. That is an integer exponent of 2, so it represents a shift. For example, if Z=0, then you have to multiply the 17 bit number times 2^-1, that is, shift it one right. Okay, still interested? We're halfway there!
  • ManAtWorkManAtWork Posts: 2,176
    edited 2014-05-16 13:07
    Ok, I found the solution. The voltage can be calculated with the folowing algorithm:

    * multiply t with the time-scale factor to fit the address range of the table
    * lookup y:= table[2048-t] + $10000
    * calculate v:= ($20000-y) * voltage-scale

    The table holds a "window" of the exp-function y=2^x in the range 0<=x<1 and 1<=y<2. That window looks exactly like the range -1<=x<0 and 0.5<=y<1 except for x-offset and y-scale.

    The correct scaling factors can be found as follows: an input (after the divider) of half the supply voltage has to result in t=2048. Then, y is equal to $10000 and the final result has to be the voltage before the divider.

    RickB, thanks for the hint but I prefer the RC+software solution because...
    * it's more "the propeller way": make use of what's already there instead of adding external hardware
    * math exercises are good for the brain
    * I hate adding yet another bin to my IC stock :smile:

    PS: Tracy, I think we started typing about the same time but you were faster. Thanks for the detailed explanation.
  • Tracy AllenTracy Allen Posts: 6,664
    edited 2014-05-17 00:06
    Oh! I see I misplaced the multiplier for base conversion in my last post. Should be,
    Vtrig = Vtbd * (1 - exp(-t/RC))
    Vtrig= Vtbd * (1 - 2^(-t/(R*C*0.693))) base e to base 2, ln(2)=0.693
    That is easier because it is all rolled into one constant, R*C*0.693 before the division in the exponent.

    Of course, all that and more is taken care of automatically if you use the floating point package, but what fun is that?!
  • ManAtWorkManAtWork Posts: 2,176
    edited 2014-05-17 07:18
    It works!
                  mov    rcDuty,PHSB                ' pulse width voltage measurement
                  sub    rcDuty,lastRcCnt           ' input divider 411.6V -> 2,5V -> 33.33µs
                  add    lastRcCnt,rcDuty           ' 33.33µs = 2619 clocks
                  mov    rcTemp,rcDuty
                  shr    rcTemp,#2                  ' 2619 - 2619/4 + 2619/32 &#8776; 2048
                  sub    rcDuty,rcTemp               
                  shr    rcTemp,#3
                  add    rcDuty,rcTemp
                  shl    rcDuty,#1                  ' *2 = word adrdress
                  max    rcDuty,bit12               ' max 2048
                  neg    rcDuty,rcDuty wz
            if_nz add    rcDuty,expTableEnd
            if_nz rdword rcDuty,rcDuty
            if_nz neg    rcDuty,rcDuty
            if_nz add    rcDuty,bit16
                  wrlong rcDuty,adrVolt
    
    bit12         long      $1000
    bit16         long      $10000
    expTableEnd   long      $E000
    
    
    I have aprox. 1% offset that seems to be caused by the mismatch of the rise and fall time of the optocoupler. But linearity and gain seem to match very well. The result is scaled so that $10000 means max voltage (411V).
  • Tracy AllenTracy Allen Posts: 6,664
    edited 2014-05-17 09:15
    I'm curious what you're doing with 411 volts full scale, and how you have that arranged through the opto-coupler.
  • ManAtWorkManAtWork Posts: 2,176
    edited 2014-05-19 00:35
    I just re-activated an old project I never finished:
    asset.php?fid=93481&uid=57667&d=1350124479
    A propeller based VFD
    Attachment not found.
Sign In or Register to comment.