CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Mixing Int8 and float in CCS C math

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
rovtech



Joined: 24 Sep 2006
Posts: 262

View user's profile Send private message AIM Address

Mixing Int8 and float in CCS C math
PostPosted: Wed Mar 15, 2023 3:52 pm     Reply with quote

Doing math in CCS C
Y = mX + B
where Y and X are 8 bit integers (max 255), B is a constant 35, and m is a fraction 0.374
X and B get promoted in the expression to float for the evaluation, and the result is demoted by assignment to integer in Y. X remains int8 after the expression is evaluated.
Since mX + B can never exceed 255 then Y, X, and B can all be int8.
Am I correct? I don't want to have to test this on a PIC with a display.
Can I write the expression so B does not get promoted to float?
temtronic



Joined: 01 Jul 2010
Posts: 9081
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Mar 15, 2023 4:30 pm     Reply with quote

hmm, my first idea is to just code using 'scaled integers'.....

m becomes 374 instead of .374. Y,X and B have to be scaled as well....

this eliminates floats AND decreases the 'time of calculation by 10-15x.
,it'll also reduce code space a LOT as well.

others will reply that do this daily.
PICs don't play well with 'floats'.

Jay
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

Re: Mixing Int8 and float in CCS C math
PostPosted: Wed Mar 15, 2023 5:15 pm     Reply with quote

rovtech wrote:

I don't want to have to test this on a PIC with a display.

Since it's pure math, you can easily test it with MPLAB vs. 8.92 and the
built-in simulator.

Links to download MPLAB vs. 8.92 and the CCS plugin, if you don't have
them already:
http://www.ccsinfo.com/forum/viewtopic.php?t=59016&start=2

See this link for how to use the UART1 feature of MPLAB vs. 8.92 to display
printf statements in the Output window:
http://www.ccsinfo.com/forum/viewtopic.php?t=40045

You don't need hardware or a display. You can do it all in MPLAB vs. 8.92.
rovtech



Joined: 24 Sep 2006
Posts: 262

View user's profile Send private message AIM Address

PostPosted: Wed Mar 15, 2023 6:18 pm     Reply with quote

Thank you, I use MPLAB 8.92
I read the link but see a problem. My clock is 32kHz so this may not work.
I wasn't looking for another project but appreciate learning about it and will try it when I have time.
For now I like Y = (374 * X)/1000 +35 and can try it but that product can be as high as 95,370 (374 * 255) so can X still be Int8?
I thought there may be a way using casting to do this.

What about what I originally asked? Are my assumptions correct?
Since the PIC16F1509 is dedicated to running 4 PWM at 50 Hz it has lots of memory and time. It gets an I2C update about once a second.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Mar 15, 2023 8:20 pm     Reply with quote

0.374 x 255 = 95.37 and then add 35 to that and you get 130.7.
So yes, as long as m is always 0.374 and B is 35, you can use int8
variables for X, Y, and B.
Code:
#include <18F46K22.h>
#fuses NOWDT 
#use delay(internal=4M)
#use rs232(UART1, baud=9600, ERRORS)

#define m  0.374

//=================================
void main (void)
{
int8 Y;
int8 X;
int8 B;

B = 35;

X = 255;

Y = (m * X) + B;

printf("Y=%u\r", Y);

while(TRUE);
}

Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Thu Mar 16, 2023 4:53 am     Reply with quote

and, in answer to:

"Can I write the expression so B does not get promoted to float?".
Yes:

Y = (int8)(m*X) + B;

Will evaluate m*x as float, then convert this to int8, and add the result to
B. So with the example of X=255, you get:

255*.374 = 95.37 -> gives 95 as an int.
95+35 = 130.

However it is also worth realising that the error between 0.374 and 0.375
is less than one in this. So you could use:

Code:

int8 t;

t=X/4;

Y=t+t/2 + B;


Which for the example of 255, gives t=63, then Y = 63+31+35 = 129

