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

Out of ROM, A segment or the program is too large

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



Joined: 23 Sep 2011
Posts: 32

View user's profile Send private message AIM Address

Out of ROM, A segment or the program is too large
PostPosted: Fri Sep 23, 2011 11:55 pm     Reply with quote

Ok, I'm having this problem trying to compile a float into my code. I'm using PIC 16F627A and it's giving me the Out of ROM error. The objective of this code is to gather as many pulses from a flow sensor possible in a 1 second period so that I can get a measurement of how many GPM of water is flowing through a pipe (k factor is 344 pulses per gallon). The results of this is suppose to go into variable fltGallonsPerMinute so that I can divide it by 60 (to convert gallons per second to gallons per minute) then display the results on an LCD screen. However the program stops compiling at fltGallonsPerMinute /= 344;. Does anyone have any idea on how to fix this?

Code:

void main() {
   unsigned long int uliMicroseconds, uliMilliseconds, uliSeconds;
   unsigned long int uliSecondsBuffer, uliPulses, uliPulseBuffer;
   unsigned char uchToggleBuffer, uchLCDBuffer[20];
   float fltGallonsPerMinute;

   StartupSettings();
   
   uliMicroseconds = 0;
   uliMilliseconds = 0;
   uliSeconds = 0;
   uliSecondsBuffer = 0;
   uliPulses = 0;
   uchToggleBuffer = 0;

   InitializeDisplay();
   delay_ms(400);
   
   sprintf(uchLCDBuffer, "Testing?");
   WriteString(uchLCDBuffer, 8);

   while(1) {
      if (input(SENSOR) == 1) {
         output_bit(LED_GREEN, 1);
         uliPulses++;
      }
      else {
         output_bit(LED_GREEN, 0);
      }
      //-----------------------------
      if (input(CRYSTAL) == 1) {
         uliMicroseconds++;

         if (uliMicroseconds > 1000) { //1000
            uliMicroseconds = 0;
            uliMilliseconds++;
         }

         if (uliMilliseconds > 10) { //10
            uliMilliseconds = 0;
            uliSeconds++;
         }

         if (uliSeconds > 0) {
            uliSeconds = 0;
            
            if (uchToggleBuffer == 0) {
               uchToggleBuffer = 1;
               output_bit(LED_RED, 1);

               uliPulseBuffer = uliPulses;
               fltGallonsPerMinute = (float)uliPulses;
            }
            else {
               uchToggleBuffer = 0;
               output_bit(LED_RED, 0);
            
               fltGallonsPerMinute /= 344; //stalls program
               fltGallonsPerMinute /= 60;

               sprintf(uchLCDBuffer, "%Lu",uliPulseBuffer);
               DataCommand(0x80);
               WriteString(uchLCDBuffer, 8);   

               sprintf(uchLCDBuffer, "%f", fltGalonsPerMinute);
               DataCommand(0xC0);
               WriteString(uchLCDBuffer, 8);

               uliPulses = 0;
               uliPulseBuffer = 0;
            }
         }
      }
   }

   return;
}
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Sat Sep 24, 2011 2:47 am     Reply with quote

The microseconds counter will never work. Use a processor timer to generate a one seconds interval. Depending on the actual number of pulses per second, you probably would want to use a longer counting interval to achieve some accuracy.

Regarding out of ROM error, you should determine if the available code space is nearly exhausted when omitting a few instructions, or if it's only a problem of the main() function size. I think, the calculations can be performed with fixed point integer as well. If float is needed in your opinion, you should replace the dual float divison by a reasonable constant multiplication.

Code:
fltGallonsPerMinute /= 344;
fltGallonsPerMinute /= 60;

fltGallonsPerMinute *= (1.0/(344*60));
Ttelmah



Joined: 11 Mar 2010
Posts: 19328

View user's profile Send private message

PostPosted: Sat Sep 24, 2011 4:24 am     Reply with quote

and, of course, just try searching here for this error, to find many dozens of explanations/suggestions...

Best Wishes
temtronic



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

View user's profile Send private message

PostPosted: Sat Sep 24, 2011 5:08 pm     Reply with quote

You could also lookup 'tachometer' and find code as well.
Basically same thing.

