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 CCS Technical Support

round function for a double

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



Joined: 26 Feb 2008
Posts: 6

View user's profile Send private message

round function for a double
PostPosted: Tue Mar 18, 2008 1:26 pm     Reply with quote

Hi there,

I am building a programmable power supply and I use an 8 bit output to drive an R2R ladder circuit, then I use a voltage amplifier to amplify by a factor of 6 because I want a maximum output of 30V.
Then trough a potential divider I read the output voltage and feed it to a 10 bit analogue input on the PIC 18f4550.
Everything works fine except that the display is not very stable.
Every time I increment the 8 bit counter the display increment by 20mV and I get funny output voltages.
I would like to increment the 8 bit counter in step of 100mV and the output voltage to be the some displaying steps of 100mV.
Anything between 100 I want to round to 0 if is less than 50 and round to 1 if it more than 51.
I try to use the round function in CCS C but there is not one.
I only found the floor and ceil function which is not good to me.
I do not understand why CCS does not support round function it is a standard C function
Please have a look at the relevant code:
Any help will be very much appreciated as I am at the desperation point.
At the end I will write my own round function and post it for every one to use it but I am hopping to save a bit of time.


CCS C compiler 4.038 in MPLAB


Code:
#include <18F4550.h>
#device adc=10
//#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NOPBADEN,NOVREGEN
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=20000000)
#use  standard_io(A)


#include <lcd(8).c>
#include <kbdd.c>
#include <math.h>
#include <keyboard.c>
#include <check.c>
#include <usb_cdc.h>

//code part of the main.c



#define AN0_TO_AN2   0x0C

set_adc_channel(0);
delay_ms(30);
adc_value = read_adc();
temp = (float)(adc_value * 5)/1023.0;
volts = (float)(temp * 6);
lcd_gotoxy(2,1);
printf(lcd_putc, "%3.2fV ", volts);


//code part of the keyboard.c
Code:
float iset;
int8 VCOUNT;
int8 icount; 

void voltage(){

//Voltage +
if(!input(PIN_C0)  )
  {
   if(vcount<255) vcount = vcount + 1;
     OUTPUT_D(vCOUNT);
  }
     
//Voltage -
   
if( !input(PIN_C1)  )
 {
   if (vcount>0) vCOUNT =  vCOUNT - 1 ;
      OUTPUT_D(vCOUNT);
  }
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Mar 18, 2008 2:22 pm     Reply with quote

Your program is missing some of the adc setup functions.
Post a small but complete test program that shows the required functions
and that demonstrates the problem. Example:
http://www.ccsinfo.com/forum/viewtopic.php?t=32168

The program that you post should be small, but also it must be
compilable without errors. Don't put #include files in it that
are not needed to show the problem.
Guest








round double
PostPosted: Tue Mar 18, 2008 3:06 pm     Reply with quote

Hi PCM Programmer,

You are a much respected member of this forum and I think of you very highly, I do appreciate helping beginners like me.
This is my all main function without the include:
I want to control the PPS through usb using the usb_cdc.h driver.

Code:

#include <18F4550.h>
#device adc=10
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=20000000)

#include <lcd(8).c>
#include <math.h>
#include <keyboard.c>

#define AN0_TO_AN2   0x0C

void main()
{
int16 adc_value;

float volts;   
float temp;
float current;
char string[7];

int1 sby; //true when system is not running
setup_adc(ADC_CLOCK_DIV_8);
lcd_init();
lcd_gotoxy(0,1);
printf(lcd_putc, "\Initializing .    ");
delay_ms(1500);
lcd_gotoxy(0,1);
printf(lcd_putc, "\Initializing ..   ");
delay_ms(1500);
lcd_gotoxy(0,1);
printf(lcd_putc, "\Initializing ...  ");
delay_ms(1500);
lcd_gotoxy(0,1);
printf(lcd_putc, "\fInit...OK");
delay_ms(3000);
printf(lcd_putc, "\f");
delay_ms(1000);
//Initialise
vCOUNT = 76 ;      //Initialise vCOUNT
icount = 7 ;       //Initialise COUNT
OUTPUT_D(0x00);      //Clear Port D
output_bit( PIN_E0, 0);
output_bit( PIN_E1, 1);
sby = 0; //System is normal
while(1)
  {
      set_adc_channel(0);
      delay_ms(30);
      adc_value = read_adc();
      temp = (float)(adc_value * 5)/1023.0;
      volts = (float)(temp * 6);
      lcd_gotoxy(2,1);
      printf(lcd_putc, "%3.2fV ", volts);
   }
     
      delay_ms(250);
      set_adc_channel(1);
      delay_ms(30);
      adc_value = read_adc();
 
      current = (float)(adc_value * 5)/1023.0;
      lcd_gotoxy(11,1);
      printf(lcd_putc, "%3.2fA", current);
      if (usb_cdc_kbhit())
        {
        }
      output_low(pin_E0);
      delay_ms(250);
      voltage();
     }         
 
}


