Проблема кучи ESP32

esp32 heap

Я написал простую программу на 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

, 👍0


1 ответ


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);).

,

Дорогой Мэт, большое вам спасибо, что нашли время ответить на мой вопрос. Сейчас это работает. С уважением, Карлос., @Carlos Gityn Hochberg