From 90d951f191c315d502a7586efe1975ffae31e19c Mon Sep 17 00:00:00 2001 From: Jochen Vothknecht <jochen3120@gmail.com> Date: Thu, 26 Oct 2023 06:10:31 +0200 Subject: [PATCH] Adding BallMill and SimplePWM --- .../SiliconTorch/Hardware/SimplePWM.cpp | 127 +++++++++++++++++ .../SiliconTorch/Hardware/SimplePWM.hpp | 63 +++++++++ CLC-qthing/SiliconTorch/Service/BallMill.cpp | 130 ++++++++++++++++++ CLC-qthing/SiliconTorch/Service/BallMill.hpp | 74 ++++++++++ .../SiliconTorch/Service/SpiderFurnace.hpp | 2 +- .../SiliconTorch/Service/__services__.cpp | 2 + 6 files changed, 397 insertions(+), 1 deletion(-) create mode 100644 CLC-qthing/SiliconTorch/Hardware/SimplePWM.cpp create mode 100644 CLC-qthing/SiliconTorch/Hardware/SimplePWM.hpp create mode 100644 CLC-qthing/SiliconTorch/Service/BallMill.cpp create mode 100644 CLC-qthing/SiliconTorch/Service/BallMill.hpp diff --git a/CLC-qthing/SiliconTorch/Hardware/SimplePWM.cpp b/CLC-qthing/SiliconTorch/Hardware/SimplePWM.cpp new file mode 100644 index 0000000..657ca38 --- /dev/null +++ b/CLC-qthing/SiliconTorch/Hardware/SimplePWM.cpp @@ -0,0 +1,127 @@ +#include "SimplePWM.hpp" + +// C++ system level +// #include <cstdio> // sprintf +// #include <functional> + +// ESP32 specific +#include "esp_log.h" +#include "driver/gpio.h" +#include "driver/ledc.h" + +// project specific +#include <Types.hpp> +#include "SiliconTorch/NVSExplorer.hpp" + +// qthing stuff +#include <qthing> +//#include <qthing/mqtt_common.hpp> +#include "SiliconTorch/CyanBus.hpp" + + + +static const char* TAG = "SimplePWM"; + + +namespace SimplePWM { + + SimplePWM::SimplePWM(u8 gpio, u8 ledcChannel, u8 timerChannel) { + + // Setup IO + gpio_config_t conf; + + conf.intr_type = GPIO_INTR_DISABLE; + conf.mode = GPIO_MODE_OUTPUT; + conf.pin_bit_mask = 1ULL << gpio; + conf.pull_up_en = GPIO_PULLUP_DISABLE; + conf.pull_down_en = GPIO_PULLDOWN_DISABLE; + + gpio_config(&conf); + gpio_set_level((gpio_num_t)gpio, 0); + + + // Setup PWM + timer_cfg.duty_resolution = (ledc_timer_bit_t)resolution; + timer_cfg.freq_hz = frequency; + timer_cfg.speed_mode = LEDC_HIGH_SPEED_MODE; + timer_cfg.timer_num = (ledc_timer_t)timerChannel; + timer_cfg.clk_cfg = LEDC_AUTO_CLK; + + channel_cfg.channel = (ledc_channel_t)ledcChannel; + channel_cfg.duty = 0; + channel_cfg.gpio_num = (gpio_num_t)gpio; + channel_cfg.speed_mode = LEDC_HIGH_SPEED_MODE; + channel_cfg.hpoint = 0; + channel_cfg.timer_sel = (ledc_timer_t)timerChannel; + channel_cfg.intr_type = LEDC_INTR_DISABLE; + + ledc_fade_func_install(0); + ledc_timer_config(&timer_cfg); + ledc_channel_config(&channel_cfg); + + } + + + void SimplePWM::setDuty(u32 _duty) { + + u32 limit = (1 << resolution) - 1; + + if (_duty > limit) _duty = limit; + + ledc_set_duty(LEDC_HIGH_SPEED_MODE, channel_cfg.channel, _duty); + ledc_update_duty(LEDC_HIGH_SPEED_MODE, channel_cfg.channel); + + duty = _duty; + } + + void SimplePWM::setDutyFloat(f32 _duty) { + + if (_duty < 0.0f) _duty = 0.0f; + if (_duty > 1.0f) _duty = 1.0f; + + u32 limit = (1 << resolution) - 1; + + setDuty(_duty * limit); + } + + bool SimplePWM::setFrequency(u32 _frq) { + return setFrqRes(_frq, resolution); + } + + bool SimplePWM::setResolution(u8 _res) { + return setFrqRes(frequency, _res); + } + + bool SimplePWM::setFrqRes(u32 _frq, u8 _res) { + + timer_cfg.duty_resolution = (ledc_timer_bit_t)_res; + timer_cfg.freq_hz = _frq; + + if (ledc_timer_config(&timer_cfg) == ESP_OK) { + frequency = _frq; + resolution = _res; + + ESP_LOGI(TAG, "frequency[ %i Hz ] resolution[ %i bit ]", _frq, _res); + return true; + + } else { + + ESP_LOGW(TAG, "Invalid frequency[ %i Hz ] and resolution[ %i bit ] setting!", _frq, _res); + return false; + + } + } + + u32 SimplePWM::getDuty() const { + return duty; + } + + u32 SimplePWM::getFrequency() const { + return frequency; + } + + u8 SimplePWM::getResolution() const { + return resolution; + } + +} diff --git a/CLC-qthing/SiliconTorch/Hardware/SimplePWM.hpp b/CLC-qthing/SiliconTorch/Hardware/SimplePWM.hpp new file mode 100644 index 0000000..781b227 --- /dev/null +++ b/CLC-qthing/SiliconTorch/Hardware/SimplePWM.hpp @@ -0,0 +1,63 @@ +#pragma once + +// C++ system level +// #include <cstdio> // sprintf +// #include <functional> + +// ESP32 specific +#include "esp_log.h" +#include "driver/ledc.h" + +// project specific +#include <Types.hpp> +#include "SiliconTorch/NVSExplorer.hpp" + +// qthing stuff +#include <qthing> +//#include <qthing/mqtt_common.hpp> +#include "SiliconTorch/CyanBus.hpp" + + + +namespace SimplePWM { + + constexpr u16 DEFAULT_FREQUENCY = 1000; + constexpr u16 DEFAULT_RESOLUTION = 10; + + + class SimplePWM { + + public: + + SimplePWM(u8 gpio, u8 ledcChannel = 0, u8 timerChannel = 0); + + + u32 getDuty() const; + u32 getFrequency() const; + u8 getResolution() const; + + void setDuty(u32 _duty); + void setDutyFloat(f32 _duty); // accepts range [0, 1] + bool setFrequency(u32 _frq); + bool setResolution(u8 _res); + bool setFrqRes(u32 _frq, u8 _res); + + + // TODO: should we block copy/assignment by default…? + //SimplePWM() {}; + SimplePWM(const SimplePWM&) = delete; + SimplePWM& operator=(SimplePWM const&) = delete; + + + private: + + u32 frequency = DEFAULT_FREQUENCY; + u8 resolution = DEFAULT_RESOLUTION; + u32 duty = 0; + + ledc_timer_config_t timer_cfg; + ledc_channel_config_t channel_cfg; + + }; + +} diff --git a/CLC-qthing/SiliconTorch/Service/BallMill.cpp b/CLC-qthing/SiliconTorch/Service/BallMill.cpp new file mode 100644 index 0000000..7c7adae --- /dev/null +++ b/CLC-qthing/SiliconTorch/Service/BallMill.cpp @@ -0,0 +1,130 @@ +#include "BallMill.hpp" + +// C++ system level +#include <cstdio> // sprintf +// #include <functional> + +// ESP32 specific +#include "esp_log.h" +#include "driver/gpio.h" + +// project specific +#include <Time.hpp> +#include <Types.hpp> +#include "SiliconTorch/NVSExplorer.hpp" + +// qthing stuff +#include <qthing> +//#include <qthing/mqtt_common.hpp> +#include "SiliconTorch/CyanBus.hpp" + +// misc +#include <nlohmann/json.hpp> + + +using nlohmann::json; +using SpiderLib::Time; + + +static const char* TAG = "BallMill"; + +static u32 _frq = 0; + +namespace SiliconTorch { + + namespace Service { + + namespace BallMill { + + void BallMill::init() { + setIcon("🪩"); + setName("BallMill"); + setNameSpace("BallMill"); + } + + + void BallMill::start() { + + /* + // Load config values from NVS + f32 _kP = SiliconTorch::NVSExplorer::NVSExplorer::instance().getFloat(getNameSpace(), "kP"); + f32 _kI = SiliconTorch::NVSExplorer::NVSExplorer::instance().getFloat(getNameSpace(), "kI"); + f32 _kD = SiliconTorch::NVSExplorer::NVSExplorer::instance().getFloat(getNameSpace(), "kD"); + + if (!std::isnan(_kP)) kP = _kP; + if (!std::isnan(_kI)) kI = _kI; + if (!std::isnan(_kD)) kD = _kD; + + ESP_LOGI(TAG, "PIDvals: kP[ %.3f ] kI[ %.3f ] kD[ %.3f ]", kP, kI, kD); + */ + + ch0 = new SimplePWM::SimplePWM(CH0_STEP); + ch0->setFrqRes(1, 10); + ch0->setDuty(0); + + // Setup stepper task + stepTask = new SpiderLib::Util::LambdaTask([&](){ + + TickType_t lastWakeTime = xTaskGetTickCount(); + + while (true) { + + i32 frq = currentRPM / 60.0f * CFG_STEPS_PER_ROUND; + + // TODO: Handle negative FRQ!! + //if (frq > 0) { + // ch0->setDuty(1); + // ch0->setFrqRes(frq, 1); + //} else { + // ch0->setDuty(0); + //} + + ch0->setFrqRes(_frq, 10); + ch0->setDuty(1 << (10 - 1)); // TODO: is setDutyFloat(0.5f) precise enough…? + + + if (abs(targetRPM - currentRPM) < CFG_RPM_CHANGE_PER_SECOND) { + currentRPM = targetRPM; + } else { + f32 sign = (targetRPM - currentRPM) < 0.0f ? -1.0f : 1.0f; + currentRPM = targetRPM + sign * CFG_RPM_CHANGE_PER_SECOND; + } + + ESP_LOGI(TAG, "frq[ %i ] currentRPM[ %f ] targetRPM[ %f ]", frq, currentRPM, targetRPM); + + vTaskDelayUntil(&lastWakeTime, 1000 / CFG_TICK_FRQ / portTICK_PERIOD_MS); + } + }); + + + qthing::add_message_callback(deviceTopic(TAG, "setRPM"), [&](const str& message) { + f32 rpm = std::strtof(message.c_str(), NULL); + + if (!std::isnan(rpm)) + targetRPM = rpm; + }); + + qthing::add_message_callback(deviceTopic(TAG, "setFRQ"), [&](const str& message) { + _frq = std::strtol(message.c_str(), NULL, 0); + }); + + } + + + + json BallMill::getConfigJSON() const { + + json out; + + out["bla"] = "fasel"; + + return out; + } + + + + } + } +} + + diff --git a/CLC-qthing/SiliconTorch/Service/BallMill.hpp b/CLC-qthing/SiliconTorch/Service/BallMill.hpp new file mode 100644 index 0000000..082c729 --- /dev/null +++ b/CLC-qthing/SiliconTorch/Service/BallMill.hpp @@ -0,0 +1,74 @@ +#pragma once + +// C++ system level +#include <vector> +// #include <cstring> // memset, strncmp +// #include <cstdlib> // TODO: is this for memcpy? +// #include <functional> + +// ESP32 specific +#include "esp_log.h" +#include "driver/ledc.h" + +// project specific +#include <SpiderLib.hpp> +#include "Service.hpp" +#include "../Hardware/SimplePWM.hpp" + +// qthing stuff +#include "SiliconTorch/FxCyanRGB8.hpp" +// #include <qthing> + +// misc +#include <nlohmann/json.hpp> + + +namespace SiliconTorch { + + namespace Service { + + namespace BallMill { + + + constexpr u8 CH0_STEP = 23; + constexpr u8 CH0_DIRECTION = 22; + + constexpr u8 CFG_TICK_FRQ = 10; + constexpr u16 CFG_STEPS_PER_ROUND = 200; + constexpr f32 CFG_RPM_CHANGE_PER_SECOND = 13.37f; + + + + + class BallMill : public ServiceManager::Service, public SpiderLib::HasMQTT { + + public: + + void init(); + + void start(); + + virtual nlohmann::json getConfigJSON() const; + + + // TODO: should we block copy/assignment by default…? + BallMill() {}; + BallMill(const BallMill&) = delete; + BallMill& operator=(BallMill const&) = delete; + + + private: + + f32 targetRPM = 0.0f; + f32 currentRPM = 0.0f; + + SimplePWM::SimplePWM* ch0 = NULL; + + SpiderLib::Util::LambdaTask* stepTask = NULL; + + }; + + + } + } +} diff --git a/CLC-qthing/SiliconTorch/Service/SpiderFurnace.hpp b/CLC-qthing/SiliconTorch/Service/SpiderFurnace.hpp index f3c9b00..ee549a4 100644 --- a/CLC-qthing/SiliconTorch/Service/SpiderFurnace.hpp +++ b/CLC-qthing/SiliconTorch/Service/SpiderFurnace.hpp @@ -46,7 +46,7 @@ namespace SiliconTorch { constexpr u8 IO_MOSI = 16; constexpr u8 IO_SCLK = 27; constexpr u8 IO_HEATER = 22; - + constexpr u8 IO_FAN = 23; // enum FurnaceState { // RUNNING, diff --git a/CLC-qthing/SiliconTorch/Service/__services__.cpp b/CLC-qthing/SiliconTorch/Service/__services__.cpp index b830724..ec7ae05 100644 --- a/CLC-qthing/SiliconTorch/Service/__services__.cpp +++ b/CLC-qthing/SiliconTorch/Service/__services__.cpp @@ -3,6 +3,7 @@ // our services #include "FxCyanF.hpp" #include "CyanBus.hpp" +#include "BallMill.hpp" #include "FxPublish.hpp" #include "CyanStripe.hpp" #include "SpiderFurnace.hpp" @@ -19,6 +20,7 @@ namespace SiliconTorch { mgr->registerService(new SiliconTorch::Service::FxCyanF()); mgr->registerService(new SiliconTorch::Service::CyanBus()); mgr->registerService(new SiliconTorch::Service::FxPublish()); + mgr->registerService(new SiliconTorch::Service::BallMill::BallMill()); mgr->registerService(new SiliconTorch::Service::CyanStripe::CyanStripe()); mgr->registerService(new SiliconTorch::Service::SpiderFurnace::SpiderFurnace()); -- GitLab