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

Printf not printing floating point numbers correctly.
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
CCS newby



Joined: 27 May 2011
Posts: 5

View user's profile Send private message

Printf not printing floating point numbers correctly.
PostPosted: Fri May 27, 2011 7:54 am     Reply with quote

I am using printf in a function off main to printf a floating point variable. This does not work work correctly and always prints the variable as 0.00. If I insert a line into the main function to printf a floating point variable this then works and also makes the printf in the other function work correctly. Any ideas what the problem is? Is this a compiler bug?
temtronic



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

View user's profile Send private message

PostPosted: Fri May 27, 2011 8:50 am     Reply with quote

Sounds like you have a 'local' variable in the printf function and not a 'global' one.

We'd need to see your code to be sure.

You could look at any of the examples that CCS supplies in the 'examples' folder to see how it can be done....
CCS newby



Joined: 27 May 2011
Posts: 5

View user's profile Send private message

PostPosted: Wed Jun 01, 2011 3:47 am     Reply with quote

Thanks for the repsonse.
I am using this line in a function to print a value:
printf("tempf= %f",tempf);
The variable is defined in the function thus: float tempf;
This will not print the varaible correctly until I add a line such as this to the main function: printf("Hello %lf",1.0f);
A strange problem..!
SherpaDoug



Joined: 07 Sep 2003
Posts: 1640
Location: Cape Cod Mass USA

View user's profile Send private message

PostPosted: Wed Jun 01, 2011 5:35 am     Reply with quote

Send us a whole compilable program that shows the problem, preferably a very short one. Also tell us your compiler version.
_________________
The search for better is endless. Instead simply find very good and get the job done.
ERICOO



Joined: 13 Jun 2011
Posts: 14
Location: NIGERIA

View user's profile Send private message

PRINTF NOT PRINTING FLOATING POINT NUMBERS CORRECTLY
PostPosted: Tue Jun 28, 2011 4:52 am     Reply with quote

According to temtronic it would be best if you send your code.
however you be sure that all variables you using for your formular are globally declared as float or if you are simply wanting to display an integer as float e.g you want display 12 as 12.00
first store 12 in a float type variable and display using the printf format. see below

float newby = 12.00 (instead of 12)
.
.
.
.
printf(lcd_putc "\f%2.2f", newby)
.
.
}
brock



Joined: 29 Jun 2011
Posts: 8

View user's profile Send private message

PRINTF NOT PRINTING FLOATING POINT NUMBERS CORRECTLY
PostPosted: Wed Jun 29, 2011 9:20 am     Reply with quote

All,

I am having the exact issue that CCS newby is having except that putting a print in main doesn't get me out of it, but insertion of a print in another function does.

I even tried the following:
Code:

temp = adc_sample(i);
printf(" PV: ADC:  %f\r",temp);
printf(" PV: ADC:  %f\r",5.27);
printf(" PV: ADC:  %f\r",temp);
temp = 1.234;
printf(" PV: ADC:  %f\r",temp);

and all printed 0.000.

When I inserted a printf elsewhere in the program, it works perfectly.

There is some sort of compiler bug, I think.

I'll submit the entire code post if requested.
CCS newby



Joined: 27 May 2011
Posts: 5

View user's profile Send private message

PostPosted: Wed Jun 29, 2011 9:33 am     Reply with quote

I also managed to get rid of the issue by putting more spaces before the %f in between the quotes on the relevant printfs.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jun 29, 2011 11:54 am     Reply with quote

Post your PIC, #fuses and compiler version.
brock



Joined: 29 Jun 2011
Posts: 8

View user's profile Send private message

PRINTF NOT PRINTING FLOATING POINT NUMBERS CORRECTLY
PostPosted: Wed Jun 29, 2011 1:42 pm     Reply with quote

#FUSES INTRC,NOWDT,PUT,MCLR,NOPROTECT,NOCPD,BROWNOUT,NOIESO,NOFCMEN,NOLVP

