Проблема кучи ESP32
Я написал простую программу на C++ (просто main.cpp и соответствующие platform.io файлы и библиотеки) для получения показаний датчика BME280. Это работало нормально, пока я не решил использовать хорошие методы программирования, используя заголовочные файлы и отделяя функцию чтения от main.cpp, я получаю ошибку кучи, указанную ниже:
CORRUPT HEAP: Bad head at 0x3ffb8444. Expected 0xabba1234 got 0x3ffb84c4
abort() was called at PC 0x40083b99 on core 1
ELF file SHA256: 0000000000000000
Backtrace:
0x400857f0:0x3ffb1aa0
0x40085a65:0x3ffb1ac0
0x40083b99:0x3ffb1ae0
0x40083cc5:0x3ffb1b10
0x400d90a3:0x3ffb1b30
0x400d55bd:0x3ffb1df0
0x400d5558:0x3ffb1e40
0x4008a0f1:0x3ffb1e70
0x40081dee:0x3ffb1e90
0x40083a91:0x3ffb1eb0
0x4000bec7:0x3ffb1ed0
0x400e89b5:0x3ffb1ef0
0x400d13ab:0x3ffb1f10
0x400d0f75:0x3ffb1f30
0x400d3ba9:0x3ffb1fb0
0x40086a75:0x3ffb1fd0
Rebooting...
Есть какие-нибудь идеи на этот счет?
Кстати, я также использовал указатели как для функции, так и для передаваемой ей переменной, но безрезультатно.
Я также попробовал ряд комбинаций с библиотеками, которые я использую - Adafruit BME280 и Adafruit Unified Sensor.
Возвращаясь к тому, что весь код в одном файле работает...
Спасибо
Мой код:
//main.cpp
#include <sensor_readings.h>
#include <settings.h>
void refresh_readings(); // Объявить в заголовке, чтобы компилятор знал об этом до того, как он будет вызван в loop()
Adafruit_BME280 bme; // I2C
void setup() {
pinMode(LED_BUILTIN,OUTPUT);
Serial.begin(9600);
bool status;
// (вы также можете передать объект Wire library, например &Wire2)
status = bme.begin(0x76);
if (!status) {
Serial.println("Не удалось найти действительный датчик BME280, проверьте проводку!");
while (1);
}
}
void loop() {
void (*fcnPtr)(Adafruit_BME280){ &refresh_readings };
(*fcnPtr)(bme);
//refresh_readings(bme);
delay(4000);
}
;platformio.ini
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
lib_deps =
Adafruit_Sensor
adafruit/Adafruit Unified [email protected]
adafruit/Adafruit BME280 Library@^2.2.2
upload_port = /dev/cu.SLAB_USBtoUART
monitor_port = /dev/cu.SLAB_USBtoUART
monitor_speed = 9600
//sensor_readings.cpp
#include <sensor_readings.h>
#include <settings.h>
void refresh_readings(Adafruit_BME280 bme) {
float f_temperature;
float f_humidity;
float f_pressure;
float f_altitude;
digitalWrite(LED_BUILTIN, HIGH);
f_temperature = bme.readTemperature();
f_humidity = bme.readHumidity();
f_pressure = bme.readPressure() / 100.0F;
f_altitude = bme.readAltitude(SEALEVELPRESSURE_HPA);
// Temperature
Serial.print(f_temperature);
Serial.println(" °C");
// Humidity
Serial.print(f_humidity);
Serial.println(" %");
// Pressure
Serial.print(f_pressure);
Serial.println(" hPa");
// Appx altitude
Serial.print(f_altitude);
Serial.println(" m");
digitalWrite(LED_BUILTIN, LOW);
Serial.println("------------");
}
//sensor_readings.h
#ifndef SENSOR_READINGS_H
#define SENSOR_READINGS_H
#include <Arduino.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#define SEALEVELPRESSURE_HPA (1013.25)
void refresh_readings(Adafruit_BME280 bme);
#endif
//settings.h
#ifndef SETTINGS_H
#define SETTINGS_H
#define LED_BUILTIN 2 // This is valid for my devkit
#endif
1 ответ
Есть пара проблем с вашим кодом.
void refresh_readings(); // Объявить в заголовке, чтобы
// компилятор знал об этом
// до того, как он будет вызван в loop ()
Это ложь! Не говорите компилятору, что существует функция refresh_readings, которая не принимает аргументов, если вы ее не определили. Удалите эту строку, у вас уже есть объявление функции в заголовке.
void (*fcnPtr)(Adafruit_BME280){ &refresh_readings };
(*fcnPtr)(bme);
Это просто очень запутанный способ ввода текста:
refresh_readings(bme);
Поэтому просто используйте обычный синтаксис вызова функции.
Однако главная проблема, насколько я могу судить, заключается в том, что вы копируете объект bme
при передаче его функции readings, что вообще не рекомендуется для такого рода объектов (они представляют собой аппаратную часть, которую вы не можете скопировать). В этом классе, в частности, есть куча членов указателя, деструктор, который удаляет их, но нет конструктора копирования, насколько я могу судить, и это плохо.
Измените свою функцию на эту подпись (как в заголовке, так и в файле C++):
void refresh_readings(Adafruit_BME280& bme);
// передать по ссылке ^
И используйте обычный синтаксис вызова (refresh_readings(bme);
).
- Безопасно ли использовать std::string (и выделение памяти в целом) для ESP32 Arduino?
- esp32, platformio A fatal error occurred: Packet content transfer stopped (received 8 bytes) *** [upload] Error 2
- Как выбрать альтернативные контакты I2C на ESP32?
- Драйверы для чипа последовательного порта CH9102X
- Как преобразовать форматированный оператор print в строковую переменную?
- ESP32 - "Детектор Браунаута был активирован" при запуске Wi-Fi
- Питание esp32cam от аккумулятора
- Контакты RX и TX на esp32
Дорогой Мэт, большое вам спасибо, что нашли время ответить на мой вопрос. Сейчас это работает. С уважением, Карлос., @Carlos Gityn Hochberg