this is the keyboard.c
Code:

int8 VCOUNT;
void voltage(){

//Voltage +
if(!input(PIN_C0)  )
  {
    if(vcount<255) vcount = vcount + 1;
      OUTPUT_D(vCOUNT);
  }
     
//Voltage -
if( !input(PIN_C1)  )
  {
    if (vcount>0) vCOUNT =  vCOUNT - 1 ;
      OUTPUT_D(vCOUNT);
  }
}

If you should require the lcd(8).c please let me know

I will post it a.s.a.p

Thanks for you trying to help me.

Best regards
marken
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Mar 18, 2008 3:38 pm     Reply with quote

Quote:
#use delay(clock=20000000)

setup_adc(ADC_CLOCK_DIV_8);


Look at this table in the A/D section of the 18F4550 data sheet. It shows
that you should use a divisor of 16 (not 8) for a 20 MHz oscillator.
Code:

TABLE 21-1: TAD vs. DEVICE OPERATING FREQUENCIES

Divisor    Max Frequency
8 TOSC     11.43 MHz
16 TOSC    22.86 MHz


Change it to this:
Code:
setup_adc(ADC_CLOCK_DIV_16);
Guest








PostPosted: Tue Mar 18, 2008 4:15 pm     Reply with quote

Hi there,

I have change the settings to the adc divisor 16.
It makes no difference to my display.
Any other suggestions about the round function ?

Regards
Marken
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Mar 18, 2008 4:22 pm     Reply with quote

One thing I want to check: What is your crystal frequency ?
Guest








PostPosted: Tue Mar 18, 2008 4:31 pm     Reply with quote

Hi PCM,
It is a crystal at 20Mhz.

Regards

Marken
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Mar 18, 2008 5:00 pm     Reply with quote

Quote:
#include <18F4550.h>
#device adc=10
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=20000000)

It is a crystal at 20Mhz.

Your PIC is really running at 48 MHz.


If I take the following test program and use your #fuses settings, and
change the #use delay() statement to 48 MHz, the LED on pin B0 blinks
at a 1 second interval when timed with a stop watch.
Code:
#include <18F4550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)

//===============================
void main()
{

while(1)
  {
   output_high(PIN_B0);
   delay_ms(100);
   output_low(PIN_B0);
   delay_ms(900);
  }

}


You need to change the A/D divisor to 64 now, so it will work with
a 48 MHz oscillator frequency. This could be the source of most
of your A/D problems. Also change the #use delay() statement
to 48 MHz as shown above. Example:
Code:
#use delay(clock=48000000)

and
Code:
setup_adc(ADC_CLOCK_DIV_64);
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Tue Mar 18, 2008 5:44 pm     Reply with quote

Quote:
I do not understand why CCS does not support round function it is a standard C function
Round is a relative new C function, it was not available in the ISO C89 standard. Reason for this might be that round is not so universal as you think it is, for example: how to handle rounding in negative numbers? What to do if the rounded value goes outside the range of the return type? That's why C99 defines multiple new rounding functions besides ceil and floor: trunc, round, nearbyint / rint and lrint.
It would be nice for CCS to add these functions (send them an email) but it's easy enough to roll them yourself.

Quote:
Then trough a potential divider I read the output voltage and feed it to a 10 bit analogue input on the PIC 18f4550.
What are the resistor values in your voltage divider? For a reliable reading the impedance as seen by the PIC must be relative low, check the datasheet.
Ttelmah
Guest







PostPosted: Wed Mar 19, 2008 8:55 am     Reply with quote

Yes.
Ckielstra's comment here, is very much a likely start to the problems. Once the code is working (timing the ADC right, which otherwise could be part of the problem), when dealing with a voltage like this, there are likely to be a number of difficulties. First, the DAC itself, is likely to exhibit some lag, or overshoot (or even both), on the output voltage generated. Then the voltage fed back to the PIC, from the output, will take time to respond (depending on the capacitance, and resistances present in the potential divider). To design a DAC/ADC combination, with gives fast response, without oversoot, is quite a complex task....
Look at the Microchip application notes. Select 'signal conditioning and measurement', then ADC.
Though a lot of the notes are for older chips (like the 16C71), the details a the same for all the Microchip converters. You may find out why you might want to use 1024, rather than 1023 as the divider for Microchip ADC's - the most accurate conversion, is actually:

float_val = ((read_adc()*2)+1)/2048;

Best Wishes
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