Compiler Version: 4.122
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jun 29, 2011 1:54 pm     Reply with quote

But what PIC are you using ? No one in this thread has ever stated
what PIC they are using.
brock



Joined: 29 Jun 2011
Posts: 8

View user's profile Send private message

PRINTF NOT PRINTING FLOATING POINT NUMBERS CORRECTLY
PostPosted: Wed Jun 29, 2011 2:50 pm     Reply with quote

Sorry - I am using a 16F887.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jun 29, 2011 3:10 pm     Reply with quote

I made a test program and it works fine. I ran it in MPLAB simulator
(MPLAB vs. 8.70) and compiled it with CCS compiler vs. 4.122.
Here's the result in the Output Window:
Quote:

PV: ADC: 5.67
PV: ADC: 5.27
PV: ADC: 5.67
PV: ADC: 1.23

I also ran it in hardware with a 16F887 on a PicDem2-Plus board and
got the same result. I only changed the '\r' at the end of each line
into "\n\r" so it would go to a newline in the TeraTerm window.

Here's the test program:
Code:

#include <16F887.H>
#FUSES INTRC,NOWDT,PUT,MCLR,NOPROTECT,NOCPD,BROWNOUT,NOIESO,NOFCMEN,NOLVP
#use delay(clock = 4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

float adc_sample(int8 ch)
{
return(5.678);
}


//======================================
void main()
{
int8 i;
float temp;

i = 0;

temp = adc_sample(i);
printf(" PV: ADC:  %f\r",temp);
printf(" PV: ADC:  %f\r",5.27);
printf(" PV: ADC:  %f\r",temp);
temp = 1.234;
printf(" PV: ADC:  %f\r",temp);

while(1);
}
brock



Joined: 29 Jun 2011
Posts: 8

View user's profile Send private message

PRINTF NOT PRINTING FLOATING POINT NUMBERS CORRECTLY
PostPosted: Wed Jun 29, 2011 3:52 pm     Reply with quote

i can make it work too...if I add another printf in a completely different routine.

Here's the complete code file. It should work as-is, but fail if the printf (search for CCSINFO) is commented out.
Code:

#include <16F887.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>

#FUSES INTRC,NOWDT,PUT,MCLR,NOPROTECT,NOCPD,BROWNOUT,NOIESO,NOFCMEN,NOLVP

// Setup Clock
#use delay(internal=8M)
// Setup the Serial Port to (9600,8,N,1)
#use rs232(baud=9600,BITS=8,PARITY=N,STOP=1,xmit=PIN_C6,rcv=PIN_C7,)

// Register Map      
#byte   porta   = 0x05
#byte   portb   = 0x06
#byte   portc   = 0x07
#byte   portd   = 0x08
#byte   porte   = 0x09
#byte    pir2   = 0x0d
#byte   sspbuf    = 0x13
#byte   sspcon   = 0x14
#byte   adresh   = 0x1e
#byte   adcon0   = 0x1f
#byte   trisa   = 0x85
#byte   trisb   = 0x86
#byte   trisc   = 0x87
#byte   trisd   = 0x88
#byte   pie1   = 0x8c
#byte   pie2   = 0x8d
#byte   sspcon2   = 0x91
#byte   sspstat   = 0x94
#byte   wpub   = 0x95
#byte   adresl   = 0x9e
#byte   adcon1   = 0x9f
#byte   cm2con0   = 0x108
#byte   eedat   = 0x10c
#byte   eeadr   = 0x10d
#byte   eedath   = 0x10e
#byte   eedatl   = 0x10f
#byte   anselh   = 0x189
#byte   eecon1   = 0x18c
#byte   eecon2   = 0x18d


#bit    C2OE     = 0x108.5   

