I am writing a clock program that constructs the current date as a string to scroll across a 16x8 led matrix. The code seems to be working fine but I have read posts that suggest avoiding String() as it fragments memory. Am I likely to find the clock crashing after days/weeks of continual use? A possible solution would be to use a char array but what would be the best solution to replicate String() functions below as copying them from PROGMEM complicates things. I'm no C++ programmer and do not fully understand the syntax for using pointers though I grasp the principal.
// Display Date
void doDate2(){
String myDate;
RTC.readClock(); //Read clock
// DayOfWeek
int x = RTC.getDayOfWeek();
myDate=CopyProgmemMessage((prog_uchar*)pgm_read_word(&(day_table[x-1])));
// Day
x = RTC.getDate();
myDate += String(x,DEC);
myDate += " ";
// Month
x = RTC.getMonth();
myDate +=CopyProgmemMessage((prog_uchar*)pgm_read_word(&(month_table[x])));
// Year
x = RTC.getYear();
myDate += "20";
myDate += String(x,DEC);
myDate += " \0";
scrollRamMessage(myDate);
}
// Display Temperature
void doTemperature(){
String myTemp =" Its ";
float temperature=RTC.getTemperature(); //Read clock
myTemp += String(lround(temperature));
myTemp += ".";
temperature = (temperature-floor(temperature))*100;
myTemp += String(lround(temperature));
myTemp += (char) 0x7f;
myTemp += " \0";
scrollRamMessage(myTemp);
}
// Copy zero terminated string from program memory into String variable
String CopyProgmemMessage(prog_uchar * messageString){
int counter = 0;
char myChar;
String myString="";
do {
// read back a char
myChar = pgm_read_byte_near(messageString + counter);
if (myChar != 0){
myString += myChar;
}
counter++;
}
while (myChar != 0);
return myString;
}
// Scroll Message
void scrollRamMessage(String messageString) {
int counter = 0;
clearDisplay();
while (messageString[counter] !=0){
loadBufferLong(messageString[counter]);
for (int x=0; x<12;x++){
rotateBufferLong();
printBufferLong();
delay(scrollDelay);
}
counter++;
}
}
Another quick question, does using const to define a value reserve RAM space or does the compiler substitute it's reference with an immediate value? Should I be using define instead for below items?
const int DIN = 12; // DataIn pin (18)
const int CLK = 11; // Clock pin (17)
const int LOAD = 10; // Load pin (16)
const int numDevices = 2; // Number of MAX7219 LED Driver Chips (1-8)
const int ldrPin = A0; // Select the input pin for the light dependent resistor (LDR)
const int ledMin = 3; // Minimum LED brightness value used in map command
const int ledMax = 12; // Maximum LED brightness value used in map command
const int ldrMax = 80; // Inital maximum reading from LDR (0-1023)
const int ldrMin = 0; // Initial minimum reading from LDR (0-1023)
const int fadeDelay = 30; // Millisecond delay between each intensity step change
const int encButton = 5; // Rotary Encoder button pin (11)
const int encoder0PinA = 6; // Rotary Encoder A pin (12)
const int encoder0PinB = 7; // Rotary Encoder B pin (13)
const long debounceDelay = 90; // Button debounce time
const long adjustDelay = 15000; // 15 Second Adjust timeout
const long buttonDelay = 3000; // Button hold time to go into adjust mode (3 seconds)
const int scrollDelay = 35; // Text Scroll speed delay (lower is faster)
If you are assembling text and then outputting that to a serial connection then stop and think;
You get serial data a character at a time and you send serial data the same way. What you assemble to an array or String could more easily just be output to serial as if it is a buffer that doesn't use ram.
When you want a drink and there is a water fountain, do you really need to fill a cup from the fountain to get a drink?
GoForSmoke:
If you are assembling text and then outputting that to a serial connection then stop and think;
I assemble the string and then call a routine to extract font pixel data from an PROGMEM array and scroll it across a LED matrix. To keep things simple and the scroll steady I cannot construct the scroll message as I go.
majenko:
When making up strings of data in a specific format sprintf is your friend.
As for consts, the compiler treats them just the same as #define except it has the benefit of type checking.
I cannot see how to use sprintf with PROGMEM char arrays as they hold full day and month names (Saturday / December)
I'm not certain about the Arduino, but in other C implementations you use %S as a placeholder for a string in flash (as opposed to %s for a string in RAM).
The String class seems easy to use, but takes a lot of SRAM.
The per-string overhead of using the String class is only seven or eight bytes per instance; the danger in using it lies in potential memory fragmentation after multiple String operations.
I wonder if someone could help me as I'm getting in a right pickle trying to convert routines to not use String().
The routine I'm trying to convert is this...
// Display Date
void doDate2(){
String myDate;
RTC.readClock(); //Read clock
// DayOfWeek
int x = RTC.getDayOfWeek();
myDate=CopyProgmemMessage((prog_uchar*)pgm_read_word(&(day_table[x-1])));
// Day
x = RTC.getDate();
myDate += String(x,DEC);
myDate += " ";
// Month
x = RTC.getMonth();
myDate +=CopyProgmemMessage((prog_uchar*)pgm_read_word(&(month_table[x])));
// Year
x = RTC.getYear();
myDate += "20";
myDate += String(x,DEC);
myDate += " \0";
scrollRamMessage(myDate);
}
// Copy zero terminated string from program memory into String variable
String CopyProgmemMessage(prog_uchar * messageString){
int counter = 0;
char myChar;
String myString="";
do {
// read back a char
myChar = pgm_read_byte_near(messageString + counter);
if (myChar != 0){
myString += myChar;
}
counter++;
}
while (myChar != 0);
return myString;
}
Below I have trimmed the sketch down to it bare minimum to get example running and show what I have tried to implement but get compile errors that I don't understand. Also I'm unsure how to convert and concatenate a integer number onto the current string
I keep them as separate entries as they are stored in PROGMEM and you need a pointer table to the character arrays. My problem is pulling them from PROGMEM to build up a string of text like 'Saturday 16 June 2012'. I see there is suitable commands built in but compiling errors on this line
You don't -need- a pointer table if you store fixed-length strings in your table. All you need then is base address, index, and the fixed-length to find any element. Pad with zeros, ex: "March\0\0\0\0", they terminate the C string. A few bytes of flash wasted is no biggie.