added HA integration (not discovered)

This commit is contained in:
2022-09-16 12:13:13 +02:00
parent 938c6f7481
commit 034eb4c393
10 changed files with 261 additions and 244 deletions

View File

@@ -19,138 +19,122 @@ monitor_flags =
--eol=CRLF
--echo
--filter=esp32_exception_decoder
lib_deps =
askuric/Simple FOC @ 2.2.0
infineon/TLV493D-Magnetic-Sensor @ 1.0.3
bxparks/AceButton @ 1.9.1
build_flags =
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
lib_deps =
askuric/Simple FOC @ 2.2.0
infineon/TLV493D-Magnetic-Sensor @ 1.0.3
bxparks/AceButton @ 1.9.1
build_flags =
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
[env:view]
extends = base_config
; platform = https://github.com/platformio/platform-espressif32.git#feature/arduino-upstream
; platform_packages =
; framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32#master
board = esp32doit-devkit-v1
lib_deps =
; askuric/Simple FOC @ 2.2.1
; bxparks/AceButton @ 1.9.1
${base_config.lib_deps}
bodmer/TFT_eSPI@2.4.25
fastled/FastLED @ 3.5.0
bogde/HX711 @ 0.7.5
adafruit/Adafruit VEML7700 Library @ 1.1.1
lib_deps =
${base_config.lib_deps}
bodmer/TFT_eSPI@2.4.25
fastled/FastLED @ 3.5.0
bogde/HX711 @ 0.7.5
adafruit/Adafruit VEML7700 Library @ 1.1.1
dawidchyrzynski/home-assistant-integration@^1.3.0
build_flags =
${base_config.build_flags}
-DSK_DISPLAY=1
-DSK_LEDS=1
-DNUM_LEDS=8
-DSENSOR_MT6701=1
-DSK_STRAIN=1
-DSK_INVERT_ROTATION=1
-DSK_ALS=1
-DPIN_UH=26
-DPIN_UL=25
-DPIN_VH=27
-DPIN_VL=32
-DPIN_WH=12
-DPIN_WL=33
-DPIN_BUTTON_NEXT=-1
-DPIN_BUTTON_PREV=-1
-DPIN_SDA=15
-DPIN_SCL=8
-DPIN_MT_DATA=37
-DPIN_MT_CLOCK=13
-DPIN_MT_CSN=14
-DPIN_LED_DATA=7
-DPIN_LCD_BACKLIGHT=19
-DDESCRIPTION_FONT=Roboto_Thin_24
-DDESCRIPTION_Y_OFFSET=20
-DVALUE_OFFSET=30
-DDRAW_ARC=0
-DUSER_SETUP_LOADED=1
-DGC9A01_DRIVER=1
-DCGRAM_OFFSET=1
-DTFT_WIDTH=240
-DTFT_HEIGHT=240
-DTFT_MISO=-1
-DTFT_MOSI=5
-DTFT_SCLK=20
-DTFT_CS=21
-DTFT_DC=22
-DTFT_RST=4
-DTFT_BL=-1
-DLOAD_GLCD=1
-DLOAD_GFXFF=1
-DSPI_FREQUENCY=40000000
-DFASTLED_UNUSABLE_PIN_MASK=0x100740LL
-DSOC_GPIO_VALID_GPIO_MASK=0xFF0EFFFFFF
-DSOC_GPIO_VALID_OUTPUT_GPIO_MASK=0x30EFFFFFF
build_flags =
${base_config.build_flags}
-DSK_DISPLAY=1
-DSK_LEDS=1
-DNUM_LEDS=8
-DSENSOR_MT6701=1
-DSK_STRAIN=1
-DSK_INVERT_ROTATION=1
-DSK_ALS=1
-DPIN_UH=26
-DPIN_UL=25
-DPIN_VH=27
-DPIN_VL=32
-DPIN_WH=12
-DPIN_WL=33
-DPIN_BUTTON_NEXT=-1
-DPIN_BUTTON_PREV=-1
-DPIN_SDA=15
-DPIN_SCL=8
-DPIN_MT_DATA=37
-DPIN_MT_CLOCK=13
-DPIN_MT_CSN=14
-DPIN_LED_DATA=7
-DPIN_LCD_BACKLIGHT=19
-DDESCRIPTION_FONT=Roboto_Thin_24
-DDESCRIPTION_Y_OFFSET=20
-DVALUE_OFFSET=30
-DDRAW_ARC=0
-DUSER_SETUP_LOADED=1
-DGC9A01_DRIVER=1
-DCGRAM_OFFSET=1
-DTFT_WIDTH=240
-DTFT_HEIGHT=240
-DTFT_MISO=-1
-DTFT_MOSI=5
-DTFT_SCLK=20
-DTFT_CS=21
-DTFT_DC=22
-DTFT_RST=4
-DTFT_BL=-1
-DLOAD_GLCD=1
-DLOAD_GFXFF=1
-DSPI_FREQUENCY=40000000
; Reduce loop task stack size (only works on newer IDF Arduino core)
; -DARDUINO_LOOP_STACK_SIZE=2048
; Modify the default unusable pin mask to allow GPIO 7 (allowed to use on ESP32-PICO-V3-02)
; Unusable bits: 6, 8, 9, 10, 20
; (0ULL | _FL_BIT(6) | _FL_BIT(8) | _FL_BIT(9) | _FL_BIT(10) | _FL_BIT(20))
-DFASTLED_UNUSABLE_PIN_MASK=0x100740LL
; 0~39 except from 24, 28~31 are valid
; (0xFFFFFFFFFFULL & ~(0ULL | _FL_BIT(24) | _FL_BIT(28) | _FL_BIT(29) | _FL_BIT(30) | _FL_BIT(31)))
-DSOC_GPIO_VALID_GPIO_MASK=0xFF0EFFFFFF
; GPIO >= 34 are input only
; (SOC_GPIO_VALID_GPIO_MASK & ~(0ULL | _FL_BIT(34) | _FL_BIT(35) | _FL_BIT(36) | _FL_BIT(37) | _FL_BIT(38) | _FL_BIT(39)))
-DSOC_GPIO_VALID_OUTPUT_GPIO_MASK=0x30EFFFFFF
[env:handheld_tdisplay]
extends = base_config
board = esp32doit-devkit-v1
lib_deps =
${base_config.lib_deps}
bodmer/TFT_eSPI@2.4.25
build_flags =
${base_config.build_flags}
-DSK_DISPLAY=1
-DSK_STRAIN=0
-DSK_LEDS=0
-DPIN_UH=17
-DPIN_UL=2
-DPIN_VH=13
-DPIN_VL=32
-DPIN_WH=33
-DPIN_WL=25
-DPIN_BUTTON_NEXT=35
-DPIN_BUTTON_PREV=0
-DPIN_SDA=-1
-DPIN_SCL=-1
-DSENSOR_MT6701=1
-DPIN_MT_DATA=21
-DPIN_MT_CLOCK=22
-DPIN_MT_CSN=12
-DPIN_LCD_BACKLIGHT=4
-DDESCRIPTION_FONT=FreeSans9pt7b
-DDESCRIPTION_Y_OFFSET=80
-DVALUE_OFFSET=0
-DDRAW_ARC=1
-DUSER_SETUP_LOADED=1
-DST7789_DRIVER=1
-DCGRAM_OFFSET=1
-DTFT_WIDTH=135
-DTFT_HEIGHT=240
-DTFT_MISO=-1
-DTFT_MOSI=19
-DTFT_SCLK=18
-DTFT_CS=5
-DTFT_DC=16
-DTFT_RST=23
-DTFT_BL=-1
-DLOAD_GLCD=1
-DLOAD_GFXFF=1
-DSPI_FREQUENCY=40000000
lib_deps =
${base_config.lib_deps}
bodmer/TFT_eSPI@2.4.25
dawidchyrzynski/home-assistant-integration@^1.3.0
build_flags =
${base_config.build_flags}
-DSK_DISPLAY=1
-DSK_STRAIN=0
-DSK_LEDS=0
-DPIN_UH=17
-DPIN_UL=2
-DPIN_VH=13
-DPIN_VL=32
-DPIN_WH=33
-DPIN_WL=25
-DPIN_BUTTON_NEXT=35
-DPIN_BUTTON_PREV=0
-DPIN_SDA=-1
-DPIN_SCL=-1
-DSENSOR_MT6701=1
-DPIN_MT_DATA=21
-DPIN_MT_CLOCK=22
-DPIN_MT_CSN=12
-DPIN_LCD_BACKLIGHT=4
-DDESCRIPTION_FONT=FreeSans9pt7b
-DDESCRIPTION_Y_OFFSET=80
-DVALUE_OFFSET=0
-DDRAW_ARC=1
-DUSER_SETUP_LOADED=1
-DST7789_DRIVER=1
-DCGRAM_OFFSET=1
-DTFT_WIDTH=135
-DTFT_HEIGHT=240
-DTFT_MISO=-1
-DTFT_MOSI=19
-DTFT_SCLK=18
-DTFT_CS=5
-DTFT_DC=16
-DTFT_RST=23
-DTFT_BL=-1
-DLOAD_GLCD=1
-DLOAD_GFXFF=1
-DSPI_FREQUENCY=40000000

