Уменьшение размера программирования функций
У меня есть код Arduino, который использует библиотеку I2CDev для управления MPU-6050. Я новичок в кодировании и скопировал и вставил большую часть кода из примеров, которые нашел. У меня начинает заканчиваться место для программирования на моем Arduino, и я обнаружил, что одна строка кода занимает 21%, или 6000 байт памяти программирования. Я нашел функцию, к которой относилась эта строка, и показал ее ниже.
Ссылку на библиотеку I2CDev можно также найти на Github здесь: https://github.com/jrowberg/i2cdevlib
Есть ли способ уменьшить его? Может кто-нибудь объяснить мне, почему он занимает так много места? Спасибо!
uint8_t MPU6050::dmpInitialize() {
// сброс устройства
DEBUG_PRINTLN(F("\n\nResetting MPU6050..."));
reset();
delay(30); // ждем после сброса
// включить режим сна и цикл пробуждения
/*Serial.println(F("Enabling sleep mode..."));
setSleepEnabled(true);
Serial.println(F("Enabling wake cycle..."));
setWakeCycleEnabled(true);*/
// отключить спящий режим
DEBUG_PRINTLN(F("Disabling sleep mode..."));
setSleepEnabled(false);
// получить аппаратную версию MPU
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);
// проверка OTP банка на действительность
DEBUG_PRINTLN(F("Reading OTP bank valid flag..."));
DEBUG_PRINT(F("OTP bank is "));
DEBUG_PRINTLN(getOTPBankValid() ? F("valid!") : F("invalid!"));
// получить смещения гироскопа X/Y/Z
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);
// настройка странных рабских штучек (?)
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);
// загрузить код DMP в банки памяти
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."));
// запись конфигурации DMP
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); // 1 кГц/(1 + 4) = 200 Гц
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"));
//записать начальный адрес MSB в регистр
setDMPConfig1(0x03);
//записать начальный адрес LSB в регистр
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: правильный код ошибки при отсутствии памяти
}*/
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; // загрузка блока конфигурации не удалась
}
} else {
DEBUG_PRINTLN(F("ERROR! DMP code verification failed."));
return 1; // загрузка основного двоичного блока не удалась
}
return 0; // успех
}
@M.Schindler, 👍0
1 ответ
Лучший ответ:
Одна строка кода не использует 6000 байт памяти. Однако если она вызывает функцию, которая в противном случае не была бы вызвана, то компилятор должен включить функцию.
Так, например, если у вас есть функция, которая занимает 6000 байт, но вы ее не вызываете, то компилятор может пропустить саму функцию.
Предположим, что DEBUG_PRINTLN что-то делает, тогда я насчитаю там 2480 байт строковых литералов. Следовательно, ваша функция займет как минимум 2480 байт. И это вызывается 71 раз, так что если DEBUG_PRINTLN занимает (скажем) 10 байт для вызова каждый раз, это еще 710 байт. Мы уже достигли 3190 байт. Другие вещи (не связанные с отладкой) также, вероятно, занимают довольно много байт.
У меня начинает заканчиваться место для программирования на моем Arduino
Это не проблема, пока у вас фактически не закончится место. Кого волнует, что вы используете 99% доступной памяти?
Тот факт, что что-то вызывает скачок в использовании памяти, сам по себе не является причиной для беспокойства. Например, этот набросок:
void setup() {
Serial.begin(115200);
int a;
Serial.println (a);
}
void loop() { }
Скомпилировал для Uno с использованием IDE 1.6.9 и получил:
Sketch uses 2,122 bytes (6%) of program storage space. Maximum is 32,256 bytes.
Итак, 2122 байта. Теперь измените a
на float:
void setup() {
Serial.begin(115200);
float a;
Serial.println (a);
}
void loop() { }
Теперь он использует 3668 байт:
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.
Однако, если вы добавите вторую такую переменную, это не займет еще 1546 байт.
void setup() {
Serial.begin(115200);
float a;
float b;
Serial.println (a);
Serial.println (b);
}
void loop() { }
Это использует всего лишь еще 18 байт:
Sketch uses 3,686 bytes (11%) of program storage space. Maximum is 32,256 bytes.
Другими словами, библиотека с плавающей точкой теперь включена компилятором. Это единовременный скачок в использовании. Конечно, если я сейчас что-то сделаю с I2C, произойдет еще один скачок, поскольку будет загружена эта дополнительная библиотека.
- Как подключить MPU9250 к NodeMCU с помощью SPI или I2C Slave?
- Изменение адреса I2C MPU-6050
- MPU6050 не выдает выход
- MPU-9250 IMU на SPI, внешнем датчике или магнитометре с использованием мастера I2C
- Использование MPU-6050 без I2C
- Почему Wire.write дважды?
- Сбой при записи данных MPU-6050 на SD-карту
- Мультиплексор Adafruit MPU-6050 и adafruit I2C