#DEFINE   POT_STEPS               1024
#DEFINE   UPPER_CAL_LIMIT            POT_STEPS - 1
#DEFINE LOWER_CAL_LIMIT            0x0000   
#DEFINE NOP                     0x0000
#DEFINE WRITE_RDAC_REGISTER         0x0400      
#DEFINE   READ_RDAC_REGISTER         0x0800
#DEFINE   STORE_RDAC_SETTING_TO_TP0   0x0c00
#DEFINE   REFRESH_RDAC_FROM_LAST_TP   0x1000
#DEFINE   REFRESH_RDAC_FROM_SPEC_TP   0x1400
#DEFINE   READ_LAST_TP_ADDR_STORED   0x1800
#DEFINE   WRITE_CONTROL_REGISTER      0x1c00
#DEFINE   READ_CONTROL_REGISTER      0x2000
#DEFINE PLACE_DEVICE_IN_SHUTDOWN   0x2400

#DEFINE POT_AVERAGING_COUNT         20
#DEFINE POT_SETTLE_TIME_MS         2
#DEFINE   POT_COUNT               1
#DEFINE POT_PARAMETERS            3   
#DEFINE TOTAL_POT_PARAMETER_COUNT   POT_PARAMETERS*POT_COUNT

#DEFINE CAL_PRESENT_ADDRESS         0x0
#DEFINE   POT_CAL_TABLE_BASE_ADDRESS   0x1   
#DEFINE CAL_FLAG               0xf0


const  float nominal_rail_voltages[POT_COUNT] =
{
   0.9                              // Nominal Voltage Targets
};

float   pot_cal_table[TOTAL_POT_PARAMETER_COUNT];

void init_io()                        
{                                 
   adcon0  &= 0xfe;      
   trisb     = 0xff;         
   anselh    |= 0x01;         
   adcon0   |= 0x80;            
   adcon1    |= 0x90;         
   wpub    &= 0x00;         
   adcon0    |= 0x01;         
   trisc   &= 0xD7;            
   sspstat  = 0x80;            
   sspcon    = 0x22;         
   sspcon2    = 0x0;                     
   portd   |= 0x10;            
   trisd    = 0xef;            
}

float adc_sample(int target_pot)       
{
    int       i,adc_mask;
   float      v8,sum8;

   sum8 = 0;
   adcon0 &= 0xc3;          
   adc_mask = (target_pot + 1) * 32;      
        adcon0 |= adc_mask;                
   delay_ms(POT_SETTLE_TIME_MS);         
   for (i = 0; i < POT_AVERAGING_COUNT; i++)
   {
      adcon0 |= 0x02;            
      while (adcon0 & 0x02) {}         
      v8 = (float) (adresh * 256 + adresl + 2) * 4.096 / 1024;
      sum8 = sum8 + v8;                  }
   sum8 = sum8 / i;                  
   printf(" ADCS: %4.3f\r",sum8);  // CCSINFO:  IF I COMMENT THIS PRINT OUT, NO FLOATING POINT printf WORKs
   return sum8;                     
}

long set_pot(long write_val)
{

    int     write_valh, write_vall;
    int       return_valueh,return_valuel;
   long    return_value;

//   printf("Set Pot: WV:  %04Lx\r",write_val);
    write_valh = write_val >> 8;
    write_vall = write_val & 0x00ff;
   portd   &= 0xef;                  // Drop the CS
   sspbuf     = write_valh;               // Ship the data
   delay_us(100);                     // Manditory delay
   return_valueh = sspbuf;               // Clear the input buffer and save-off the return string.
   sspbuf     = write_vall;               // Ship the data
   delay_us(100);                     // Manditory delay
   portd   |= 0x10;                  // Raise CS
   return_valuel = sspbuf;               // Clear the input buffer and save-off the return string
   return_value = return_valueh * 256 + return_valuel;
   delay_ms(20);                     //  Make sure we have cleared everything out
   return return_value;
}

