From 858a64fc98a1c0785747c5c5a63660d0bfd9e245 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=B3r=C3=A1nt=20Pint=C3=A9r?= Date: Mon, 15 Jul 2024 21:22:37 +0200 Subject: [PATCH] Publish motor current for chicken-door --- src/devices/UglyDucklingMk4.hpp | 4 +- src/devices/UglyDucklingMk5.hpp | 6 +-- src/devices/UglyDucklingMk6.hpp | 11 ++++-- src/devices/UglyDucklingMk7.hpp | 11 ++++-- src/kernel/drivers/CurrentSenseDriver.hpp | 29 ++++++++++++++ src/kernel/drivers/Drv8801Driver.hpp | 7 +++- src/kernel/drivers/Drv8874Driver.hpp | 7 +++- src/kernel/drivers/MotorDriver.hpp | 28 +++++++++++++ src/peripherals/Motorized.hpp | 41 -------------------- src/peripherals/Peripheral.hpp | 25 ++++++++++++ src/peripherals/chicken_door/ChickenDoor.hpp | 17 ++++---- src/peripherals/flow_control/FlowControl.hpp | 12 ++---- src/peripherals/valve/Valve.hpp | 9 ++--- 13 files changed, 132 insertions(+), 75 deletions(-) create mode 100644 src/kernel/drivers/CurrentSenseDriver.hpp delete mode 100644 src/peripherals/Motorized.hpp diff --git a/src/devices/UglyDucklingMk4.hpp b/src/devices/UglyDucklingMk4.hpp index 6dfa15de..2727b9c3 100644 --- a/src/devices/UglyDucklingMk4.hpp +++ b/src/devices/UglyDucklingMk4.hpp @@ -96,8 +96,8 @@ class UglyDucklingMk4 : public DeviceDefinition { pins::VALVE_SLEEP }; - const ServiceRef motor { "motor", motorDriver }; - const std::list> motors { motor }; + const ServiceRef motor { "motor", motorDriver }; + const std::list> motors { motor }; ValveFactory valveFactory { motors, ValveControlStrategyType::NormallyClosed }; FlowMeterFactory flowMeterFactory; diff --git a/src/devices/UglyDucklingMk5.hpp b/src/devices/UglyDucklingMk5.hpp index 24b16292..449c7a3d 100644 --- a/src/devices/UglyDucklingMk5.hpp +++ b/src/devices/UglyDucklingMk5.hpp @@ -108,9 +108,9 @@ class UglyDucklingMk5 : public DeviceDefinition { pins::NSLEEP }; - const ServiceRef motorA { "a", motorADriver }; - const ServiceRef motorB { "b", motorBDriver }; - const std::list> motors { motorA, motorB }; + const ServiceRef motorA { "a", motorADriver }; + const ServiceRef motorB { "b", motorBDriver }; + const std::list> motors { motorA, motorB }; ValveFactory valveFactory { motors, ValveControlStrategyType::Latching }; FlowMeterFactory flowMeterFactory; diff --git a/src/devices/UglyDucklingMk6.hpp b/src/devices/UglyDucklingMk6.hpp index 559272fd..b5b8ff07 100644 --- a/src/devices/UglyDucklingMk6.hpp +++ b/src/devices/UglyDucklingMk6.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -119,9 +120,13 @@ class UglyDucklingMk6 : public DeviceDefinition { config.motorNSleepPin.get() }; - const ServiceRef motorA { "a", motorDriver.getMotorA() }; - const ServiceRef motorB { "b", motorDriver.getMotorB() }; - const std::list> motors { motorA, motorB }; + SimpleCurrentSenseDriver currentSense { pins::DIPROPI }; + ExternalCurrentSensingMotorDriver motorADriver { motorDriver.getMotorA(), currentSense }; + ExternalCurrentSensingMotorDriver motorBDriver { motorDriver.getMotorB(), currentSense }; + + const ServiceRef motorA { "a", motorADriver }; + const ServiceRef motorB { "b", motorBDriver }; + const std::list> motors { motorA, motorB }; ValveFactory valveFactory { motors, ValveControlStrategyType::Latching }; FlowMeterFactory flowMeterFactory; diff --git a/src/devices/UglyDucklingMk7.hpp b/src/devices/UglyDucklingMk7.hpp index 93683f18..1167c548 100644 --- a/src/devices/UglyDucklingMk7.hpp +++ b/src/devices/UglyDucklingMk7.hpp @@ -113,9 +113,14 @@ class UglyDucklingMk7 : public DeviceDefinition { pins::LOADEN, }; - const ServiceRef motorA { "a", motorDriver.getMotorA() }; - const ServiceRef motorB { "b", motorDriver.getMotorB() }; - const std::list> motors { motorA, motorB }; + // TODO Implement proper current sensing for MK7 + SimpleCurrentSenseDriver currentSense { pins::IOA1 }; + ExternalCurrentSensingMotorDriver motorADriver { motorDriver.getMotorA(), currentSense }; + ExternalCurrentSensingMotorDriver motorBDriver { motorDriver.getMotorB(), currentSense }; + + const ServiceRef motorA { "a", motorADriver }; + const ServiceRef motorB { "b", motorBDriver }; + const std::list> motors { motorA, motorB }; ValveFactory valveFactory { motors, ValveControlStrategyType::Latching }; FlowMeterFactory flowMeterFactory; diff --git a/src/kernel/drivers/CurrentSenseDriver.hpp b/src/kernel/drivers/CurrentSenseDriver.hpp new file mode 100644 index 00000000..95d643ae --- /dev/null +++ b/src/kernel/drivers/CurrentSenseDriver.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include + +namespace farmhub::kernel::drivers { +class CurrentSenseDriver { + +public: + virtual double readCurrent() const = 0; +}; + +class SimpleCurrentSenseDriver + : public CurrentSenseDriver { +public: + SimpleCurrentSenseDriver(gpio_num_t pin, double scale = 4096) + : pin(pin) + , scale(scale) { + pinMode(pin, INPUT); + } + + double readCurrent() const override { + return analogRead(pin) / scale; + } + +private: + gpio_num_t pin; + double scale; +}; +} // namespace farmhub::kernel::drivers diff --git a/src/kernel/drivers/Drv8801Driver.hpp b/src/kernel/drivers/Drv8801Driver.hpp index 33ce2c8b..a70ad5e7 100644 --- a/src/kernel/drivers/Drv8801Driver.hpp +++ b/src/kernel/drivers/Drv8801Driver.hpp @@ -6,6 +6,7 @@ #include #include +#include #include using namespace std::chrono; @@ -18,7 +19,7 @@ namespace farmhub::kernel::drivers { * https://www.ti.com/lit/gpn/DRV8801 */ class Drv8801Driver - : public PwmMotorDriver { + : public CurrentSensingMotorDriver { private: const uint32_t PWM_FREQ = 25000; // 25kHz @@ -91,6 +92,10 @@ class Drv8801Driver return sleeping; } + double readCurrent() const override { + return analogRead(currentPin) / 4096.0; + } + private: const gpio_num_t enablePin; const PwmChannel phaseChannel; diff --git a/src/kernel/drivers/Drv8874Driver.hpp b/src/kernel/drivers/Drv8874Driver.hpp index 627ac865..abe6faf7 100644 --- a/src/kernel/drivers/Drv8874Driver.hpp +++ b/src/kernel/drivers/Drv8874Driver.hpp @@ -6,6 +6,7 @@ #include #include +#include #include using namespace std::chrono; @@ -18,7 +19,7 @@ namespace farmhub::kernel::drivers { * https://www.ti.com/lit/gpn/DRV8874 */ class Drv8874Driver - : public PwmMotorDriver { + : public CurrentSensingMotorDriver { private: const uint32_t PWM_FREQ = 25000; // 25kHz @@ -88,6 +89,10 @@ class Drv8874Driver return sleeping; } + double readCurrent() const override { + return analogRead(currentPin) / 4096.0; + } + private: const PwmChannel in1Channel; const PwmChannel in2Channel; diff --git a/src/kernel/drivers/MotorDriver.hpp b/src/kernel/drivers/MotorDriver.hpp index cad63905..94761483 100644 --- a/src/kernel/drivers/MotorDriver.hpp +++ b/src/kernel/drivers/MotorDriver.hpp @@ -1,5 +1,7 @@ #pragma once +#include + namespace farmhub::kernel::drivers { enum class MotorPhase { @@ -22,4 +24,30 @@ class PwmMotorDriver { virtual void drive(MotorPhase phase, double duty = 1) = 0; }; +class CurrentSensingMotorDriver + : public PwmMotorDriver, + public CurrentSenseDriver { +}; + +class ExternalCurrentSensingMotorDriver + : public CurrentSensingMotorDriver { +public: + ExternalCurrentSensingMotorDriver(PwmMotorDriver& motor, CurrentSenseDriver& currentSense) + : motor(motor) + , currentSense(currentSense) { + } + + void drive(MotorPhase phase, double duty = 1) override { + motor.drive(phase, duty); + } + + double readCurrent() const override { + return currentSense.readCurrent(); + } + +private: + PwmMotorDriver& motor; + CurrentSenseDriver& currentSense; +}; + } // namespace farmhub::kernel::drivers diff --git a/src/peripherals/Motorized.hpp b/src/peripherals/Motorized.hpp deleted file mode 100644 index 6af9d08e..00000000 --- a/src/peripherals/Motorized.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include - -#include - -#include - -#include - -#include - -using namespace farmhub::kernel::drivers; - -namespace farmhub::peripherals { - -class Motorized { -public: - Motorized(const std::list>& motors) - : motors(motors) { - } - -protected: - PwmMotorDriver& findMotor(const String& motorName) { - // If there's only one motor and no name is specified, use it - if (motorName.isEmpty() && motors.size() == 1) { - return motors.front().get(); - } - for (auto& motor : motors) { - if (motor.getName() == motorName) { - return motor.get(); - } - } - throw PeripheralCreationException("failed to find motor: " + motorName); - } - -private: - const std::list> motors; -}; - -} // namespace farmhub::peripherals diff --git a/src/peripherals/Peripheral.hpp b/src/peripherals/Peripheral.hpp index 9b7cad85..c3398e28 100644 --- a/src/peripherals/Peripheral.hpp +++ b/src/peripherals/Peripheral.hpp @@ -243,4 +243,29 @@ class PeripheralManager std::list> peripherals; }; +template +class ServiceContainer { +public: + ServiceContainer(const std::list>& services) + : services(services) { + } + +protected: + T& findService(const String& name) { + // If there's only one service and no name is specified, use it + if (name.isEmpty() && services.size() == 1) { + return services.front().get(); + } + for (auto& motor : services) { + if (motor.getName() == name) { + return motor.get(); + } + } + throw PeripheralCreationException("failed to find service: " + name); + } + +private: + const std::list> services; +}; + } // namespace farmhub::peripherals diff --git a/src/peripherals/chicken_door/ChickenDoor.hpp b/src/peripherals/chicken_door/ChickenDoor.hpp index bc4bbe98..2e524af3 100644 --- a/src/peripherals/chicken_door/ChickenDoor.hpp +++ b/src/peripherals/chicken_door/ChickenDoor.hpp @@ -16,10 +16,10 @@ #include #include +#include #include #include -#include #include #include #include @@ -95,7 +95,7 @@ class ChickenDoorComponent shared_ptr mqttRoot, SleepManager& sleepManager, SwitchManager& switches, - PwmMotorDriver& motor, + CurrentSensingMotorDriver& motor, TLightSensorComponent& lightSensor, gpio_num_t openPin, gpio_num_t closedPin, @@ -155,6 +155,7 @@ class ChickenDoorComponent telemetry["state"] = lastState; telemetry["targetState"] = lastTargetState; telemetry["operationState"] = operationState; + telemetry["current"] = motor.readCurrent(); if (overrideState != DoorState::NONE) { time_t rawtime = system_clock::to_time_t(overrideUntil); auto timeinfo = gmtime(&rawtime); @@ -319,7 +320,7 @@ class ChickenDoorComponent } SleepManager& sleepManager; - PwmMotorDriver& motor; + CurrentSensingMotorDriver& motor; TLightSensorComponent& lightSensor; double openLevel = std::numeric_limits::max(); @@ -363,7 +364,7 @@ class ChickenDoor uint8_t lightSensorAddress, SleepManager& sleepManager, SwitchManager& switches, - PwmMotorDriver& motor, + CurrentSensingMotorDriver& motor, const ChickenDoorDeviceConfig& config) : Peripheral(name, mqttRoot) , lightSensor( @@ -423,15 +424,15 @@ class NoLightSensorComponent : public LightSensorComponent { class ChickenDoorFactory : public PeripheralFactory, - protected Motorized { + protected ServiceContainer { public: - ChickenDoorFactory(const std::list>& motors) + ChickenDoorFactory(const std::list>& motors) : PeripheralFactory("chicken-door") - , Motorized(motors) { + , ServiceContainer(motors) { } unique_ptr> createPeripheral(const String& name, const ChickenDoorDeviceConfig& deviceConfig, shared_ptr mqttRoot, PeripheralServices& services) override { - PwmMotorDriver& motor = findMotor(deviceConfig.motor.get()); + CurrentSensingMotorDriver& motor = findService(deviceConfig.motor.get()); auto lightSensorType = deviceConfig.lightSensor.get().type.get(); try { if (lightSensorType == "bh1750") { diff --git a/src/peripherals/flow_control/FlowControl.hpp b/src/peripherals/flow_control/FlowControl.hpp index d1d23acf..af309c01 100644 --- a/src/peripherals/flow_control/FlowControl.hpp +++ b/src/peripherals/flow_control/FlowControl.hpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -74,20 +73,20 @@ class FlowControlDeviceConfig class FlowControlFactory : public PeripheralFactory, - protected Motorized { + protected ServiceContainer { public: FlowControlFactory( - const std::list>& motors, + const std::list>& motors, ValveControlStrategyType defaultStrategy) : PeripheralFactory("flow-control", defaultStrategy) - , Motorized(motors) { + , ServiceContainer(motors) { } unique_ptr> createPeripheral(const String& name, const FlowControlDeviceConfig& deviceConfig, shared_ptr mqttRoot, PeripheralServices& services) override { const ValveDeviceConfig& valveConfig = deviceConfig.valve.get(); const FlowMeterDeviceConfig& flowMeterConfig = deviceConfig.flowMeter.get(); - PwmMotorDriver& targetMotor = findMotor(valveConfig.motor.get()); + PwmMotorDriver& targetMotor = findService(valveConfig.motor.get()); ValveControlStrategy* strategy; try { strategy = createValveControlStrategy( @@ -110,9 +109,6 @@ class FlowControlFactory flowMeterConfig.qFactor.get(), flowMeterConfig.measurementFrequency.get()); } - -private: - const std::list> motors; }; } // namespace farmhub::peripherals::flow_control diff --git a/src/peripherals/valve/Valve.hpp b/src/peripherals/valve/Valve.hpp index 7752c677..a8fb13d6 100644 --- a/src/peripherals/valve/Valve.hpp +++ b/src/peripherals/valve/Valve.hpp @@ -14,7 +14,6 @@ #include #include -#include #include #include #include @@ -59,17 +58,17 @@ class Valve class ValveFactory : public PeripheralFactory, - protected Motorized { + protected ServiceContainer { public: ValveFactory( - const std::list>& motors, + const std::list>& motors, ValveControlStrategyType defaultStrategy) : PeripheralFactory("valve", defaultStrategy) - , Motorized(motors) { + , ServiceContainer(motors) { } unique_ptr> createPeripheral(const String& name, const ValveDeviceConfig& deviceConfig, shared_ptr mqttRoot, PeripheralServices& services) override { - PwmMotorDriver& targetMotor = findMotor(deviceConfig.motor.get()); + CurrentSensingMotorDriver& targetMotor = findService(deviceConfig.motor.get()); ValveControlStrategy* strategy; try { strategy = createValveControlStrategy(