PDA

View Full Version : 12F683 Maths and code genius reqd.



retepsnikrep
- 19th September 2013, 02:42
Dear Members

I have an 8mhz 12F683 monitoring a 2khz pwm signal. I am using pulsin to determine the high time and at 8mhz I get 5us resolution or 100 units over a 2khz 500us pulse. That's all fine.

I also have two rail to rail pots being monitored by 8 bits adc's and then multiplied to give 0-100 units resolution.
Again that's fine.

I am also using the pic HPWM to duplicate the incoming pwm data stream multiplying the incoming puslin data to provide the 8 bit hpwm data reqd. That's fine.

What I am doing is modifying the incomming pwm data using the two pots and then sending the modified pwm out of the hpwm.
The issue is my maths and logic seems horribly complicated.

Lets take a pwm signal with a high time of 51-90% I want to modify that with one of the pots called AssistPot so that

The first pot called AssistPot is only reqd to work on signals with a duty of 51-90%
1) When the pot is at 50% (in the middle) then it has no effect on the signal.
2) When it is 51-100% I want it to lengthen the pwm high time by 0-100% upto a maximum of 90% duty.
3) When it is 49-0% I want it to shorten the pwm high time by 0-100% down to a minimum of 51% duty.


The second pot called RegenPot does something similar but is reqd to only works on signals with a duty of 49-10%
1) When the pot is at 50% (in the middle) then it has no effect on the signal.
2) When it is 51-100% I want it to shorten the pwm high time by 0-100% down to a minimum of 10% duty.
3) When it is 49-0% I want it to lengthen the pwm high time by 0-100% upto to a maximum of 49% duty.

Now my code below works but feels clunky and I had to add a couple of checks to stop the maths going negative.
I think there must be a more elegant solution. The RegenPot maths seemed much harder.
I have it working using the code below and proteus simulates correctly. It also works with my hardware.
So I'm really looking for improvements, coding tricks or other brilliant insight :?



pulsin CmdPwrIn,1,CmdPwrHigh 'Measures length of Incoming CmdPwr 2khz Pwm Duty High pulse

If CmdPwrHigh > 50 then 'Assist Requested Duty > 50%
PwrLevel = CmdPwrHigh - 50
High Led 'Turn On Red Assist Led
ADCIN 0,AssistPot 'Get AssistPot Setting
AssistPot = (AssistPot * 100) / 255
If AssistPot > 50 then
AssistPot = AssistPot - 50
Multiplier = 100 + ((AssistPot * 100) / (100 - AssistPot))
PwrLevel = 50 + ((Pwrlevel * Multiplier)/100)
elseIf AssistPot < 50 then
AssistPot = 50 - AssistPot
Multiplier = 100 + ((AssistPot * 100) / (100 - AssistPot))
PwrLevel = 50 + (PwrLevel-(((Pwrlevel * Multiplier)/100)-Pwrlevel))
elseif AssistPot = 50 then
AssistPot = 0
PwrLevel = CmdPwrHigh
endif
endif


If CmdPwrHigh < 50 then 'Regen Requested Duty < 50%
PwrLevel = 50 - CmdPwrHigh
low Led 'Turn On Green Regen Led
ADCIN 1,RegenPot 'Get RegenPot Setting
RegenPot = (RegenPot * 100) / 255
If RegenPot > 50 then
RegenPot = RegenPot - 50
Multiplier = 100 + ((RegenPot * 100) / (100 - RegenPot))
General16 = ((Pwrlevel * Multiplier)/100)
if General16 > 50 then General16 = 50 'Prevents Result Negative Overflow error
PwrLevel = 50 - General16
elseIf RegenPot < 50 then
RegenPot = 50 - RegenPot
Multiplier = 100 + ((RegenPot * 100) / (100 - RegenPot))
PwrLevel = 50 - (PwrLevel-(((Pwrlevel * Multiplier)/100)-PwrLevel))
elseif RegenPot = 50 then
RegenPot = 0
PwrLevel = CmdPwrHigh
endif
endif

