Skip to content

Commit 76f67f1

Browse files
committed
Setup encoder
1 parent 4a5f6d8 commit 76f67f1

4 files changed

Lines changed: 158 additions & 10 deletions

File tree

include/INA260.hpp

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
#pragma once
2+
3+
#include "LoadConfig.hpp"
4+
#include <Adafruit_INA260.h>
5+
#include <atomic>
6+
#include <etl/format_spec.h>
7+
#include <etl/string.h>
8+
#include <etl/to_string.h>
9+
10+
namespace INA260 {
11+
constexpr uint_fast16_t m_TO_BASE = 1000;
12+
static constexpr int_fast8_t MIN_VOLTAGE_V = -32;
13+
static constexpr int_fast16_t MIN_VOLTAGE_mV = MIN_VOLTAGE_V * m_TO_BASE;
14+
static constexpr int_fast8_t MAX_VOLTAGE_V = 32;
15+
static constexpr int_fast16_t MAX_VOLTAGE_mV = MAX_VOLTAGE_V * m_TO_BASE;
16+
static constexpr int_fast8_t MIN_CURRENT_A = -15;
17+
static constexpr int_fast16_t MIN_CURRENT_mA = MIN_CURRENT_A * m_TO_BASE;
18+
static constexpr int_fast8_t MAX_CURRENT_A = 15;
19+
static constexpr int_fast16_t MAX_CURRENT_mA = MAX_CURRENT_A * m_TO_BASE;
20+
static constexpr int_fast16_t MIN_POWER_W =
21+
MIN_VOLTAGE_V * MIN_CURRENT_A * -1;
22+
static constexpr int_fast16_t MIN_POWER_mW = MIN_POWER_W * m_TO_BASE;
23+
static constexpr int_fast16_t MAX_POWER_W = MAX_VOLTAGE_V * MAX_CURRENT_A;
24+
static constexpr int_fast16_t MAX_POWER_mW = MAX_POWER_W * m_TO_BASE;
25+
26+
static constexpr const char *TAG = "PS";
27+
Adafruit_INA260 powerSensor;
28+
29+
std::atomic<int_fast16_t> voltage_mV = 0;
30+
std::atomic<int_fast16_t> current_mA = 0;
31+
std::atomic<int_fast32_t> power_mW = 0;
32+
33+
bool begin(uint8_t i2c_addr, INA260_AveragingCount avgCount,
34+
INA260_ConversionTime convTime) {
35+
if (!powerSensor.begin(i2c_addr)) {
36+
ESP_LOGE("TAG", "Failed to initialize INA260 at 0x%02X", i2c_addr);
37+
return false;
38+
}
39+
powerSensor.setAveragingCount(avgCount);
40+
powerSensor.setVoltageConversionTime(convTime);
41+
42+
return true;
43+
}
44+
45+
/**
46+
* @brief Update the sensor readings and check if they are within the
47+
* defined bounds.
48+
* @return Whether the readings are valid (within bounds)
49+
*/
50+
bool updateReadings() {
51+
bool result = true;
52+
53+
auto vTemp_mV = (uint_fast32_t)powerSensor.readBusVoltage();
54+
if ((vTemp_mV > MAX_VOLTAGE_mV) ||
55+
(vTemp_mV < PSENSOR::MIN_VOLTAGE_mV)) {
56+
ESP_LOGE("TAG", "V reading out of bounds: %u mV", vTemp_mV);
57+
result &= false;
58+
} // Else: Valid reading
59+
voltage_mV = vTemp_mV;
60+
61+
auto iTemp = (uint_fast32_t)powerSensor.readCurrent();
62+
if ((iTemp > MAX_CURRENT_mA) || (iTemp < MIN_CURRENT_mA)) {
63+
ESP_LOGE("TAG", "C reading out of bounds: %d mA", iTemp);
64+
result &= false;
65+
} // Else: Valid reading
66+
current_mA = iTemp;
67+
68+
auto pTemp = (uint_fast32_t)powerSensor.readPower();
69+
if ((pTemp > (MAX_VOLTAGE_mV * MAX_CURRENT_A)) ||
70+
(pTemp < (PSENSOR::MIN_VOLTAGE_mV * MIN_CURRENT_A))) {
71+
ESP_LOGE("TAG", "P out of bounds: %d mW", pTemp);
72+
result &= false;
73+
} // Else: Valid reading
74+
power_mW = pTemp;
75+
76+
return result;
77+
}
78+
79+
// TODO - improve this and null terminator may not be needed
80+
static constexpr uint_fast8_t LOG_STRING_SIZE =
81+
3 + 6 + 5 + 6 + 5 + 5 + 5 + 1;
82+
/**
83+
* @brief Get at string that describes the current state of the PID instance
84+
* @returns the current state of the PID instance as a string
85+
*/
86+
etl::string<LOG_STRING_SIZE> getLogString() {
87+
etl::string<LOG_STRING_SIZE> logString(TAG); // 3 chars
88+
logString.append(": mV: "); // 6 chars
89+
90+
etl::format_spec decFormatA;
91+
decFormatA.width(5).fill('0'); // [5 chars]
92+
/**
93+
* @details I don't think we need strong guarantees on logging data
94+
* @see
95+
* https://stackoverflow.com/questions/12346487/what-do-each-memory-order-mean
96+
* @see https://en.cppreference.com/cpp/atomic/memory_order
97+
*/
98+
etl::to_string(voltage_mV.load(std::memory_order::relaxed), logString,
99+
decFormatA, true); // 5 chars
100+
logString.append(", mA: "); // 6 chars
101+
etl::to_string(current_mA.load(std::memory_order::relaxed), logString,
102+
decFormatA, true); // 5 chars
103+
logString.append(", W: "); // 5 chars
104+
etl::to_string(power_mW.load(std::memory_order::relaxed) / m_TO_BASE,
105+
logString, decFormatA, true); // 5 chars
106+
107+
return logString;
108+
}
109+
} // namespace INA260