View File

@@ -1,28 +0,0 @@
#include "commu_task.h"
#include "semaphore_guard.h"
CommuTask::CommuTask(const uint8_t task_core) : Task{"Communication", 4048, 1, task_core} {
mutex_ = xSemaphoreCreateMutex();
assert(mutex_ != NULL);
}
CommuTask::~CommuTask()
{
}
void CommuTask::run() {
WiFi.begin("poes", "Rijnstraat214");
while(1)
{
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
delay(100);
}
}

View File

@@ -0,0 +1,85 @@
#include "commu_task.h"
#include "semaphore_guard.h"
static byte mac[] = {0x00, 0x10, 0xFA, 0x6E, 0x38, 0x4A};
WiFiClient client;
HADevice device(mac, sizeof(mac));
HAMqtt mqtt(client, device);
HASensor angle("angle");
CommuTask::CommuTask(const uint8_t task_core) : Task{"Communication", 4048, 1, task_core} {
knob_state_queue_ = xQueueCreate(1, sizeof(KnobState));
assert(knob_state_queue_ != NULL);
mutex_ = xSemaphoreCreateMutex();
assert(mutex_ != NULL);
}
CommuTask::~CommuTask()
{
vQueueDelete(knob_state_queue_);
vSemaphoreDelete(mutex_);
}
QueueHandle_t CommuTask::getKnobStateQueue() {
return knob_state_queue_;
}
void CommuTask::setAngleValue(uint32_t angle)
{
angle_ = angle;
//log_d("setAngleCalled = %u", angle);
}
void CommuTask::run() {
WiFi.begin("poes", "Rijnstraat214");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
KnobState state;
device.setName("SmartKnob001");
device.setSoftwareVersion("1.0.0");
angle.setUnitOfMeasurement("°");
angle.setDeviceClass("None");
angle.setName("SmartKnob Angle");
mqtt.begin(BROKER_ADDR, BROKER_USERNAME, BROKER_PASSWORD);
uint32_t lastSensorUpdate = millis();
angle.setValue(angle_);
if(mqtt.isConnected())
{
printf("mqtt connected");
}
else{
printf("mqtt NOT connected");
}
while(1)
{
if (xQueueReceive(knob_state_queue_, &state, portMAX_DELAY) == pdFALSE) {
continue;
}
if(millis() - lastSensorUpdate > 1000)
{
angle.setValue(state.current_position);
log_d("new angle=%u", state.current_position);
lastSensorUpdate = millis();
}
mqtt.loop();
delay(10);
}
}

