PDA

View Full Version : Duty cycle - Another Math dilemma



Ramius
- 8th September 2012, 19:26
Hi All!
Okay so I have a time period of 9.9210 ms and as part of this time period a pulse width of 4.9474 ms. If you divide 4.9475 by 9.9210 you get a duty cycle of 50.1310 which is actually a percent. Using the time period and the pulse width how do you get to 50.1310 since it is actually .501310?

Thanks, Ed

HenrikOlsson
- 8th September 2012, 22:01
Hi,
It depends on how much resolution you need and can fit within your variables.
If you multiply the dividend by 1000 before actually performing the division the equation (on paper) becomes 4947.5/9.9210=498.7 then you take 1000-498.7=501.3 which is now in units of 1/10 of a percent. In PBP you aren't going to use numbers like 9.9210 so in reallity you'd need to round that off to 10 and the *1000 will be truncated to 4947. 1000-(4947/10)=506 so it's a bit off.

Another way could be to use the ** operator, 4947**6606=498, 1000-498=502, or 50.2%, a bit better.

Yet another way would be to use DIV32, it all depends on the range of the numbers, your variable size, what resolution you need etc.

/Henrik.

Ramius
- 9th September 2012, 16:14
Hi Henrik!
Thank you and I have never seen the use of the number 6606! Basically the formula I am trying to use is (Pulse Width / Time Period - Duty Cycle) /8. The tilt sensor is very sensitive to temperature changes so I am trying to be as accurate as possible. Maybe I should be attempting the calculations with Longs?

HenrikOlsson
- 9th September 2012, 16:30
Hi Ed,
Instead of dividing by 9.9210 you can multiply by 0.100796 (1 / 9.9210). The number 6606 comes from 65536*0.100796=6606.

When you do something like 4947**6605 what happens is that PBP does 4947*6505 which internally results in a 32bit value, it then takes the middle 16bits of that 32bit result and return those 16bits to you. In effect that is the same thing as dividing the 32 bit result by 65536. If we do that with pen and paper we get, 4947*6605/65536=498 which is exactly what PBP will give you.

I guess you're not actually getting the period and pulsewidth i units of milliseconds? How do you measure it and what are the actual values you get. It best to work with the raw numbers for the calculations, internally any number can mean 50% or 8ms or whatever. It's only when the result must be presented to a human that you need to convert it into "real" units like ms or percent or whatever.

/Henrik.

Acetronics2
- 9th September 2012, 18:27
Hi, Ed

may be , as you use PBP, you could remember about the maximum " pulsin " resolution that won't exceed 1µs @ 40 Mhz ...

so your numbers will be @ best 4947 and 9921 ... ;)

from that, DIV32 or use of LONGS looks to be the decent way to get enough significant decimals ...

Alain

Ramius
- 9th September 2012, 21:15
Thanks Guys!
For some reason my 13F1320 seems to have a problem so I can not see what the math is doing yet with an ICD compile. :mad: The MAX232 works fine until I connect it to pin 9, the TX and then it stops talking! As for measuring I am using one of the greatest devices ever produced, The Saleae Logic Analyzer! I can see all the Memsic 2125 values change with temperature so I do not have 1 or more "fixed" values to use. The "duty cycle" value seems affect the accuracy more than the pulse widths. The duty cycle value varies from 498 to 504 which then gets worse when using the look up tables! Just a couple of degrees of room temperature change seems to make a big difference.

Ramius
- 9th September 2012, 21:30
Okay so I found another 18F1320 and it does not communicate either!
Did I miss something in the code?
It may be time for new glasses! :D

6661

HenrikOlsson
- 10th September 2012, 06:13
Hi Ed,
Is that all the code? I don't see a Goto Read_Force anywhere so it would run once and then weird things might occur, like stop communicating with the software ICD perhaps.

/Henrik.

Ramius
- 12th September 2012, 01:57
Okay so I have to be doing something fundamentally stupid! Just not sure what? Any ideas?


DEFINE OSC 20 'Define crystal frequency

Include "Modedefs.bas"
include "hpwm10L.pbp"
Enable Debug