include/LoadConfig.hpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
static_assert(__cplusplus >= 202302L, "C++23 standard or later required.");
77

88
// Imports
9+
#include <Adafruit_INA260.h>
910
#include <cstddef>
1011
#include <cstdint>
1112
#include <etl/array.h>
@@ -104,6 +105,31 @@ namespace RUN {
104105
// SLEEP_TIME_SECS * CONSTS::MILLIS_PER_SEC;
105106
} // namespace RUN
106107

108+
// MARK: PSENSOR
109+
namespace PSENSOR {
110+
constexpr uint8_t I2C_ADDRESS = 0x41; // 7-bit address for Adafruit INA260
111+
// CONFIG - Averaging count for sensor readings
112+
constexpr INA260_AveragingCount AVG_COUNT = INA260_COUNT_1; // CONFIG
113+
constexpr INA260_ConversionTime CONV_TIME = INA260_TIME_588_us; // CONFIG
114+
115+
constexpr uint_fast16_t m_TO_BASE = 1000;
116+
117+
constexpr int16_t MIN_VOLTAGE_V = -1; // CONFIG
118+
// CONFIG
119+
constexpr int_fast16_t MIN_VOLTAGE_mV = MIN_VOLTAGE_V * m_TO_BASE;
120+
constexpr int_fast16_t MAX_VOLTAGE_V = 48; // CONFIG
121+
// CONFIG
122+
constexpr uint_fast16_t MAX_VOLTAGE_mV = MAX_VOLTAGE_V * m_TO_BASE;
123+
constexpr int_fast16_t MIN_CURRENT_A = -20; // CONFIG
124+
constexpr int_fast16_t MIN_CURRENT_mA = MIN_CURRENT_A * m_TO_BASE; // CONFIG
125+
constexpr int_fast16_t MAX_CURRENT_A = 20; // CONFIG
126+
constexpr int_fast16_t MAX_CURRENT_mA = MAX_CURRENT_A * m_TO_BASE; // CONFIG
127+
// CONFIG
128+
constexpr int_fast32_t MIN_POWER_mW = MIN_VOLTAGE_mV * MIN_CURRENT_mA;
129+
// CONFIG
130+
constexpr int_fast32_t MAX_POWER_mW = MAX_VOLTAGE_mV * MAX_CURRENT_mA;
131+
} // namespace PSENSOR
132+
107133
// MARK: Load
108134
namespace LOAD {
109135
constexpr uint8_t I2C_ADDRESS = 0x4E; // A0-A2 all high

include/LoadContainer.hpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22

33
#include <cstdint>
44

5+
#include "INA260.hpp"
56
#include "LoadConfig.hpp"
67
#include "LoadTasks.hpp"
78
#include "MCP23008T.hpp"
9+
#include <Adafruit_INA260.h>
810

911
/**
1012
* @brief Class to manage the container for load data
@@ -42,26 +44,25 @@ class LoadContainer {
4244
~LoadContainer() = default;
4345

4446
inline bool getSafetyFlag() const { return safetyFlag; }
45-
inline bool isPowerPositive() const { return powerPositive; } // todo
46-
inline bool isSteadyRPM() const { return false; } // todo
47-
inline bool isTargetRPMExceeded() const { return false; } // todo
47+
inline bool isPowerPositive() const { return (INA260::current_mA > 0); }
48+
inline bool isSteadyRPM() const { return false; } // todo
49+
inline bool isTargetRPMExceeded() const { return false; } // todo
4850

4951
inline void updateSafetyFlag(bool safetyFlag) {
5052
this->safetyFlag = (digitalRead(UM_PROS3::ESTOP_PIN) ==
51-
LOW) /*|| getPPCCurrent() < threhold*/; // todo
52-
}
53-
inline void updatePowerPositive(bool powerPositive) {
54-
this->powerPositive = powerPositive;
53+
LOW) /*|| getPPCCurrent() < threshold*/; // todo
5554
}
55+
// inline void updatePowerPositive(bool powerPositive) {
56+
// this->powerPositive = powerPositive;
57+
// }
5658
inline void setLoadGPIO(uint_fast8_t value) {
5759
loadDevice.setGPIO((uint32_t)value);
5860
}
5961

