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

Big numbers and the PIC16F
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
rovtech



Joined: 24 Sep 2006
Posts: 262

View user's profile Send private message AIM Address

Big numbers and the PIC16F
PostPosted: Sun Dec 10, 2017 1:42 pm     Reply with quote

I have some equations with int64 variables that are supposed to run on an Aduino. I need to run them on a PIC16F866.
A few simple tests on a PIC16F886 reveals that it is easy to overflow and get garbage with no warnings.

Code:
float32 SENS;
SENS = 123456789;


results in displaying SENS = -5392220.13

Code:
SENS = 12345678;


displays as 12345678.08

Code:
SENS = 1.23456789E6;


displays as 1234567.92

Code:
SENS = 1.23456789E7;


displays as 12345679.36

Code:
SENS = 1.23456789E8;


displays as -5392220.13

where did I see that before (above)
So the following gives garbage, unlike my HP48 calculator that gives the correct answer.

Code:
float32 SENS;    // or just float SENS;
dT=6.8261E4;
C1=3.4857E4;
C3=2.0538E4;
    SENS = (C1*3.2768E4) + ((C3*dT)/256);


What am I doing wrong and what should I do?
Why does the compiler not complain or warn?
The big numbers are coming from a sensor via I2c and the original code uses in64 for several variables.
Switching to a 24bit PIC was suggested but the compiler is $400 which is a bit much to solve one problem.
I would think the compiler would round off the numbers to maximum digits and get the correct answer.
Any other suggestions?
Ttelmah



Joined: 11 Mar 2010
Posts: 19540

View user's profile Send private message

PostPosted: Sun Dec 10, 2017 1:54 pm     Reply with quote

Quote:


I have some equations with int64 variables that are supposed to run on an Aduino. I need to run them on a PIC16F866.
A few simple tests on a PIC16F886 reveals that it is easy to overflow and get garbage with no warnings.

Code:
float32 SENS;
SENS = 123456789;


results in displaying SENS = -5392220.13


How are you seeing this 'result'.
What is your compiler version?.

The maths doesn't overflow like this. What it does do is give the small errors like you have in your next part. However all FP systems do give these to some extent. There are numbers (1/3 for example), that just won't represent in binary FP. The 4 byte version typically gives about 6 digits of usable accuracy.

A wrong display may occur on some compiler versions if you don't specify a 'width' for an FP output.
So %f may give a display error like this. Try %7f instead and you may well find this problem disappears.
It happens when the output can't decide if it should display normally or in exponential form.
rovtech



Joined: 24 Sep 2006
Posts: 262

View user's profile Send private message AIM Address

PostPosted: Sun Dec 10, 2017 4:12 pm     Reply with quote

Thanks Ttelmah, here is more of my code. The results are displayed on a 4 line x 20 LCD. It has worked well so I don't suspect it. I was using %f and changing as you suggested gave completely different values.
%f gave -5392220.13
%7f gave -2030.024528 for both OFFSET and SENS
PCM compiler ver 5.05 MPLAB v 8.92 PIC16F886

Code:
  float32 SENS = 0;
  float OFFSET = 0;
  text_position(0,2);                   // 1st column, 3rd line
OFFSET = 123456789;
  sprintf(buff, "offset %7f", OFFSET);
  send_str(buff);
 SENS = 1.23456789E8;
  text_position(0,3);                   // 1st column, 4th line
  sprintf(buff, "Sens %7f", SENS);
  send_str(buff);


I am away this evening but will check back tomorrow. Thanks.
Ttelmah



Joined: 11 Mar 2010
Posts: 19540

View user's profile Send private message

PostPosted: Mon Dec 11, 2017 4:38 am     Reply with quote

There isn't any such compiler version as 5.05. CCS versions are always x.xxx
However if this is 5.005, then this was an early beta. The V5 compilers need to be around 5.012, before they started working at all well....
rovtech



Joined: 24 Sep 2006
Posts: 262

View user's profile Send private message AIM Address

PostPosted: Mon Dec 11, 2017 8:18 am     Reply with quote

Sorry, I was in a hurry to leave yesterday. My compiler is:
CCS PCM C Compiler, Version 5.055

I will strip my code (several pages) down to minimum and post the whole thing but I don't think it will make any difference. Except for where the definitions are located the rest of the code is one block in main() so it should not matter what happened to the variables before that.

I could buy the latest version but if it doesn't work then I may have to consider going to the 24 bit PIC which would be wasted money on the update. I really don't want to run the code on an Arduino either.

My problems with the Arduino from my original post was explained to me:
"The reason you are unable to print at int64_t is because there is no "Serial.print" function definition for Serial.print(int64_t var). The math libraries support the 64 bit operations but you cannot print the numbers with Arduino's current code."
temtronic



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

View user's profile Send private message

PostPosted: Mon Dec 11, 2017 8:29 am     Reply with quote

re:
My problems with the Arduino from my original post was explained to me:
"The reason you are unable to print at int64_t is because there is no "Serial.print" function definition for Serial.print(int64_t var). The math libraries support the 64 bit operations but you cannot print the numbers with Arduino's current code."