#CONFIG
__CONFIG _CONFIG1H, _HS_OSC_1H & _FSCM_OFF_1H
__CONFIG _CONFIG2H, _WDT_OFF_2H & _WDTPS_8K_2H
__CONFIG _CONFIG2L, _PWRT_ON_2L & _BOR_OFF_2L & _BORV_27_2L
__CONFIG _CONFIG3H, _MCLRE_OFF_3H
__CONFIG _CONFIG4L, _DEBUG_OFF_4L & _LVP_ON_4L & _STVR_ON_4L
__CONFIG _CONFIG5L, _CP0_OFF_5L & _CP1_OFF_5L
__CONFIG _CONFIG5H, _CPB_OFF_5H & _CPD_OFF_5H
__CONFIG _CONFIG6L, _WRT0_OFF_6L & _WRT1_OFF_6L
__CONFIG _CONFIG6H, _WRTC_OFF_6H & _WRTB_OFF_6H & _WRTD_OFF_6H
__CONFIG _CONFIG7L, _EBTR0_OFF_7L & _EBTR1_OFF_7L
__CONFIG _CONFIG7H, _EBTRB_OFF_7H
#ENDCONFIG


'********************* Declaired Pins **************************

INPUT PortB.2 ' X Data is clocked on rising edge of this pin


' ** Variables **

PxRaw VAR Long ' Low part of Pulse from Memsic 2125
WxRaw var Long ' High part of Pluse from Memsic 2125
WxTRaw var long ' Total of High and low Pluse from Memsic 2125
Dcycle var Long ' Duty cycle
xGForce VAR Word ' x axis g force (1000ths)
xTilt VAR Word ' x axis tilt (100ths)
xidx VAR byte ' Table index
xmult VAR Word ' Multiplier - whole part
xfrac VAR Word ' Multiplier - fractional part
xPosNeg var byte ' ositive angle or Negative angle flag

ADCON1 = 255 ' Make everything digital (no analog)

TRISB.2 = 1 ' Make B.2 an input

Read_Force:

PULSIN PORTB.2, 1, WxRaw
PULSIN PORTB.2, 0, PxRaw

WxRaw = WxRaw * 20 ' The high part of the pulse
PxRaw = PxRaw * 20 ' The low part of the pluse

WxTRaw = wxraw + pxraw ' The total time of the pluses

Dcycle = (Pxraw * 10000) / WxTRaw

xGForce = (((WxRaw * 10000)/ WxTRaw) - Dcycle) * 8 'xGForce = ((t1 / t2) - duty) / 12.5%


Read_Tiltx: 'tilt = g x k Select tilt conversion factor based on static G force. Table data derived from Memsic specs.

LOOKDOWN2 ABS xGForce, <=[174, 344, 508, 661, 2000], xidx ' Table is in thousandths g results for 10,20,30,40 and max value degrees
LOOKUP xidx, [57, 58, 59, 60, 62], xmult 'integer lookup
LOOKUP2 xidx, [32768, 10486, 2621, 30802, 22938], xfrac 'gets fractional result
xTilt = xmult * (ABS xGForce / 10) + (xfrac ** (ABS xGForce / 10))

Check_SignX: 'Check the sign of X angle
IF (xGForce.Bit15 = 0) THEN XT_Exit ' if positive, skip correct for g force sign
xPosNeg = 0 ' If xPosNeg = 0 then the angle is negative (-)

XT_Exit:
xPosneg = 1 ' If xPosNeg = 1 then the angle is positive (+)


gosub Read_Force

HenrikOlsson
- 12th September 2012, 06:05
Okay so I have to be doing something fundamentally stupid! Just not sure what? Any ideas?
Yes, you're using GOSUB instead of GOTO.
GOSUB is used to jump to a subroutine which "ends" with a RETURN - that's not what you have.

/Henrik.

Ramius
- 12th September 2012, 12:32
Thanks, easy to fix. I still can not get the math to come out right!

HenrikOlsson
- 15th September 2012, 15:14
Hi Ed,

