2

Chip: PIC18f26j50
Compiler: C18

My objective is to store values in a table in the RAM memory using structures and feed in the values which are quite large.

#include <p18F46J53.h>

 struct table
    { 
      float temp;
      float humidity;
      float pressure;

    }entry[300];

This is my sample code and I have to store such members into the controller's memory. This is for the purpose of monitoring the surrounding data of the atmosphere. And later dump this data into EEPROM.

But I am having trouble building the code as it give the following error:

Error - section '.udata_main.o' can not fit the section. Section '.udata_main.o' length=0x000013ec

I tried searching Google for fixing this udata error and ended up with How to Create Objects Larger than 256 Bytes with Microchip's MPLAB C18.

But this shows how to store each variable. How can I store structs in C18? Or is it impossible?

I'll try to be more specific. I found this method to store data greater than 255 bytes.

#pragma udata large_udata
unsigned char big_buff1[300];
unsigned char big_buff2[350];
#pragma udata

How can I store structures greater than that so that I would just need 3000 bytes at the for the table preparation?

I would prefer to use float but I can settle for using int/char.

I hope this makes things clearer.

embedded.kyle
  • 8,411
  • 2
  • 26
  • 44
Rookie91
  • 2,108
  • 4
  • 29
  • 46

2 Answers2

4

EDIT: There are two issues - the structure array is too large for the memory, and the compiler cannot create variables larger than 256 bytes

Problem 1: Structure too large for RAM

The chip you are using has a RAM size of 3776 bytes (1) and the error says it requires 5100 bytes.

You either need a new chip with more RAM, or you must reduce the size of your table. I suggest storing you values as unsigned integers (2 bytes). If you need the decimal places, simply multiply by 10 to the power of the number of places. E.g. 3.157 becomes 3157.

Why do you need 300 values? Perhaps you can store to EEPROM more often and reduce this number. If you are just having a large number to do averaging, consider adding to an accumulator variable instead.

E.g.

TempAccum += temp;

Then after 300 readings

TempTotal = TempAccum / 300;
TempAccum = 0;

Problem 2: No variables larger than 256 bytes:

A solution was posted in the link in the question but that was for variables. Instead of a structure, use individual variables:

float temp[300];
float humidity[300];
float pressure[300];

To access the variables (according to the link) you need to use pointers. e.g.

float *tempPtr;
tempPtr = temp;
tempPtr[100] = some_value;
geometrikal
  • 4,921
  • 2
  • 23
  • 41
  • Well i'm having trouble accommodating more than 255 bytes .I saw an example to store so for variables.But what can i do to store more for structures? – Rookie91 Jan 03 '14 at 09:30
  • 2
    You might like to try the more modern XC8 compiler, which seems to handle large contiguous RAM allocations better than C18. But you will still have to reduce the amount you hope to store. – David Jan 03 '14 at 09:35
  • What will be the amount of Ram space that i can use to handle the Code properly.Can i suppose to use tha available 2000 Bytes of 3.6KB. – Rookie91 Jan 03 '14 at 12:23
2

Float uses 4-bytes memory. If you can even half the used area, that would be much better for you. Maybe it becomes complex in programming way, but it solves your problem.

Lets think about temperature. In 1-byte, you can store values between -128 and 127. If you will need more detailed, you can use 1 more byte for the value after the point. So, instead of float, you can define 2 byte variables for temperature and it is halved. Actually, by using bit level, you might fit all of them into 1 byte as well. But this may make it more complex.

If you apply same consideration for other two fields by thinking about their possible value ranges, you can solve your problem I think.

--- EFFICIENT WAY TO USE MEMORY --- (This is added later)

Your array is too big, but you are using it to store data only. There is no calculation until you write its content to EEPROM. If that is so, make the array smaller. Let's say 50 items.

entry[50]

Totally you would need 300. So, you can create a counter to know at which part of that 300 you are.

int counter = 1;

After the array entry is filled with 50 items, calculate the offset value for EEPROM.

int offset = 50 * counter;

Then write the content of that array to EEPROM by starting from that offset address. Finally increase the value of counter by 1. counter += 1;

Since EEPROMs have a limited write cycle, by increasing that 50 as long as it fits the memory, you can decrease number of write operations.

tcak
  • 479
  • 6
  • 17
  • Is there any way where i could still keep the data type and allocate more space.?:Or I should Reconsider the Software design right. – Rookie91 Jan 03 '14 at 08:47
  • Even if it is Char i would still need a large entry '300'.That would still make it difficult. – Rookie91 Jan 03 '14 at 08:53
  • Why 300? If you tell us maybe we can suggest creative ways around this. – geometrikal Jan 03 '14 at 11:17
  • OK. I have to store temperatures, humidity and pressure for a day that have that will be 300 times a day[In total b/w 24 hours].I can reduce the total to maximum 100 or something.But i want to know what is the limit to use this structure such that there will not be any possible clash or error. – Rookie91 Jan 03 '14 at 11:44
  • I wanted to follow structures because it is a formidable solution to store tables.I would like to have your suggestions regarding that. – Rookie91 Jan 03 '14 at 11:45
  • 1
    AFAIK, you can write different parts of EEPROM directly. So, what you can do is to reduce the number of items of that array, and define an integer variable to use as a counter. Once that array is filled, calculate offset value by using that counter, and dump the array into EEPROM by starting from that offset address and increase counter by one. – tcak Jan 03 '14 at 14:28