6062
private:
61-
// INA260&
6263
MCP23008T &loadDevice;
6364

6465
bool safetyFlag = false; // todo
65-
bool powerPositive = false;
66+
// bool powerPositive = false;
6667
int_fast16_t currentRPM = 0; // todo
6768
};

src/main.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <temperature_sensor.h>
99

1010
// Library Includes
11+
#include <Adafruit_NeoPixel.h>
1112
#include <Arduino.h>
1213

1314
// Project Includes
@@ -20,11 +21,11 @@
2021
// #include "2026Core/Net/Net-Application/OTA.hpp"
2122
#include "2026Core/Net/Net-Link/AdapterESPNow.hpp"
2223
#include "2026Core/Net/Net-Phy/AdapterWLAN.hpp"
24+
#include "INA260.hpp"
2325
#include "LoadContainer.hpp"
2426
#include "LoadFSM.hpp"
2527
#include "LoadTasks.hpp"
2628
#include "MCP23008T.hpp"
27-
#include <Adafruit_NeoPixel.h>
2829

2930
/* Config */
3031
static constexpr const char *TAG = "LoMa";
@@ -53,6 +54,13 @@ LoadFSM loadFSM(load);
5354

5455
// todo: move
5556
bool configureLoad() {
57+
if (!INA260::begin(PSENSOR::I2C_ADDRESS, PSENSOR::AVG_COUNT,
58+
PSENSOR::CONV_TIME)) {
59+
ESP_LOGE(TAG, "Failed to initialize INA260 power sensor at 0x%02X",
60+
PSENSOR::I2C_ADDRESS);
61+
return false;
62+
}
63+
5664
if (!loadDevice.begin()) {
5765
ESP_LOGE(TAG, "Failed to initialize MCP23008T device at 0x%02X",
5866
loadDevice.getAddress());
@@ -303,6 +311,7 @@ vTaskUpdateFSM([[maybe_unused]] void *pvParameters) { // NOSONAR
303311
[[noreturn]] void
304312
vTaskPollSensors([[maybe_unused]] void *pvParameters) { // NOSONAR
305313
while (true) {
314+
INA260::updateReadings();
306315
delay(RUN::TASK_INTERVALS::TI_POLL_SENSORS_mS);
307316
}
308317
}
@@ -563,6 +572,9 @@ constexpr uint32_t LOG_ITEM_INTERVAL_MS = RUN::TASK_INTERVALS::TI_LOG_DATA_ms;
563572
}
564573
// Disable the temperature sensor if it is not needed and save the power
565574
ESP_ERROR_CHECK(temperature_sensor_disable(tempSensHandle));
575+
// delay(LOG_ITEM_INTERVAL_MS);
576+
577+
ESP_LOGI(TAG, "%s", INA260::getLogString().c_str());
566578
delay(LOG_ITEM_INTERVAL_MS);
567579

568580
// esp_wifi_get_bandwidth

0 commit comments

Comments
 (0)