Помогите сократить использование динамической памяти с помощью библиотеки LoRa
Я объединил код, который считывает частоту сердечных сокращений и SPO2, а затем отправляет данные с помощью LoRaWAN. Использую эти 2 библиотеки, которые хорошо работают сами по себе LoraWAN lib | MAX30102 lib. Моя плата — Arduino Pro или Pro Mini с процессором ATmega 328P (3,3 В, 8 МГц).
Глобальные переменные используют 2098 байт (102%) динамической памяти, оставляя -50 байт для локальных переменных. Максимум 2048 байт
Я пробовал уменьшить размер массива символов до 8, удалив некоторые вещи Serial.print, и лучшее, что я смог получить, это ровно 2048 байт и загрузка, но она не запускается. Вот мой код Arduino:
#include <DFRobot_MAX30102.h>
#include <lorawan.h>
DFRobot_MAX30102 particleSensor;
//Учетные данные ABP
const char *devAddr = "27FD.....";
const char *nwkSKey = "9E74A99C9FE480........................";
const char *appSKey = "E2A779DC190B343.......................";
const unsigned long interval = 20000; // 10-секундный интервал для отправки сообщения
unsigned long previousMillis = 0; // сохранит время последней отправки сообщения
char myStr[50];
const sRFM_pins RFM_pins = {
.CS = 10,
.RST = 9,
.DIO0 = 2,
.DIO1 = 6,
};
void setup() {
//Инициализация серийного номера
Serial.begin(115200);
lora.init();
particleSensor.begin();
particleSensor.sensorConfiguration(/*ledBrightness=*/50, /*sampleAverage=*/SAMPLEAVG_4, \
/*ledMode=*/MODE_MULTILED, /*sampleRate=*/SAMPLERATE_100, \
/*pulseWidth=*/PULSEWIDTH_411, /*adcRange=*/ADCRANGE_16384);
// Установить изменение класса LoRaWAN CLASS_A или CLASS_C
lora.setDeviceClass(CLASS_C);
// Установить скорость передачи данных
lora.setDataRate(SF12BW125);
// установить канал случайным образом
lora.setChannel(MULTI);
// Поместите здесь ключ ABP и адрес устройства
lora.setNwkSKey(nwkSKey);
lora.setAppSKey(appSKey);
lora.setDevAddr(devAddr);
}
int32_t SPO2; //SPO2
int8_t SPO2Valid; //Флаг для отображения, если расчет SPO2 действителен
int32_t heartRate; //Частота сердечных сокращений
int8_t heartRateValid; //Флаг для отображения, если расчет частоты сердечных сокращений действителен
void loop() {
if(millis() - previousMillis > interval) {
previousMillis = millis();
particleSensor.heartrateAndOxygenSaturation(/**SPO2=*/&SPO2, /**SPO2Valid=*/&SPO2Valid, /**heartRate=*/&heartRate, /**heartRateValid=*/&heartRateValid);
//Распечатать результат
Serial.print(heartRate, DEC);
Serial.println(SPO2, DEC);
sprintf(myStr, "%d,%d", heartRate,SPO2);
Serial.print(F("Send: "));
Serial.println(myStr);
lora.sendUplink(myStr, strlen(myStr), 0);
}
lora.update();
}
@Inversionist, 👍-1
Обсуждение1 ответ
Судя по исходному коду, ваш скетч не выглядит слишком требовательным к оперативной памяти. все. Высокое использование оперативной памяти почти наверняка происходит из-за библиотек, которые вы используют. Кроме использования разных библиотек или другой платы, У вас здесь нет особых рычагов влияния.
В самом скетче единственное, что выделяется — это myStr
массив, который вы могли бы сделать намного меньше. Кроме этого, я предлагаю
перемещение константных строк devAddr
, nwkSKey
и appSKey
в
PROGMEM и копирование их в оперативную память только при необходимости:
const char devAddr[] PROGMEM = "27FD.....";
// и так далее для nwkSKey и appSKey
void setup() {
// ...
char buffer[39]; // буфер RAM для nwkSKey, appSKey и devAddr
memcpy_P(buffer, nwkSKey, sizeof nwkSKey);
lora.setNwkSKey(nwkSKey);
memcpy_P(buffer, appSKey, sizeof appSKey);
lora.setAppSKey(appSKey);
memcpy_P(buffer, devAddr, sizeof devAddr);
lora.setDevAddr(devAddr);
}
Таким образом, три строки разделяют одно и то же пространство оперативной памяти, которое освобождается как
как только setup()
вернется.
Кроме этого, вы можете попробовать отправить данные в двоичном формате вместо ASCII. Хотя я не уверен, что это сэкономит много оперативной памяти:
void loop() {
// ...
struct {
int32_t heartRate;
int32_t SPO2;
} loraPacket;
char dummy;
particleSensor.heartrateAndOxygenSaturation(
/** SPO2 = */ &loraPacket.SPO2,
/** SPO2Valid = */ &dummy,
/** heartRate = */ &loraPacket.heartRate,
/** heartRateValid=*/ &dummy);
lora.sendUplink(loraPacket, strlen(loraPacket), 0);
}
Это позволит вам удалить переменную myStr
ценой необходимости
изменить код получателя и усложнить протокол связи
читать.
Редактировать: Если вы не против модификации библиотеки DFRobot_MAX30102, вы
можно сэкономить 184 байта оперативной памяти, сохранив uch_spo2_table
в PROGMEM:
// In src/SPO2/algorithm.h, add PROGMEM:
const uint8_t uch_spo2_table[184] PROGMEM = {/* ... */ };
// In src/SPO2/algorithm.h, line 199, add pgm_read_byte():
n_spo2_calc = pgm_read_byte(&uch_spo2_table[n_ratio_average]);
- Есть ли способ подключить оперативную память компьютера к Arduino?
- Последовательная печать из флэш-памяти (F() macro, PROGMEM, sprintf_P, SPTR)
- Есть ли способ добавить внешнюю оперативную память (скажем, 100 МБ или 200 МБ) в этом контексте микширования аудиобуфера?
- Как уменьшить использование глобальных переменных? Attiny85
- Подключить SDRAM к STM32
- ЛДЦ в паре с Ардуино зависает и зависает. Закончились СПРАМ?
- Оперативная память стоимость ввода функций
- Как заставить BLE и WiFi IoT работать с памятью без проблем ?
Замена
sprintf()
была бы шагом в правильном направлении., @VE7JROЯ пробовал удалить sprintf, все равно слишком много памяти, @Inversionist
Конечно, вам не нужен int32 для хранения чьего-то пульса. И вам не нужен буфер в 50 символов для записи двух целых чисел., @Delta_G
Зачем вообще хранить это в буфере? Просто выведите heartRate, пробел и SPO2 тремя отдельными выводами и избавьтесь от sprintf И буфера., @Delta_G
А также на forum.arduino.cc и привлечении там внимания., @Delta_G
Я голосую за закрытие этого вопроса, поскольку он привлекает внимание на другом форуме., @Delta_G
@Delta_G это не является веской причиной для закрытия вопроса здесь, @Juraj
Тогда не голосуйте таким образом., @Delta_G
Найдите еще одну библиотеку Max30102, в ней спрятаны два буфера, которые заняли [800 байт памяти](https://github.com/DFRobot/DFRobot_MAX30102/blob/master/src/SPO2/algorithm.h#L83-L84)., @hcheung