gee ain't that great....NO way to confirm/deny the numbers are right !!
rovtech



Joined: 24 Sep 2006
Posts: 262

View user's profile Send private message AIM Address

PostPosted: Mon Dec 11, 2017 9:22 am     Reply with quote

Here is my full code stripped down to minimum:

Code:
/* Pre-processor directives */
#include <16F886.H>
#include <math.h>
 #fuses INTRC_IO, NOWDT, PUT, NOPROTECT, BROWNOUT, MCLR
 #use delay (clock=2000000)
 #use I2C (master, SCL=PIN_C3, SDA=PIN_C4)
 #byte portc = getenv("SFR:PORTC")

// define I2C address, constants, & global variables
#define LCD_WRT_ADDR    0X4E            // LCD display
#define buff_size       21              // characters per line plus one
     
// Function prototypes
    void clear_LCD (void);                      // Clear LCD
    void text_position (int line, int column);  // set start for next text
    void Set_Col_Rows(char col, char row);      // set #columns & rows
    void send_str(char *buff);                  // Send string to LCD

// The main function
void main(void)
 {
// setup
  set_tris_c (0x00);         // all outputs
  char buff[buff_size];
  float32 SENS = 0;
  float OFFSET = 0;

  delay_ms(1000);                       // allow I2C display module to start
  clear_LCD();                          // clear the LCD
// Set_Col_Rows(20,4);                   // 20 columns, 4 rows

  text_position(0,2);                   // 1st column, 3rd line
  OFFSET = 123456789;
  sprintf(buff, "offset %f", OFFSET);
  send_str(buff);
  SENS = 1.23456789E8;
  text_position(0,3);                   // 1st column, 4th line
  sprintf(buff, "Sens %6f", SENS);
  send_str(buff);

 }                                      // end of main function

// Functions
// ** Clear Display
void clear_LCD (void)
   {
   I2C_START ();                // start I2C
   I2C_WRITE (LCD_WRT_ADDR);    // addr of LCD
   I2C_WRITE ('C');             // C CL to clear display
   I2C_WRITE ('L');             // L
   I2C_STOP ();                 // stop I2C
   }

// ** Set position of next text
void text_position(int line, int column)
   {
   I2C_START ();                // start I2C
   I2C_WRITE (LCD_WRT_ADDR);    // addr of LCD
   I2C_WRITE ('T');             // T, TP set text position
   I2C_WRITE ('P');             // P
   I2C_WRITE (line);            // line position
   I2C_WRITE (column);          // column position
   I2C_STOP ();                 // stop I2C
   }

// ** Set Text Columns and Rows
void Set_Col_Rows(char col, char row)
    {
   I2C_START ();                // start I2C
   I2C_WRITE (LCD_WRT_ADDR);    // addr of LCD
   I2C_WRITE ('S');             // STCRT, set Col & Row
   I2C_WRITE ('T');
   I2C_WRITE ('C');
   I2C_WRITE ('R');
   I2C_WRITE (col);             // # columns
   I2C_WRITE (row);             // # rows
   I2C_WRITE (0x80);
   I2C_WRITE (0xC0);
   I2C_WRITE (0x94);
   I2C_WRITE (0xD4);
   I2C_STOP ();                 // stop I2C
    }

// ** Send string to LCD
void send_str(char *buff)
   {
   int i;
   I2C_START ();                // start I2C
   I2C_WRITE (LCD_WRT_ADDR);    // addr of LCD
   I2C_WRITE('T');              // send TT for text coming
   I2C_WRITE('T');
    for (i=0; i<buff_size; i++)
   {
   I2C_WRITE(buff[i]);          // start with a Z
   }
   I2C_WRITE(0);
   I2C_STOP ();                 // stop I2C   
   }
               
// end


OFFSET displays as -5392220.13 (using %f)
SENS displays as -2030.024528 (using %6f)
interestingly SENS also displays as -2030.024528 (using %2f or %7f)
I get -5392220.132 (using %f2)

Edit:

Code:
  OFFSET = 123456789;
  OFFSET = OFFSET - 123456788;
  sprintf(buff, "offset %f", OFFSET);
  send_str(buff);


gives OFFSET as 8.00 not as good as my HP48 calculator which gives 1. I just had to check.
and
Code:

 OFFSET = 123456789;
 OFFSET = OFFSET - 123450000;


gives 6792.00 which is close but not good enough.
rovtech



Joined: 24 Sep 2006
Posts: 262

View user's profile Send private message AIM Address

PostPosted: Mon Dec 11, 2017 10:05 am     Reply with quote

Disaster:
I found I had a CCS PCM C Compiler, Version 5.064 downloaded but never installed (if it ain't broke don't fix it).
I installed it but now even my LCD display does not work. It compiles, programs the PIC and verifies, clears it, etc. but just a blank LCD. That's why I hate installing the latest updates.
Was this a bad version?

Help! How do I go back to the old version?
Ttelmah



Joined: 11 Mar 2010
Posts: 19540

View user's profile Send private message

PostPosted: Mon Dec 11, 2017 11:35 am     Reply with quote

Quote:


Code:
OFFSET = 123456789;
OFFSET = OFFSET - 123456788;
sprintf(buff, "offset %f", OFFSET);
send_str(buff);