If CmdPwrHigh = 50 then
TRISIO.4 = 1 'Turn Off Led
PwrLevel = 128
else
if Pwrlevel > 90 then PwrLevel = 90 'Prevent Assist request Error Duty > 90%
if PwrLevel < 10 then PwrLevel = 10 'Prevent Regen request Error Duty < 10%
PwrLevel = (PwrLevel * 255) / 100 'Calculate HPWM Duty 8 bit data
endif


Any Ideas?

HenrikOlsson
- 19th September 2013, 07:52
I'm neither a math or a code genius and I'm most certainly missing something but how about this (compiles but not tested):

Temp VAR BYTE
AssistPot VAR BYTE
RegenPot VAR BYTE
CmdPwrHigh VAR BYTE
PwrLevel VAR BYTE

CmdPwrIn VAR GPIO.0

' 50 counts for 50% dutycyle @2kHz input and 8MHz oscillator
PULSIN CmdPwrIn, 1, CmdPwrHigh

' Read inputs (8bit mode!) and convert values to +/-40 in two's complement.
ADCIN 0, Temp
AssistPot = (Temp ** 20480) - 40

ADCIN 1, Temp
RegenPot = (Temp ** 20480) - 40

'-------------------------------------------------------------------------------
IF CmdPwrHigh > 50 THEN ' Assist pot in play
PwrLevel = CmdPwrHigh + AssistPot ' No risk of overflowing a BYTE here
If PwrLevel > 90 THEN PwrLevel = 90 ' But we need to clamp at 90% for top end...
If PwrLevel < 51 THEN PwrLevel = 51 ' ...and at 51% for the bottom end.
ENDIF
'-------------------------------------------------------------------------------
If CmdPwrHigh < 50 THEN ' Regen pot in play
PwrLevel = CmdPwrHigh - RegenPot
If PwrLevel < 10 THEN PwrLevel = 10 ' Clamp at 10 for the low end
IF PwrLevel.7 THEN PwrLevel = 10 ' Clamp at 10% if we went negative
If PwrLevel > 49 THEN PwrLevel = 49 ' Clamp at 49% for the top end.
ENDIF
'-------------------------------------------------------------------------------

/Henrik.

retepsnikrep
- 19th September 2013, 11:51
I'm afraid that does not work at all as expected.
Also the increase or decrease should be a percentage of the pot level.
Thanks for the idea though.

retepsnikrep
- 19th September 2013, 18:56
Opps sorry Henrik my simulation was not set up correctly your version does seem to be working and is half the size.

Still looking for any other ideas.

Thanks Peter

retepsnikrep
- 31st December 2013, 14:40
How can I simulate/enter this formula in a spreadsheet?
I want to experiment with the values for the the calculation.
The special 2's complement maths is making my head explode.
Thanks

ADCIN 1, Temp 'Temp = a number between 0-255
RegenPot = (Temp ** 20480) - 40

HenrikOlsson
- 31st December 2013, 15:42
Hi,
Try something like:


=TRUNC((A4*20480/65536)-40)

Where A4 is the cell in which you put your TEMP value. Now, MS insists on changing the names of the functions depending on what language you're running but I think TRUNC is what you want, as long as you're running an English version of Excel - which I'm not.....here it's called AVKORTA....

This will give you a result of -39 when TEMP is 0 and 39 when TEMP is 255 and it truncates the result (instead of rounding it) just like it will when run on the PIC.

We could get it display as a real two's complement number but I'll have to dwell on that for a moment - if needed. In the meantime:
253 = -3
254 = -2
255 = -1
0 = 0
1 = 1
2 = 2
3 = 3

And so on.....

/Henrik.

retepsnikrep
- 1st January 2014, 08:17
How can i modify the formula to get +/- 20 or +/- 10

AssistPot = (AssistPot ** 20480) - 40
RegenPot = (RegenPot ** 20480) - 40

HenrikOlsson
- 1st January 2014, 08:44
Hi,
+/- 20: Change 20480 to 10240 (1/2 of 20480) and subtract 20 instead of 40.
+/- 10: Change 20480 to 5120 (1/4 of 20480) and subtract 10 instead of 40.

Just think of the ** operator as multiplying by units of 1/65536.

/Henrik.