Skip to content

Commit eb2d668

Browse files
committed
Add fan, USB-C PD and wroom_v1 configuration
1 parent 8001143 commit eb2d668

File tree

14 files changed

+250
-20
lines changed

14 files changed

+250
-20
lines changed

platformio.ini

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,22 @@ board = lolin_s2_mini
6666
[env:esp32_c3_supermini]
6767
board = lolin_c3_mini
6868

69+
[env:esp32_s3_wroom_n8r2]
70+
board = esp32-s3-devkitc-1
71+
board_build.arduino.memory_type = qio_qspi
72+
board_build.flash_mode = qio
73+
board_build.psram_type = qio
74+
board_upload.flash_size = 8MB
75+
board_upload.maximum_size = 8388608
76+
board_build.partitions = default_8MB.csv
77+
build_flags =
78+
${env.build_flags}
79+
-DARDUINO_USB_CDC_ON_BOOT=1
80+
-DARDUINO_USB_MODE=1
81+
-DBOARD_HAS_PSRAM
82+
-DCONFIG_PINOUT_WROOM_V1
83+
84+
6985
; debug_server =
7086
; ${platformio.packages_dir}/tool-openocd-esp32/bin/openocd
7187
; -f

src/configuration.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
#include "configuration_lolin_c3_mini.h"
1010
#endif
1111

12+
#ifdef CONFIG_PINOUT_WROOM_V1
13+
#include "configuration_wroom_v1.h"
14+
#endif
15+
1216

1317
#define APB_STATUS_LED_INVERT_LOGIC false
1418
#define WIFIMANAGER_MAX_STATIONS 5
@@ -32,7 +36,7 @@
3236

3337
#define APB_INA1219_ADDRESS 0x40
3438

35-
#define MAX_EVENTS_SIZE 800
39+
#define MAX_EVENTS_SIZE 1200
3640

3741
#if __has_include ("configuration_custom.h")
3842
#include "configuration_custom.h"

src/configuration_wroom_v1.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#define I2C_SDA_PIN 15
2+
#define I2C_SCL_PIN 16
3+
#define APB_STATUS_LED_PIN 4
4+
5+
6+
#define SPI_SCK 12
7+
#define SPI_MISO 13
8+
#define SPI_MOSI 11
9+
#define SPI_SS 10
10+
11+
#define APB_PWM_0_PIN 41
12+
#define APB_PWM_1_PIN 42
13+
#define APB_PWM_2_PIN 46
14+
#define APB_PWM_3_PIN 9
15+
#define APB_PWM_4_PIN 14
16+
#define APB_PWM_5_PIN 21
17+
#define APB_PWM_FAN_PIN 3
18+
#define APB_THERMISTOR_0_PIN 2
19+
#define APB_THERMISTOR_1_PIN 1
20+
21+
#define CH224K_CFG1_PIN 17
22+
#define CH224K_CFG2_PIN 18
23+
#define CH224K_CFG3_PIN 8
24+
25+
#define ONEBUTTON_USER_BUTTON_1 7
26+
27+
// Thermistor PWM pinout. First number in a pair is the PWM pin (output), second thermistor PIN (analog input)
28+
// IMPORTANT: there is no compiler check for pinout size, so be careful.
29+
#define APB_PWM_OUTPUTS_PWM_PINOUT {APB_PWM_0_PIN,APB_THERMISTOR_0_PIN, Heater}, \
30+
{APB_PWM_1_PIN,APB_THERMISTOR_1_PIN, Heater}, \
31+
{APB_PWM_2_PIN,-1, Output}, \
32+
{APB_PWM_3_PIN,-1, Output}, \
33+
{APB_PWM_4_PIN,-1, Output}, \
34+
{APB_PWM_5_PIN,-1, Output}
35+
#define APB_PWM_OUTPUTS_SIZE 6
36+
#define APB_PWM_OUTPUTS_TEMP_SENSORS 2