gives OFFSET as 8.00 not as good as my HP48 calculator which gives 1. I just had to check.
and
Code:

OFFSET = 123456789;
OFFSET = OFFSET - 123450000;


gives 6792.00 which is close but not good enough.


They are both as good as you are going to get.

Float (On the PIC18, there is only one type), has a 23.5 bit mantissa. It is coded as a 23 bit mantissa, with an invisible starting '1'. So numbers that code as 11111111... get 24 bit equivalent accuracy, but anything requiring a '0' at the end, only gets 23 bits. 6.8 digits of equivalent decimal 'accuracy'.
Also though coding as binary fractions in this way has limitations. Some numbers expand to infinite series, and will give errors no matter how many digits you have.

Your values shown are integer. Int32, gives 9.4 digits supported. Your maths would work perfectly in integer.

Float is designed to give _flexibility_ by automatically scaling numbers to display the most significant digits, but at a lot of precision.

Just re-install the old version from your backup.

However that 5.064 doesn't work may well be showing that there is something fundamentally flawed in the code. The later compiler will almost certainly default to using the I2C hardware, and will clock it as fast as possible. Are you sure your LCD can support this rate?. Specify a baud rate in the setup.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Dec 11, 2017 11:42 am     Reply with quote

rovtech wrote:

How do I go back to the old version?

1. If you have the old installer file (.exe file) for vs. 5.055, just run it.

2. If you have System Restore enabled on your Windows PC, you can go
back to a previous restore point. Choose the latest one, just before you
installed vs. 5.064.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Dec 11, 2017 12:08 pm     Reply with quote

Ttelmah, to me it looks like a bug in printf. The test program shown below,
compiled with vs. 5.075, gives the following output in MPLAB vs. 8.92
simulator. The 2nd number is incorrect:
Quote:

1234567.040
-539224.061


If I look at the .LST file for the 2nd case, I see this encoding:
Code:
..... temp = 12345678.0; 
01ED:  MOVLW  4E
01EE:  MOVWF  temp+3
01EF:  MOVLW  61
01F0:  MOVWF  temp+2
01F1:  MOVLW  3C
01F2:  MOVWF  temp+1
01F3:  MOVLW  96
01F4:  MOVWF  temp

I next use the floatconv.exe program from this Zip file:
http://www.piclist.com/images/floatconv10.zip
I set the format to "MicroChip 32bit".

If I plug the numbers from the .LST file into the floatconv.exe program as follows,
Code:
BYTE1  BYTE2  BYTE3  BYTE4
 96     3C     61     4E

I get this number in the "float" box at the top:
Quote:
12345678.0

It's correct. So that tells me the problem is in printf.

Test program:
Code:
#include <16F886.H>
#fuses INTRC_IO, NOWDT, PUT, NOPROTECT, BROWNOUT, MCLR
#use delay (clock=4M)
#use rs232(baud=9600, UART1, ERRORS)

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

temp = 1234567.0;
printf("%7.3f \r", temp);

temp = 12345678.0;
printf("%7.3f \r", temp);

while(TRUE);
}                                     
Ttelmah



Joined: 11 Mar 2010
Posts: 19540

View user's profile Send private message

PostPosted: Mon Dec 11, 2017 12:15 pm     Reply with quote

Just worth adding that calculators generally use BCD arithmetic, not floats. It is not hard to use a BCD library on the PIC.
The PIC does include two features that help with BCD. Swap (allows a nibble to be swapped in one instruction), and the DC bit which flags a carry from the bottom nibble.

Also as a comment, on the PIC24/30/33 the int64 type does print correctly.
rovtech



Joined: 24 Sep 2006
Posts: 262

View user's profile Send private message AIM Address

PostPosted: Mon Dec 11, 2017 1:43 pm     Reply with quote

Windows restore did not restore ver 5.055
I cannot find the 5.055 ver install file
I installed ver 5.019 which does the same as 5.064 and my LCD is still blank with blinking cursor top left.
It looks like the update somehow messed up my LCD serial driver, most likely changed it's address. I will sort this out.
The install says it saved a copy of 5.055 but I cannot find instructions on how to open it. I may as well use 5.064.

So the problem is in printf but will purchasing the latest pcm fix the problem?
I don't mind that but pcd is another matter and probably means new circuit boards, a learning curve, and who knows, besides the cost.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Dec 11, 2017 1:46 pm     Reply with quote

I did my testing with the latest version (vs. 5.075). It has the problem.
Ttelmah



Joined: 11 Mar 2010
Posts: 19540

View user's profile Send private message

PostPosted: Mon Dec 11, 2017 2:01 pm     Reply with quote

There is another problem. Your functions are fundamentally flawed.

send_str, will keep punching out data past the end of the string. Could be anything....

Then if the compiler switches to exponential format, there is nothing to stop the data overflowing the buffer. This will then result in garbage being displayed.

Make your buffer larger. 32 characters. Then only print the 20 your display supports. You also say 'start with a Z', but don't do so. Does the display need this?. Hopefully you will then see the data, and can work out how much it is actually overflowing.
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