You seem reluctant to post the full source but given the discussion I think you'll find it beneficial to yourself to do so.
Heres the full code. It was too long thats why I only posted the code that I needed help on.
/*
Arduino Uno
*/
#include <LcdBarGraph.h> //include bar graph library
#include <EEPROM.h> // Add in the EEPROM library
#include <MenuBackend.h> //MenuBackend library - copyright by Alexander Brevig
#include <LiquidCrystal.h> //this library is included in the Arduino IDE
#include <MemoryFree.h> // used to determin how much ram is used.
#include <avr/pgmspace.h> //used to decrese ram usage == free up ram==
// LiquidCrystal display with:
// rs on pin 7
// rw on ground
// enable on pin 6
// d4, d5, d6, d7 on pins 5, 4, 3, 2
LiquidCrystal lcd(2, 12, 4, 13, 6, 7);
//Setup for screen backlight
const byte backLED = 3; // Use PWM pin 3 for the backlight
byte lightadj = EEPROM.read(2);
//Setup for contrast setting
const byte contrastlight = 5; // use PWM pin 5 for the contrast control
byte contrastadj = EEPROM.read(3);
// setup for bar graph and other inputs/outputs
byte lcdNumCols = 11; // -- number of columns in the LCD used for the bar graph
byte sensorbar = A0; // sensor input set to byte
byte afrbar = A1; // afr input set to byte
LcdBarGraph lbg(&lcd, lcdNumCols); // -- creating line bar graph
float peaksensor = 0; //set peak sensor to a low value so it'll work properly
float aaa = 10; //
const byte clearPB = 8; // set button two on pin 8 to clear Peak sensor HOld value to zero
byte sstwarn = EEPROM.read(1); // sensor warning
// Menu Pin Inputs
const byte buttonPinLeft = 8; // pin for the Up button
const byte buttonPinRight = 9; // pin for the Down button
const byte buttonPinEsc = 10; // pin for the Esc button
const byte buttonPinEnter = 11; // pin for the Enter button
// Pins combination used to enable menu
const byte buttonPressed = 11; // use to enable the alreadyPressed state to enable menu
const byte cancelButtonPressed = 10; // used to enable the alreadyPressed state to enable menu
int alreadyPressed; // trigger the menu to turn on if its on
// Use for MENU
int lastButtonPushed = 0;
int lastButtonEnterState = LOW; // the previous reading from the Enter input pin
int lastButtonEscState = LOW; // the previous reading from the Esc input pin
int lastButtonLeftState = LOW; // the previous reading from the Left input pin
int lastButtonRightState = LOW; // the previous reading from the Right input pin
long lastEnterDebounceTime = 0; // the last time the output pin was toggled
long lastEscDebounceTime = 0; // the last time the output pin was toggled
long lastLeftDebounceTime = 0; // the last time the output pin was toggled
long lastRightDebounceTime = 0; // the last time the output pin was toggled
long debounceDelay = 500; // the debounce time
//Menu variables
MenuBackend menu = MenuBackend(menuUsed,menuChanged);
//initialize menuitems
MenuItem BackLight = MenuItem("Backlight");
MenuItem BackLight10 = MenuItem("10%");
MenuItem BackLight20 = MenuItem("20%");
MenuItem BackLight30 = MenuItem("30%");
MenuItem BackLight40 = MenuItem("40%");
MenuItem BackLight50 = MenuItem("50%");
MenuItem BackLight60 = MenuItem("60%");
MenuItem BackLight70 = MenuItem("70%");
MenuItem BackLight80 = MenuItem("80%");
MenuItem BackLight90 = MenuItem("90%");
MenuItem BackLight100 = MenuItem("100%");
/* MenuItem Contrast = MenuItem("Contrast");
MenuItem Contrast10 = MenuItem("10%");
MenuItem Contrast20 = MenuItem("20%");
MenuItem Contrast30 = MenuItem("30%");
MenuItem Contrast40 = MenuItem("40%");
MenuItem Contrast50 = MenuItem("50%");
MenuItem Contrast60 = MenuItem("60%");
MenuItem Contrast70 = MenuItem("70%");
MenuItem Contrast80 = MenuItem("80%");
MenuItem Contrast90 = MenuItem("90%");
MenuItem Contrast100 = MenuItem("100%");*/
MenuItem sensorWarning = MenuItem("Set sensor Warning");
MenuItem sensor1 = MenuItem("1");
MenuItem sensor2 = MenuItem("2");
MenuItem sensor3 = MenuItem("3");
MenuItem sensor4 = MenuItem("4");
MenuItem sensor5 = MenuItem("5");
MenuItem sensor6 = MenuItem("6");
MenuItem sensor7 = MenuItem("7");
MenuItem sensor8 = MenuItem("8");
MenuItem sensor9 = MenuItem("9");
MenuItem sensor10 = MenuItem("10");
MenuItem sensor11 = MenuItem("11");
MenuItem sensor12 = MenuItem("12");
MenuItem sensor13 = MenuItem("13");
MenuItem sensor14 = MenuItem("14");
MenuItem sensor15 = MenuItem("15");
MenuItem sensor16 = MenuItem("16");
MenuItem sensor17 = MenuItem("17");
MenuItem sensor18 = MenuItem("18");
MenuItem sensor19 = MenuItem("19");
MenuItem sensor20 = MenuItem("20");
MenuItem sensor21 = MenuItem("21");
MenuItem sensor22 = MenuItem("22");
MenuItem sensor23 = MenuItem("23");
MenuItem sensor24 = MenuItem("24");
MenuItem sensor25 = MenuItem("25");
MenuItem sensor26 = MenuItem("26");
MenuItem sensor27 = MenuItem("27");
MenuItem sensor28 = MenuItem("28");
MenuItem sensor29 = MenuItem("29");
MenuItem sensor30 = MenuItem("30");
MenuItem sensor31 = MenuItem("31");
MenuItem sensor32 = MenuItem("32");
MenuItem sensor33 = MenuItem("33");
MenuItem sensor34 = MenuItem("34");
MenuItem sensor35 = MenuItem("35");
MenuItem sensor36 = MenuItem("36");
MenuItem sensor37 = MenuItem("37");
MenuItem sensor38 = MenuItem("38");
MenuItem sensor39 = MenuItem("39");
MenuItem sensor40 = MenuItem("40");
MenuItem sensor41 = MenuItem("41");
MenuItem sensor42 = MenuItem("42");
MenuItem sensor43 = MenuItem("43");
MenuItem sensor44 = MenuItem("44");
MenuItem sensor45 = MenuItem("45");
MenuItem Calibration = MenuItem("Calibration");
void setup()
{
Serial.begin(9600); // setup up serial connection for testing
analogWrite(backLED, lightadj); //turn on backlight
analogWrite(contrastlight, contrastadj); // turn on the contrast
// Analog Input setup
pinMode(A0, INPUT); // Set pin A0 as input
pinMode(A1, INPUT); // Set pin A1 as input
// Digital Input Setup
pinMode(buttonPinLeft, INPUT);
pinMode(buttonPinRight, INPUT);
pinMode(buttonPinEnter, INPUT);
pinMode(buttonPinEsc, INPUT);
pinMode(buttonPressed, INPUT);
pinMode(cancelButtonPressed, INPUT);
//pinMode(13, OUTPUT); // onbaord LED as indicator only
//pinMode(contrastlight, OUTPUT);
lcd.begin(20, 2);// LCD Setup
//configure menu order
menu.getRoot().add(BackLight);
BackLight.addRight(sensorWarning).addRight(Calibration);
BackLight.add(BackLight10).addRight(BackLight20).addRight(BackLight30).addRight(BackLight40).addRight(BackLight50).addRight(BackLight60)
.addRight(BackLight70).addRight(BackLight80).addRight(BackLight90).addRight(BackLight100);
sensorWarning.add(sensor1).addRight(sensor2).addRight(sensor3).addRight(sensor4).addRight(sensor5).addRight(sensor6).addRight(sensor7)
.addRight(sensor8).addRight(sensor9).addRight(sensor10).addRight(sensor11).addRight(sensor12).addRight(sensor13).addRight(sensor14)
.addRight(sensor15).addRight(sensor16).addRight(sensor17).addRight(sensor18).addRight(sensor19).addRight(sensor20).addRight(sensor21)
.addRight(sensor22).addRight(sensor23).addRight(sensor24).addRight(sensor25).addRight(sensor26).addRight(sensor27).addRight(sensor28)
.addRight(sensor29).addRight(sensor30).addRight(sensor31).addRight(sensor32).addRight(sensor33).addRight(sensor34).addRight(sensor35).addRight(sensor36)
.addRight(sensor37).addRight(sensor38).addRight(sensor39).addRight(sensor40).addRight(sensor41).addRight(sensor42).addRight(sensor43).addRight(sensor44)
.addRight(sensor45);
//Contrast.add(Contrast10).addRight(Contrast20).addRight(Contrast30).addRight(Contrast40).addRight(Contrast50).addRight(Contrast60)
//.addRight(Contrast70).addRight(Contrast80).addRight(Contrast90).addRight(Contrast100);
//menu.toRoot();
lcd.setCursor(0,0);
lcd.print(" test");
lcd.setCursor(0,1);
lcd.print(" test");
delay(3000); // Delay set to show the into for 2.3 seconds
lcd.clear(); // clear the screen
delay(500); // delay for 1 sec before going to the loop
} // setup()...
more code...
void loop(){
//---------------------Determine Free Memory -----------------------------------
Serial.print("freeMemory()=");
Serial.println(freeMemory());
Serial.println(contrastadj);
//delay(1000);
//--------------------------------------------------------------------------------
//--------------------- Contrast set in EEPROM-----------------------------------
if(EEPROM.read(3) == 0 || EEPROM.read(3) > 80) { // contrast condition. If greater than 80 or equal to zero, then write 80 to address 3 on EEPROM
EEPROM.write(3,80);
}
//contrastadj = EEPROM.read(3); // read contrast value
analogWrite(contrastlight, contrastadj); // send EEPROM value to generate the PWM for contrast pin output
//--------------------------- Backlight set in EEPROM-------------------------------
if(EEPROM.read(2) < 40) { // check backlight condition. If not greater than or
EEPROM.write(2,40);
}
lightadj = EEPROM.read(2); // read backlight value
analogWrite(backLED, lightadj); // send EEPROM value to backlight PIN using PWM
//--------------------------- sensor Setting saved in EEPROM--------------------------
sstwarn = EEPROM.read(1); // sensor warning read from eeprom memory
//---------------------- Button for Menu -------------------------------------------
if( digitalRead(buttonPressed) == HIGH) { // if button is pressed, then do the following
if( ! alreadyPressed ) { // if alreadyPressed is not True, then do the following
alreadyPressed = true; // makes the variable alreadyPressed to True... turn on menu
lcd.clear();
}
}
if(digitalRead(cancelButtonPressed) == HIGH) {
alreadyPressed = false;
lcd.clear();
}
if (alreadyPressed == true) {
lcd.setCursor(0,0);
lcd.print("Menu Setting ");
readButtons(); //I splitted button reading and navigation in two procedures because
navigateMenus(); //in some situations I want to use the button for other purpose (eg. to change some settings)
//digitalWrite(13, HIGH); used for testing purposes only. not for production
}
else {
sensorafr(); // get sensor/afr to display on the lcd
}
if(alreadyPressed == false) {
digitalWrite(13, LOW);
}
}
more code....
void menuChanged(MenuChangeEvent changed){
MenuItem newMenuItem=changed.to; //get the destination menu
lcd.setCursor(0,1); //set the start position for lcd printing to the second row
lcd.print(newMenuItem.getName()); // Print the Menu selection onto the LCD
lcd.print(" "); // Print spaces to clear the trailing spaces that should be blank
}
void menuUsed(MenuUseEvent used){
//}
// ----------------------------backlight adjustment--------------------------------
if(used.item.getName() == BackLight10 || used.item.getName() == BackLight20 || used.item.getName() == BackLight30 || used.item.getName() == BackLight40 || used.item.getName() == BackLight50 ||
used.item.getName() == BackLight60 || used.item.getName() == BackLight70 || used.item.getName() == BackLight80 || used.item.getName() == BackLight90 || used.item.getName() == BackLight100) {
if(used.item.getName() == "10%") {
if(EEPROM.read(2) != 40) {
EEPROM.write(2,40);
}
}
else if(used.item.getName() == "20%") {
if(EEPROM.read(2) != 60) {
EEPROM.write(2,60);
}
}
else if(used.item.getName() == "30%") {
if(EEPROM.read(2) != 80) {
EEPROM.write(2,80);
}
}
else if(used.item.getName() == "40%") {
if(EEPROM.read(2) != 100) {
EEPROM.write(2,100);
}
}
else if(used.item.getName() == "50%") {
if(EEPROM.read(2) != 120) {
EEPROM.write(2,120);
}
}
else if(used.item.getName() == "60%") {
if(EEPROM.read(2) != 140) {
EEPROM.write(2,140);
}
}
else if(used.item.getName() == "70%") {
if(EEPROM.read(2) != 160) {
EEPROM.write(2,160);
}
}
else if(used.item.getName() == "80%") {
if(EEPROM.read(2) != 180) {
EEPROM.write(2,180);
}
}
else if(used.item.getName() == "90%") {
if(EEPROM.read(2) != 210) {
EEPROM.write(2,210);
}
}
else if(used.item.getName() == "100%") {
if(EEPROM.read(2) != 240) {
EEPROM.write(2,240);
}
}
}
// ----------------------------Contrast adjustment--------------------------------
/* else if(used.item.getName() == Contrast10 || used.item.getName() == Contrast20 || used.item.getName() == Contrast30 || used.item.getName() == Contrast40 || used.item.getName() == Contrast50 ||
used.item.getName() == Contrast60 || used.item.getName() == Contrast70 || used.item.getName() == Contrast80 || used.item.getName() == Contrast90 || used.item.getName() == Contrast100) {
if(used.item.getName() == "10%") {
if(EEPROM.read(3) != 80) {
EEPROM.write(3,80);
}
}
else if(used.item.getName() == "20%") {
if(EEPROM.read(3) != 85) {
EEPROM.write(3,85);
}
}
else if(used.item.getName() == "30%") {
if(EEPROM.read(3) != 70) {
EEPROM.write(3,70);
}
}
else if(used.item.getName() == "40%") {
if(EEPROM.read(3) != 60) {
EEPROM.write(3,60);
}
}
else if(used.item.getName() == "50%") {
if(EEPROM.read(3) != 50) {
EEPROM.write(3,50);
}
}
else if(used.item.getName() == "60%") {
if(EEPROM.read(3) != 40) {
EEPROM.write(3,40);
}
}
else if(used.item.getName() == "70%") {
if(EEPROM.read(3) != 30) {
EEPROM.write(3,30);
}
}
else if(used.item.getName() == "80%") {
if(EEPROM.read(3) != 20) {
EEPROM.write(3,20);
}
}
else if(used.item.getName() == "90%") {
if(EEPROM.read(3) != 10) {
EEPROM.write(3,10);
}
}
else if(used.item.getName() == "100%") {
if(EEPROM.read(3) != 1) {
EEPROM.write(3,1);
}
}
}*/
lcd.setCursor(0,0);
lcd.print("Saving. ");
delay(500);
lcd.setCursor(0,0);
lcd.print("Saving.. ");
delay(500);
lcd.setCursor(0,0);
lcd.print("Saving... ");
delay(500);
lcd.setCursor(0,0);
lcd.print("Saving.... ");
delay(500);
lcd.setCursor(0,0);
lcd.print("Saving..... ");
delay(500);
lcd.setCursor(0,0);
lcd.print("Saving......");
lcd.setCursor(0,0);
lcd.print("Saved! ");
lcd.setCursor(0,1);
lcd.print(used.item.getName());
delay(1000); //delay to allow message reading
menu.toRoot(); //back to Main
lcd.setCursor(0,1);
lcd.clear();
//lcd.print(" ");
}
heres the last of the code
void readButtons(){ //read buttons status
int reading;
int buttonEnterState=LOW; // the current reading from the Enter input pin
int buttonEscState=LOW; // the current reading from the input pin
int buttonLeftState=LOW; // the current reading from the input pin
int buttonRightState=LOW; // the current reading from the input pin
//Enter button
// read the state of the switch into a local variable:
reading = digitalRead(buttonPinEnter);
// check to see if you just pressed the enter button
// (i.e. the input went from LOW to HIGH), and you've waited
// long enough since the last press to ignore any noise:
// If the switch changed, due to noise or pressing:
if (reading != lastButtonEnterState) {
// reset the debouncing timer
lastEnterDebounceTime = millis();
}
if ((millis() - lastEnterDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer
// than the debounce delay, so take it as the actual current state:
buttonEnterState=reading;
lastEnterDebounceTime=millis();
}
// save the reading. Next time through the loop,
// it'll be the lastButtonState:
lastButtonEnterState = reading;
//Esc button
// read the state of the switch into a local variable:
reading = digitalRead(buttonPinEsc);
// check to see if you just pressed the Down button
// (i.e. the input went from LOW to HIGH), and you've waited
// long enough since the last press to ignore any noise:
// If the switch changed, due to noise or pressing:
if (reading != lastButtonEscState) {
// reset the debouncing timer
lastEscDebounceTime = millis();
}
if ((millis() - lastEscDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer
// than the debounce delay, so take it as the actual current state:
buttonEscState = reading;
lastEscDebounceTime=millis();
}
// save the reading. Next time through the loop,
// it'll be the lastButtonState:
lastButtonEscState = reading;
//Down button
// read the state of the switch into a local variable:
reading = digitalRead(buttonPinRight);
// check to see if you just pressed the Down button
// (i.e. the input went from LOW to HIGH), and you've waited
// long enough since the last press to ignore any noise:
// If the switch changed, due to noise or pressing:
if (reading != lastButtonRightState) {
// reset the debouncing timer
lastRightDebounceTime = millis();
}
if ((millis() - lastRightDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer
// than the debounce delay, so take it as the actual current state:
buttonRightState = reading;
lastRightDebounceTime =millis();
}
// save the reading. Next time through the loop,
// it'll be the lastButtonState:
lastButtonRightState = reading;
//Up button
// read the state of the switch into a local variable:
reading = digitalRead(buttonPinLeft);
// check to see if you just pressed the Down button
// (i.e. the input went from LOW to HIGH), and you've waited
// long enough since the last press to ignore any noise:
// If the switch changed, due to noise or pressing:
if (reading != lastButtonLeftState) {
// reset the debouncing timer
lastLeftDebounceTime = millis();
}
if ((millis() - lastLeftDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer
// than the debounce delay, so take it as the actual current state:
buttonLeftState = reading;
lastLeftDebounceTime=millis();
;
}
// save the reading. Next time through the loop,
// it'll be the lastButtonState:
lastButtonLeftState = reading;
//records which button has been pressed
if (buttonEnterState==HIGH){
lastButtonPushed=buttonPinEnter;
}
else if(buttonEscState==HIGH){
lastButtonPushed=buttonPinEsc;
}
else if(buttonRightState==HIGH){
lastButtonPushed=buttonPinRight;
}
else if(buttonLeftState==HIGH){
lastButtonPushed=buttonPinLeft;
}
else{
lastButtonPushed=0;
}
}
void navigateMenus() {
MenuItem currentMenu=menu.getCurrent();
switch (lastButtonPushed){
case buttonPinEnter:
if(!(currentMenu.moveDown())){ //if the current menu has a child and has been pressed enter then menu navigate to item below
menu.use();
}
else{ //otherwise, if menu has no child and has been pressed enter the current menu is used
menu.moveDown();
}
break;
case buttonPinEsc:
menu.toRoot(); //back to main
break;
case buttonPinRight:
menu.moveRight();
break;
case buttonPinLeft:
menu.moveLeft();
break;
}
lastButtonPushed=0; //reset the lastButtonPushed variable
}
The code has been posted. I need help trying to reduce the sram usage. I can't seem to add more menu items because it''ll use up more memory and crash so i deleted the menu that I had created last week. I need to figure out the proper way of using progmem for my program to optimize it so I can add in more menu and functions. I've read a couple of post and tried to mirror what they had but it did not work for me. I think something is missing somewhere. I was at about 19k bytes when it started to crash.
Goal: reduce memory usage by using progmem so more menu setups/items and functions can be added.
Purpose: read sensor and out put to the LCD screen.
If anyone can give me an idea of how to use progmem, I will test it out. I've tried it based on what others posted in the forums here but it did not work.
void sensorafr(){
//----------------------------sensor Section------------------------------------------
//sensor section input, calculations and output
float sst = analogRead(A0); // make variable sst equal to analog value from pin A0
float sstoutput = (sst-0)*(43.51508-(-10))/(1023+ (-10)); //converting analog input to sensor value
float sstoutput1 = sstoutput - aaa; //
float vacoutput = 0;
lcd.setCursor(0,1); // set cursor to first column row 2
vacoutput = sstoutput1 * 2.036021; // convert
if (vacoutput <= (-10)){ //if sstoutput1 is less than or equal to -10 value, then run the following
lcd.setCursor(0,1); // set cursor to column 0 row 2
lcd.print("SEN:"); //print to the LCD
lcd.print(vacoutput,1); // print the sensor value
delay(50); //set delay
}
else if ((vacoutput < 0 ) && (vacoutput > (-10))) { //set condition if value is less than 0 and more than or equal -9 then use VAC
lcd.setCursor(0,1); //set cursor to column 0 row 2
lcd.print("SEN: "); //print on LCD
lcd.print(vacoutput,1); // print the sensor value
delay(50); //set delay
}
else if ((sstoutput1 < 10) && (sstoutput1 >= 0)) { //set condition so if sensor if less than 10 and greater than 0, then the sst adds in an extra space so that it'll display correctly and not shift
lcd.print("SEN: "); //Print sst to LCD
lcd.print(sstoutput1,1); // print sensor value to LCD. the one means to print one decimal point only
delay(50); //delay for .1sec
}
else {
lcd.print("SEN: "); // print sst
lcd.print(sstoutput1,1); // print sensor output value
delay(50); // set delay
}
//---------------------------PEAK sensor------------------------------------------
if(sstoutput1 > peaksensor) { // check to see if sensor if higher than peak sensor
peaksensor = sstoutput1; // make peaksensor equal to current sensor if condition is true
}
if (peaksensor < 10 ) { // check the peak sensor value. If less than 10, then do the following statement
lcd.print(" "); //put a space after sensor value
lcd.print("PB"); // print PB for peak sensor
lcd.print(" "); // put a space after sensor value
lcd.print(peaksensor,1); // print peak sensor value
}
else {
lcd.print(" "); //put a space after sensor value
lcd.print("PB"); // print PB for peak sensor
lcd.print(peaksensor,1); // print peak sensor value
}
//-------------------------- Peaksensor Clear------------------------------------------
if ( digitalRead(clearPB) == HIGH) { // if button is pressed, then the peaksensor resets to zero
peaksensor = 0; // set peaksensor back to zero
}
//---------------------------------- LCD BAR ---------------------------------------
//sensor LCD Bar
//lcd.setCursor(10,1); //set bar graph to start on column 10 row 2
//lbg.drawValue(analogRead(sensorbar), 600);
// Sensor Ratio LCD Bar
lcd.setCursor(9,0); //set cursor to column 10 row 1
lbg.drawValue(analogRead(afrbar), 1023); //bar graph output
//------------------------------------------------------------------------------
// Input, Calculation and output
float afrValue = analogRead(A1); //Read input
float afroutput = (afrValue-0)*(22-8)/(1023-0) +8; // convert values
//Serial.println("AFR Output:");
//Serial.println(afroutput); // print out the value you read:
//Serial.println("AFR Value:");
//Serial.println(afrValue);
lcd.setCursor(0,0); // Print to LCD top Left
if (afroutput < 10) {
lcd.print("LVL: ");
lcd.print(afroutput,1);
//delay(50);
}
else {
lcd.print("LVL: ");
lcd.print(afroutput,1);
//delay(50);
}
//------------------------------sensor Warning--------------------------------
if (sstoutput1 >= sstwarn) {
lcd.noDisplay();// Turn off the display
delay(400);
lcd.display();// Turn on the display
delay(300);
}
}
You know you can attach a file to a forum posting? Click on "Additional Options" below the post and use the Attach option.
Which version of the IDE is in use?
Some simple things such as replacing
lcd.setCursor(0,0);
lcd.print("Saving. ");
delay(500);
lcd.setCursor(0,0);
lcd.print("Saving.. ");
delay(500);
lcd.setCursor(0,0);
lcd.print("Saving... ");
delay(500);
lcd.setCursor(0,0);
lcd.print("Saving.... ");
delay(500);
lcd.setCursor(0,0);
lcd.print("Saving..... ");
delay(500);
lcd.setCursor(0,0);
lcd.print("Saving......");
lcd.setCursor(0,0);
with a loop that adds the requisite numbre of dots/spaces will mean you only need 3 string ("Saving","."and," ") so using 1/6 of the storage you currently use might help.
You can also use the F() macro to avoid copying strings to SRAM when you are print()'ing them, i.e.:
lcd.print (F("Saving"));
I saw it after I copied/pasted the code in so I just left it.
Hopefully someone has an insight progmem with menubackend.
Here are pieces of code I used to put menu into PROGMEM. I also put error messages, etc, there.
You need some #includes to use PROGMEM:
#include <avr/io.h>
#include <avr/pgmspace.h>
Here I have a 7 line menu (80 characters per line) stored to PROGMEM, and a special pointer to get the data with:
const char PROGMEM usageMsg[][80] = { // all this text stored in flash
" Piezo touch sensor tuner.",
"Adjust vertical; enter W to subtract or X to add, and a number 0-255",
"Adjust timescaler; enter A to subtract or D to add, and 0-16535",
"to add 250 to vertical enter W250 in Serial Monitor and press enter",
"seperate multiple commands with spaces; ex: W25 D240",
" ** this message stored in flash ram **",
" ** and printed with a 1 byte buffer ** :-P"
};
PGM_P Msg; // pointer into flash memory
The full program stores -every- const char string (not C++ String!) in PROGMEM. It has serial user I/O error messages, etc, as well as the menu.
I made this function to print the stored strings one char at a time:
void printMsg( PGM_P FM )
{
do
{
B = pgm_read_byte( FM++ ); // FM++ is pointer math; look Ma, no indexes!
if ( B ) Serial.print( B );
}
while ( B ); // when it reaches the terminating zero, it exits
}
And this function just to print the whole menu:
void printHelp(void)
{
for ( byte i = 0; i < HELPLINES; i++ )
{
printMsg( usageMsg[ i ]);
Serial.println();
}
Serial.println();
}
SukkoPera:
You can also use the F() macro to avoid copying strings to SRAM when you are print()'ing them, i.e.:lcd.print (F("Saving"));
I'm going to try this out. Thanks SukkoPera.
Countrypaul. I will take a stab at it and you are right; it should reduce the code and sram some more. I'm using the lastest IDE version on an uno v3.
thanks
countrypaul:
Which version of the IDE is in use?Some simple things such as replacing
lcd.setCursor(0,0);
lcd.print("Saving. ");
delay(500);
lcd.setCursor(0,0);
lcd.print("Saving.. ");
delay(500);
lcd.setCursor(0,0);
lcd.print("Saving... ");
delay(500);
lcd.setCursor(0,0);
lcd.print("Saving.... ");
delay(500);
lcd.setCursor(0,0);
lcd.print("Saving..... ");
delay(500);
lcd.setCursor(0,0);
lcd.print("Saving......");
lcd.setCursor(0,0);
with a loop that adds the requisite numbre of dots/spaces will mean you only need 3 string ("Saving","."and," ") so using 1/6 of the storage you currently use might help.
This really helped alot. I went from 98 available sram to 477 available.
SukkoPera:
You can also use the F() macro to avoid copying strings to SRAM when you are print()'ing them, i.e.:lcd.print (F("Saving"));
countrypaul,
I went ahead and took your advice and shorten the code to
lcd.clear();
lcd.setCursor(0,1);
lcd.print(used.item.getName());
lcd.setCursor(0,0);
lcd.print(F("Saving"));
//print dots for saving mode
for (byte i = 0; i < 14;i++ ){
lcd.print(F("."));
I'm reducing flash memory and sram usage. Now I need to get progmem working for the menu. Thanks!
GoForSmoke:
I made this function to print the stored strings one char at a time:void printMsg( PGM_P FM )
{
do
{
B = pgm_read_byte( FM++ ); // FM++ is pointer math; look Ma, no indexes!
if ( B ) Serial.print( B );
}
while ( B ); // when it reaches the terminating zero, it exits
}
This could be actually shortened down to:
void printMsg( PGM_P FM )
{
Serial.print (reinterpret_cast<__FlashStringHelper *> (FM));
}
It would be better to do the same thing with a macro, thought. Or even always doing the cast explicitly.
PS: Use lowercase - and meaningul - names for variables (i.e.: FM -> str).
I don't worry about long names inside such a short, transparent function. If anything, just to not be distracted. It's easier for me to associate the type (the Important Part) with a short name than with a long name for such brief use. When you've done dozens of those a day for weeks it gets to be apparent but a psychology prof or student can tell you the same.
Long names are better for code that runs a screen or more and for globals but are not any kind of universal better IME. Your mileage may vary. I've seen people who won't debug 20 lines of code without a flowchart and a staff meeting; they would long-name everything.
FM is flashMemory... perhaps it should be FMP or full length for finger exercise?
I have never seen the like of reinterpret_cast<__FlashStringHelper *> (FM). Where are docs for that and what-all includes are necessary? Why wouldn't it be better to ditch the printMsg function totally and just inline the print statement?
Will it work with IDE 0022? My Arduino as ISP works with 0022 and I don't feel safe with 1.0.
The reinterpret_cast thing works because of how serial.Print() is implemented, but it would be too long to explain here :). Ditching the printMSG() function would be great, IMHO! I'm not sure it works with 0022, as I started with 1.0.1 :).
Of course using that name in such a short function won't be a problem, but once you start using clever names, you tend to always do that, and then it never hurts, in particular if other people will be reading your code.
Noted. But really I use long names for important things or what isn't right close to see. I went through a couple years of interpreter basic where variables were single letter with number combinations so yeah, I know how bad it can get. But that was over 30 years ago, "I feel Much Better now" (John Aston Night Court line, I'm saying the old var names were a bit insane), LOL!
Some time I should try 1.01 Arduino as ISP and if it works, switch. There were too many maybes for me with 1.0 when it came out. Some of the improvements like what you show are awfully tempting.