0

I have Arduino Code that utilizes the I2CDev library to control an MPU-6050. I am pretty new to coding and copied and pasted most of the code from examples I have found around. I am starting to run out of programming space on my Arduino, and I have found that one line of the code takes up 21%, or 6000 bytes of the programming memory. I found the function that the line related to and I have it shown below.

The link to the I2CDev libarary can be found on Github here as well: https://github.com/jrowberg/i2cdevlib

Is there a way to decrease it? Ot can someone explain to me why it is taking up so much space? Thanks!

uint8_t MPU6050::dmpInitialize() {
// reset device
DEBUG_PRINTLN(F("\n\nResetting MPU6050..."));
reset();
delay(30); // wait after reset

// enable sleep mode and wake cycle
/*Serial.println(F("Enabling sleep mode..."));
setSleepEnabled(true);
Serial.println(F("Enabling wake cycle..."));
setWakeCycleEnabled(true);*/

// disable sleep mode
DEBUG_PRINTLN(F("Disabling sleep mode..."));
setSleepEnabled(false);

// get MPU hardware revision
DEBUG_PRINTLN(F("Selecting user bank 16..."));
setMemoryBank(0x10, true, true);
DEBUG_PRINTLN(F("Selecting memory byte 6..."));
setMemoryStartAddress(0x06);
DEBUG_PRINTLN(F("Checking hardware revision..."));
DEBUG_PRINT(F("Revision @ user[16][6] = "));
DEBUG_PRINTLNF(readMemoryByte(), HEX);
DEBUG_PRINTLN(F("Resetting memory bank selection to 0..."));
setMemoryBank(0, false, false);

// check OTP bank valid
DEBUG_PRINTLN(F("Reading OTP bank valid flag..."));
DEBUG_PRINT(F("OTP bank is "));
DEBUG_PRINTLN(getOTPBankValid() ? F("valid!") : F("invalid!"));

// get X/Y/Z gyro offsets
DEBUG_PRINTLN(F("Reading gyro offset TC values..."));
int8_t xgOffsetTC = getXGyroOffsetTC();
int8_t ygOffsetTC = getYGyroOffsetTC();
int8_t zgOffsetTC = getZGyroOffsetTC();
DEBUG_PRINT(F("X gyro offset = "));
DEBUG_PRINTLN(xgOffsetTC);
DEBUG_PRINT(F("Y gyro offset = "));
DEBUG_PRINTLN(ygOffsetTC);
DEBUG_PRINT(F("Z gyro offset = "));
DEBUG_PRINTLN(zgOffsetTC);

// setup weird slave stuff (?)
DEBUG_PRINTLN(F("Setting slave 0 address to 0x7F..."));
setSlaveAddress(0, 0x7F);
DEBUG_PRINTLN(F("Disabling I2C Master mode..."));
setI2CMasterModeEnabled(false);
DEBUG_PRINTLN(F("Setting slave 0 address to 0x68 (self)..."));
setSlaveAddress(0, 0x68);
DEBUG_PRINTLN(F("Resetting I2C Master control..."));
resetI2CMaster();
delay(20);

// load DMP code into memory banks
DEBUG_PRINT(F("Writing DMP code to MPU memory banks ("));
DEBUG_PRINT(MPU6050_DMP_CODE_SIZE);
DEBUG_PRINTLN(F(" bytes)"));
if (writeProgMemoryBlock(dmpMemory, MPU6050_DMP_CODE_SIZE)) {
    DEBUG_PRINTLN(F("Success! DMP code written and verified."));

    // write DMP configuration
    DEBUG_PRINT(F("Writing DMP configuration to MPU memory banks ("));
    DEBUG_PRINT(MPU6050_DMP_CONFIG_SIZE);
    DEBUG_PRINTLN(F(" bytes in config def)"));
    if (writeProgDMPConfigurationSet(dmpConfig, MPU6050_DMP_CONFIG_SIZE)) {
        DEBUG_PRINTLN(F("Success! DMP configuration written and verified."));

        DEBUG_PRINTLN(F("Setting clock source to Z Gyro..."));
        setClockSource(MPU6050_CLOCK_PLL_ZGYRO);

        DEBUG_PRINTLN(F("Setting DMP and FIFO_OFLOW interrupts enabled..."));
        setIntEnabled(0x12);

        DEBUG_PRINTLN(F("Setting sample rate to 200Hz..."));
        setRate(4); // 1khz / (1 + 4) = 200 Hz

        DEBUG_PRINTLN(F("Setting external frame sync to TEMP_OUT_L[0]..."));
        setExternalFrameSync(MPU6050_EXT_SYNC_TEMP_OUT_L);

        DEBUG_PRINTLN(F("Setting DLPF bandwidth to 42Hz..."));
        setDLPFMode(MPU6050_DLPF_BW_42);

        DEBUG_PRINTLN(F("Setting gyro sensitivity to +/- 2000 deg/sec..."));
        setFullScaleGyroRange(MPU6050_GYRO_FS_2000);

        DEBUG_PRINTLN(F("Setting DMP programm start address"));
        //write start address MSB into register
        setDMPConfig1(0x03);
        //write start address LSB into register
        setDMPConfig2(0x00);

        DEBUG_PRINTLN(F("Clearing OTP Bank flag..."));
        setOTPBankValid(false);

        DEBUG_PRINTLN(F("Setting X/Y/Z gyro offset TCs to previous values..."));
        setXGyroOffsetTC(xgOffsetTC);
        setYGyroOffsetTC(ygOffsetTC);
        setZGyroOffsetTC(zgOffsetTC);

        DEBUG_PRINTLN(F("Setting X/Y/Z gyro user offsets to zero..."));
        //setXGyroOffset(0);
        //setYGyroOffset(0);
        //setZGyroOffset(0);

        DEBUG_PRINTLN(F("Writing final memory update 1/7 (function unknown)..."));
        uint8_t dmpUpdate[16], j;
        uint16_t pos = 0;
        for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
        writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);

        DEBUG_PRINTLN(F("Writing final memory update 2/7 (function unknown)..."));
        for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
        writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);

        DEBUG_PRINTLN(F("Resetting FIFO..."));
        resetFIFO();

        DEBUG_PRINTLN(F("Reading FIFO count..."));
        uint16_t fifoCount = getFIFOCount();
        uint8_t fifoBuffer[128];

        DEBUG_PRINT(F("Current FIFO count="));
        DEBUG_PRINTLN(fifoCount);
        getFIFOBytes(fifoBuffer, fifoCount);

        DEBUG_PRINTLN(F("Setting motion detection threshold to 2..."));
        setMotionDetectionThreshold(2);

        DEBUG_PRINTLN(F("Setting zero-motion detection threshold to 156..."));
        setZeroMotionDetectionThreshold(156);

        DEBUG_PRINTLN(F("Setting motion detection duration to 80..."));
        setMotionDetectionDuration(80);

        DEBUG_PRINTLN(F("Setting zero-motion detection duration to 0..."));
        setZeroMotionDetectionDuration(0);

        DEBUG_PRINTLN(F("Resetting FIFO..."));
        resetFIFO();

        DEBUG_PRINTLN(F("Enabling FIFO..."));
        setFIFOEnabled(true);

        DEBUG_PRINTLN(F("Enabling DMP..."));
        setDMPEnabled(true);

        DEBUG_PRINTLN(F("Resetting DMP..."));
        resetDMP();

        DEBUG_PRINTLN(F("Writing final memory update 3/7 (function unknown)..."));
        for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
        writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);

        DEBUG_PRINTLN(F("Writing final memory update 4/7 (function unknown)..."));
        for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
        writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);

        DEBUG_PRINTLN(F("Writing final memory update 5/7 (function unknown)..."));
        for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
        writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);

        DEBUG_PRINTLN(F("Waiting for FIFO count > 2..."));
        while ((fifoCount = getFIFOCount()) < 3);

        DEBUG_PRINT(F("Current FIFO count="));
        DEBUG_PRINTLN(fifoCount);
        DEBUG_PRINTLN(F("Reading FIFO data..."));
        getFIFOBytes(fifoBuffer, fifoCount);

        DEBUG_PRINTLN(F("Reading interrupt status..."));

        DEBUG_PRINT(F("Current interrupt status="));
        DEBUG_PRINTLNF(getIntStatus(), HEX);

        DEBUG_PRINTLN(F("Reading final memory update 6/7 (function unknown)..."));
        for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
        readMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);

        DEBUG_PRINTLN(F("Waiting for FIFO count > 2..."));
        while ((fifoCount = getFIFOCount()) < 3);

        DEBUG_PRINT(F("Current FIFO count="));
        DEBUG_PRINTLN(fifoCount);

        DEBUG_PRINTLN(F("Reading FIFO data..."));
        getFIFOBytes(fifoBuffer, fifoCount);

        DEBUG_PRINTLN(F("Reading interrupt status..."));

        DEBUG_PRINT(F("Current interrupt status="));
        DEBUG_PRINTLNF(getIntStatus(), HEX);

        DEBUG_PRINTLN(F("Writing final memory update 7/7 (function unknown)..."));
        for (j = 0; j < 4 || j < dmpUpdate[2] + 3; j++, pos++) dmpUpdate[j] = pgm_read_byte(&dmpUpdates[pos]);
        writeMemoryBlock(dmpUpdate + 3, dmpUpdate[2], dmpUpdate[0], dmpUpdate[1]);

        DEBUG_PRINTLN(F("DMP is good to go! Finally."));

        DEBUG_PRINTLN(F("Disabling DMP (you turn it on later)..."));
        setDMPEnabled(false);

        DEBUG_PRINTLN(F("Setting up internal 42-byte (default) DMP packet buffer..."));
        dmpPacketSize = 42;
        /*if ((dmpPacketBuffer = (uint8_t *)malloc(42)) == 0) {
            return 3; // TODO: proper error code for no memory
        }*/

        DEBUG_PRINTLN(F("Resetting FIFO and clearing INT status one last time..."));
        resetFIFO();
        getIntStatus();
    } else {
        DEBUG_PRINTLN(F("ERROR! DMP configuration verification failed."));
        return 2; // configuration block loading failed
    }
} else {
    DEBUG_PRINTLN(F("ERROR! DMP code verification failed."));
    return 1; // main binary block loading failed
}
return 0; // success

}

  • Which line? Put a marker on it and refer to it in your question. – Nick Gammon May 21 '18 at 8:21
  • A lot of PLINTLN lines aren’t very useful. Most of them are just comments. Removing them or converting them to regular comments would reduce the size. – Gerben May 21 '18 at 8:58
  • 1
    There is no magic recipe for reducing the code size. The only general rule is: “remove everything that is not strictly needed”, but you cannot make use of that rule unless you really understand what the program is doing. You can start nevertheless by looking at which functions take up the most space. C.f. Determining which section of code uses the most flash. – Edgar Bonet May 21 '18 at 9:02
  • i know that you are new to coding ... i am just wondering why it did not occur to you to remove the DEBUG_PRINTLN( commands – jsotola May 21 '18 at 21:42
  • @jsotola, that was the first thing I tried but it didn't change the size of the code at all. – M.Schindler May 21 '18 at 21:48
0

One line of code doesn't use 6000 bytes of memory. However if it calls a function, which otherwise would not be called, then the compiler has to include the function.

So, for example, if you have a function that takes 6000 bytes, but don't call it, then the compiler can omit the function itself.


Assuming DEBUG_PRINTLN does something, then I count 2480 bytes of string literals there. Therefore your function would at the very least take up 2480 bytes. And that is called 71 times, so if DEBUG_PRINTLN takes (say) 10 bytes to call each time, that is another 710 bytes. We are already up to 3190 bytes. Other stuff (unrelated to debugging) also probably takes quite a few bytes.


I am starting to run out of programming space on my Arduino

That's not a problem until you actually run out of space. Who cares if you use 99% of available memory?


The fact that something causes a jump in memory usage is not, in itself, cause for worry. For example this sketch:

void setup() {
  Serial.begin(115200);
  int a;
  Serial.println (a);
}

void loop() {  }

Compiled for a Uno using IDE 1.6.9 I get:

Sketch uses 2,122 bytes (6%) of program storage space. Maximum is 32,256 bytes.

So, 2,122 bytes. Now change a to be float:

void setup() {
  Serial.begin(115200);
  float a;
  Serial.println (a);
}

void loop() {  }

Now it uses 3,668 bytes:

Sketch uses 3,668 bytes (11%) of program storage space. Maximum is 32,256 bytes. That's another 1,546 bytes just by changing one variable's type.

However it doesn't take another 1,546 bytes if you add a second such variable.

void setup() {
  Serial.begin(115200);
  float a;
  float b;
  Serial.println (a);
  Serial.println (b);
}

void loop() {  }

That only uses another 18 bytes:

Sketch uses 3,686 bytes (11%) of program storage space. Maximum is 32,256 bytes.

In other words, the floating-point library has now been included by the compiler. This is a once-off jump in usage. Of course, if I now do something with I2C there will be another jump as that additional library is loaded.

  • Yeah sorry for the misconfusion. The single line was in the arduino code. I then opened up the function that that line was referring to and pasted it above. My question is what in this function is taking up so much space? – M.Schindler May 21 '18 at 8:25
  • What in what function? Can you please be more explicit? – Nick Gammon May 21 '18 at 9:09
  • What does DEBUG_PRINTLN do? Try to post enough information to enable us to answer your question. – Nick Gammon May 21 '18 at 9:10
  • See my amended answer. – Nick Gammon May 21 '18 at 9:23
  • You could save a lot of memory by replacing those rather wordy debugging message with something like DEBUG_PRINTLN(F("1")) (and then 2 and so on) and have a spreadsheet that tells you which one each one means. You are working on a microcontroller, not a PC with 20 gigabytes of RAM. – Nick Gammon May 21 '18 at 9:24

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.