|
|
View previous topic :: View next topic |
Author |
Message |
Guest
|
int32 comparison |
Posted: Tue Mar 13, 2007 1:31 pm |
|
|
Quick question. I want to compare to int32's, but I have to scale one of the ADC readings a second time in order to compare apples and apples. How can I make it so the int32 current will end up as an int32 rather than a float or whatever it will be cast as in my line of code?
Code: | int32 compare_with_user(int32 duty_cycle) {
int16 current;
int16 user;
int32 scale = 100;
int32 compare;
current=(read_adc()*scale)/1024; //note, adc_channel should already be set to 0 from check_current method!
current = 3.125*(current - 50); //this is the line I'm sure will bring me problems...
set_adc_channel( 1 );
//delay_us( 10 ); //10uS delay is necessary for proper ADC reading.
user=(read_adc()*scale)/1024;
if (compare > 0) {
if (duty_cycle < 100) {
duty_cycle = duty_cycle + 1;
}
}
if (compare < 0) {
if (duty cycle > 0) {
duty_cycle = duty_cycle - 1;
}
}
set_pwm1_duty(duty_cycle);
/* This sets the time the pulse is high each cycle.
The high time will be:
if value is LONG INT: value*(1/clock)*t2div
if value is INT: value*4*(1/clock)*t2div
for example a value of 30 and t2div of 1 the high time 12uS
A value too high or too low will prevent the output from changing.
*/
return duty_cycle;
} |
|
|
|
Ttelmah Guest
|
|
Posted: Tue Mar 13, 2007 1:52 pm |
|
|
The line, won't cause a problem.
What will happen, is that 'current-50' will be evaluated using int16 maths, then this will be converted to a float, and multiplied by 3.125. The floating point result, will then be converted back to an int16, and stored in 'current'.
Best Wishes |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Mar 13, 2007 1:53 pm |
|
|
Any time you have doubts about what the output will be, just make
a little test program. I do this all the time. In your case, you have
doubts about what number will be placed into 'current' when your
scaling equation is evaluated. Look at the following program.
It evaluates the equation and displays the results. If you use
MPLAB, as I do, then you can run it in the simulator and display
the output from printf() in the Output window. There's a feature
in the MPLAB simulator called "Uart1", which takes output sent the
hardware UART and displays it in the Output window. You don't
even have to touch hardware to test your program.
Code: |
#include <16F877.H>
#fuses XT, NOWDT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
//=======================================
void main()
{
int16 current;
current = 150;
current = 3.125 * (current - 50);
printf("current = %lu", current);
while(1);
} |
You have a few other worrisome problems in your program.
1. You're using the 'compare' variable, but it's never initialized.
2. You have a comment in there that the A/D channel is set
in some other routine. This is very unsafe programming practice.
What if you cut out or modify that other routine at some future date ?
Then your A/D setup for this routine is trashed. You should put
the code to select the channel in that routine.
3. You have commented out the setup delay for the A/D (10 usec).
That delay is necessary. Also, look at the data sheet and verify
that the minimum delay is actually 10 us. The data sheet will have
a section where they crank through a series of calculations and come
up with a typical minimum delay. Look at that section.
4. As Ttelmah says, what if the A/D reads a value less than 50 ? |
|
|
Guest
|
|
Posted: Tue Mar 13, 2007 2:25 pm |
|
|
I believe this clears up the problems
Code: | int16 compare_with_user(int16 duty_cycle) {
int16 current;
int16 user;
int32 scale = 100;
set_adc_channel( 0 );
delay_us( 10 );
current=(read_adc()*scale)/1024;
if (current < 50) {
current = 0;
}
else {
current = 3.125*(current - 50); //this should be cast as an int16 when all is said and done
}
set_adc_channel( 1 );
delay_us( 10 );
user=(read_adc()*scale)/1024;
if (user > current) {
if (duty_cycle < 100) {
duty_cycle = duty_cycle + 1;
}
}
if (user < current) {
if (duty_cycle > 0) {
duty_cycle = duty_cycle - 1;
}
}
set_pwm1_duty(duty_cycle);
/* This sets the time the pulse is high each cycle.
The high time will be:
if value is LONG INT: value*(1/clock)*t2div
if value is INT: value*4*(1/clock)*t2div
for example a value of 30 and t2div of 1 the high time 12uS
A value too high or too low will prevent the output from changing.
*/
return duty_cycle;
} |
|
|
|
|
|
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
|