src/main.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <asyncbufferedtcplogger.h>
2222
#include <arduinoota-manager.h>
2323
#include <ArduinoOTA.h>
24+
#include "pd_protocol.h"
2425

2526
Scheduler scheduler;
2627

@@ -61,7 +62,12 @@ void setup() {
6162

6263
LittleFS.begin();
6364
APB::Settings::Instance.setup();
64-
65+
66+
PDProtocol::setVoltage(APB::Settings::Instance.pdVoltage());
67+
68+
#ifdef APB_PWM_FAN_PIN
69+
analogWrite(APB_PWM_FAN_PIN, static_cast<int>(APB::Settings::Instance.fanDuty() * 255.0));
70+
#endif
6571
APB::StatusLed::Instance.setup(&scheduler);
6672
#ifdef WIFI_POWER_TX
6773
WiFi.setTxPower(WIFI_POWER_TX);
@@ -107,7 +113,19 @@ void setup() {
107113
Log.infoln("[OneButton] User button 1 double clicked, reconnecting WiFi");
108114
WiFiManager::Instance.reconnect();
109115
});
110-
userButton.setup(ONEBUTTON_USER_BUTTON_1, INPUT, false);
116+
userButton.attachLongPressStop([]() {
117+
Log.infoln("[OneButton] User button 1 long press, restarting");
118+
delay(2000);
119+
ESP.restart();
120+
});
121+
#ifdef ONEBUTTON_USER_BUTTON_1_ACTIVE_HIGH
122+
#define _BTN_ACTIVELOW false
123+
#define _BTN_MODE INPUT_PULLDOWN
124+
#else
125+
#define _BTN_ACTIVELOW true
126+
#define _BTN_MODE INPUT_PULLUP
127+
#endif
128+
userButton.setup(ONEBUTTON_USER_BUTTON_1, _BTN_MODE, _BTN_ACTIVELOW);
111129
#endif
112130

113131
new Task(100, TASK_FOREVER, [](){ ArduinoOTAManager::Instance.loop(); }, &scheduler, true);

src/pd_protocol.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#include "pd_protocol.h"
2+
#include <ArduinoLog.h>
3+
4+
const std::map<PDProtocol::Voltage, PDProtocol::PinoutConfig> PDProtocol::voltageToCommand = {
5+
{Voltage::NOT_AVAILABLE, {0, 0, 0}},
6+
{Voltage::V5, {1, 0, 0}},
7+
{Voltage::V9, {0, 0, 0}},
8+
{Voltage::V12, {0, 0, 1}},
9+
{Voltage::V15, {0, 1, 1}},
10+
};
11+
12+
PDProtocol::PinoutConfig PDProtocol::lastConfig = PDProtocol::voltageToCommand.at(Voltage::NOT_AVAILABLE);
13+
14+
const std::forward_list<PDProtocol::Voltage> PDProtocol::supportedVoltages = {
15+
#if defined(CH224K_CFG1_PIN) && defined(CH224K_CFG2_PIN) && defined(CH224K_CFG3_PIN)
16+
Voltage::V5,
17+
Voltage::V9,
18+
Voltage::V12,
19+
Voltage::V15,
20+
#else
21+
Voltage::NOT_AVAILABLE,
22+
#endif
23+
};
24+
25+
void PDProtocol::setVoltage(Voltage voltage) {
26+
#if defined(CH224K_CFG1_PIN) && defined(CH224K_CFG2_PIN) && defined(CH224K_CFG3_PIN)
27+
if(voltage == NOT_AVAILABLE || voltageToCommand.find(voltage) == voltageToCommand.end()) {
28+
Log.error("PDProtocol: Unsupported voltage %dV\n", static_cast<int>(voltage));
29+
return;
30+
}
31+
const auto &[cfg1, cfg2, cfg3] = voltageToCommand.at(voltage);
32+
pinMode(CH224K_CFG1_PIN, OUTPUT);
33+
pinMode(CH224K_CFG2_PIN, OUTPUT);
34+
pinMode(CH224K_CFG3_PIN, OUTPUT);
35+
digitalWrite(CH224K_CFG1_PIN, cfg1);
36+
digitalWrite(CH224K_CFG2_PIN, cfg2);
37+
digitalWrite(CH224K_CFG3_PIN, cfg3);
38+
lastConfig = std::make_tuple(cfg1, cfg2, cfg3);
39+
Log.infoln("PDProtocol: Set voltage to %dV (CFG1=%d, CFG2=%d, CFG3=%d)", static_cast<int>(voltage), cfg1, cfg2, cfg3);
40+
#endif
41+
}
42+
43+
PDProtocol::Voltage PDProtocol::getVoltage() {
44+
#if defined(CH224K_CFG1_PIN) && defined(CH224K_CFG2_PIN) && defined(CH224K_CFG3_PIN)
45+
for(const auto &[voltage, pinout] : voltageToCommand) {
46+
if(pinout == lastConfig) {
47+
return voltage;
48+
}
49+
}
50+
#endif
51+
return NOT_AVAILABLE;
52+
}
53+
54+
std::forward_list<PDProtocol::Voltage> PDProtocol::getSupportedVoltages() {
55+
return supportedVoltages;
56+
}