void increment_pot(long steps)
{
   long    return_value, new_set_value;
   
   return_value =  set_pot(READ_RDAC_REGISTER);
   return_value =  set_pot(READ_RDAC_REGISTER);
   new_set_value = return_value + steps;
   new_set_value |= 0x0400;                        // Set the write control bit
//   printf("RV: %04Lx, Steps: %04Lx, NV: %04Lx\r",return_value, steps, new_set_value);
   return_value =  set_pot(new_set_value);
}

void decrement_pot(long steps)
{
   long    return_value, new_set_value;
   
   return_value =  set_pot(READ_RDAC_REGISTER);
   return_value =  set_pot(READ_RDAC_REGISTER);
   new_set_value = return_value - steps;
   new_set_value |= 0x0400;                        // Set the write control bit
//   printf("Pot: RV: %04Lx, Steps: %04Lx, NV: %04Lx\r",return_value, steps, new_set_value);
   return_value =  set_pot(new_set_value);
}

void set_pot_to_voltage(int pot_address, float target_voltage)   // Routine sets a pot to a voltage
{
   float   actual_voltage;
   float   error_high, error_low;
   float   offset_voltage,cal_divisor;
   int      convergence_error;
   long   steps;

   actual_voltage = adc_sample(pot_address);
   if (target_voltage > actual_voltage)
   {
      offset_voltage = (target_voltage - actual_voltage);
      cal_divisor = ((pot_cal_table[pot_address] - pot_cal_table[pot_address + 1])/POT_STEPS);
      error_high = (float)(offset_voltage/cal_divisor);
      steps = (long) error_high;
      printf("Note: In > Actual, Steps:  0x%04lx    %Ld\r",steps,steps);

      increment_pot(steps);

      actual_voltage = adc_sample(pot_address);
      if(target_voltage > actual_voltage)
      {   
         while (target_voltage > actual_voltage)
         {
                increment_pot(1);
            actual_voltage = adc_sample(pot_address);
         }
         error_high = actual_voltage - target_voltage;
         decrement_pot(1);
         actual_voltage = adc_sample(pot_address);
         error_low = target_voltage - actual_voltage;
         if (error_high < error_low)
         {
            increment_pot(1);
         }
      }
      else if (target_voltage < actual_voltage)
      {
         while (target_voltage < actual_voltage)
         {
                decrement_pot(1);
            actual_voltage = adc_sample(pot_address);
         }
         error_low = target_voltage - actual_voltage;
         increment_pot(1);
         actual_voltage = adc_sample(pot_address);
         error_high = actual_voltage - target_voltage;
         if (error_low < error_high)
         {
            decrement_pot(1);
         }
      }
      else
      {
         convergence_error = 1;
      }
   }
   else if (target_voltage < actual_voltage)
   {
      offset_voltage = (actual_voltage - target_voltage);
      cal_divisor = ((pot_cal_table[pot_address] - pot_cal_table[pot_address + 1])/POT_STEPS);
      error_low = (float)(offset_voltage/cal_divisor);
      steps = (long) error_low;
      printf("Note: Actual > In, Steps:  0x%04lx    %Ld\r",steps,steps);

      decrement_pot(steps);

      actual_voltage = adc_sample(pot_address);
      if(target_voltage > actual_voltage)
      {   
         while (target_voltage > actual_voltage)
         {
                increment_pot(1);
            actual_voltage = adc_sample(pot_address);
         }
         error_high = actual_voltage - target_voltage;
         decrement_pot(1);
         actual_voltage = adc_sample(pot_address);
         error_low = target_voltage - actual_voltage;
         if (error_high < error_low)
         {
            increment_pot(1);
         }
      }
      else if (target_voltage < actual_voltage)
      {
         while (target_voltage < actual_voltage)
         {
                   decrement_pot(1);
                actual_voltage = adc_sample(pot_address);
         }
         error_low = target_voltage - actual_voltage;
         increment_pot(1);
         actual_voltage = adc_sample(pot_address);
         error_high = actual_voltage - target_voltage;
         if (error_low < error_high)
         {
            decrement_pot(1);
         }
      }
      else   
      {
         convergence_error = 1;
      }
   }
   if (convergence_error == 1)   
   {
      printf("ERROR!\r");
   }   
}


