Address strip WS2812B: различия между версиями

Нет описания правки
Строка 583: Строка 583:


Есть и минусы: если вы совершите ошибку в коде и будет возникал kernel panic / fatal, тогда вам уже точно придется тащить железку к компу и прошивать фикс через кабель
Есть и минусы: если вы совершите ошибку в коде и будет возникал kernel panic / fatal, тогда вам уже точно придется тащить железку к компу и прошивать фикс через кабель
==Добавление настроек==
Допустим, мы захотели управлять какой-то настройкой еще, пускай это будет скорость обновления светодиодов. Ранее у нас была определена константа
<syntaxhighlight lang="c++">
#define UPDATES_PER_SECOND 500
</syntaxhighlight>
теперь нам её придётся сделать обычной переменной:
<syntaxhighlight lang="c++">
int UPDATES_PER_SECOND = 500;
</syntaxhighlight>
теперь нужно подписать на новый топик:
<syntaxhighlight lang="c++">
void modbusCallback(char* topic, byte* payload, unsigned int length) {
  char payloadChar[sizeof(payload)];
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
    payloadChar[i] = (char)payload[i];
  }
  Serial.println();
  String payloadStr = String(payloadChar);
  payloadStr.trim();
 
  if (strcmp(topic, "/devices/ws2812b/controls/brightness") == 0) {
    BRIGHTNESS = payloadStr.toInt();
    Serial.printf("brithness set to %d\n", BRIGHTNESS);
  }
  if (strcmp(topic, "/devices/ws2812b/controls/hueLoop") == 0) {
    if(payloadStr.toInt() == 1) {
      hueLoop = true;
    } else {
      hueLoop = false;
    }
  }
  if (strcmp(topic, "/devices/ws2812b/controls/updatesPerSecond") == 0) {
      UPDATES_PER_SECOND = payloadStr.toInt();
  }
}
void modbusReconnect() {
  // Loop until we're reconnected
  while (!pubSubClient.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP32Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (pubSubClient.connect(clientId.c_str())) {
      Serial.println("connected");
      pubSubClient.subscribe("/devices/ws2812b/controls/brightness");
      pubSubClient.subscribe("/devices/ws2812b/controls/hueLoop");
      pubSubClient.subscribe("/devices/ws2812b/controls/updatesPerSecond");
    } else {
      Serial.print("failed, rc=");
      Serial.print(pubSubClient.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}
</syntaxhighligh>
заливаем прошивку в esp32.
осталось обновить виртуальное устройство в wirenboard:
<syntaxhighlight lang="javascript">
defineVirtualDevice("ws2812b", {
    title: "ws2812b",
    cells: {
      enabled: {
        title: "состояние",
        type: "switch",
        value: false,
      },
      brightness: {
        title: "яркость",
        type: "range",
        min: 0,
        max: 255,
        value: 50,
      },     
  hueLoop: {
        title: "смена оттенков",
        type: "switch",
        value: true,  
  },
      updatesPerSecond: {
        title: "скорость обновления светодиодов",
        type: "range",
        min: 10,
        max: 1000,
        value: 100,
      },
}
})
</syntaxhighlight>
после применения виртуального устройства можно управлять скорость обновления светодиодов из интерфейса wirenboard.
==Какие могут быть проблемы==
# изначально лента тестировалась на arduino nano, и на LED_TYPE==WS2812B оно работало странно, но с учетом того что какие-то отдельные светодиоды загорались, я пришёл к выводу что цифра работает, но есть какие-то проблемы с частотой, в итоге заработало на WS2811_400, то есть на частоте 400кгц, однако, в случае с esp32 всё заработало со штатным типом WS2812B
# важно учитывать тот факт, что нельзя допускать подключения ленты без стабильного плюса, то есть в случае подключения ленты к GND и DIN-пину, есть риск, что пин спалится, чтобы подстраховаться - ставится резистор на 220ом, но всё равно лучше избегать таких вот нештатных ситуаций
# на самом деле проблемы могут быть самые разнообразные, потому что это DIY, если что пишите в чатике - попробуем разобраться


==Финальный код скетча==
==Финальный код скетча==
Строка 611: Строка 723:




#define WIFI_SSID "ssid"
#define WIFI_SSID "q.O.p"
#define WIFI_PASSWORD "xxx"
#define WIFI_PASSWORD "ILoveYouBaby"
void setupWifi() {
void setupWifi() {
   WiFi.mode(WIFI_STA);
   WiFi.mode(WIFI_STA);
Строка 659: Строка 771:
CRGB leds[NUM_LEDS];
CRGB leds[NUM_LEDS];
   
   
#define UPDATES_PER_SECOND 50
int UPDATES_PER_SECOND = 500;


uint8_t BRIGHTNESS = 50;
uint8_t BRIGHTNESS = 50;
Строка 687: Строка 799:
void modbusCallback(char* topic, byte* payload, unsigned int length) {
void modbusCallback(char* topic, byte* payload, unsigned int length) {
   char payloadChar[sizeof(payload)];
   char payloadChar[sizeof(payload)];
   Serial.print("Message arrived [");
   Serial.print("Message arrived [");
   Serial.print(topic);
   Serial.print(topic);
Строка 698: Строка 809:


   String payloadStr = String(payloadChar);
   String payloadStr = String(payloadChar);
  payloadStr.trim();
    
    
   if (topic == "/devices/ws2812b/controls/brightness") {
   if (strcmp(topic, "/devices/ws2812b/controls/brightness") == 0) {
     BRIGHTNESS = payloadStr.toInt();
     BRIGHTNESS = payloadStr.toInt();
    Serial.printf("brithness set to %d\n", BRIGHTNESS);
   }
   }
   if (topic == "/devices/ws2812b/controls/hueLoop") {
   if (strcmp(topic, "/devices/ws2812b/controls/hueLoop") == 0) {
     if(payloadChar == "true") {
     if(payloadStr.toInt() == 1) {
       hueLoop = true;
       hueLoop = true;
     } else {
     } else {
       hueLoop = false;
       hueLoop = false;
     }
     }
  }
  if (strcmp(topic, "/devices/ws2812b/controls/updatesPerSecond") == 0) {
      UPDATES_PER_SECOND = payloadStr.toInt();
   }
   }
}
}
Строка 714: Строка 830:
   pubSubClient.setServer(MODBUS_SERVER, MODBUS_PORT);
   pubSubClient.setServer(MODBUS_SERVER, MODBUS_PORT);
   pubSubClient.setCallback(modbusCallback);
   pubSubClient.setCallback(modbusCallback);
  pubSubClient.subscribe("/devices/ws2812b/controls/brightness");
  pubSubClient.subscribe("/devices/ws2812b/controls/hueLoop");
}
}


Строка 728: Строка 842:
     if (pubSubClient.connect(clientId.c_str())) {
     if (pubSubClient.connect(clientId.c_str())) {
       Serial.println("connected");
       Serial.println("connected");
      pubSubClient.subscribe("/devices/ws2812b/controls/brightness");
      pubSubClient.subscribe("/devices/ws2812b/controls/hueLoop");
      pubSubClient.subscribe("/devices/ws2812b/controls/updatesPerSecond");
     } else {
     } else {
       Serial.print("failed, rc=");
       Serial.print("failed, rc=");
Строка 777: Строка 894:
     static uint8_t lastSecond = 99;
     static uint8_t lastSecond = 99;
      
      
    FastLED.setBrightness(BRIGHTNESS);
    if(!hueLoop) {
        return;
    }
     if( lastSecond != secondHand) {
     if( lastSecond != secondHand) {
         lastSecond = secondHand;
         lastSecond = secondHand;
Строка 933: Строка 1055:
{
{
     modbusLoop();
     modbusLoop();
    if(!hueLoop) {
        return;
    }
     ChangePalettePeriodically();
     ChangePalettePeriodically();
      
      
Строка 947: Строка 1066:
}
}
</syntaxhighlight>
</syntaxhighlight>
==Добавление настроек==
Допустим, мы захотели управлять какой-то настройкой еще, пускай это будет скорость обновления светодиодов. Ранее у нас была определена константа
<syntaxhighlight lang="c++">
#define UPDATES_PER_SECOND 500
</syntaxhighlight>
теперь нам её придётся сделать обычной переменной:
<syntaxhighlight lang="c++">
int UPDATES_PER_SECOND = 500;
</syntaxhighlight>
теперь нужно подписать на новый топик:
<syntaxhighlight lang="c++">
void modbusCallback(char* topic, byte* payload, unsigned int length) {
  char payloadChar[sizeof(payload)];
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
    payloadChar[i] = (char)payload[i];
  }
  Serial.println();
  String payloadStr = String(payloadChar);
  payloadStr.trim();
 
  if (strcmp(topic, "/devices/ws2812b/controls/brightness") == 0) {
    BRIGHTNESS = payloadStr.toInt();
    Serial.printf("brithness set to %d\n", BRIGHTNESS);
  }
  if (strcmp(topic, "/devices/ws2812b/controls/hueLoop") == 0) {
    if(payloadStr.toInt() == 1) {
      hueLoop = true;
    } else {
      hueLoop = false;
    }
  }
  if (strcmp(topic, "/devices/ws2812b/controls/updatesPerSecond") == 0) {
      UPDATES_PER_SECOND = payloadStr.toInt();
  }
}
void modbusReconnect() {
  // Loop until we're reconnected
  while (!pubSubClient.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP32Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (pubSubClient.connect(clientId.c_str())) {
      Serial.println("connected");
      pubSubClient.subscribe("/devices/ws2812b/controls/brightness");
      pubSubClient.subscribe("/devices/ws2812b/controls/hueLoop");
      pubSubClient.subscribe("/devices/ws2812b/controls/updatesPerSecond");
    } else {
      Serial.print("failed, rc=");
      Serial.print(pubSubClient.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}
</syntaxhighligh>
заливаем прошивку в esp32.
осталось обновить виртуальное устройство в wirenboard:
<syntaxhighlight lang="javascript">
defineVirtualDevice("ws2812b", {
    title: "ws2812b",
    cells: {
      enabled: {
        title: "состояние",
        type: "switch",
        value: false,
      },
      brightness: {
        title: "яркость",
        type: "range",
        min: 0,
        max: 255,
        value: 50,
      },     
  hueLoop: {
        title: "смена оттенков",
        type: "switch",
        value: true,  
  },
      updatesPerSecond: {
        title: "скорость обновления светодиодов",
        type: "range",
        min: 10,
        max: 1000,
        value: 100,
      },
}
})
</syntaxhighlight>
после применения виртуального устройства можно управлять скорость обновления светодиодов из интерфейса wirenboard.
==Какие могут быть проблемы==
# изначально лента тестировалась на arduino nano, и на LED_TYPE==WS2812B оно работало странно, но с учетом того что какие-то отдельные светодиоды загорались, я пришёл к выводу что цифра работает, но есть какие-то проблемы с частотой, в итоге заработало на WS2811_400, то есть на частоте 400кгц, однако, в случае с esp32 всё заработало со штатным типом WS2812B
# важно учитывать тот факт, что нельзя допускать подключения ленты без стабильного плюса, то есть в случае подключения ленты к GND и DIN-пину, есть риск, что пин спалится, чтобы подстраховаться - ставится резистор на 220ом, но всё равно лучше избегать таких вот нештатных ситуаций
# на самом деле проблемы могут быть самые разнообразные, потому что это DIY, если что пишите в чатике - попробуем разобраться
123

правки