src/pd_protocol.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#pragma once
2+
#include "configuration.h"
3+
#include <map>
4+
#include <tuple>
5+
#include <forward_list>
6+
7+
class PDProtocol {
8+
public:
9+
enum Voltage { NOT_AVAILABLE=0, V5 = 5, V9 = 9, V12 = 12, V15 = 15 };
10+
11+
static void setVoltage(Voltage voltage);
12+
static Voltage getVoltage();
13+
static std::forward_list<Voltage> getSupportedVoltages();
14+
private:
15+
using PinoutConfig = std::tuple<uint8_t, uint8_t, uint8_t>; // (CFG1, CFG2, CFG3)
16+
static const std::map<Voltage, PinoutConfig> voltageToCommand;
17+
static const std::forward_list<Voltage> supportedVoltages;
18+
static PinoutConfig lastConfig;
19+
};

src/settings.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#define APB_KEY_VERSION "version"
1010

1111
#define APB_KEY_STATUS_LED_DUTY "status_led_duty"
12+
#define APB_KEY_FAN_DUTY "fan_duty"
1213
#define APB_KEY_POWER_SOURCE_TYPE "power_src_type"
1314

1415
#define LOG_SCOPE "APB::Configuration - "
@@ -50,6 +51,8 @@ void APB::Settings::load() {
5051
return;
5152
}
5253
_statusLedDuty = prefs.getFloat(APB_KEY_STATUS_LED_DUTY, 1);
54+
_fanDuty = prefs.getFloat(APB_KEY_FAN_DUTY, 1.0);
55+
_pdVoltage = static_cast<PDProtocol::Voltage>(prefs.getUShort("pd_voltage", static_cast<uint16_t>(PDProtocol::V12)));
5356
_powerSource = static_cast<PowerMonitor::PowerSource>(prefs.getUShort(APB_KEY_POWER_SOURCE_TYPE, static_cast<uint16_t>(PowerMonitor::AC)));
5457
wifiSettings.load();
5558
Log.infoln(LOG_SCOPE "Preferences loaded");
@@ -59,6 +62,8 @@ void APB::Settings::loadDefaults() {
5962
wifiSettings.loadDefaults();
6063
_powerSource = PowerMonitor::AC;
6164
_statusLedDuty = 1.0;
65+
_fanDuty = 1.0;
66+
_pdVoltage = PDProtocol::V12;
6267
}
6368

6469