Almost the same answer, for the cost of two integer divisions, and two
additions.
Smaller and faster than getting float involved at all....
rovtech



Joined: 24 Sep 2006
Posts: 262

View user's profile Send private message AIM Address

PostPosted: Thu Mar 16, 2023 9:17 am     Reply with quote

Thank you all, these are exactly the ideas I was hoping for but easier than I anticipated.
The problem of slow clock I am using got me re-thinking where to do the math. Briefly, my submersible ROV has a slave PIC in the surface control console that reads switches, pots, and a Joystick. It passes the results to the Master PIC that sends, down 300ft of tether, to a Master PIC in the ROV which sends to various slaves including one that controls the servos. The climb/dive byte from the Joystick is X in the equation but also goes to my side thruster rotate control PIC that uses a motor and feedback pot so I cannot change X in the console. I could do the math in the ROV master PIC before it passes the data to the slave servo PIC. I don't want to mess with the Master PIC and slow it down. Just thinking aloud.
The math changes 0 to 5v from the Joystick to be 800 to 1800 uS pulses out of the PWM of the PIC at 50 Hz. Either variable is Int8 so it does not matter where the math is done except for speed and efficiency. It might be simpler to send an extra separate byte from the surface.
I will try PCM Programmers suggestion of using the UART1 feature of MPLAB in my Console slave PIC to confirm the math. It will be a very useful debug tool for me.
Updating from using delays to PWM is turning out to be unpleasant. However adding 2 more servos to rotate the camera and a sonar transducer dictate the change.

I also see that .375 = 3/8 so I can use
Y = ((3/8) * X) + B which Ttelmah used, but why that way?
Using X/4 in place of t in your equation gives Y=X/4 + (X/4)(1/2) + B
So 2X/8 + X/8 = 3/8 X why not use this?

However the m is the slope of a line and can easily be different for different ranges of servo travel. I must use float. I like Ttelmah's
Y = (int8)(m*X) + B;
I wonder if my 32kHz PIC can handle this. This would be the easiest solution.


Last edited by rovtech on Thu Mar 16, 2023 10:54 am; edited 1 time in total
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Thu Mar 16, 2023 10:20 am     Reply with quote

Key is that if you do *3, this has to use the generic integer multiply.
Now /2, /4 & /8 in integer can all be optimised to a simple rotation.
So generating /4 and /2 each only use a couple of instructions. 3/8,
will use tens of instructions.
You could optimise it as X+=(X*2), then X/=8, which would be quite
efficient.
rovtech



Joined: 24 Sep 2006
Posts: 262

View user's profile Send private message AIM Address

PostPosted: Fri Mar 17, 2023 6:31 pm     Reply with quote

To get a PWM frequency of 50 Hz compatible with RC servos I had to use 31.25 kHz and a PR2 of 156. I measured the time for a loop of While (1) without the math, with the math, and with the math and cast as Ttelmah described. Slope m wound up at 0.14 so the exercise was well worth the effort.
Since 31.25 KHz froze my I2C communications I used 2 MHz and setup_timer_2(T2_DIV_BY_64,156,1) to retain the PRW 50 Hz and measured the times again.

31.25 kHz
No math = 3.6 mS
mX+B = 133 mS
Int8)(mX)+b = 110 mS

2 MHz
No math = 16 uS
mX+B = 1.7 mS
Int8)(mX)+b = 1.6 mS

My Rudder, Elevator, and Camera Tilt are working beautifully.
Thanks for the help.
Peter
alan



Joined: 12 Nov 2012
Posts: 349
Location: South Africa

View user's profile Send private message

PostPosted: Sat Mar 18, 2023 2:31 am     Reply with quote

Just my 2c worth. Been using Horner method very sucessfully in floating point multiplication and division and works like a dream.

See TI app note
Quote:
slaa329

https://www.ti.com/lit/pdf/slaa329
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group