count pulse for a fixed time period( 1 second),do some math, display result...
Wolf



Joined: 23 Sep 2011
Posts: 32

View user's profile Send private message AIM Address

PostPosted: Sun Sep 25, 2011 11:48 pm     Reply with quote

temtronic wrote:
You could also lookup 'tachometer' and find code as well.
Basically same thing.

count pulse for a fixed time period( 1 second),do some math, display result...


You see, I got that, http://www.instrumart.com/products/31039/lake-monitors-flowstat-sensors that flow sensor basically behaves like a tachometer. I can get my pulses counted per 1 second, thats no problem its stuffing the float calculated number into the sprintf(); function....

Code:

void main() {
   unsigned long int uliSeconds, uliPulses, uliPulseBuffer;
   unsigned char uchLCDBuffer[20];

   StartupSettings();
   
   uliSeconds = 0;
   uliPulses = 0;
   uliPulseBuffer = 0;

   InitializeDisplay();
   delay_ms(400);
   
   sprintf(uchLCDBuffer, "FlowCtrl");
   WriteString(uchLCDBuffer, 8);

   while(1) {
      if (input(CRYSTAL) == 1) {
         uliSeconds++;
      }
      
      if (uliSeconds > 15000) {
         uliSeconds = 0;
         output_toggle(LED_RED);
         
         sprintf(uchLCDBuffer, "%f", (((float)uliPulseBuffer)/1000));
         DataCommand(0xC0);
         WriteString(uchLCDBuffer, 8);

         uliPulseBuffer = uliPulses;
         uliPulses = 0;
      }
      else {
         if (input(SENSOR) == 1) {
            uliPulses++;
            output_bit(LED_GREEN, 1);
         }
         else {
            output_bit(LED_GREEN, 0);
         }
      }
   }

   return;
}


the sprintf(uchLCDBuffer, "%f", (((float)uliPulseBuffer)/1000)); is what causes the program to overload. And I cannot find any better way to do this.
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Mon Sep 26, 2011 1:30 am     Reply with quote

You are asking a 1K flash PIC to do floating point... it should come as no surprise that you are getting out of ROM, i.e. flash. If you are going to get this to fit in such a small flash space then you are going to have to:

a) Use integer arithmetic all the way through. Float library code takes up a lot of space.

b) Get hardware to do as much as possible for you. This reduces the amount of code you need.

c) Format the values for output yourself. Generic formatting code, such as printf and its relatives, is bloated compared to well written application specific code.

In short you are trying to squeeze a quart into a pint pot and it simply won't go. The compiler is telling you it won't go, end of story.

Another answer is to simply get a bigger PIC.

RF Developer.
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Mon Sep 26, 2011 2:13 am     Reply with quote

RF_Developer wrote:

b) Get hardware to do as much as possible for you. This reduces the amount of code you need.


Thinking about it, if I were a tutor setting this as an assignment, and I have to add I'm not, then I'd have a particular reason for requiring the use of a PIC16F627A. That's because it is very limited and that naive approaches cannot be successful. A software only approach is doomed due to code space limits and even if it can be shoehorned into the device, it will give poor accuracy. So... what would I be hoping for? I'd hope that someone would think laterally and see this is not an assignment about software. Its about using the hardware resources effectively. To get this to work, and I confess I haven't actually tried this approach, I'd be expecting a solution along the lines of using a timer to give a hardware accurate timebase and using the CCP module in capture mode, probably with prescale to reduce capture frequency and hence processor load, to capture the timer count based on the unknown input frequency. I'd then expect the software to just compute the final result and output it, bearing in mind that this is not direct frequency counting but period measurement. I.e. that capture value represent timer counts per tick/ticks of the input, not ticks per time interval.

The temptation to go float is still there however, and I'd hope for my students to avoid that, but fully expect none of them to actually do so.

In short I'd have set this up as an assignment I'd expect them to "fail". However that's because that "failure" sets up important lessons in how to approach problems from more than one direction.

RF Developer.
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Mon Sep 26, 2011 7:18 am     Reply with quote

Two suggestions:
- You can save some code space by writing *0.001 instead of /1000, as previously mentioned.
- You should look for the %w format option. It allows you to print integer as fixed point without using float
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