Corrupt object variables in C++ for ESP32

1 day ago 4
ARTICLE AD BOX

I am creating a project for an ESP32. I'm quite new to ESP and C++ coding. I use PlatformIO inside VSCode.

It's a robot that will be driving around. It has Ultrasonic sensors to detect any obstacles. The sensors. I store the pins for each sensor in an object of type ProximitySensor.

I have a problem that at runtime, the values of the stored pins change, to seemingly arbitrary values.

Here's the class representing the sensors:

class ProximitySensor : public potbot::Sensor { private: const int pin_trig; const int pin_echo; const int16_t orientation; // degrees relative to middle axis (front = 0°) public: ProximitySensor(const int pin_trig, const int pin_echo, const int16_t orientation); void setup() override; float read() override; int16_t getOrientation(){return orientation;} };

and the corresponding implementation:

ProximitySensor::ProximitySensor(const int pin_trig, const int pin_echo, const int16_t orientation) : Sensor("Proximity Sensor"), pin_trig(pin_trig), pin_echo(pin_echo), orientation(orientation) { //setup(); } void ProximitySensor::setup(){ Serial.println("Proximity sensor initialized with trig pin " + String(pin_trig) + " and echo pin " + String(pin_echo) + " at orientation " + String(orientation)); pinMode(pin_trig, OUTPUT); pinMode(pin_echo, INPUT); } float ProximitySensor::read(){ delay(10); Serial.println("reading prox sensors pins at: " + String(orientation)); Serial.print("pin_trig = "+ String(pin_trig) + " pin_echo = " + String(pin_echo)); Serial.println(); digitalWrite(pin_trig, LOW); delayMicroseconds(2); digitalWrite(pin_trig, HIGH); delayMicroseconds(10); digitalWrite(pin_trig, LOW); unsigned long duration = pulseIn(pin_echo, HIGH); long dist = duration * SOUND_SPEED / 2; return dist; }

In the main file, I create five objects of it like this:

ProximitySensor *prox_sensors[5] = {new ProximitySensor(23, 36, 0), new ProximitySensor(22, 39, -25), new ProximitySensor(19, 35, 25), new ProximitySensor(18, 32, -120), new ProximitySensor(21, 34, 120)};

and i call each one's setup() from the main setup() function.

Then i periodically read each one. Here's where the problem occurs with the arbitrary values.

Here's an example from the logs from the serial monitor:

reading prox sensor at: 0 degrees pin_trig = 23, pin_echo = 36 reading prox sensor at: 20924 degrees pin_trig = -1413869004, pin_echo = 20 E (12594) gpio: gpio_set_level(227): GPIO output gpio_num error E (12596) gpio: gpio_set_level(227): GPIO output gpio_num error E (12601) gpio: gpio_set_level(227): GPIO output gpio_num error reading prox sensor at: 22136 degrees pin_trig = 39, pin_echo = 1027538919 E (13617) gpio: gpio_set_level(227): GPIO output gpio_num error E (13618) gpio: gpio_set_level(227): GPIO output gpio_num error E (13624) gpio: gpio_set_level(227): GPIO output gpio_num error reading prox sensor at: 20896 degrees pin_trig = 20, pin_echo = 1061179836 reading prox sensor at: 32 degrees pin_trig = -949616615, pin_echo = -1163045256

It's also important to note, that at each attempt of reading, the values are different.

Things i already checked:

available memory: more than 200KB and largest chunk around 110KB using ESP.getFreeHeap() and ESP.getMaxAllocHeap()

array-out-of-bounds writes: fixed one potential case, but corruption still remains

Thanks in advance for any advice

EDIT (reproducible example):

main.cpp:

#ifndef POTBOT_INO #define POTBOT_INO #include <Arduino.h> #include "Globals.h" #include "sensors/impl/ProximitySensor.h" #include "navigation/NavigationManager.h" void setupProxSensors(); void updateObstacles(); ProximitySensor *prox_sensors[5] = {new ProximitySensor(23, 36, 0), new ProximitySensor(22, 39, -25), new ProximitySensor(19, 35, 25), new ProximitySensor(18, 32, -120), new ProximitySensor(21, 34, 120)}; ulong tick = 0; long lastObstacleUpdate = 0; NavigationManager driveManager(prox_sensors[0]); void setup() { Serial.begin(115200); delay(500); setupProxSensors(); } void loop() { tick++; updateObstacles(); delay(10); if(tick % 100 == 0){ Serial.println("....................."); Serial.print("free heap: "); Serial.println(ESP.getFreeHeap()); Serial.print("biggest free chunk: "); Serial.println(ESP.getMaxAllocHeap()); } } void updateObstacles() { if (millis() - lastObstacleUpdate > 5000) { driveManager.updateMapFromSensors(false); lastObstacleUpdate = millis(); } } void setupProxSensors() { for (uint8_t i = 0; i < PROX_SENSOR_COUNT; i++) { ProximitySensor *sensor = prox_sensors[i]; sensor->setup(); } } #endif

NavigationManager.h:

#ifndef DRIVERMANAGER_H #define DRIVERMANAGER_H #define OBS_GRID_SIZE 50 #define OBS_CELL_SIZE 20 #include <cstdint> #include "../sensors/impl/ProximitySensor.h" #include "Globals.h" class NavigationManager { private: uint8_t obstacleGrid[OBS_GRID_SIZE][OBS_GRID_SIZE]; int x, y; float heading; ProximitySensor *proxSensors; public: NavigationManager(ProximitySensor *prxSns) : x(0), y(0), heading(0), proxSensors(prxSns) {} void updateMapFromSensors(bool isExploring_p) { for (int i = 0; i < PROX_SENSOR_COUNT; i++) { ProximitySensor sensor = proxSensors[i]; float reading = sensor.read(); uint8_t maxDistance = isExploring_p ? 200 : 50; if (reading > maxDistance || reading < 5) continue; int16_t absolute_orientation = (int)(heading + sensor.getOrientation()) % 360; double rad_angle = absolute_orientation * PI / 180.0; double dx_grid = (reading * cos(rad_angle)) / OBS_CELL_SIZE; double dy_grid = (reading * sin(rad_angle)) / OBS_CELL_SIZE; int gridX = (int)(x + dx_grid); int gridY = (int)(y + dy_grid); if (gridX >= 0 && gridX < OBS_GRID_SIZE && gridY >= 0 && gridY < OBS_GRID_SIZE) { obstacleGrid[gridX][gridY] = 1; } } } }; #endif

ProximitySensor.h

#ifndef PROXIMITY_SENSOR_H #define PROXIMITY_SENSOR_H #include <cstdint> #include <Arduino.h> #define SOUND_SPEED 0.0343 // m/microsec class ProximitySensor { private: const int pin_trig; const int pin_echo; const int16_t orientation; public: ProximitySensor(const int pin_trig_p, const int pin_echo_p, const int16_t orientation_p):pin_trig(pin_trig_p), pin_echo(pin_echo_p), orientation(orientation_p){} void setup() { Serial.println("Proximity sensor initialized with trig pin " + String(pin_trig) + " and echo pin " + String(pin_echo) + " at orientation " + String(orientation)); pinMode(pin_trig, OUTPUT); pinMode(pin_echo, INPUT); } float read() { delay(10); Serial.println("reading prox sensor at: " + String(orientation) + " degrees"); Serial.print("pin_trig = " + String(pin_trig) + ", pin_echo = " + String(pin_echo)); Serial.println(); digitalWrite(pin_trig, LOW); delayMicroseconds(2); digitalWrite(pin_trig, HIGH); delayMicroseconds(10); digitalWrite(pin_trig, LOW); unsigned long duration = pulseIn(pin_echo, HIGH); double dist = duration * SOUND_SPEED / 2; return (float)dist; } int16_t getOrientation() { return orientation; } }; #endif
Read Entire Article