void init_pots()                  // Routine opens the POTs RDAC register for writing
{
   long   return_value;
   int   i;
   
//   printf("Init Pots\r");
//  Read the value of the control register - Command 8
   return_value =  set_pot(READ_CONTROL_REGISTER);
   return_value =  set_pot(READ_CONTROL_REGISTER);
   delay_ms(5);
//  Write the value of the control register - Command 7
   return_value =  set_pot(WRITE_CONTROL_REGISTER | 0x02);
   return_value =  set_pot(WRITE_CONTROL_REGISTER | 0x02);
   delay_ms(5);
//  Read the value of the control register - Command 8
   return_value =  set_pot(READ_CONTROL_REGISTER);
   return_value =  set_pot(READ_CONTROL_REGISTER);
//   printf("RV:  %04x\r",return_value);
   
   for (i=0; i< POT_COUNT; i++)         // Set All Pots to nominal
   {
      set_pot_to_voltage(i,nominal_rail_voltages[i]);
   }
   delay_ms(5);                     //  Make sure we have cleared everything out
}

void load_cal_data()
{
   int      int_array[4],i,j;
   float   *float_ptr;

//   printf("Load Cal Data:\r");
   for (j=0; j < TOTAL_POT_PARAMETER_COUNT; j++)
   {
      for(i = 0; i<4 ; i++)
      {
         int_array[i] = read_eeprom(POT_CAL_TABLE_BASE_ADDRESS+i+(4*j));
      }      
      float_ptr = int_array;
      pot_cal_table[j] = *float_ptr;
//      printf("LCD: Addr: %02x: Value %4.8f\r",j,pot_cal_table[j]);
   }
}

void clear_cal()
{
   printf("CC:\r");
   write_eeprom(CAL_PRESENT_ADDRESS, 0xAA);
   delay_ms(50);   
}

void write_cal_parameter(int eeprom_addr, int *ptr, int range)
{
   int   i,eeprom_data;

   for(i = 0; i< range ; i++)
   {
      eeprom_data = ptr[i];
//      printf("WCP: %02x  %02x, PIE2: %02x\r",eeprom_addr+i, eeprom_data, pie2);
      write_eeprom(eeprom_addr+i, eeprom_data);
      delay_ms(30);
   }
//   printf("EEPROM:  ");
//   for(i = 0; i<24 ; i++)
//   {
//      printf("%02x  ",read_eeprom(i));
//   }
//   printf("\r");      
}

void cal_pot()
{
   long   return_value;
   float   high_value, low_value, step_size;
   int      eeprom_data, i;
   int      *ptr;
   
//   printf("Cal Pot\r");
   eeprom_data = read_eeprom(CAL_PRESENT_ADDRESS);
   if (eeprom_data != CAL_FLAG)            // Read the EEPROM - if cal flag in addr 0, then blow this step off
   {
      for(i=0; i < POT_COUNT; i++)
      {
         printf("No Cal Data present.  Calibrating.\r");
         return_value = set_pot(WRITE_RDAC_REGISTER | UPPER_CAL_LIMIT);      
         delay_ms(10);
         high_value = adc_sample(i);
         return_value = set_pot(WRITE_RDAC_REGISTER | LOWER_CAL_LIMIT);      
         delay_ms(10);
         low_value = adc_sample(i);
         printf("Addr: 0x%02x: Cal High: %4.3f, Low: %4.3f\r",i,high_value,low_value);
         ptr = &high_value;
         write_cal_parameter(POT_CAL_TABLE_BASE_ADDRESS+(i*POT_PARAMETERS),ptr,4);
         ptr = &low_value;
         write_cal_parameter(POT_CAL_TABLE_BASE_ADDRESS+(i*POT_PARAMETERS)+4,ptr,4);
         write_eeprom(CAL_PRESENT_ADDRESS,CAL_FLAG);
         step_size = (high_value - low_value)/POT_STEPS;
         ptr = &step_size;
         write_cal_parameter(POT_CAL_TABLE_BASE_ADDRESS +(i*POT_PARAMETERS)+8,ptr,4);
         write_eeprom(CAL_PRESENT_ADDRESS,CAL_FLAG);
         
         delay_ms(30);
      }
   }
   load_cal_data();
}

