I am having a problem with two global scope objects being assigned the same memory address by the compiler. One is a class instance (accelHighG in the code below) and one is an array of floats (accelOffsetErrors[] in the code below). When I print the address of accelOffsetErrors[0] and the address of accelerationReading[2] (a private data member of the accelHighG object) they are both at address 0x200002C8. This, of course, is leading to problems when the program runs. I have included a reduced version of my program below that still demonstrates the issue. I have also included the .h file for the H3LIS331 class. Any ideas as to what I might be doing wrong to cause this?
I am using Arduino IDE 2.3.2 and an Adafruit Feather M0 RFM95.
This is the program code:
// ============================== Include Files ==================================
#include <SPI.h> // Sensor and micro SD card communication
#include <SD.h> // SD card library functions
#include <BMP3XX.h> // BMP390 sensor library code
#include <LSM6DSO32.h> // LSM6DSO32 sensor library code
#include "wiring_private.h" // pinPeripheral() function
#include "RTClib.h" // Real Time Clock library by Adafruit
#include <RWP_GPS.h> // GPS Library
#include <RH_RF95.h> // Radio Head driver class for LoRa Radio
#include <RHReliableDatagram.h> // Radio Head manager class for reliable comms
#include <H3LIS331.hpp> // H3LIS331 sensor library code
#include <Arduino.h>
#include <ArduinoJson.h> // JASON file support for app settings
#include <lowPassFilter.h>
// =============================== Constants =====================================
#define GPSSerial Serial1
// Feather M0 pin assignments
const uint8_t H3LIS331_CS = SDA; // PA22
const uint8_t RADIO_SPI_CS = 8; // PA06
const uint8_t RADIO_SPI_IRQ = 3; // PA09
const uint8_t SENSOR_SPI_CLK = 12; // PA19
const uint8_t SENSOR_SPI_MOSI = 10; // PA18
const uint8_t SENSOR_SPI_MISO = 11; // PA16
// Other Global Constants
const uint8_t MAX_MESSAGE_LENGTH = 20; // Maximum LoRa radio message length
enum states { START_UP,
FAULT,
READY,
ARMED,
LOGGING,
POST_FLIGHT,
GOTO_ARM,
GOTO_LOGGING,
GOTO_POST_FLIGHT,
GOTO_READY };
enum errors { NONE,
GYRO,
ACCEL,
ALT,
BATTERY
};
// Struct to hold the app parameters that are set via the SD card settings file
struct Settings {
double bat1VoltLow; // 3.7v LiPo battery voltage threshold for low charge
double bat1VoltOK; // 3.7V LiPo battery voltage threshold for medium charge
double bat1VoltFull; // 3.7V LiPo battery voltage threshold for full charge
bool bat2Present; // True: External event battery installed
double bat2VoltLow; // 7.4V LiPo battery voltage threshold for low charge
double bat2VoltOK; // 7.4V LiPo battery voltage threshold for medium charge
double bat2VoltFull; // 7.4V LiPo battery voltage threshold for full charge
uint8_t parachute; // 0: function not used; 1 to 4: The event to use for this function
uint16_t parachuteReleaseDelay; // Delay in milliseconds from appogee to parachute release
uint8_t drogueParachute; // 0: function not used; 1 to 4: The event to use for this function
uint16_t drogueChuteReleaseDelay; // Delay in milliseconds from parachute release to drogue chute release
uint8_t secondStage; // 0: function not used; 1 to 4: The event to use for this function
uint16_t secondStageIgnitionDelay; // Delay in milliseconds from first stage burnout to second stage ignition
uint8_t firstStateIgnition; // 0: function not used; 1 to 4: The event to use for this function
double seaLevelPressure; // Atmospheric pressure at sea level
double launchAccelThreshold; // Acceleration level above which a launch will be detected
double landedThreshold; // Axial rotation rate below which a landing will be detected
int flightTimeout; // Time after which we will assume we have landed if landing has not been detected (seconds).
uint8_t upGoVAddr; // LoRa radio address of this UpGoV avionics instance
bool groundTest; // True: Ground test mode activated.
};
// =================================== Global Objects ===================================================
SPIClass sensorSPI(&sercom1, 11, 12, 10, SPI_PAD_2_SCK_3, SERCOM_RX_PAD_0); // The sensor SPI bus instance
BMP3XX altimeter; // Altimeter sensor object instance
LSM6DSO32 accelerometer_gyro; // Accelerometer/Gyro sensor object instance
H3LIS331 accelHighG; // H3LIS331 high accelerometer object instance
RH_RF95 radioDriver(RADIO_SPI_CS, RADIO_SPI_IRQ); // LoRa radio driver object
RHReliableDatagram radioManager(radioDriver); // LoRa radio manager object
Adafruit_GPS gps(&GPSSerial); // GPS object
File dataFile; // Data file object
File logFile; // Log file object
Settings settings; // Application settings
LowPassFilter xAxisAccel; // Filter for x-axis acceleration reading
LowPassFilter altitudeFilter; // Filter for altitude reading
LowPassFilter xAxisHighGAccel; // Filter for the high G accelerometer
// ================================ Global Variables ======================================================
volatile bool rtcInterruptFlag = false; // Flag set by rtc interrupt handler
double temperature = 0.0; // Temperature in degrees C as measured by the BMP390 sensor
double pressure = 0.0; // Pressure in hpa as measured by the BMP390 sensor
double altitude = 0.0; // Altitude in meters as measured or computed from the BMP390 sensor
int8_t altErrCode = 0; // Result code returned from BMP390 API calls
bool dataFileOpen = false; // Flag to indicate dataFile state
uint32_t launchTime = 0; // Time at launch in millisends
states state = START_UP; // The current state
errors error = NONE; // Error
double maxAcceleration = 0.0; // The maximum X-Axis acceleration measured during flight
double maxAltitude = 0.0; // The maximum altitude measured during flight
uint32_t flightLength = 0; // The flight duration (launch to landing) in seconds
double velocity = 0.0; // The computed velocity
double maxVelocity = 0.0; // The maximum computed velocity during flight
uint32_t prevTime = 0; // Previous time measurement used by velocityCalculator() ms
double prevAcc = 0.0; // Previous acceleration measurement used by velocityCalculator() ft/sec2
double prevVelocity = 0.0; // Previous calculated velocity used by velocityCalculator() ft/sec
bool gpsFix = false; // Flag indicating if a GPS fix has been made
double launchPointLat = 0.0; // Launch point lattitude as obtained from GPS
double launchPointLon = 0.0; // Launch point longitude as obtained from GPS
double launchPointAlt = 0.0; // Altitude above MSL in meters as obtained from GPS
double baroAltitudeError = 0.0; // Difference between baro computed alt and GPS alt
uint8_t buffer[MAX_MESSAGE_LENGTH]; // LoRa radio message buffer
int radioError = 0; // The number of radio messages not receiving an ack
float accelOffsetErrors[] = { 0.0, 0.0, 0.0 }; // Accelerometer zero offset errors
float gyroOffsetErrors[] = { 0.0, 0.0, 0.0 }; // Gyro zero offset erros
float highG_AccelOffsetError = 0.0; // X Axis offset error for the high G Accel
uint32_t apogeeTime = 0;
uint32_t drogueChuteReleaseTime = 0;
uint32_t parachuteReleaseTime = 0;
uint32_t firstStageEngineBurnoutTime = 0;
uint32_t secondStageIgnitionTime = 0;
bool landed = false;
uint32_t landingTime = 0;
// ============================= Setup Function ===================================
void setup() {
Serial.begin(115200); // Make sure the Serial Monitor is set to 115200 baud
while (!Serial) {
;
}
// ====================== Initialize the Sensor SPI Bus ============================
sensorSPI.begin();
pinPeripheral(10, PIO_SERCOM);
pinPeripheral(11, PIO_SERCOM);
pinPeripheral(12, PIO_SERCOM);
accelHighG.begin(H3LIS331_CS, &sensorSPI);
Serial.print("accelOffsetErrors[0] address: ");
Serial.println((uint32_t)&accelOffsetErrors[0], HEX);
accelHighG.getAcceleration();
} // End setup code
void loop() {
}
This is the .h file code for the H3LIS331 class.
class H3LIS331 {
public:
//Constructor
H3LIS331();
//Initialization
bool begin(uint8_t cs, SPIClass *spiPtr = &SPI, uint32_t spiFrequency = DEFAULT_SPI_FREQ);
//Configuration
void setRange(h3lis331dl_fs_t range);
h3lis331dl_fs_t getRange(void);
void setOutputDataRate(h3lis331dl_dr_t ODR);
h3lis331dl_dr_t getOutputDataRate(void);
void enableAxis(h3lis331_axis_t axis);
h3lis331_axis_t getEnabledAxis(void);
void setBlockDataUpdate(void);
void clearBlockDataUpdate(void);
bool blockDataUpdateEnabled(void);
//Interrupt configuration
void setInterruptPinsConfig(h3lis331dl_i1_cfg_t pin1Source, h3lis331dl_i2_cfg_t pin2Source,
bool latched = false, bool activeHigh = true, bool pushPull = true);
void interrupt1Config(uint8_t eventsEnabled, bool orEvents,
uint8_t threshold, uint8_t duration);
void interrupt2Config(uint8_t eventsEnabled, bool orEvents,
uint8_t threshold, uint8_t duration);
//Accelerometer Data
h3lis331dl_status_reg_t getStatus(void);
bool isDataReady(void);
float getX_Accel(void);
float getY_Accel(void);
float getZ_Accel(void);
void getAcceleration(void);
h3lis331dl_int1_src_t getInterrupt1Source();
h3lis331dl_int2_src_t getInterrupt2Source();
bool isInt1Active();
bool isInt2Active();
private:
bool _init(void);
stmdev_ctx_t sensorAPI_intf; // Structure holds pointers to spi read/write functions
// and spi bus object
h3lis331dl_fs_t accelRange;
float accelerationReading[3]; // X, Y, and Z axis acceleration in Gs
};