currentMeas

This commit is contained in:
Jakob Gegeniger committed 2026-09-12 00:18:54 +02:00
1 parent f93a8aaabd
commit d2b8e1de3c
9 files changed
+91 -26

No files matched your search

+2 -2
View File
@@ -11,9 +11,9 @@
"request": "launch",
"program": "${workspaceFolder}/build/src/sword/SwordMain",
"args": [
//"test",
"promo",
"promo", //"test",
"${workspaceFolder}/assets",
"-n", "SwordDebug",
"-b", "'mqtts://nerdyssey.de:8883'",
"-t", "'staging/outdoor/king-arthur/sword/'",
"-p", "'awesomeexodusoutdooradventures'",
Submodule platform updated: 35a7eb5b40...6f6a0474cb.
+6
View File
@@ -23,3 +23,9 @@ Service to connect the Throne via MQTT
Throne station
Features Throne for final coronation
## MQTT Testcommands
```sh
mosquitto_sub -h nerdyssey.de -p 8883 -t "staging/outdoor/king-arthur/#" -u "exodususer" -P "awesomeexodusoutdooradventures" --capath /etc/ssl/certs/ -d
```
Regular → Executable
+1
View File
@@ -1,6 +1,7 @@
#!/bin/bash
/home/gustice/workspace/swordStation/SwordMain \
promo /home/gustice/workspace/swordStation/assets \
-n Sword \
-b mqtts://nerdyssey.de:8883 \
-t outdoor/king-arthur/sword/ \
-p awesomeexodusoutdooradventures \
Regular → Executable
+1
View File
@@ -1,6 +1,7 @@
#!/bin/bash
/home/gustice/workspace/swordStation/SwordMain \
test /home/gustice/workspace/swordStation/assets \
-n SwordDebug \
-b mqtts://nerdyssey.de:8883 \
-t staging/outdoor/king-arthur/sword/ \
-p awesomeexodusoutdooradventures \
+1
View File
@@ -3,6 +3,7 @@ add_executable(SwordMain swordMain.cpp)
target_link_libraries(SwordMain
PkgConfig::LIBGPIOD
base
adc
palAdapt
loRa
os
+16 -6
View File
@@ -1,10 +1,10 @@
#pragma once
#include "swordMain.hpp"
#include "defines.hpp"
#include "swordMain.hpp"
class MqttChannel {
public:
MqttChannel(string version, SwordConfig cfg, DeviceIoState& ioStat, SeqLogger& log)
MqttChannel(string name, string version, SwordConfig cfg, DeviceIoState& ioStat, SeqLogger& log)
: Config(cfg),
IoStat(ioStat),
Logger(log),
@@ -35,9 +35,7 @@ class MqttChannel {
{"promoDelay", ServiceCommands_e::SetConfigPromoDelay},
}),
subTopics{{runTopic, cfgTopic, resetTopic}},
client("Sword",
cfg.BrockerUrl,
subTopics,
client(name, cfg.BrockerUrl, subTopics,
{cfg.MqttUser, cfg.MqttPassword}) {
fmt::println("MQTT: Starting task:");
mqttCall = [this](string topic, string payload) {
@@ -86,7 +84,7 @@ class MqttChannel {
fmt::println("Input queue flushed, {} Messages discarted", cnt);
}
static void runMasterService(Thread::Context& ctx, MqttChannel& instance, function<void()> resetCall) {
static void runMasterService(Thread::Context& ctx, MqttChannel& instance, function<void()> resetCall, CurrMon& mon) {
while (true) {
auto serMsg = instance.MasterQueue.dequeue();
if (!serMsg) {
@@ -129,9 +127,21 @@ class MqttChannel {
switch (code) {
case ServiceCommands_e::SetLockOpen: {
instance.IoStat.SwordLatch.moveIn();
auto tE = std::chrono::steady_clock::now() + 6s;
while (std::chrono::steady_clock::now() < tE) {
Thread::sleep(100ms);
auto curr = mon.sampleCurrent();
}
auto currE = mon.sampleCurrent();
} break;
case ServiceCommands_e::SetLockClose: {
instance.IoStat.SwordLatch.moveOut();
auto tE = std::chrono::steady_clock::now() + 6s;
while (std::chrono::steady_clock::now() < tE) {
Thread::sleep(100ms);
auto curr = mon.sampleCurrent();
}
auto currE = mon.sampleCurrent();
} break;
case ServiceCommands_e::PlaySoundPromo: {
MediaPlayer::playWavFile(instance.Config.SoundPromo);
+25 -14
View File
@@ -8,9 +8,7 @@ using namespace std::literals::string_view_literals;
using namespace std::literals::chrono_literals;
using namespace std;
constexpr uint8_t VersionArr[4] = {'V', 0, 8, 0};
const string Version = "V 0.8.0";
// const string Version = fmt::format("{} {}.{}.{}", VersionArr[0], VersionArr[1], VersionArr[2], VersionArr[3]);
const string Version = "V 0.9.0";
unique_ptr<SwordConfig> SwordCfg;
unique_ptr<DeviceIoState> IoStat;
@@ -21,6 +19,7 @@ void processProduction(MqttChannel& mqtt, SeqLogger& log);
int main(int argc, char* argv[]) {
CLI::App app{"Sword Firmware"};
string appName = "SwordDebug";
string modeArg = "test";
string assetsBasePath = "/home/user/assets/sword";
string brocker = "mqtts://nerdyssey.de:8883";
@@ -31,6 +30,7 @@ int main(int argc, char* argv[]) {
string logApiKey = "uYpJC6WyZAbFK2MUgwNH";
app.add_option("startmode", modeArg, "Startup mode")->required();
app.add_option("basepath", assetsBasePath, "Base bath for assets")->required();
app.add_option("-n,--name", appName, "Name of App");
app.add_option("-b,--brocker", brocker, "MQTT Topic URL");
app.add_option("-t,--topic", topic, "MQTT Topic");
app.add_option("-p,--passwd", password, "MQTT Brocker password");
@@ -40,7 +40,7 @@ int main(int argc, char* argv[]) {
CLI11_PARSE(app, argc, argv);
SeqLogger log(logUrl, logApiKey, "Sword");
SeqLogger log(logUrl, logApiKey, appName);
SwordCfg = make_unique<SwordConfig>(assetsBasePath, brocker, topic, user, password);
fmt::println("{}", app.get_description());
@@ -78,15 +78,23 @@ int main(int argc, char* argv[]) {
InputTransAware SwordPulled(spPort);
LinMot SwordLatch(mOut1, mOut2);
I2cMaster i2cDev(II2cMaster::ClockRate::_400k);
AdcAds1115 adc(i2cDev, AdcAds1115::I2CAddress::Gnd);
// Check if the ADC is connected
if (!adc.isConnected()) {
fmt::println("Failed to connect ot Sensor {}", modeArg);
}
CurrMon mon(adc);
IoStat = make_unique<DeviceIoState>(SwordEntry, SwordEnd, SwordPulled, SwordLatch);
MqttChannel mqtt(Version, *SwordCfg, *IoStat, log);
MqttChannel mqtt(appName, Version, *SwordCfg, *IoStat, log);
auto resetCall = [&]() {
log.sendEvent("Reset", "");
};
mqtt.flushInput();
static auto conTask = Thread::createExplicit("MqttTask", MqttChannel::runMasterService, ref(mqtt), resetCall);
static auto conTask = Thread::createExplicit("MqttTask", MqttChannel::runMasterService, ref(mqtt), resetCall, ref(mon));
SwordLatch.moveOut();
fmt::println("Running App");
@@ -128,23 +136,26 @@ void processPromo(MqttChannel& mqtt, SeqLogger& log) {
Tick tmu(1min);
Tick tn(1s);
Tick tsf(30min);
Waiter dP;
auto& serCmds = mqtt.getSerCommands();
while (true) {
Thread::sleep(10ms);
IoStat->tick();
if (IoStat->SwordPulled.isPosEdge()) {
if (!IoStat->Mute) {
log.sendEvent("Pull", "Start Audio");
if (dP.tick(IoStat->PromoDelay)) {
log.sendEvent("Pull", "Start Audio");
if (tsf.tick()) {
MediaPlayer::playWavFile(SwordCfg->SoundPromo);
if (tsf.tick()) {
MediaPlayer::playWavFile(SwordCfg->SoundPromo);
} else {
MediaPlayer::playWavFile(SwordCfg->SoundPromoShort);
}
dP.sample();
fmt::println("Muting next for {}", IoStat->PromoDelay);
} else {
MediaPlayer::playWavFile(SwordCfg->SoundPromoShort);
fmt::println("still muted");
}
fmt::println("Waiting for {}", IoStat->PromoDelay);
Thread::sleep(IoStat->PromoDelay);
fmt::println("Waiting done");
}
}
if (tn.tick()) {
+38 -3
View File
@@ -20,9 +20,11 @@
#include <thread>
#include <vector>
#include "Ads1115.hpp"
#include "MqttClient.hpp"
#include "coreExcept.hpp"
#include "gpioPort.hpp"
#include "i2cPort.hpp"
#include "logging.hpp"
#include "queue.hpp"
#include "textUtils.hpp"
@@ -50,6 +52,39 @@ class LinMot {
}
};
class CurrMon {
// https://www.monolithicpower.com/en/documentview/productdocument/index/version/2/document_type/Datasheet/lang/EN/sku/MCS1802/document_id/5066/
public:
CurrMon(AdcAds1115& adc)
: _adc(adc) {
adc.setPga(AdcAds1115::Pga::FSR_4_096V);
adc.startContinuousConversion();
float val{};
for (size_t i = 0; i < 8; i++) {
val += sampe();
}
_refVal = val / 8;
}
float sampleCurrent() {
auto val = sampe() - _refVal;
val = val / 0.264;
fmt::println("{:.2} A", val);
return val;
}
private:
float _refVal{};
AdcAds1115& _adc;
float sampe() {
float volt;
_adc.readConversionVoltage(volt);
return volt;
}
};
class DeviceIoState {
public:
DeviceIoState(pal::InputTransAware& entry,
@@ -75,7 +110,7 @@ class DeviceIoState {
std::chrono::seconds PromoDelay{150};
int Volume{50};
bool Mute{false};
bool Mute{true};
};
struct SwordConfig {
@@ -113,7 +148,7 @@ class MediaPlayer {
return;
}
thread audioThread([filePath]() {
auto cmd = fmt::format("aplay '{}' 2>/dev/null", filePath);
auto cmd = fmt::format("aplay '{}'", filePath);
auto result = system(cmd.c_str());
if (result != 0) {
fmt::println(stderr, "ERROR: Failed to play audio file: '{}'", filePath);
@@ -134,7 +169,7 @@ class MediaPlayer {
fmt::println(stderr, "ERROR: No ALSA volume control found");
return;
}
auto cmd = fmt::format("amixer -q sset '{}' {}% 2>/dev/null", control, volume);
auto cmd = fmt::format("amixer -q sset '{}' {}%", control, volume);
auto result = system(cmd.c_str());
if (result != 0) {
fmt::println(stderr, "ERROR: Failed to set volume to {}%", volume);