void print_help()
{
   printf("\r\r\r\r\rSPI Test\r");
}

void print_volts()
{
   int      i;
   float temp;

   for (i=0; i  < POT_COUNT; i++)
   {
      temp = adc_sample(i);
      printf(" PV: ADC:  %f\r",temp);
      printf(" PV: ADC:  %f\r",5.27);
      printf(" PV: ADC:  %f\r",temp);
      temp = 1.234;
      printf(" PV: ADC:  %f\r",temp);
   }
}

struct char_input   // character input buffer
{
   char *characters[10];
   int8 len;
   int1 err;
} user_input;

// Character input routine with backspace editing
void get_string(int max)
{
   int len;
   char c;

   --max;
   len=0;
   do
   {
      c=getc();
        if(c==8)   // Backspace
      {
           if(len>0)
         {
                   len--;
                   putc(c);
                   putc(' ');
                   putc(c);
           }
        }
      else if ((c>=' ')&&(c<='~'))
             if(len<max)
         {
               user_input.characters[len++]=c;
               putc(c);
             }
      } while (c!=13);
      user_input.characters[len]=0;
      user_input.len = len;
}

float parse_input() {
   float   result_float;
   char   ptr[10];
   int      i;

   user_input.len = 0;         // Initialize the port variables prior to get_string call
   user_input.err = 0;
   get_string(10);            // Load the global string with command line stuff
   for (i=0;i<10;i++)         // Load the global buffer output locally - some weird compiler stuff otherwise.
   {
      ptr[i] = user_input.characters[i];
   }
   result_float = strtof(ptr,ptr + strlen(ptr));
   printf("\rReceived Float: %5.4f\r",result_float);
   return result_float;
}

void main()
{

   float   input_value;
   int      error;

reset:
   print_help();
   init_io();
   cal_pot();
    init_pots();
                                       // Set them all to mid-range
   while (1)
   {
      printf("> ");                     // Print the Prompt
      input_value = parse_input();
      printf("\rInput Value: %4.3f\r",input_value);
      
      error = 0;
      if ((input_value <= pot_cal_table[0]) && (input_value >= pot_cal_table[1]))
      {
         set_pot_to_voltage(0,input_value);
      }
      else if (input_value == 0)
      {
         clear_cal();
         goto reset;
      }
      else
      {
         printf("Input of range!\r");
      }      
      print_volts();
   }
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jun 29, 2011 4:52 pm     Reply with quote

This is too much code and it's too convoluted for me.
I did notice one thing. Here you've declared an array of pointers to chars
but you use it as an ordinary array of characters. You should remove the *.
Quote:

struct char_input // character input buffer
{
char *characters[10];
int8 len;
int1 err;
} user_input;


c=getc();
user_input.characters[len++]=c;
brock



Joined: 29 Jun 2011
Posts: 8

View user's profile Send private message

PRINTF NOT PRINTING FLOATING POINT NUMBERS CORRECTLY
PostPosted: Wed Jun 29, 2011 5:11 pm     Reply with quote

Did you build it and see if it does what I said it does?

I could strip it down, but then the issue probably will submerge.

The fact remains that with this code NO printf prints floats correctly. Comment out the line labeled CCSINFO and you should see it....

Not that it's relevant, but but the line input works...so I don't see how the usage could be off....
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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