Compare commits

...
4 Commits
17 changed files with 243 additions and 62 deletions
+10 -1
View File
@@ -41,7 +41,16 @@ board_build.f_cpu = 80000000L
board = dfrobot_beetle_esp32c3 board = dfrobot_beetle_esp32c3
platform = espressif32 platform = espressif32
framework = arduino framework = arduino
monitor_speed = 460800 monitor_speed = 115200
monitor_filters =
esp32_exception_decoder
time
lib_deps = lib_deps =
fastled/FastLED@^3.7.0 fastled/FastLED@^3.7.0
knolleary/PubSubClient@^2.8 knolleary/PubSubClient@^2.8
[env:esp32c3_supermini_network]
extends = env:esp32c3_supermini
upload_protocol = espota
upload_port = 10.206.0.101
+21 -11
View File
@@ -7,10 +7,16 @@ uint8_t controlPins[] = {
PIN_KEY, PIN_KEY,
}; };
uint16_t thresholds[] = {
2048,
1000,
3072,
};
uint16_t prevState[3]; uint16_t prevState[3];
uint8_t controlPinCount = sizeof(controlPins) / sizeof(controlPins[0]);
auto lastChange = micros(); auto lastChange = micros();
uint8_t pinChanges[128]; uint8_t pinChanges[128];
uint8_t pinChangeIndex = 0; uint8_t pinChangeIndex = 0;
@@ -39,28 +45,31 @@ void Controls_loop(void *pvParameters){
lastChange = 0; lastChange = 0;
while(true){ while(true){
for(uint8_t a=0; a<sizeof(controlPins); a++){ for(uint8_t a=0; a<controlPinCount; a++){
auto pin = controlPins[a]; auto pin = controlPins[a];
auto currentValueAnalog = analogRead(pin); auto currentValueAnalog = analogRead(pin);
auto currentValue = currentValueAnalog > 3072; auto currentValue = currentValueAnalog > thresholds[a];
auto prevValue = prevState[a]; auto prevValue = prevState[a];
if(CONTROLS_DEBUG){ if(CONTROLS_DEBUG > 200){
Serial.printf("Pin %d: %d->%d (%d)\n", pin, prevValue, currentValue, currentValueAnalog); Serial.printf("Pin %d: %d->%d (%d)\n", pin, prevValue, currentValue, currentValueAnalog);
} }
// if(abs(currentValue - prevValue) > 100){ // if(abs(currentValue - prevValue) > 100){
if(currentValue != prevValue){ if(currentValue != prevValue){
if(CONTROLS_DEBUG > 100){
Serial.printf("Change on pin %d: %d -> %d (%d)\n", pin, prevValue, currentValue, currentValueAnalog);
}
if(pin == PIN_KEY){ if(pin == PIN_KEY){
if(currentValue){ if(currentValue){
auto duration = micros() - lastKey; auto duration = micros() - lastKey;
if(duration > KEY_DURATION_MS * 1000){ if(duration > KEY_DURATION_MS * 1000){
if(CONTROLS_DEBUG){ if(CONTROLS_DEBUG > 10){
Serial.printf("Key: %d\n", duration); Serial.printf("Key: %d\n", duration);
} }
Controls_send_event({Key, (int)duration}); Controls_send_event({Key, (int)duration});
}else{ }else{
if(CONTROLS_DEBUG){ if(CONTROLS_DEBUG > 20){
Serial.println("Too short"); Serial.println("Too short");
} }
} }
@@ -89,7 +98,7 @@ void Controls_loop(void *pvParameters){
pinChanges[base + 3] == PIN_B pinChanges[base + 3] == PIN_B
){ ){
if(CONTROLS_DEBUG){ if(CONTROLS_DEBUG > 10){
Serial.println("Dir A"); Serial.println("Dir A");
} }
Controls_send_event({Counterclockwise, NULL}); Controls_send_event({Counterclockwise, NULL});
@@ -100,13 +109,14 @@ void Controls_loop(void *pvParameters){
pinChanges[base + 3] == PIN_A pinChanges[base + 3] == PIN_A
){ ){
if(CONTROLS_DEBUG){ if(CONTROLS_DEBUG > 10){
Serial.println("Dir B"); Serial.println("Dir B");
} }
Controls_send_event({Clockwise, NULL}); Controls_send_event({Clockwise, NULL});
}else{ }else{
if(CONTROLS_DEBUG){ if(CONTROLS_DEBUG > 20){
Serial.println("Unknown direction"); Serial.println("Unknown direction");
Serial.printf("[%d, %d, %d, %d]\n", pinChanges[base + 0], pinChanges[base + 1], pinChanges[base + 2], pinChanges[base + 3]);
} }
} }
} }
@@ -116,14 +126,14 @@ void Controls_loop(void *pvParameters){
if(lastChange){ if(lastChange){
if(micros() - lastChange > 100 * 1000){ if(micros() - lastChange > 100 * 1000){
if(CONTROLS_DEBUG){ if(CONTROLS_DEBUG > 100){
Serial.println("changes expired"); Serial.println("changes expired");
} }
Controls_direction_reset(); Controls_direction_reset();
} }
} }
vTaskDelay(1/portTICK_PERIOD_MS); vTaskDelay(2/portTICK_PERIOD_MS);
} }
} }
+6 -4
View File
@@ -1,14 +1,16 @@
#pragma once #pragma once
#include "config.h"
#include <Arduino.h> #include <Arduino.h>
#define PIN_A 2 #define PIN_A 1
#define PIN_B 1 #define PIN_B 0
#define PIN_KEY 0 #define PIN_KEY 2
#define KEY_DURATION_MS 150 #define KEY_DURATION_MS 150
#define CONTROLS_DEBUG false #define CONTROLS_DEBUG 1
enum ControlEventType { enum ControlEventType {
+97 -10
View File
@@ -3,25 +3,106 @@
CRGB colorTable[] = { CRGB colorTable[] = {
CRGB(255, 142, 32), // "warm wit"
// CRGB(255, 100, 4), // CRGB(255, 100, 4),
// CRGB(255, 128, 4), // CRGB(255, 128, 4),
// CRGB(255, 100, 32), // CRGB(255, 100, 32),
// CRGB(255, 128, 32), // CRGB(255, 128, 32),
CRGB::White, CRGB::White,
CRGB(255, 142, 32), // "warm wit" CRGB::Red,
CRGB::Green,
CRGB::Blue,
CRGB::Yellow,
CRGB::Turquoise,
CRGB::Purple,
}; };
Hanglamp::Hanglamp(){ Hanglamp::Hanglamp(){
turnOn();
} }
void parseHexColor(const String& hexColor, uint8_t& r, uint8_t& g, uint8_t& b) {
String cleanHex = hexColor;
// Remove leading '#' if present
if (cleanHex.startsWith("#")) {
cleanHex = cleanHex.substring(1);
}
// Make sure it's exactly 6 characters
if (cleanHex.length() != 6) {
r = g = b = 0; // default/fallback
return;
}
// Parse the color components
r = strtoul(cleanHex.substring(0, 2).c_str(), NULL, 16);
g = strtoul(cleanHex.substring(2, 4).c_str(), NULL, 16);
b = strtoul(cleanHex.substring(4, 6).c_str(), NULL, 16);
}
void Hanglamp::setup(){ void Hanglamp::setup(){
#ifdef ENABLE_MQTT
MQTT_subscribe("hanglamp/CMD/brightness", [&](unsigned char* payload, unsigned int len){
String input = String((const char*)payload).substring(0, len);
int brightness = constrain(input.toInt(), 0, 255);
setBrightness(brightness);
});
MQTT_subscribe("hanglamp/CMD/color", [&](unsigned char* payload, unsigned int len){
String input = String((const char*)payload).substring(0, len);
uint8_t r, g, b;
parseHexColor(input, r, g, b);
Serial.printf("input: %s, r: %d, g: %d, b: %d\n", input, r, g, b);
CRGB color(r, g, b);
setColor(color);
});
MQTT_subscribe("hanglamp/CMD/power", [&](unsigned char* payload, unsigned int len){
String input = String((const char*)payload).substring(0, len);
Serial.printf("Have power command: [%s]\n", input.c_str());
if(input == "true" || input == "1" || input == "on" || input == "ON"){
Serial.printf("Setting power to true\n");
turnOn();
}else{
Serial.printf("Setting power to false\n");
turnOff();
}
});
#endif
setColor(colorTable[this->colorIndex]);
turnOn();
} }
void Hanglamp::setColor(CRGB color){ void Hanglamp::setColor(CRGB color){
jumpTo(color); currentColor = color;
jumpTo(currentColor);
changed();
}
void Hanglamp::changed(){
#ifdef ENABLE_MQTT
char buff[128];
snprintf(buff, sizeof(buff),
"{\"color\":\"%02X%02X%02X\",\"brightness\":%d,\"power\":%s}",
currentColor.r,
currentColor.g,
currentColor.b,
brightness,
on ? "true" : "false"
);
MQTT_publish("hanglamp/status", buff);
#endif
} }
void Hanglamp::nextColor(){ void Hanglamp::nextColor(){
@@ -35,17 +116,15 @@ void Hanglamp::nextColor(){
} }
void Hanglamp::setBrightness(int brightness){ void Hanglamp::setBrightness(int brightness){
uint8_t newBrightness = uint8_t newBrightness = constrain(brightness, 0, 255);
brightness < 0 ? 0 : if(!isOn()){
brightness > 255 ? 255 : turnOn();
brightness; }
this->brightness = newBrightness; this->brightness = newBrightness;
Serial.printf("new brightness: %d\n", newBrightness); Serial.printf("new brightness: %d\n", newBrightness);
FastLED.setBrightness(newBrightness); FastLED.setBrightness(newBrightness);
FastLED.show(); FastLED.show();
#ifdef ENABLE_MQTT changed();
MQTT_publish("hanglamp/brightness", String(newBrightness));
#endif
} }
void Hanglamp::adjustBrightness(int add){ void Hanglamp::adjustBrightness(int add){
@@ -88,6 +167,10 @@ void Hanglamp::status(CRGB color){
void Hanglamp::setOn(bool on){ void Hanglamp::setOn(bool on){
Serial.printf("Hanglamp::setOn(%d -> %d)\n", this->on, on); Serial.printf("Hanglamp::setOn(%d -> %d)\n", this->on, on);
this->on = on; this->on = on;
if(currentColor == CRGB::Black){
nextColor();
}
changed();
} }
bool Hanglamp::isOn(){ bool Hanglamp::isOn(){
@@ -96,6 +179,10 @@ bool Hanglamp::isOn(){
void Hanglamp::turnOn(){ void Hanglamp::turnOn(){
if(!this->on){ if(!this->on){
this->colorIndex = 1;
setColor(colorTable[1]);
FastLED.setBrightness(this->brightness); FastLED.setBrightness(this->brightness);
FastLED.show(); FastLED.show();
this->setOn(true); this->setOn(true);
+8
View File
@@ -1,9 +1,13 @@
#pragma once #pragma once
#include "config.h"
#include <FastLED.h> #include <FastLED.h>
#include "Led.h" #include "Led.h"
#include "Controls.h" #include "Controls.h"
#include "MQTT.h"
class Hanglamp { class Hanglamp {
public: public:
@@ -20,9 +24,13 @@ class Hanglamp {
void turnOn(); void turnOn();
void turnOff(); void turnOff();
// void receiveBrightnessFromMQTT(uint8_t * payload, unsigned int len);
private: private:
void changed();
char colorIndex = 0; char colorIndex = 0;
CRGB currentColor;
int brightness = 128; int brightness = 128;
bool on = false; bool on = false;
void setOn(bool on); void setOn(bool on);
+2
View File
@@ -127,6 +127,8 @@ void Led_setup(){
FastLED.addLeds<WS2812B, PIN_STRIP2, GRB>(strip2, NUM_LEDS).setRgbw(RgbwDefault()); FastLED.addLeds<WS2812B, PIN_STRIP2, GRB>(strip2, NUM_LEDS).setRgbw(RgbwDefault());
strip1[0] = CRGB::Black; strip1[0] = CRGB::Black;
strip2[0] = CRGB::Black; strip2[0] = CRGB::Black;
FastLED.show();
#endif #endif
#ifdef LED_NEOPIXEL_BUS #ifdef LED_NEOPIXEL_BUS
+3
View File
@@ -1,7 +1,10 @@
#pragma once #pragma once
#include "stdint.h" #include "stdint.h"
#include <cstdio> #include <cstdio>
#include "config.h"
#include <Arduino.h> #include <Arduino.h>
// #define LED_NEOPIXEL_BUS // #define LED_NEOPIXEL_BUS
+12 -16
View File
@@ -10,7 +10,7 @@ PubSubClient client(espClient);
std::vector<SubscribedChannel> * channels = new std::vector<SubscribedChannel>(); std::vector<SubscribedChannel> * channels = new std::vector<SubscribedChannel>();
char mqtt_server[40] = "manus"; char mqtt_server[40] = "10.206.0.175";
char mqtt_port[6] = "1883"; char mqtt_port[6] = "1883";
@@ -46,20 +46,18 @@ void connect() {
} }
void MQTT_publish(const char * topic, String str){ void MQTT_publish(const char * topic, String str){
char * buff = new char[str.length() + 1]; // char * buff = new char[str.length() + 1];
str.toCharArray(buff, str.length() + 1); // str.toCharArray(buff, str.length() + 1);
MQTT_publish(topic, buff); MQTT_publish(topic, str.c_str());
delete buff; // delete buff;
} }
void MQTT_publish(const char * topic, const char * msg){ void MQTT_publish(const char * topic, const char * msg){
Serial.printf("MQTT_publish(%s, %s)\n", topic, msg);
client.publish(topic, msg); client.publish(topic, msg);
} }
void (*pCallback)(uint8_t *, unsigned int) = NULL; void MQTT_subscribe(char * topic, mqtt_callback callback){
void MQTT_subscribe(char * topic, void (*callback)(uint8_t *, unsigned int)){
Serial.println("MQTT_subscribe"); Serial.println("MQTT_subscribe");
Serial.printf("Topic: [%s]\n", topic); Serial.printf("Topic: [%s]\n", topic);
@@ -97,13 +95,8 @@ void MQTT_setup(){
client.setServer(mqtt_server, String(mqtt_port).toInt()); client.setServer(mqtt_server, String(mqtt_port).toInt());
client.setCallback(MQTT_callback); client.setCallback(MQTT_callback);
// Serial.println("MQTT_init after callback");
// char buff[256];
// sprintf(buff, "%08x", _pCallback);
// Serial.println(buff);
TaskHandle_t taskMqtt = NULL; TaskHandle_t taskMqtt = NULL;
xTaskCreate(MQTT_loop, "Wifi_loop", 10000, NULL, tskIDLE_PRIORITY, &taskMqtt); xTaskCreate(MQTT_loop, "MQTT_loop", 10000, NULL, tskIDLE_PRIORITY, &taskMqtt);
} }
void MQTT_loop(void* params){ void MQTT_loop(void* params){
@@ -119,7 +112,10 @@ void MQTT_loop(void* params){
connect(); connect();
if(client.connected()){ if(client.connected()){
Serial.println("MQTT: succes!"); Serial.println("MQTT: success!");
for (auto channel = channels->begin(); channel != channels->end(); ++channel){
client.subscribe(channel->topic->c_str());
}
break; break;
}else{ }else{
Serial.println("MQTT: connection failed, try again in 5 seconds"); Serial.println("MQTT: connection failed, try again in 5 seconds");
+8 -2
View File
@@ -1,6 +1,6 @@
#pragma once #pragma once
#include "settings.h" #include "config.h"
#include "Arduino.h" #include "Arduino.h"
@@ -11,14 +11,20 @@
using namespace std; using namespace std;
extern char mqtt_server[40];
extern char mqtt_port[6];
typedef std::function<void(unsigned char *, unsigned int)> mqtt_callback;
struct SubscribedChannel { struct SubscribedChannel {
String * topic; String * topic;
void (*callback)(uint8_t *, unsigned int); mqtt_callback callback;
}; };
void MQTT_subscribe(char * topic, mqtt_callback callback);
void MQTT_publish(const char * topic, String str); void MQTT_publish(const char * topic, String str);
void MQTT_publish(const char * topic, const char * msg); void MQTT_publish(const char * topic, const char * msg);
+44
View File
@@ -0,0 +1,44 @@
#include "OTA.h"
#include <ArduinoOTA.h>
void OTA_setup(){
ArduinoOTA
.onStart([]() {
String type;
if (ArduinoOTA.getCommand() == U_FLASH) {
type = "sketch";
} else { // U_SPIFFS
type = "filesystem";
}
// NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
Serial.println("Start updating " + type);
})
.onEnd([]() {
Serial.println("\nEnd");
})
.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
})
.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) {
Serial.println("Auth Failed");
} else if (error == OTA_BEGIN_ERROR) {
Serial.println("Begin Failed");
} else if (error == OTA_CONNECT_ERROR) {
Serial.println("Connect Failed");
} else if (error == OTA_RECEIVE_ERROR) {
Serial.println("Receive Failed");
} else if (error == OTA_END_ERROR) {
Serial.println("End Failed");
}
});
ArduinoOTA.begin();
}
void OTA_loop(){
ArduinoOTA.handle();
}
+2
View File
@@ -0,0 +1,2 @@
void OTA_loop();
void OTA_setup();
+3
View File
@@ -1,2 +1,5 @@
#include "config.h"
void PinFinder_setup(); void PinFinder_setup();
void PinFinder_loop(); void PinFinder_loop();
+4 -1
View File
@@ -30,8 +30,11 @@ void Wifi_loop(void* params){
{ {
while (WiFi.status() != WL_CONNECTED) while (WiFi.status() != WL_CONNECTED)
{ {
vTaskDelay(500 / portTICK_PERIOD_MS);
Serial.println("Wifi waiting..."); Serial.println("Wifi waiting...");
vTaskDelay(5000 / portTICK_PERIOD_MS);
if(WiFi.status() != WL_CONNECTED){
WiFi.reconnect();
}
} }
Serial.println(""); Serial.println("");
+1 -1
View File
@@ -1,3 +1,3 @@
#include "config.h"
void Wifi_setup(); void Wifi_setup();
+12
View File
@@ -0,0 +1,12 @@
#pragma once
#define INCLUDE_LED
#define ENABLE_MQTT
#define ENABLE_OTA
#define ENABLE_WIFI
// #define ENABLE_FS
// #define ENABLE_PINFINDER
#define ENABLE_COLORS
// #define ENABLE_PIN_SENSING
#define ENABLE_CONTROLS
+9 -8
View File
@@ -1,4 +1,6 @@
#define INCLUDE_LED
#include "config.h"
#ifdef INCLUDE_LED #ifdef INCLUDE_LED
#include "Led.h" #include "Led.h"
#endif #endif
@@ -8,18 +10,17 @@
#define _TASK_SLEEP_ON_IDLE_RUN // Enable 1 ms SLEEP_IDLE powerdowns between runs if no callback methods were invoked during the pass #define _TASK_SLEEP_ON_IDLE_RUN // Enable 1 ms SLEEP_IDLE powerdowns between runs if no callback methods were invoked during the pass
#define _TASK_STATUS_REQUEST // Compile with support for StatusRequest functionality - triggering tasks on status change events in addition to time only #define _TASK_STATUS_REQUEST // Compile with support for StatusRequest functionality - triggering tasks on status change events in addition to time only
#define ENABLE_MQTT
#define ENABLE_WIFI
// #define ENABLE_FS
// #define ENABLE_PINFINDER
#define ENABLE_COLORS
// #define ENABLE_PIN_SENSING
#define ENABLE_CONTROLS
#ifdef ENABLE_WIFI #ifdef ENABLE_WIFI
#include "Wifi.h" #include "Wifi.h"
#endif #endif
#ifdef ENABLE_OTA
#include "OTA.h"
#endif
#ifdef ENABLE_MQTT #ifdef ENABLE_MQTT
#include "MQTT.h" #include "MQTT.h"
#endif #endif
-7
View File
@@ -1,7 +0,0 @@
#ifndef SETTINGS_H
#define SETTINGS_H
extern char mqtt_server[40];
extern char mqtt_port[6];
#endif