View File

@@ -2,10 +2,20 @@
#include <Arduino.h>
#include <WiFi.h>
#include <Client.h>
#include <ArduinoHA.h>
#include "knob_data.h"
#include "task.h"
#define BROKER_ADDR IPAddress(192,168,4,58)
#define BROKER_USERNAME "mqtt_broker_user" // replace with your credentials
#define BROKER_PASSWORD "mqtt2022"
//HA vars
class CommuTask : public Task<CommuTask> {
friend class Task<CommuTask>; // Allow base Task to invoke protected run()
@@ -13,13 +23,20 @@ class CommuTask : public Task<CommuTask> {
CommuTask(const uint8_t task_core);
~CommuTask();
void setAngleValue(uint32_t angle);
QueueHandle_t getKnobStateQueue();
protected:
void run();
private:
uint32_t angle_ =0;
SemaphoreHandle_t mutex_;
QueueHandle_t knob_state_queue_;
};

View File

@@ -6,7 +6,7 @@
static const uint8_t LEDC_CHANNEL_LCD_BACKLIGHT = 0;
DisplayTask::DisplayTask(const uint8_t task_core) : Task{"Display", 4048, 1, task_core} {
DisplayTask::DisplayTask(const uint8_t task_core) : Task{"Display", 2048, 1, task_core} {
knob_state_queue_ = xQueueCreate(1, sizeof(KnobState));
assert(knob_state_queue_ != NULL);
@@ -19,66 +19,11 @@ DisplayTask::~DisplayTask() {
vSemaphoreDelete(mutex_);
}
static void HSV_to_RGB(float h, float s, float v, uint8_t *r, uint8_t *g, uint8_t *b)
{
int i;
float f,p,q,t;
h = fmax(0.0, fmin(360.0, h));
s = fmax(0.0, fmin(100.0, s));
v = fmax(0.0, fmin(100.0, v));
s /= 100;
v /= 100;
if(s == 0) {
// Achromatic (grey)
*r = *g = *b = round(v*255);
return;
}
h /= 60; // sector 0 to 5
i = floor(h);
f = h - i; // factorial part of h
p = v * (1 - s);
q = v * (1 - s * f);
t = v * (1 - s * (1 - f));
switch(i) {
case 0:
*r = round(255*v);
*g = round(255*t);
*b = round(255*p);
break;
case 1:
*r = round(255*q);
*g = round(255*v);
*b = round(255*p);
break;
case 2:
*r = round(255*p);
*g = round(255*v);
*b = round(255*t);
break;
case 3:
*r = round(255*p);
*g = round(255*q);
*b = round(255*v);
break;
case 4:
*r = round(255*t);
*g = round(255*p);
*b = round(255*v);
break;
default: // case 5:
*r = round(255*v);
*g = round(255*p);
*b = round(255*q);
}
}
void DisplayTask::run() {
tft_.begin();
tft_.invertDisplay(1);
spr_.setColorDepth(8);
tft_.setRotation(0);
tft_.fillScreen(TFT_DARKGREEN);
@@ -86,7 +31,7 @@ void DisplayTask::run() {
ledcAttachPin(PIN_LCD_BACKLIGHT, LEDC_CHANNEL_LCD_BACKLIGHT);
ledcWrite(LEDC_CHANNEL_LCD_BACKLIGHT, UINT16_MAX);
spr_.setColorDepth(16);
//spr_.setColorDepth(16);
if (spr_.createSprite(TFT_WIDTH, TFT_HEIGHT) == nullptr) {
Serial.println("ERROR: sprite allocation failed!");
@@ -103,10 +48,10 @@ void DisplayTask::run() {
const uint16_t FILL_COLOR = spr_.color565(90, 18, 151);
const uint16_t DOT_COLOR = spr_.color565(80, 100, 200);
int32_t pointer_center_x = TFT_WIDTH / 2;
int32_t pointer_center_y = TFT_HEIGHT / 2;
int32_t pointer_length_short = 10;
int32_t pointer_length_long = TFT_WIDTH / 2 - 5;
// int32_t pointer_center_x = TFT_WIDTH / 2;
// int32_t pointer_center_y = TFT_HEIGHT / 2;
// int32_t pointer_length_short = 10;
// int32_t pointer_length_long = TFT_WIDTH / 2 - 5;
spr_.setTextDatum(CC_DATUM);
spr_.setTextColor(TFT_WHITE);
@@ -165,6 +110,7 @@ void DisplayTask::run() {
float raw_angle = left_bound - state.current_position * state.config.position_width_radians;
float adjusted_angle = raw_angle - adjusted_sub_position;
if (state.config.num_positions > 0 && ((state.current_position == 0 && state.sub_position_unit < 0) || (state.current_position == state.config.num_positions - 1 && state.sub_position_unit > 0))) {
spr_.fillCircle(TFT_WIDTH/2 + (RADIUS - 10) * cosf(raw_angle), TFT_HEIGHT/2 - (RADIUS - 10) * sinf(raw_angle), 5, DOT_COLOR);

View File

@@ -123,7 +123,11 @@ static KnobConfig configs[] = {
},
};
InterfaceTask::InterfaceTask(const uint8_t task_core, MotorTask& motor_task, DisplayTask* display_task) : Task("Interface", 4048, 1, task_core), motor_task_(motor_task), display_task_(display_task) {
InterfaceTask::InterfaceTask(const uint8_t task_core, MotorTask& motor_task, DisplayTask* display_task, CommuTask& commu_task) :
Task("Interface", 4048, 1, task_core),
motor_task_(motor_task),
display_task_(display_task),
commu_task_(commu_task){
#if SK_DISPLAY
assert(display_task != nullptr);
#endif
@@ -201,6 +205,7 @@ void InterfaceTask::run() {
last_als = millis();
}
#endif
#if SK_STRAIN
// TODO: calibrate and track (long term moving average) zero point (lower); allow calibration of set point offset
@@ -235,7 +240,7 @@ void InterfaceTask::run() {
#if SK_LEDS
for (uint8_t i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB::Red;
leds[i] = CRGB::White;
}
FastLED.show();
#endif

View File

@@ -5,6 +5,7 @@
#include "display_task.h"
#include "motor_task.h"
#include "commu_task.h"
#include "task.h"
#define ALSCHECKINTERVAL 4000
@@ -13,7 +14,7 @@ class InterfaceTask : public Task<InterfaceTask>, public ace_button::IEventHandl
friend class Task<InterfaceTask>; // Allow base Task to invoke protected run()
public:
InterfaceTask(const uint8_t task_core, MotorTask& motor_task, DisplayTask* display_task);
InterfaceTask(const uint8_t task_core, MotorTask& motor_task, DisplayTask* display_task, CommuTask& commu_task);
~InterfaceTask();
void handleEvent(ace_button::AceButton* button, uint8_t event_type, uint8_t button_state) override;
@@ -24,6 +25,7 @@ class InterfaceTask : public Task<InterfaceTask>, public ace_button::IEventHandl
private:
MotorTask& motor_task_;
DisplayTask* display_task_;
CommuTask& commu_task_;
int current_config_ = 0;

View File

@@ -13,10 +13,10 @@ static DisplayTask* display_task_p = &display_task;
static DisplayTask* display_task_p = nullptr;
#endif
static MotorTask motor_task = MotorTask(0);
static CommuTask commu_Task = CommuTask(1);
static CommuTask commu_Task = CommuTask(0);
InterfaceTask interface_task = InterfaceTask(0, motor_task, display_task_p);
InterfaceTask interface_task = InterfaceTask(0, motor_task, display_task_p, commu_Task);
static QueueHandle_t knob_state_debug_queue;
@@ -25,7 +25,7 @@ void setup() {
motor_task.begin();
interface_task.begin();
//commu_Task.begin();
commu_Task.begin();
#if SK_DISPLAY
display_task.begin();
@@ -34,6 +34,8 @@ void setup() {
motor_task.addListener(display_task.getKnobStateQueue());
#endif
motor_task.addListener(commu_Task.getKnobStateQueue());
// Create a queue and register it with motor_task to print knob state to serial (see loop() below)
knob_state_debug_queue = xQueueCreate(1, sizeof(KnobState));
assert(knob_state_debug_queue != NULL);

View File

@@ -53,8 +53,8 @@ void MotorTask::run() {
// float zero_electric_offset = -0.8; // handheld 2
// float zero_electric_offset = 2.93; //0.15; // 17mm test
// float zero_electric_offset = 0.66; // 15mm handheld
float zero_electric_offset = 7.07;
Direction foc_direction = Direction::CCW;
float zero_electric_offset = 5.44;
Direction foc_direction = Direction::CW;
motor.pole_pairs = 7;
driver.voltage_power_supply = 5;

View File

@@ -6,44 +6,48 @@
#include "knob_data.h"
#include "task.h"
enum class CommandType {
enum class CommandType
{
CONFIG,
HAPTIC,
};
struct HapticData {
struct HapticData
{
bool press;
};
struct Command {
struct Command
{
CommandType command_type;
union CommandData {
union CommandData
{
KnobConfig config;
HapticData haptic;
};
CommandData data;
};
class MotorTask : public Task<MotorTask> {
class MotorTask : public Task<MotorTask>
{
friend class Task<MotorTask>; // Allow base Task to invoke protected run()
public:
MotorTask(const uint8_t task_core);
~MotorTask();
public:
MotorTask(const uint8_t task_core);
~MotorTask();
void setConfig(const KnobConfig& config);
void playHaptic(bool press);
void setConfig(const KnobConfig &config);
void playHaptic(bool press);
void addListener(QueueHandle_t queue);
void addListener(QueueHandle_t queue);
protected:
void run();
protected:
void run();
private:
QueueHandle_t queue_;
private:
QueueHandle_t queue_;
std::vector<QueueHandle_t> listeners_;
std::vector<QueueHandle_t> listeners_;
void publish(const KnobState& state);
void publish(const KnobState &state);
};