0

I wrote a simple C++ program (just main.cpp and corresponding platform.io files & libraries) to get BME280 sensor readings. It worked fine until I decided to use good programming practices, using header files and separating the read function from main.cpp, I get a heap error, stated below:

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

Any ideas on that?

By the way, I also used pointers for both the function and the variable passed to it, to no avail.

I also tried a series of combinations with the libraries I am using - Adafruit BME280 and Adafruit Unified Sensor.

Going back to having all the code in one file works...

Thanks

My code:

//main.cpp
#include <sensor_readings.h>
#include <settings.h>

void refresh_readings();  // Declare in the header so that the compiler knows about it before it is called in loop()

Adafruit_BME280 bme; // I2C

void setup() {
  pinMode(LED_BUILTIN,OUTPUT);
  Serial.begin(9600);
  bool status;

  // (you can also pass in a Wire library object like &Wire2)
  status = bme.begin(0x76);
  if (!status) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    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 Answer 1

1

There's a couple problems with your code.

void refresh_readings();  // Declare in the header so that
                          // the compiler knows about it
                          // before it is called in loop()

This is a lie! Don't tell your compiler there's a refresh_readings function that takes no arguments when you haven't defined one. Remove that line, you already have the function declaration in your header.

void (*fcnPtr)(Adafruit_BME280){ &refresh_readings };
(*fcnPtr)(bme);

This is just a very convoluted way of typing:

refresh_readings(bme);

So just use the normal function call syntax.

The main issue as far as I can tell though is that you are copying the bme object when passing it to the readings function, which is not advisable in general for this sort of object (they represent a piece of hardware that you can't really copy). That class in particular has a bunch of pointer members, a destructor that deletes them, but no copy constructor as far as I can tell, which is a bad thing.

Change your function to this signature (both in the header and the C++ file):

void refresh_readings(Adafruit_BME280& bme);
//                 pass by reference ^

And use the normal call syntax (refresh_readings(bme);).

1
  • Dear Mat, thank you VERY much for taking your time to answer to my question. It is working now. Regards, Carlos. Commented Jan 3, 2022 at 12:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.