@@ -68,11 +73,16 @@ void APB::Settings::save() {
6873
prefs.putUShort(APB_KEY_VERSION, APB_PREFS_VERSION);
6974
wifiSettings.save();
7075
prefs.putFloat(APB_KEY_STATUS_LED_DUTY, _statusLedDuty);
76+
prefs.putFloat(APB_KEY_FAN_DUTY, _fanDuty);
7177
prefs.putUShort(APB_KEY_POWER_SOURCE_TYPE, static_cast<uint16_t>(_powerSource));
78+
prefs.putUShort("pd_voltage", static_cast<uint16_t>(_pdVoltage));
7279
Log.infoln(LOG_SCOPE "Preferences saved");
7380
}
7481

75-
APB::PowerMonitor::PowerSource APB::Settings::powerSource() const {
82+
83+
84+
APB::PowerMonitor::PowerSource APB::Settings::powerSource() const
85+
{
7686
return _powerSource;
7787
}
7888

src/settings.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <wifisettings.h>
77
#include "powermonitor.h"
88
#include <unordered_map>
9+
#include "pd_protocol.h"
910

1011
#define APB_CONFIG_DIRECTORY "/config"
1112

@@ -20,7 +21,11 @@ class Settings {
2021
GuLinux::WiFiSettings &wifi() { return wifiSettings; }
2122

2223
float statusLedDuty() const { return _statusLedDuty; };
24+
float fanDuty() const { return _fanDuty; };
25+
PDProtocol::Voltage pdVoltage() const { return _pdVoltage; }
26+
void setPdVoltage(PDProtocol::Voltage voltage) { _pdVoltage = voltage; }
2327
void setStatusLedDuty(float duty) { _statusLedDuty = duty; }
28+
void setFanDuty(float duty) { _fanDuty = duty; }
2429
PowerMonitor::PowerSource powerSource() const;
2530
void setPowerSource(PowerMonitor::PowerSource powerSource);
2631

@@ -29,6 +34,8 @@ class Settings {
2934
Preferences prefs;
3035
GuLinux::WiFiSettings wifiSettings;
3136
float _statusLedDuty;
37+
float _fanDuty;
38+
PDProtocol::Voltage _pdVoltage = PDProtocol::V12;
3239
PowerMonitor::PowerSource _powerSource;
3340
void loadDefaults();
3441
};

src/webserver.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ void APB::WebServer::setup() {
3737
onJsonRequest("/api/config/accessPoint", [](AsyncWebServerRequest *request, JsonVariant &json){ WiFiManager::Instance.onConfigAccessPoint(request, json); }, HTTP_POST | HTTP_DELETE);
3838
onJsonRequest("/api/config/station", [](AsyncWebServerRequest *request, JsonVariant &json){ WiFiManager::Instance.onConfigStation(request, json); }, HTTP_POST | HTTP_DELETE);
3939
onJsonRequest("/api/config/statusLedDuty", std::bind(&WebServer::onConfigStatusLedDuty, this, _1, _2), HTTP_POST);
40+
onJsonRequest("/api/config/fanDuty", std::bind(&WebServer::onConfigFanDuty, this, _1, _2), HTTP_POST);
41+
onJsonRequest("/api/config/pdVoltage", std::bind(&WebServer::onConfigPDVoltage, this, _1, _2), HTTP_POST);
4042
onJsonRequest("/api/config/powerSourceType", std::bind(&WebServer::onConfigPowerSourceType, this, _1, _2), HTTP_POST);
4143
webserver.on("/api/metrics", HTTP_GET, std::bind(&WebServer::onGetMetrics, this, _1));
4244
webserver.on("/api/config/write", HTTP_POST, std::bind(&WebServer::onPostWriteConfig, this, _1));
@@ -107,13 +109,18 @@ void APB::WebServer::onGetStatus(AsyncWebServerRequest *request) {
107109
response.root()["has_power_monitor"] = PowerMonitor::Instance.status().initialised;
108110
response.root()["has_ambient_sensor"] = Ambient::Instance.isInitialised();
109111
response.root()["has_serial"] = static_cast<bool>(Serial);
112+
response.root()["pdVoltageRequested"] = PDProtocol::getVoltage();
110113
}
111114

112115
void APB::WebServer::onGetConfig(AsyncWebServerRequest *request) {
113116
JsonWebResponse response(request);
114117
JsonObject rootObject = response.root().to<JsonObject>();
115118
WiFiManager::Instance.onGetConfig(rootObject);
116119
rootObject["ledDuty"] = Settings::Instance.statusLedDuty();
120+
#ifdef APB_PWM_FAN_PIN
121+
rootObject["fanDuty"] = Settings::Instance.fanDuty();
122+
#endif
123+
rootObject["pdVoltage"] = Settings::Instance.pdVoltage();
117124
rootObject["powerSourceType"] = Settings::PowerSourcesNames.at(Settings::Instance.powerSource());
118125
}
119126

@@ -265,6 +272,37 @@ void APB::WebServer::onConfigStatusLedDuty(AsyncWebServerRequest *request, JsonV
265272
response.root()["duty"] = StatusLed::Instance.duty();
266273
}
267274

275+
void APB::WebServer::onConfigPDVoltage(AsyncWebServerRequest *request, JsonVariant &json) {
276+
WebValidation validation{request, json};
277+
if(validation.required<PDProtocol::Voltage>("pdVoltage")
278+
.invalid()) return;
279+
bool valid_voltage = std::any_of(PDProtocol::getSupportedVoltages().begin(), PDProtocol::getSupportedVoltages().end(),
280+
[json](PDProtocol::Voltage v){ return v == json["pdVoltage"].as<PDProtocol::Voltage>(); });
281+
if(!valid_voltage) {
282+
JsonWebResponse::error(JsonWebResponse::BadRequest, "Invalid voltage", request);
283+
return;
284+
}
285+
Settings::Instance.setPdVoltage(json["pdVoltage"].as<PDProtocol::Voltage>());
286+
PDProtocol::setVoltage(Settings::Instance.pdVoltage());
287+
JsonWebResponse response(request);
288+
response.root()["pdVoltage"] = PDProtocol::getVoltage();
289+
}
290+
291+
void APB::WebServer::onConfigFanDuty(AsyncWebServerRequest *request, JsonVariant &json) {
292+
#ifndef APB_PWM_FAN_PIN
293+
JsonWebResponse(request).error(JsonWebResponse::NotFound, "Fan control not supported on this hardware", request);
294+
#else
295+
WebValidation validation{request, json};
296+
if(validation.required<float>("duty")
297+
.range("duty", {0}, {1})
298+
.invalid()) return;
299+
int analogValue = json["duty"].as<float>() * 255.0;
300+
analogWrite(APB_PWM_FAN_PIN, analogValue);
301+
JsonWebResponse response(request);
302+
response.root()["duty"] = Settings::Instance.fanDuty();
303+
#endif
304+
}
305+
268306
void APB::WebServer::onConfigPowerSourceType(AsyncWebServerRequest *request, JsonVariant &json) {
269307
WebValidation validation{request, json};
270308
std::forward_list<String> choices;

src/webserver.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ class WebServer : public AsyncWebServerBase {
3939
void onRestart(AsyncWebServerRequest *request);
4040
void onPostSetPWMOutputs(AsyncWebServerRequest *request, JsonVariant &json);
4141
void onConfigStatusLedDuty(AsyncWebServerRequest *request, JsonVariant &json);
42+
void onConfigFanDuty(AsyncWebServerRequest *request, JsonVariant &json);
43+
void onConfigPDVoltage(AsyncWebServerRequest *request, JsonVariant &json);
4244
void onConfigPowerSourceType(AsyncWebServerRequest *request, JsonVariant &json);
4345
};
4446
}

0 commit comments

Comments
 (0)