1

I have a Arduino sketch I made and I have run out of dynamic memory on my Arduino Nano. How could I possibly reduce the amount of memory the program takes? (I'm not that good at this stuff)

P.S: The code is here:

#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

const int chipSelect = 4;

#define OLED_RESET 5
Adafruit_SSD1306 display(OLED_RESET);

#if (SSD1306_LCDHEIGHT != 64)
#error("Fix Height");
#endif


/********************************************/

#define CHARWIDTH           5
#define CHARHEIGHT          8
#define AXISWIDTH           (2 + 1)                
#define VISIBLEVALUEPIXELS  (128 - AXISWIDTH)         
#define NUMVALUES           (2 * VISIBLEVALUEPIXELS) 

#define TRIGGER_ENABLE_PIN       2  
#define SCREEN_UPDATE_ENABLE_PIN 3  

byte values[NUMVALUES];        
int pos = 0;                     
int count = 0;                 
unsigned long readStartTime = 0; 
int sampleRate = 1;              

void displayln(const char* format, ...)
{
  char buffer[32];

  va_list args;
  va_start(args, format);
  vsprintf(buffer, format, args);
  va_end(args);

  int len = strlen(buffer);
  for (uint8_t i = 0; i < len; i++) {
    display.write(buffer[i]);
  }
}

// Draws the graph ticks for the vertical axis
void drawAxis()
{  
  // graph ticks
  for (int x = 0; x < 2; x++) {
    display.drawPixel(x,  0, WHITE);
    display.drawPixel(x, 13, WHITE);
    display.drawPixel(x, 26, WHITE);
    display.drawPixel(x, 38, WHITE);
    display.drawPixel(x, 50, WHITE);
    display.drawPixel(x, 63, WHITE);  
  }
}

// Draws the sampled values
void drawValues()
{
  int start = 0;

  if ( digitalRead(TRIGGER_ENABLE_PIN) ) {
    // Find the first occurence of zero
    for (int i = 0; i < NUMVALUES; i++) {
      if ( values[i] == 0 ) {
        // Now find the next value that is not zero
        for (; i < NUMVALUES; i++) {
          if ( values[i] != 0 ) {
            start = i;
            break;
          }
        }
        break;
      }
    }    
    // If the trigger point is not within half of our values, we will 
    // not have enough sample points to show the wave correctly
    if ( start >= VISIBLEVALUEPIXELS )
      return;
  }

  for (int i = 0; i < VISIBLEVALUEPIXELS; i++) {
    display.drawPixel(i + AXISWIDTH, 63 - (values[i + start]), WHITE);
  }
}

// Shows the time taken to sample the values shown on screen
void drawFrameTime(unsigned long us)
{
  display.setCursor(9 * CHARWIDTH, 7 * CHARHEIGHT - 2); // almost at bottom, approximately centered
  displayln("%ld us", us);
}

/********************************************/

void setup() {

  // Set up the display
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // Initialize with the I2C addr 0x3D (for the 128x64)
  display.setTextColor(WHITE);

  pinMode(TRIGGER_ENABLE_PIN, INPUT);
  pinMode(SCREEN_UPDATE_ENABLE_PIN, INPUT);
    // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }


  Serial.print("init start");


  if (!SD.begin(chipSelect)) {
    Serial.println("fail");
    // don't do anything more:
    while (1);
  }
  Serial.println("init ok");
}

/********************************************/

void loop() {

  // If a sampling run is about to start, record the start time
  if ( pos == 0 )
    readStartTime = micros();

  // If this iteration is one we want a sample for, take the sample
  if ( (++count) % sampleRate == 0 )
    values[pos++] = analogRead(0) >> 4; // shifting right by 4 efficiently maps 0-1023 range to 0-63

  // If we have filled the sample buffer, display the results on screen
  if ( pos >= NUMVALUES ) {
    // Measure how long the run took
    unsigned long totalSampleTime = (micros() - readStartTime) / 2;     // Divide by 2 because we are taking twice as many samples as are shown on the screen

    if ( !digitalRead(SCREEN_UPDATE_ENABLE_PIN) ) {
      // Display the data on screen   
      display.clearDisplay();
      drawAxis();
      drawValues();
      drawFrameTime(totalSampleTime);
      display.display();
    }

    // Reset values for the next sampling run
    pos = 0;
    count = 0;
  }
  String dataString = "";

  // read three sensors and append to the string:
  for (int analogPin = 0; analogPin < 3; analogPin++) {
    int sensor = analogRead(analogPin);
    dataString += String(sensor);
      dataString += ",";
  }

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
    // print to the serial port too:
    Serial.println(dataString);
  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  }
}
  • 3
    Don't use String. Put your string literals in flash with F(...). – Majenko Jan 1 at 21:43
  • 3
    1. Where is VISIBLEVALUEPIXELS defined? I get an 'undefined' error for it from the compiler when I try to compile your code. 2. Are you sure you're running out of program memory and not data memory? Please show the error message. Did it occur at compile time or at run time? – JRobert Jan 1 at 22:23
  • whoops. i accidentaly stuffed it up before and forgot to save – JustAnotherBitcoin Jan 2 at 0:50
  • THIS is the working code: – JustAnotherBitcoin Jan 2 at 0:51
  • Actuallly ill edit the post – JustAnotherBitcoin Jan 2 at 0:52
1

Few things to consider :

  • Each variable in your program take memory, try to use the smallest datatype ( don't use a float if you need an int for example).
  • Eliminate strings
  • Reduce the usage of array
  • Reduce your code size by using function for redudant task
  • Avoid using digital and analog red/write. Use port manipulation instead (link here)
  • Modify library to remove unused code inside
  • Use ICSP programmer instead of serial bootloader
  • Simplify your code for reducing its size.

Or simply ...

Use another board such as STM32 ou bigger ATmega chip with more RAM and bigger ROM size ...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.