(I'm answering your PM here since it related to this thread.)

Lets see if we can get the numbers straight on paper as a first step, then we'll move on to PBP.

According to the datasheet for the MXD2125 accelerometer (is that the one you're using). The formula is g=(T1/T2-0.5)/12.5%

The dutycycle of the output signal is 50% at 0g, that's where the subtraction of 0.5 comes from.
12.5% is the sensitivity of the device, it varies the dutycycle of the output signal 12.5% per g.

At +1g the dutycycle is 50+12.5=62.5%, the numbers becomes (0.625-0.5)/12.5% = 1g
At -1g the dutycycle is 50-12.5=37.5%, the numbers becomes (0.375-0.5)/12.5% = -1g

12.5% is the same as dividing by 12.5/100 which is the same as dividing by 0.125 which is the same as multiplying by 8.

According to the datasheet the acceleration at 30° is 0.5g which corresponds to a dutycycle 56.25% (50% is zero g, the output swings 12.5% per g so 50+6.25), lets run those numbers on paper:
(0.5625-0.5) * 8 = 0.5g

It all seems to work out on paper - wohoo!

What to do in PBP (before continuing I must point out that I haven't actaully tested this, hopefully I haven't messed it up too badly....):
I see from your posts that you're now using LONGS which makes it a bit easier. Let's try with your 0° numbers first.
Obviously we cant just do 4927/9867 (the numbers you gave for 0°) because that will result in a number less than 0 which is not of any use to us. What we can do though is to multiply the T1 time by say 10000.


T1 VAR WORD
T2 VAR WORD
Duty VAR LONG
g VAR LONG

' Number for 0°
T1 = 4927
T2 = 9867

Duty = (T1 * 10000) / T2 ' Duty will now be 4993
g = (Duty - 5000) * 8 ' g will now be -56 which is equal to -0.0056

HSEROUT["Acceleration is: ", SDEC g/10, "mg",13]


Now, in your PM you said that at 30° your values are 4535/9578 but that only works out to a dutycycle change of about 2.65% when you really should be getting around 6.25%. However you also say that the result of 4535/9578 is 0.4491 which isn't the case so something seems to be wrong with your numbers there.

But lets for the cause of the exercise use some the theoretical numbers corresponding to 30°, 0.5g, 56.25% dutycycle

T1 = 5625
T2 = 10000

Duty = (T1 * 10000) / T2 'Duty will now be 5625 (56.25%)
g = (Duty - 5000) * 8 ' G will now be 5000 which is equal to 0.5G

HSEROUT["Acceleration is: ", SDEC g/10, "mg",13] ' should print 500mg


That's the acceleration part, when that works I suspect you want to convert the acceleration value into an actual angle....

/Henrik.

Ramius
- 16th September 2012, 13:28
Hi Henrik!
Thank you and I finally got that the duty cycle is a "fixed" number assumed to be at 50%. According to the information about the device, each device can have a zero duty cycle of from 48.7% to 51.3%. My experience has been that at a room temperature of about 72 degrees F, my device has a measured duty cycle of 49.93%. However as the room temperature increase or decrease so does the zero point duty cycle! So if the submarine is sitting on a table at the park with an air temperature of 72 degrees F then 4993 works. Put the sub in water where the water temperature is 65 degrees F and 4993 is no longer valid. Originally the thinking was to measure and calculate the duty cycle however this method does not work as you first must be at an known zero degrees of tilt.

Best Wishes, Ed

6663

HenrikOlsson
- 16th September 2012, 14:09
Hi Ed,
Is the dutycycle at various temperatures repeatable? I mean, you say that 0° at 72F is 4993 and 0° at 65F it's xxxx, are those numbers repeatable from time to time or is 4993 one time and 5006 another?
If they are repeatable then all you need is a temperature sensor (which I suspect you have anyway) and a bit of more math....

Mount the tempsensor in very close proximity to the accelerometer, set the accelerometer exactly level and leave it there. Then, using a hairdryer or whatever measure and plot the dutycycle vs temperature over the range you expect to use it and see what comes out. If you're lucky you'll get a linear realationship between temp and dutycycle which is very easy to compensate for in software. If it's not a linear relationship that too can be compensated for - not as easily though.

If you're very amibitious repeat the test at 30° tilt and see if the relationship is the same.

/Henrik.

Ramius
- 28th September 2012, 01:33
Hi Henrik!
Just an update, it turned out I had a bad sensor! Got a new one and it seems to work fine!